基于OpenWhisk的无服务器计算,第3部分


本文是Priti Desai撰写的有关OpenWhisk的一系列翻译说明的继续。 今天,我们将看一下部署Zip函数,GitHub依赖项的示例,并更详细地描述客户端和OpenWhisk服务器之间的对象同步。


邮编功能


[如先前所示](),OpenWhisk支持从单个源文件创建函数。 它还支持使用带有源代码的多个文件以及该功能所依赖的一组软件包来创建功能。 函数的这种用例称为zip函数。 让我们尝试使用wskdeploy部署zip函数。


第一步


创建清单文件:


 packages: zipaction: actions: my-zip-action: function: actions/my-zip-action runtime: nodejs:6 inputs: name: Amy 

我们认为my-zip-action具有这样的目录结构,其中包含该函数的源代码:


 $ ls actions/my-zip-action index.js package.json 

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; 

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" } } 

第二步


运行npm install以安装字符串格式:


 cd actions/my-action npm install --production 

第三步


展开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. 

我们使用相关模块string-format部署了zip函数my-zip-action 。 使用function键在清单中指定目录时,将从该目录创建一个zip归档文件,并从该归档文件中创建一个函数,因此您无需在文件系统中搜索它。 部署后,您可以使用与其他功能相同的方式来使用新功能。


包含和排除zip函数中的文件


OpenWhisk允许您使用zip归档文件创建函数,该归档文件包含该函数的任意数量的文件,包括 她所有的瘾。 部署支持在function指定function目录,其中包含使该函数起作用的文件。 将根据已经从中部署功能的目录的内容创建一个档案。


文件包含


以前,可以指定一个include键,该键的工作方式与编程语言中的import大致相同,例如,允许多个函数使用代码引用同一库:


 $ 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 

您可以在greeting1目录中看到index.js文件,并在greeting1目录中看到另一个index.js ,它们都引用位于common/ utils.js


位于actions/greeting1/中的index.js文件的内容:


 /** * 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; 

位于actions/greeting2/中的index.js文件的内容:


 /** * 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; 

include键内部包含应包含在函数中的文件或目录的列表。 此列表的每个元素都必须具有source和\或destination ,例如:


 include: - [source] - [source, destination] 

注意事项:


  • source包含来自包含manimanifest.yaml的目录的相对路径。 destination表示来自函数目录的相对路径,例如以下示例中的actions/greeting1actions/greeting2
  • 如果未指定destination ,则认为它将与source相同。

清单文件的内容:


 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 sourcedestination各种组合的作品:


  • 只是source

 include: - [actions/common/utils.js] 

有了此条目, utils.js将被复制到actions/greeting/actions/common/utils.js ,并且index.js可以像这样引用它:


 var utils = require('./actions/common/utils.js') 

  • 重命名中include

 include: - ["actions/common/utils.js", "./common/myUtils.js"] 

有了这个定义, utils.js将被放置在actions/greeting/common/myUtils.js ,而index.js将会像这样引用它:


 var utils = require('./common/myUtils.js') 

  • 用另一种方式include

 include: - ["actions/common/utils.js", "./common/utility/utils.js"] 

在这种情况下, utils.js将被复制到actions/greeting/common/utility/utils.js ,并带有index.js的链接:


 var utils = require('./common/utility/utils.js') 

  • include符号*

 include: - ["actions/common/*.js", "./common/"] 

在此版本中, utils.js以及其他带有扩展名.js文件将被复制到actions/greeting/common/目录,在index.js这些文件将按以下方式连接:


 var utils = require('./common/utils.js') 

目录包含


include您可以指定一个目录,该目录将被递归复制到指定位置,然后再包含在存档中。 例如, libs`` , greeting3 /``'' libs`` , index.js libs`` ,


 $ 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 

actions/greeting3/目录中index.js的内容:


 /** * 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; 

清单文件的内容:


 packages: zipactionwithinclude: actions: greeting3: function: actions/greeting3 runtime: nodejs:6 include: - ["actions/libs/*", "libs/"] 

在此示例中, libs目录完全递归地复制到actions/greeting3/libs/


用符号*连接目录:


  • 范例1:

 include: - ["actions/libs/*/utils.js", "libs/"] 

通过编写本文,将从libs复制包含utils.js所有子目录。 来自index.js链接如下所示:


 var lib1 = require('./libs/lib1/utils.js') var lib2 = require('./libs/lib2/utils.js') var lib3 = require('./libs/lib3/utils.js') 

  • 范例2:

 include: - ["actions/*/*/utils.js"] 

使用此条目,将复制与掩码匹配且包含utils.js所有子目录。 从index.js访问将如下所示:


 var lib1 = require('./actions/libs/lib1/utils.js') var lib2 = require('./actions/libs/lib2/utils.js') var lib3 = require('./actions/libs/lib3/utils.js') 

  • 范例3:

 include: - ["actions/*/*/utils.js", "actions/"] 

此示例明确指示将所有内容复制到何处。 从index.js进行的访问将与前面的示例相同。


例外情况


exclude关键字可用作文件和目录的列表,允许使用*字符形式的掩码。 用法示例:


 exclude: - actions/common/*.js - actions/libs/*/utils.js 

共享的常见示例includeexclude


 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"] 

具有GitHub依赖项的功能


OpenWhisk支持依赖关系,因此您可以描述我们项目所依赖的其他OpenWhisk软件包。 有了这些依赖关系,OpenWhisk也将自动部署依赖的程序包。 任何带有manifest.yaml和\或deployment.yaml软件包都可以被视为依赖软件包,可以在我们的项目清单中指定。 您可以在dependencies部分的清单中描述这种依赖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 

在此示例中, helloworlds是托管在GitHub存储库上的外部软件包,位于https://github.com/apache/incubator-openwhisk-test 。 当您部署RootProject项目时, helloworlds软件包将根据其文件进行部署,以部署在packages/helloworlds 。 也可以更改依赖程序包的名称,例如helloworlds设置ChildProject代替helloworlds


 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 

您可以将多个依赖项添加到多个包中:


 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 

客户端和服务器之间如何同步OpenWhisk项目


要回答,您必须以managed deployment模式启动managed deployment 。 在这种模式下,OpenWhisk部署清单中的所有对象,并为每个对象附加一个隐藏的描述,即所谓的 managed 。 此描述如下所示:


 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 

在这里,OpenWhisk是一个常量字符串,而“ \ 0”是NULL字符。 size_of_manifest_filecontents_of_manifest_file取决于文件。 在managed deployment模式下,同一项目的部署序列在客户端上为每个对象计算一个新的__OW_PROJECT_HASH ,并将其与服务器上同一项目中的__OW_PROJECT_HASH对象进行比较。 以下有几个选项。


选项1 :如果__OW_PROJECT_HASH在客户端和服务器上匹配,即 如果客户端上的项目没有更改,则服务器上的项目将保持原样,只是通过wskdeploy新对象进行部署以接收deployment.yaml文件中的任何更改。


选项2 :如果__OW_PROJECT_HASH不匹配,即 如果客户端发生更改,则wskdeploy部署清单中的所有对象,然后在服务器上更新它们__OW_PROJECT_HASHwskdeploy还会wskdeploy所有对象:包括具有相同__OW_PROJECT_NAME函数,序列和条件__OW_PROJECT_NAME ,即 属于同一项目,但具有不同的__OW_PROJECT_HASH ,因为可以从客户端清单中删除它们。 在客户端和服务器之间同步项目时,清单中的项目名称是必需的:


 project: name: MyProjectName packages: package1: .... 

从项目中删除的对象中,OpenWhisk中的对象是项目的一部分,但使用其他工具或自动化工具进行了部署。 它们被视为外部对象,因此不会被覆盖。 您可以使用wskdeploy此类项目,将其定向到清单文件,该清单文件仅包含项目名称:


 project: name: MyProjectName 

让我们看一个示例项目,以了解managed deployment 。 在此存储库中,您可以看到带有各种清单的项目,这些清单显示managed deployment


第一步


使用managed deployment模式部署MyFirstManagedProject


 $wskdeploy -m tests/src/integration/managed-deployment/manifest.yaml --managed Deployment completed successfully. 


在OpenWhisk服务器上部署的对象列表



属性说明


第二步


我们同步客户端和服务器-删除ManagedPackage-2:


 ./wskdeploy -m tests/src/integration/managed-deployment/00-manifest-minus-second-package.yaml --managed Deployment completed successfully. 


MyFirstManagedProject中删除后的对象列表


第三步


我们同步客户端和服务器-我们删除序列ManagedSequence-2:


 ./wskdeploy -m tests/src/integration/managed-deployment/01-manifest-minus-sequence-2.yaml --managed Deployment completed successfully. 


删除后的对象列表


第四步


删除Helloworld-3函数:


 ./wskdeploy -m tests/src/integration/managed-deployment/02-manifest-minus-action-3.yaml --managed Deployment completed successfully. 


删除后的对象列表


第五步


删除ManagedPackage-1:


 ./wskdeploy -m tests/src/integration/managed-deployment/04-manifest-minus-package.yaml --managed Deployment completed successfully. 


MyFirstManagedProject中的其他对象


其他自行车文章


基于OpenWhisk的无服务器计算,第1部分
基于OpenWhisk的无服务器计算,第2部分
基于OpenWhisk的无服务器计算,第3部分
基于OpenWhisk的无服务器计算,第4部分

Source: https://habr.com/ru/post/zh-CN479492/


All Articles