В этой статье я продолжу рассказ о реализации диалогового пользовательского интерфейса для FlexDeploy поверх Oracle Digital Assistant и
Проект Fn . Сегодня я собираюсь перенести серверный API, работающий вокруг моего чат-бота, в облако, поэтому все решение работает в облаке:
API реализован в виде набора функций Fn, собранных в приложении Fn. Прелесть Fn в том, что это просто набор контейнеров Docker, которые могут одинаково работать на вашем ноутбуке на вашем локальном движке Docker и где-то в облаке. Сказав, что я могу запустить свое приложение Fn в кластере K8s от любого облачного провайдера, как описано здесь . Но сегодня не тот день. Сегодня я собираюсь запустить свой серверный API на новом облачном сервисе Oracle Functions, который построен на основе Fn. Услуга еще не является общедоступной, но я участвую в программе ограниченной доступности, поэтому у меня есть пробный доступ к ней, я могу поиграть с ней и написать об этом в блоге. В этом решении мне пришлось избавиться от реализованного здесь Fn Flow и вернуться к моей первоначальной реализации, поскольку Fn Flow еще не поддерживается функциями Oracle. Я надеюсь, что это будет скоро, поскольку это — действительно лучшая часть.
Итак, настроив нашу среду OCI и запустив службу Oracle Functions (я здесь не репостирую руководство по Oracle), нам нужно настроить CLI Fn для связи с сервисом:
1
2
3
4
5
6
|
fn create context oracle_fn --provider oracle fn use context oracle_fn fn update context oracle.compartment-id MY_COMPARTMENT_ID fn update context api-url https: //functions.us-phoenix-1.oraclecloud.com fn update context registry phx.ocir.io/flexagonoraclecloud/flexagon-repo fn update context oracle.profile oracle_fn |
Итак, теперь наш интерфейс командной строки Fn общается с функциями Oracle . Следующим шагом является создание приложения в консоли Oracle Functions :
Теперь мы можем развернуть приложение Fn для функций Oracle :
1
2
3
4
5
6
7
8
9
|
Eugenes-MacBook-Pro- 3 :fn fedor$ ls -l total 8 -rw-r--r--@ 1 fedor staff 12 Dec 4 15 : 41 app.yaml drwxr-xr-x 5 fedor staff 160 Feb 9 15 : 24 createsnapshotfn drwxr-xr-x 6 fedor staff 192 Feb 9 15 : 25 receiveFromBotFn drwxr-xr-x 6 fedor staff 192 Feb 9 15 : 25 sendToBotFn Eugenes-MacBook-Pro- 3 :fn fedor$ Eugenes-MacBook-Pro- 3 :fn fedor$ Eugenes-MacBook-Pro- 3 :fn fedor$ fn deploy --all |
Сделав это, мы можем наблюдать за приложением в консоли Oracle Functions :
Следующий шаг — обновить URL-адреса API в чат-боте и на моем ноутбуке, чтобы вызывать функции в облаке вместо предыдущей локальной реализации. URL-адреса могут быть получены с помощью следующей команды:
1
|
fn list triggers odaapp |
До сих пор переход с моего ноутбука на Oracle Functions выглядел довольно просто и легко. Но здесь немного боли. Для вызова функций, размещенных в Oracle Functions, с запросами http, запросы должны быть подписаны, чтобы они могли проходить проверку подлинности. Реализация node.js для вызова подписанного вызова функции выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
var fs = require( 'fs' ); var https = require( 'https' ); var os = require( 'os' ); var httpSignature = require( 'http-signature' ); var jsSHA = require( "jssha" ); var tenancyId = "ocid1.tenancy.oc1..aaaaaaaayonz5yhpr4vxqpbdof5rn7x5pfrlgjwjycwxasf4dkexiq" ; var authUserId = "ocid1.user.oc1..aaaaaaaava2e3wd3cu6lew2sktd6by5hnz3d7prpgjho4oambterba" ; var keyFingerprint = "88:3e:71:bb:a5:ea:68:b7:56:fa:3e:5d:ea:45:60:10" ; var privateKeyPath = "/Users/fedor/.oci/functions_open.pem" ; var privateKey = fs.readFileSync(privateKeyPath, 'ascii' ); var identityDomain = "identity.us-ashburn-1.oraclecloud.com" ; function sign(request, options) { var apiKeyId = options.tenancyId + "/" + options.userId + "/" + options.keyFingerprint; var headersToSign = [ "host" , "date" , "(request-target)" ]; var methodsThatRequireExtraHeaders = [ "POST" , "PUT" ]; if (methodsThatRequireExtraHeaders.indexOf(request.method.toUpperCase()) !== - 1 ) { options.body = options.body || "" ; var shaObj = new jsSHA( "SHA-256" , "TEXT" ); shaObj.update(options.body); request.setHeader( "Content-Length" , options.body.length); request.setHeader( "x-content-sha256" , shaObj.getHash( 'B64' )); headersToSign = headersToSign.concat([ "content-type" , "content-length" , "x-content-sha256" ]); } httpSignature.sign(request, { key: options.privateKey, keyId: apiKeyId, headers: headersToSign }); var newAuthHeaderValue = request.getHeader( "Authorization" ).replace( "Signature " , "Signature version=\"1\"," ); request.setHeader( "Authorization" , newAuthHeaderValue); } function handleRequest(callback) { return function(response) { var responseBody = "" ; response.on( 'data' , function(chunk) { responseBody += chunk; }); response.on( 'end' , function() { callback(JSON.parse(responseBody)); }); } } function createSnapshot(release) { var body = release; var options = { host: 'af4qyj7yhva.us-phoenix-1.functions.oci.oraclecloud.com' , path: '/t/createsnapshotfn' , method: 'POST' , headers: { "Content-Type" : "application/text" , } }; var request = https.request(options, handleRequest(function(data) { console.log(data); })); sign(request, { body: body, privateKey: privateKey, keyFingerprint: keyFingerprint, tenancyId: tenancyId, userId: authUserId }); request.end(body); }; |
Этот подход должен использоваться пользовательскими компонентами Oracle Digital Assistant и компонентом слушателя на моем ноутбуке при вызове бессерверного API, размещенного в функциях Oracle .
Это оно!
Опубликовано на Java Code Geeks с разрешения Евгения Федоренко, партнера нашей программы JCG . См. Оригинальную статью здесь: пользовательский интерфейс разговора с Oracle Digital Assistant и Fn Project. Часть III Переезд в облако. Мнения, высказанные участниками Java Code Geeks, являются их собственными. |