Oracle Functions is currently in limited preview and is expected to soon reach wider availability. Rolando Carrasco did this write up on Medium about his first experiences with Oracle Functions. Oracle Functions is a managed PaaS service, based on Project Fn. It supports a serverless architecture with light weight functions that can easily scale and for which no infrastructure has to be configured or managed.
Functions can be triggered for execution in several ways: from events, time scheduled, calls from other functions and of course through external calls. In this article I will describe how a function on Oracle Functions on Oracle Cloud Infrastructure can be invoked from a Node application.
I have prepared a function called shippings-generator in an application called soaring. The language used for implementing this function is not relevant when making the call to it. We simply pass the input as JSON payload and whether the function was written in Java, Python, Go, Node or something else is of no consequence.
The code for this article is on GitHub: https://github.com/lucasjellema/oci-functions-nodejs-invoke-function
Node application for invoking Function
The OCI REST API offers a set of resources and operations for Functions – also currently in preview.
Important for invoking a function is the function invocation endpoint. We can retrieve this end point from the APIs, or through the Fn CLI, using the inspect command:
fn inspect f soaring shippings-generator
This gives me the endpoint I need to pass to the OCI REST API in order to have it trigger my function.
The call I make to the Node application introduced in this article for invoking the function looks like this:
invokeFunction(
{ path : ‘/20181201/functions/ocid1.fnfunc.oc1.phx.aaaaaaaaabxgkhbi7y5vkfts/actions/invoke’
, host : ‘nub6pz.us-phoenix-1.functions.oci.oraclecloud.com’
},
{ name:”Dodo4″
, content: “My very very special Content”
})
Before making this call for the specific function, I have configured the Node application for my tenancy, compartment, user and key as described below – and as usual for interactions with the OCI API.
I made grateful use of a GitHub Repo by Christopher Beck (GitHub Repo OCI-Rest-APIs-nodejs by Christopher Beck with foundation for invoking many OCI REST APIs from NodeJS – I have used crucial elements from this example) who published a NodeJS equivalent of the REST APIs for integration from NodeJS applications. His repo is a work in progress – but already a very valuable one. If you intend to do more interactions with various OCI services from Node applications, I strongly recommend you to make use of his project. Note: he does not provide a package.json – only a package-lock,json – which I found a little disappointing because I needed his code and add on to it my own application.
In my case – I lifted a few key elements from Christopher’s repo. The main challenge I needed to overcome was with the signing of the requests in case of a passphrase protected private key. Due to a bug in http-signature (see this article) you need to make a few manual fixes in file node_modules\http-signature\lib\signer.js (after you run npm install) in order to make signing work with a private key file that is protected with a passphrase.
The steps to get the code in Node repo to work:
1. Clone this Repository
2. Run npm install
3. Make Fixes in Node Module HTTP-Signature (node_modules\http-signature\lib\signer.js ): At line 293 I inserted the following: assert.optionalString(options.passphrase, 'options.passphrase'); At line 363 (formerly line 362) I modifed the line to the following to propagate the options object: key = sshpk.parsePrivateKey(options.key, 'auto', options);
key = sshpk.parsePrivateKey(options.key, 'auto', options);
4. Copy your Private Key file into the project: At one point, you have probably used openssl genrsa
to generate a private key (protected wuth a passphrase) resulting in a *.pem file. Please copy this file into the project. In the next step, you have to set the relative location of this file in the configuration.js file – property privateKeyFile.
5. Logging – The code is configured to use the Papertrail service for logging. You will need to update the logger.js file if you do not want to use Papertrail – but a different logging service or just a local one.
6. Configure your environment parameters in configuration.js – File configuration.js contains all environment specific settings for your Cloud Tenancy, Compartment, User, Public Fingerprint and Private Key. Update this file with your own settings.
7. Modify the test call on lines 42-46 in invokeFunction.js: specify the invocation endpoint and payload for your function
Now run the code:
node invokeFunction.js
The logging is produced – to Console, File and Papertrail in my case – and the function does whatever it is supposed to do.
Resources
The code for this article is on GitHub: https://github.com/lucasjellema/oci-objectstorage-nodejs-upload-file
Fix for http-signature to wok with passphrase
Medium Article: Logging in NodeJS using Papertrail
Logging with winston npm module: https://github.com/winstonjs/winston