In this programming guide, we are going to discuss inputs
section of manifest and deployment file along with command line options --param
and --param-file
. First some background.
We define a project in manifest/deployment file which is a collection of packages. A package in turn is a collection of OpenWhisk entities such as actions, sequences, triggers, rules, apis, etc. These OpenWhisk entities in manifest/deployment files generally need data from users/environment for its successful deployment. This data includes:
Inputs can be specified at different levels:
And can be specified in multiple different ways:
--param
and --param-file
Before we dive into details of each level of inputs with all different ways, wskdeploy
follows a particular order in which the values are read:
--param
and/or --param-file
takes the highest precedence order. The values specified on CLI are taken to the server.Let's start with a simple example of a helloworld
action which has two inputs name
and place
.
packages: helloworldapp: actions: hello: inputs: name: type: string description: "your first name" required: false value: Amy place: type: string description: "The city name" required: false value: Paris code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Or (Single Line Inputs):
packages: helloworldapp: actions: hello: inputs: name: Amy place: Paris code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Whisk deploy creates bindings at the action level with two parameters name
and place
:
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_1.yaml Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "Amy" - place : "Paris" annotation:
This is how two inputs name
and place
are stored in hello
action on OpenWhisk server:
"parameters": [ { "key": "name", "value": "Amy" } { "key": "place", "value": "Paris" }, ],
packages: helloworldapp: actions: hello: inputs: name: type: string description: "your first name" required: true value: $FIRST_NAME place: type: string description: "The city name" required: true value: $CITY_NAME code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Deployment of this kind of manifest file results in following failure as inputs name
and place
are marked required
but their values $FIRST_NAME
and $CITY_NAME
could not be determined.
Error: manifestreader.go [92]: [ERROR_YAML_FILE_FORMAT_ERROR]: File: [manifest_validate_package_inputs_2.yaml]: ==> manifest_parser.go [148]: [ERROR_YAML_FILE_FORMAT_ERROR]: File: [manifest_validate_package_inputs_2.yaml]: Required inputs are missing values even after applying interpolation using env. variables. Please set missing env. variables and/or input values in manifest/deployment file or on CLI for following inputs: name, place
On the other side, single line inputs does not support this kind of validation as they are not marked as required
by default.
packages: helloworldapp: actions: hello: inputs: name: $FIRST_NAME place: $CITY_NAME code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Action is created with two bindings name
and place
set to ""
:
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_2.yaml Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "" - place : "" annotation:
Now, after setting env. variables, wskdeploy
creates an action with bindings similar to previous example:
export FIRST_NAME=Amy export CITY_NAME=Paris ./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_2.yaml Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "Amy" - place : "Paris" annotation:
--param
The input values can be overwritten using --param
on CLI. Sample manifest in [Action Inputs](#Action Inputs) can be deployed using:
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_1.yaml --param name Bob Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "Bob" - place : "Paris" annotation:
This example shows how env. variables FIRST_NAME
and CITY_NAME
are defined under project. These two variables are needed for deployment and need not be propagated to OpenWhisk server. This is the best and common practice of specifying inputs at the action level and env. variables at the project level. Here, both FIRST_NAME
and CITY_NAME
have default values but reads from environment if they are specified.
project: name: helloworld inputs: FIRST_NAME: type: string description: "your first name" required: true value: Amy CITY_NAME: type: string description: "The city name" required: true value: Paris packages: helloworldapp: actions: hello: inputs: name: type: string description: "your first name" required: true value: $FIRST_NAME place: type: string description: "The city name" required: true value: $CITY_NAME code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
This is how bindings are created only under action:
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_3.yaml Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "Amy" - place : "Paris" annotation:
With env. variables:
export FIRST_NAME=Bob export CITY_NAME=San Francisco ./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_3.yaml Packages: Name: helloworldapp bindings: annotation: * action: hello bindings: - name : "Bob" - place : "San Francisco" annotation:
project: name: helloworld inputs: FIRST_NAME: type: string description: "your first name" required: true value: Amy CITY_NAME: type: string description: "The city name" required: true value: Paris packages: helloworldapp: inputs: name: type: string description: "your first name" required: true value: $FIRST_NAME place: type: string description: "The city name" required: true value: $CITY_NAME actions: hello: code: | function main(params) { return {payload: 'Hello, ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Now, bindings are created under Package:
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_4.yaml Packages: Name: helloworldapp bindings: - name : "Amy" - place : "Paris" annotation: * action: hello bindings: annotation:
And can be overwritten using env. variables:
export FIRST_NAME=Bob export CITY_NAME=San Francisco ./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_4.yaml Packages: Name: helloworldapp bindings: - name : "Bob" - place : "San Francisco" annotation: * action: hello bindings: annotation:
Here, package helloworldapp
has three inputs defined which are available to all three actions helloWithMorning
, helloWithEvening
, and helloWithNight
during invocation. But two of the actions have redefined the same input message
which is created as an action binding on the server.
project: name: helloworld inputs: FIRST_NAME: type: string description: "your first name" required: true value: Amy CITY_NAME: type: string description: "The city name" required: true value: Paris packages: helloworldapp: inputs: name: type: string description: "your first name" required: true value: $FIRST_NAME place: type: string description: "The city name" required: true value: $CITY_NAME message: type: string description: "The Message" required: true value: "Good Night" actions: helloWithMorning: inputs: message: type: string description: "The Message" required: true value: "Good Morning" code: | function main(params) { return {payload: 'Hello, ' + params.message + ' ' + params.name + ' from ' + params.place}; } runtime: nodejs:default helloWithEvening: inputs: message: type: string description: "The Message" required: true value: "Good Evening" code: | function main(params) { return {payload: 'Hello, ' + params.message + ' ' + params.name + ' from ' + params.place}; } runtime: nodejs:default helloWithNight: code: | function main(params) { return {payload: 'Hello, ' + params.message + ' ' + params.name + ' from ' + params.place}; } runtime: nodejs:default
Now, invoking helloWithMorning
returns Good Morning
and invoking helloWithEvening
returns Good Evening
whereas invoking helloWithNight
returns Good Night
which is stored as the package binding.
./wskdeploy --preview -m tests/dat/manifest_validate_package_inputs_5.yaml Packages: Name: helloworldapp bindings: - name : "Amy" - place : "Paris" - message : "Good Night" annotation: * action: helloWithMorning bindings: - message : "Good Morning" annotation: * action: helloWithEvening bindings: - message : "Good Evening" annotation: * action: helloWithNight bindings: annotation: