OpenWhisk Skeleton Interface for Node-RED flows as functions

This flow implements the necessary interface needed by a Node-RED flow, in order to be executed as a function inside Openwhisk . Openwhisk can execute in a serverless manner any type of Docker container, as long as it implements two methods on port 8080:

owskeletonflow_witherror

-A POST /init , used in the typical OW runtime images (such as node.js etc) to retrieve the function code from the OW function DB. In the Node-RED function runtime this is not needed for functional purposes, since the code is already embedded in the flow, but it is needed in order to abide by the OW interface that expects this method. It needs to be stressed that in a warm execution (reuse of existing container from previous same function execution), the /init method is not re-executed. Hence any needed initialization per invocation should not be performed inside this method.

-A POST /run method, which is called upon invocation of the function. Any parameters used are visible in Node-RED in the msg.payload.value.<param_name> field

The flow includes also a hello world function example, getting the name for hello from the input parameters as an example. The flow has also been updated in order to include an error catching node and prepare the according error message. If not done, and for some reason the flow stalls, Openwhisk will not understand that there is an error and it will only kill a function after the timeout. It will also not report accurately that this was a flow error (and which error), but it will report only the timeout as the reason for failure.

In order to create a relevant image for execution, an example Dockerfile appears below. Starting from the official Node-RED image, we can install any extra needed Node-RED packaged nodes from npm, used in an arbitrary flow. Then copy the local myflow.json flow file into the /data directory of the container (default location used by the official Node-RED image for the workDir) and optionally copy any specific settings.js or flows_cred.json files needed. If we need to port credentials, the credentialSecret should be set and used during credential creation in our Node-RED development server, and then move also the relevant settings.js file in the newly built image. Finally, we shift the port used by Node-RED to 8080.

FROM nodered/node-red
RUN npm install <any needed node-red packaged node for your flows from npm>
#move arbitrary flow from local dir
COPY myflow.json /data/flows.json
#optional: add a specific settings.js file
COPY settings.js /data/settings.js
#optional: add a specific flows_cred.js file with credentials. If used then the #credentialSecret option should be set in the settings.js file during credential #creation in the development Node-RED server so that credentials are transferable #to the new image
COPY flows_cred.json /data/flows_cred.json
ENV PORT 8080
EXPOSE 8080:8080

Then the image can be built (in the same dir):

 docker build -t <docker_registry_account>/<image_name> .

and pushed:

docker push <docker_registry_account>/<image_name>

Following the creation of the image and its pushing to a registry, it can be registered in Openwhisk as an action through the following command:

wsk action create <action_name> --docker <docker_registry_account>/<image_name>

and invoked through:

wsk action invoke <action_name> --param name george

A readymade image that can be used containing the hello world flow (without the error catching) can be found here

[{"id":"4826e1b8.c7fb2","type":"http in","z":"1ff181c757f68588","name":"","url":"/init","method":"post","upload":false,"swaggerDoc":"","x":200,"y":180,"wires":[["12b199d2.880ba6"]]},{"id":"b25a5bda.3c55d8","type":"http in","z":"1ff181c757f68588","name":"","url":"/run","method":"post","upload":false,"swaggerDoc":"","x":200,"y":280,"wires":[["b605091d.0a9fd8"]]},{"id":"12b199d2.880ba6","type":"http response","z":"1ff181c757f68588","name":"","x":500,"y":180,"wires":[]},{"id":"b16901b9.0f459","type":"http response","z":"1ff181c757f68588","name":"","x":750,"y":280,"wires":[]},{"id":"b605091d.0a9fd8","type":"function","z":"1ff181c757f68588","name":"Hello World","func":"\nconsole.log(msg);\nmsg.payload={'response':'hello '+msg.payload.value.name};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":280,"wires":[["b16901b9.0f459"]]},{"id":"84f39d9e.4e1b9","type":"comment","z":"1ff181c757f68588","name":"OW Nodered function skeleton interface","info":"Openwhisk requires the existence of two methods on port 8080:\n * A post /init , used in the typical OW runtime images (such as node.js etc) to retrieve the function code from the OW function DB. In the Node-RED function runtime this is not needed for functional purposes, since the code is already embedded in the flow, but it is needed in order to abide by the OW interface that expects this method. It needs to be stressed that in a warm execution (reuse of existing container from previous same function execution), the /init method is not re-executed. Hence any needed intialization per invocation should not be performed inside this method.\n * A POST /run method, which is called upon invocation of the function. Any parameters used are visible in Node-RED in the msg.payload.value.<param_name> field\n","x":290,"y":100,"wires":[]},{"id":"12e7fffe953d87e0","type":"comment","z":"1ff181c757f68588","name":"ARGS INFO","info":"Beware that any parameter that is passed for the function (e.g. through the POST body) it is then encapsulated by OW in msg.payload.value.$PARAM_NAME\nand from this field we need to retrieve it for processing in the flow.\n\nIn the specific hello world flow, the param <name> used in the call is  passedd through the msg body of the /run endpoint, in order to be used for a hello $name message, and is retrievable in the msg.payload.value.name property.","x":210,"y":340,"wires":[]},{"id":"25976e8d97b3abbb","type":"comment","z":"1ff181c757f68588","name":"NEEDS JSON RESPONSE","info":"","x":720,"y":340,"wires":[]},{"id":"34cfecf52257e7e2","type":"catch","z":"1ff181c757f68588","name":"","scope":null,"uncaught":false,"x":300,"y":400,"wires":[["417fa2d038e9b413"]]},{"id":"417fa2d038e9b413","type":"function","z":"1ff181c757f68588","name":"ADD ERROR INFO","func":"var payload=msg.payload;\nmsg.payload={};\n\nmsg.payload.error=msg.error;\nmsg.payload.error.payload=payload;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":400,"wires":[["b16901b9.0f459"]]}]

Flow Info

Created 2 years, 8 months ago
Updated 2 years ago
Rating: not yet rated

Owner

Actions

Rate:

Node Types

Core
  • catch (x1)
  • comment (x3)
  • function (x2)
  • http in (x2)
  • http response (x2)

Tags

  • Openwhisk
  • skeleton
  • interface
  • function
  • flow
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option