Zip-функции
OpenWhisk поддерживает создание функции из единственного файла с исходным кодом, как это было [показано ранее](). Он же поддерживает создание функции с использованием нескольких файлов с исходным кодом и набором пакетов, от которых функция зависит. Этот вариант использования функций называется zip-функцией. Давайте попробуем развернуть zip-функцию с помощью wskdeploy.Шаг первый
Создаем файл-манифест: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 для установки string-format:
cd actions/my-action
npm install --production
Шаг третий
Разворачиваем zip-функцию:Скопировать код
Мы развернули zip-функцию my-zip-action с зависимым модулем string-format. При указании каталога в манифесте по ключу function создается zip-архив из этого каталога, а также — функция из этого архива, так что не надо искать его по файловой системе. После развертывания можно работать с новой функцией точно так же, как и с другими функциями.
Include и exclude для файлов в zip-функциях
OpenWhisk позволяет создавать функцию с использованием zip-архива, содержащего любое количество файлов для функции, в т.ч. все ее зависимости. Развертывание поддерживает указание в 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
Можно видеть файл index.js в каталоге greeting1, а также еще один index.js в каталоге greeting2, и оба ссылаются на utils.js, расположенный в common/.
Содержимое файла index.js, расположенного в actions/greeting1/:
Скопировать код
Содержимое файла index.js, расположенного в actions/greeting2/:
Скопировать код
Внутри ключа include содержится список файлов или каталогов, которые должны быть включены в функцию. Каждый элемент этого списка должен иметь source и\или destination, к примеру:
include:
- [source]
- [source, destination]
Примечания:
- source содержит относительный путь от каталога, содержащего manimanifest.yaml. destination подразумевает относительный путь от каталога с функцией, к примеру actions/greeting1 и actions/greeting2 в следующем примере.
- Если параметр destination не задается — считается что он будет такой же, как и source.
Содержимое файла-манифеста:
Скопировать код
include работает с различными сочетаниями source и destination:
- просто 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`` содержит список библиотек, на которые ссылается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
Содержимое index.js в каталоге actions/greeting3/:
Скопировать код
Содержимое файла-манифеста:
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
Общий пример совместного использования include и exclude:
Скопировать код
Функции с GitHub зависимостями
OpenWhisk поддерживает зависимости, так что можно описать другие пакеты OpenWhisk, от которых зависит наш проект. При наличии таких зависимостей OpenWhisk автоматически развернет и зависимые пакеты. Любой пакет с manifest.yaml и\или deployment.yaml можно рассматривать как зависимый пакет, который может быть указан в манифесте нашего проекта. Можно описать такую зависимость в манифесте в разделе dependencies:
Скопировать код
В этом примере helloworlds является внешним пакетом, размещенным в репозитории GitHub по адресу https://github.com/apache/incubator-openwhisk-test. Пакет helloworlds будет развернут, исходя из его файлов для развертывания в каталоге packages/helloworlds — при развертывании нашего проекта RootProject. Также есть возможность смены имени зависимого пакета, например вместо helloworlds задать ChildProject:
Скопировать код
Можно добавить несколько зависимостей к нескольким пакетам:
Скопировать код
Как работает синхронизация проектов OpenWhisk между клиентом и сервером
Для ответа надо запустить развертывание в режиме managed deployment. В этом режиме OpenWhisk производит развертывание всех объектов из манифеста, а также присоединяет к каждому из них скрытое описание, т.н. managed. Это описание можно посмотреть по ссылке.Вариант 1: Если __OW_PROJECT_HASH совпадает на клиенте и сервере, т.е. если нет изменений проекта на клиентской стороне, то проект на сервере остается как есть, за исключением развертывания через wskdeploy новых объектов из манифеста для получения любых изменений в файле deployment.yaml.
Вариант 2: Если __OW_PROJECT_HASH не совпадает, т.е. имеются изменения на стороне клиента, то wskdeploy выполняет развертывание всех объектов из манифеста, а затем обновляет их __OW_PROJECT_HASH на сервере. Также wskdeploy выполняет поиск всех объектов: включая функции, последовательности и условные срабатывания, у которых такой же __OW_PROJECT_NAME, — т.е. принадлежащих тому же проекту, но имеющих другой __OW_PROJECT_HASH, поскольку они могли быть удалены из манифеста на клиенте. Имя проекта в манифесте является обязательным для синхронизации проекта между клиентом и сервером:
project:
name: MyProjectName
packages:
package1:
....
Объекты в OpenWhisk, являющиеся частью проекта, но для которых выполняется развертывание с использованием других инструментов или средств автоматизации, остаются неизменными при их удалении из проекта. Они считаются внешними объектами и поэтому не перезаписываются. Развернуть такой проект можно с помощью wskdeploy, направляя его на файл манифеста, в котором есть только имя проекта:
project:
name: MyProjectName
Давайте посмотрим на пример проекта для понимания managed deployment. В этом репозитории можно посмотреть проект с различными манифестами, которые показывают managed deployment.
Шаг первый
Выполняем развертывание MyFirstManagedProject, используя режим managed deployment:$wskdeploy -m tests/src/integration/managed-deployment/manifest.yaml --managed
Deployment completed successfully.
Шаг второй
Синхронизируем клиент и сервер — удаляем ManagedPackage-2: https://xpaste.pro/p/5xm4eUsoШаг третий
Синхронизируем клиент и сервер — удаляем последовательность ManagedSequence-2: https://xpaste.pro/p/0E82P8r4Шаг четвертый
Удаляем функцию Helloworld-3: https://xpaste.pro/p/xjm1tvPTШаг пятый
Удаляем ManagedPackage-1: https://xpaste.pro/p/JZAfllFVДругие статьи цикла
Бессерверные вычисления на основе OpenWhisk, часть 1Бессерверные вычисления на основе OpenWhisk, часть 2
Бессерверные вычисления на основе OpenWhisk, часть 4