OpenWhisk Actions on Knative — Packaging Actions as Node.js Module

Priti Desai
Apache OpenWhisk
Published in
3 min readJun 28, 2019

This is a follow up blog post of How to run OpenWhisk actions on Knative?

Let’s look at how to package an OpenWhisk action as a Node.js module and install it on Knative. Here is a sample package.json and index.js.

package.json
index.js

Instead of writing all our action code in a single JavaScript source file, how about we try deploying an action which has dependency on some NPM libraries. This is possible using a zip file containing a Node.js module. Archived zip files are extracted into the runtime environment and dynamically imported using require() during initialization. Actions packaged as a zip file MUST contain a valid package.json with a main field specifying the module index file to return e.g. index.js. Also, including a node_modules folder in the zip file means external NPM libraries are used on the platform. Functions are exported from a module by setting main property on the exports object. The --main property on the action can be used to configure the module function invoked by the platform (this defaults to main).

Let’s try deploying this action on Knative:

Pre-requisites:

  • Secret exists on Knative, check with:
$ kubectl get secret dockerhub-user-pass
  • Service Account exists on Knative, check with:
$ kubectl get serviceaccount openwhisk-runtime-builder
  • Build Template exists on Knative, check with:
$ kubectl get buildtemplate openwhisk-nodejs-runtime

If any of the secret/service account/build template does not exist on your Knative installation, please go back to the How to run OpenWhisk actions on Knative? blog post and run Step 1 through Step 3 depending on what’s missing.

Deploy NodeJS Runtime with a Zip Action

Configure the build file to point to your Docker Hub repo by replacing DOCKER_USERNAME with your username.

build.yaml

Note: This build template has included two GitHub repos, one is for the runtime and the other is for the application source code. We are utilizing Knative build functionality in which multiple GitHub repos are cloned into a pod and make them available for further processing. In this particular build YAML, application repo has a specific target path app where the application repo is being cloned into.

Deploy NodeJS runtime with action code:

$ kubectl apply -f build.yaml
build.build.knative.dev/nodejs-10-package-npm created

Verify the build pod exists:

$ kubectl get build.build.knative.dev/nodejs-10-package-npm
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
nodejs-10-package-npm True 1m

Serve NodeJS Runtime as a Knative Service

Configure the service template to point to the Docker Hub repo where the OpenWhisk runtime (built in previous step) will be pulled from. Replace ${DOCKER_USERNAME} and create service.yaml:

service.yaml

Run Zip Action

Depending on your Knative installation, determine how to access your knative gateway and run curl:

knative-data-init-run.json
$ curl -H "Host: nodejs-package-npm.default.example.com" -H "Content-Type: application/json" -d '@knative-data-init-run.json' http://<IP_ADDRESS>:<PORT>
{
"padded":[
".........................Hello",
"..................How are you?"
]
}

Note: I ran this whole experiment on IBM Cloud and was successful in creating/invoking action on managed Knative.

Subsequent invocation can be done using knative-data-run.json:

knative-data-run.json
$ curl -H "Host: nodejs-package-npm.default.example.com" -H "Content-Type: application/json" -d '@knative-data-run.json' http://<IP_ADDRESS>:<PORT>
{
"padded":[
".........................Hello",
"..................How are you?"
]
}

Action Creation Improved on Knative

If you are familiar with OpenWhisk and a zip action creation, you might be wondering what happened to the following pre-processing steps, we didn’t run any of these steps before building/serving our sample app:

  • Install module dependencies using NPM
npm install
  • Create a .zip archive containing all files (including all dependencies)
zip -r action.zip *

Here is the answer to it, Node.JS runtime on Knative takes care of running these pre-processing steps for us. Knative build makes the application source available to the Node.JS runtime (from OW_PROJECT_URL or url as part of the init payload) which then runs npm install and creates action.zip containing source files and all the dependencies. In the end, it decodes archived zip file and sends decoded data as part of init JSON payload.

Please feel free to post your questions/comments under Responses below.

Enjoy! 👍

--

--

Priti Desai
Apache OpenWhisk

Developer Lead @IBM. Tekton maintainer. Co-founder of License Scanner @Cyclonedx