
Este artigo continua a série de notas traduzidas sobre o OpenWhisk por Priti Desai . Hoje, veremos exemplos de implantação de funções Zip, dependências do GitHub e também descreveremos mais detalhadamente a sincronização de objetos entre o cliente e o servidor OpenWhisk.
Funções zip
O OpenWhisk suporta a criação de funções a partir de um único arquivo de origem, como foi mostrado anteriormente (). Ele também suporta a criação de uma função usando vários arquivos com código fonte e um conjunto de pacotes dos quais a função depende. Esse caso de uso para funções é chamado de função zip. Vamos tentar implantar uma função zip usando o wskdeploy
.
Primeiro passo
Crie um arquivo de manifesto:
packages: zipaction: actions: my-zip-action: function: actions/my-zip-action runtime: nodejs:6 inputs: name: Amy
Acreditamos que o my-zip-action
possui uma estrutura de diretório que contém o código fonte da função:
$ ls actions/my-zip-action index.js package.json
O conteúdo do arquivo index.js :
function helloworld(params) { var format = require('string-format'); var name = params.name || 'Stranger'; payload = format('Hello, {}!', name) return { message: payload }; } exports.main = helloworld;
O conteúdo do arquivo package.json :
{ "name": "my-zip-action", "description": "Node OpenWhisk zip action to demo Whisk Deploy", "license": "Apache-2.0", "version": "1.0.0", "main": "index.js", "dependencies": { "string-format": "0.5.0" } }
Segundo passo
Execute o npm install para instalar o formato de sequência:
cd actions/my-action npm install --production
Passo três
Expanda a função zip:
./wskdeploy -i -p actions/my-zip-action/ ____ ___ _ _ _ _ _ /\ \ / _ \ _ __ ___ _ __ | | | | |__ (_)___| | __ /\ /__\ \ | | | | '_ \ / _ \ '_ \| | | | '_ \| / __| |/ / / \____ \ / | |_| | |_) | __/ | | | |/\| | | | | \__ \ < \ \ / \/ \___/| .__/ \___|_| |_|__/\__|_| |_|_|___/_|\_\ \___\/ |_| Packages: Name: zipaction bindings: * action: my-zip-action bindings: - name: name value: Amy Do you really want to deploy this? (y/N): y Deployment completed successfully.
Implementamos a função zip my-zip-action com o módulo dependente string-format
. Ao especificar um diretório no manifesto com a tecla de function
, um arquivo compactado é criado nesse diretório e também uma função desse arquivo, portanto, você não precisa procurá-lo no sistema de arquivos. Após a implantação, você pode trabalhar com a nova função da mesma maneira que com outras funções.
Incluir e excluir arquivos em funções zip
O OpenWhisk permite criar uma função usando um arquivo zip contendo qualquer número de arquivos para a função, incluindo todos os seus vícios. A implantação suporta a especificação na function
diretório com arquivos para a função funcionar. Um arquivo será criado a partir do conteúdo do diretório, a partir do qual a função já será implantada.
Inclusão de arquivo
Anteriormente, era possível especificar uma chave de include
, que funciona da mesma maneira que a import
em linguagens de programação, o que permitia, por exemplo, várias funções para referenciar a mesma biblioteca com código:
$ cd actions/ $ ls -1 ./ common/ greeting1/ greeting2/ manifest.yaml $ ls -1 common/ utils.js $ ls -1 greeting1/ index.js package.json $ ls -1 greeting2/ index.js package.json
Você pode ver o arquivo index.js
no diretório greeting1
, bem como outro index.js
no diretório greeting2
, e ambos se referem a utils.js
localizado em common/
.
O conteúdo do arquivo index.js localizado em actions/greeting1/
:
/** * Return a simple greeting message for someone. * * @param name A person's name. * @param place Where the person is from. */ var common = require('./common/utils.js') function main(params) { var name = params.name || params.payload || 'stranger'; var place = params.place || 'somewhere'; var hello = common.hello || 'Good Morning'; return {payload: hello + ', ' + name + ' from ' + place + '!'}; } exports.main = main;
O conteúdo do arquivo index.js localizado em actions/greeting2/
:
/** * Return a simple greeting message for someone. * * @param name A person's name. * @param place Where the person is from. */ var common = require('./common/utils.js') function main(params) { var name = params.name || params.payload || 'stranger'; var place = params.place || 'somewhere'; var hello = common.hello || 'Good Evening'; return {payload: hello + ', ' + name + ' from ' + place + '!'}; } exports.main = main;
Dentro da chave include
uma lista de arquivos ou diretórios que devem ser incluídos na função. Cada elemento desta lista deve ter source
e \ ou destination
, por exemplo:
include: - [source] - [source, destination]
Notas:
source
contém o caminho relativo do diretório que contém manimanifest.yaml
. destination
implica o caminho relativo do diretório de funções, por exemplo, actions/greeting1
e actions/greeting2
no exemplo a seguir.- Se o
destination
não destination
especificado, considera-se que será o mesmo que source
.
O conteúdo do arquivo de manifesto:
packages: zipactionwithinclude: actions: greeting1: function: actions/greeting1 runtime: nodejs:6 include: - ["actions/common/utils.js", "common/utils.js"] greeting2: function: actions/greeting2 runtime: nodejs:6 include: - ["actions/common/utils.js", "common/utils.js"]
include
trabalhos com várias combinações de source
e destination
:
include: - [actions/common/utils.js]
Com esta entrada, utils.js
será copiado para actions/greeting/actions/common/utils.js
, e index.js
pode se referir a ela assim:
var utils = require('./actions/common/utils.js')
include: - ["actions/common/utils.js", "./common/myUtils.js"]
Com essa definição, utils.js
será colocado no caminho actions/greeting/common/myUtils.js
, e index.js
se referirá a ela assim:
var utils = require('./common/myUtils.js')
include: - ["actions/common/utils.js", "./common/utility/utils.js"]
Nesse caso, utils.js
serão copiados para actions/greeting/common/utility/utils.js
, com um link de index.js
:
var utils = require('./common/utility/utils.js')
include
com o símbolo *
:
include: - ["actions/common/*.js", "./common/"]
Nesta versão, utils.js
, juntamente com outros arquivos com a extensão .js
, serão copiados para o diretório actions/greeting/common/
, e no index.js
esses arquivos serão conectados assim:
var utils = require('./common/utils.js')
Inclusão de diretório
Na include
você pode especificar um diretório que será copiado recursivamente para o local especificado antes de ser incluído no arquivo morto. Por exemplo, libs`` ,
index.js
greeting3 / `` '':
$ cd actions/ $ ls -1 libs/ greeting3/ manifest.yaml $ ls -1 libs/ lib1/ lib2/ lib3/ $ ls -1 libs/lib1/ utils.js $ ls -1 libs/lib2/ utils.js $ ls -1 libs/lib3/ utils.js $ ls -1 greeting3/ index.js package.json
O conteúdo de index.js no diretório actions/greeting3/
:
/** * Return a simple greeting message for someone. * * @param name A person's name. * @param place Where the person is from. */ var lib1 = require('./libs/lib1/utils.js') var lib2 = require('./libs/lib2/utils.js') var lib3 = require('./libs/lib3/utils.js') function main(params) { var name = params.name || params.payload || 'stranger'; var place = params.place || 'somewhere'; var hello = lib1.hello || lib2.hello || lib3.hello || 'Hello'; return {payload: hello + ', ' + name + ' from ' + place + '!'}; } exports.main = main;
O conteúdo do arquivo de manifesto:
packages: zipactionwithinclude: actions: greeting3: function: actions/greeting3 runtime: nodejs:6 include: - ["actions/libs/*", "libs/"]
Neste exemplo, o diretório libs
é copiado de forma totalmente recursiva para actions/greeting3/libs/
.
Conectando diretórios com o símbolo *
:
include: - ["actions/libs/*/utils.js", "libs/"]
Com isso, todos os subdiretórios que contêm utils.js
serão copiados das libs
. Os links do index.js
ficarão assim:
var lib1 = require('./libs/lib1/utils.js') var lib2 = require('./libs/lib2/utils.js') var lib3 = require('./libs/lib3/utils.js')
include: - ["actions/*/*/utils.js"]
Com essa entrada, todos os subdiretórios correspondentes à máscara e contendo utils.js
serão copiados. O acesso a partir do index.js
será assim:
var lib1 = require('./actions/libs/lib1/utils.js') var lib2 = require('./actions/libs/lib2/utils.js') var lib3 = require('./actions/libs/lib3/utils.js')
include: - ["actions/*/*/utils.js", "actions/"]
Este exemplo indica explicitamente onde tudo será copiado. O acesso a partir do index.js
será o mesmo do exemplo anterior.
Exceção
A palavra-chave exclude
pode ser usada como uma lista de arquivos e diretórios; é permitido o uso de uma máscara na forma de um caractere *
. Exemplo de uso:
exclude: - actions/common/*.js - actions/libs/*/utils.js
Um exemplo comum de compartilhamento include
e exclude
:
packages: zipactionwithexclude: actions: greeting1: function: actions runtime: nodejs:6 exclude: - actions/* include: - ["actions/common/utils.js", "common/utils.js"] - ["actions/index.js", "index.js"] - ["actions/package.json", "package.json"]
Funções com dependências do GitHub
O OpenWhisk suporta dependências, para que você possa descrever os outros pacotes OpenWhisk dos quais nosso projeto depende. Com essas dependências, o OpenWhisk também implementará automaticamente pacotes dependentes. Qualquer pacote com manifest.yaml
e \ ou deployment.yaml
pode ser considerado como um pacote dependente, que pode ser especificado no manifesto do nosso projeto. Você pode descrever essa dependência no manifesto na seção de dependencies
:
packages: RootProject: dependencies: helloworlds: location: github.com/apache/incubator-openwhisk-test/packages/helloworlds triggers: trigger1: trigger2: rules: rule1: trigger: trigger1 action: helloworlds/hello-js rule2: trigger: trigger2 action: helloworlds/helloworld-js
Neste exemplo, helloworlds
é um pacote externo hospedado no repositório do GitHub em https://github.com/apache/incubator-openwhisk-test . O pacote helloworlds
será implantado com base em seus arquivos para implantação no packages/helloworlds
- quando você implantar nosso projeto RootProject
. Também é possível alterar o nome do pacote dependente, por exemplo, em vez de helloworlds
defina ChildProject
:
packages: RootProject: dependencies: ChildProject: location: github.com/apache/incubator-openwhisk-test/packages/helloworlds triggers: trigger1: trigger2: rules: rule1: trigger: trigger1 action: ChildProject/hello-js rule2: trigger: trigger2 action: ChildProject/helloworld-js
Você pode adicionar várias dependências a vários pacotes:
packages: RootProject: dependencies: ChildProject1: location: github.com/apache/incubator-openwhisk-test/packages/helloworlds ChildProject2: location: github.com/apache/incubator-openwhisk-test/packages/hellowhisk sequences: ChildProject1-series: actions: ChildProject1/hello-js, ChildProject1/helloworld-js ChildProject2-series: actions: ChildProject2/greeting, ChildProject2/httpGet triggers: trigger1: trigger2: rules: rule1: trigger: trigger1 action: ChildProject1-series rule2: trigger: trigger2 action: ChildProject2-series
Como a sincronização de projetos OpenWhisk entre cliente e servidor
Para responder, você deve iniciar a implantação no modo de managed deployment
. Nesse modo, o OpenWhisk implanta todos os objetos do manifesto e também anexa uma descrição oculta a cada um deles, o chamado managed
. Essa descrição é assim:
managed: __OW_PROJECT_NAME: MyProjectName __OW_PROJECT_HASH: SHA1("OpenWhisk " + <size_of_manifest_file> + "\0" + <contents_of_manifest_file>) __OW_FILE: Absolute path of manifest file on file system
Aqui, OpenWhisk é uma seqüência constante e "\ 0" é o caractere NULL. size_of_manifest_file e contents_of_manifest_file dependem do arquivo. A sequência de implantação do mesmo projeto no modo de managed deployment
calcula um novo __OW_PROJECT_HASH
no cliente para cada objeto e o compara com o objeto __OW_PROJECT_HASH
do mesmo projeto no servidor. Existem várias opções abaixo.
Opção 1 : se __OW_PROJECT_HASH
corresponder no cliente e no servidor, ou seja, se não houver alterações no projeto no lado do cliente, o projeto no servidor permanecerá como está, exceto para implantar novos objetos do manifesto por meio do wskdeploy
para receber alterações no arquivo deployment.yaml
.
Opção 2 : se __OW_PROJECT_HASH
não corresponder, ou seja, se houver alterações no lado do cliente, o wskdeploy
implementará todos os objetos do manifesto e os atualizará __OW_PROJECT_HASH
no servidor. wskdeploy
também wskdeploy
todos os objetos: incluindo funções, sequências e __OW_PROJECT_NAME
condicionais que possuem o mesmo __OW_PROJECT_NAME
, ou seja, pertencentes ao mesmo projeto, mas com um __OW_PROJECT_HASH
diferente, pois eles podem ser removidos do manifesto no cliente. O nome do projeto no manifesto é necessário para sincronizar o projeto entre o cliente e o servidor:
project: name: MyProjectName packages: package1: ....
Os objetos no OpenWhisk que fazem parte do projeto, mas são implantados usando outras ferramentas ou ferramentas de automação permanecem inalterados quando são removidos do projeto. Eles são considerados objetos externos e, portanto, não são substituídos. Você pode wskdeploy
esse projeto usando wskdeploy
, direcionando-o para o arquivo de manifesto, que contém apenas o nome do projeto:
project: name: MyProjectName
Vejamos um exemplo de projeto para entender a managed deployment
. Neste repositório, você pode ver o projeto com vários manifestos que mostram a managed deployment
.
Primeiro passo
Implemente MyFirstManagedProject
usando o modo de managed deployment
:
$wskdeploy -m tests/src/integration/managed-deployment/manifest.yaml --managed Deployment completed successfully.

Lista de objetos implantados em um servidor OpenWhisk

Descrição da propriedade
Segundo passo
Sincronizamos o cliente e o servidor - excluímos ManagedPackage-2:
./wskdeploy -m tests/src/integration/managed-deployment/00-manifest-minus-second-package.yaml --managed Deployment completed successfully.

Lista de objetos após a exclusão no MyFirstManagedProject
Passo três
Sincronizamos o cliente e o servidor - excluímos a sequência ManagedSequence-2:
./wskdeploy -m tests/src/integration/managed-deployment/01-manifest-minus-sequence-2.yaml --managed Deployment completed successfully.

Lista de objetos após exclusão
Quarto passo
Exclua a função Helloworld-3:
./wskdeploy -m tests/src/integration/managed-deployment/02-manifest-minus-action-3.yaml --managed Deployment completed successfully.

Lista de objetos após exclusão
Quinto passo
Excluir ManagedPackage-1:
./wskdeploy -m tests/src/integration/managed-deployment/04-manifest-minus-package.yaml --managed Deployment completed successfully.

Outros objetos no MyFirstManagedProject
Outros artigos do ciclo
Computação sem servidor baseada no OpenWhisk, parte 1
Computação sem servidor baseada no OpenWhisk, parte 2
Computação sem servidor baseada no OpenWhisk, parte 3
Computação sem servidor baseada no OpenWhisk, parte 4