Read this in other languages: 한국어, 日本語, 繁體中文.
This project shows how serverless, event-driven architectures can execute code that scales automatically in response to demand from HTTP REST API calls. No resources are consumed until the API endpoints are called. When they are called, resources are provisioned to exactly match the current load needed by each HTTP method independently.
It shows four IBM Cloud Functions (powered by Apache OpenWhisk) actions (written in JavaScript) that write and read data in a MySQL database. This demonstrates how actions can work with supporting data services and execute logic in response to HTTP requests.
One action is mapped to HTTP POST requests. It inserts the supplied cat name and color parameters into the database. A second action is mapped to PUT requests to update those fields for an existing cat. A third action is mapped to GET requests that return specific cat data. A fourth action deletes a given cat data.
The Node.js runtime on the IBM Cloud provides a built-in list of approved npm modules. This demo also highlights how additional Node.js dependencies – such as the MySQL client – can be packaged in a ZIP file with custom actions to provide a high level of extensibility.
You should have a basic understanding of the OpenWhisk programming model. If not, try the action, trigger, and rule demo first.
Also, you'll need an IBM Cloud account and the latest OpenWhisk command line tool (ibmcloud fn
) installed and on your PATH.
As an alternative to this end-to-end example, you might also consider the more basic "building block" version of this sample.
Log into the IBM Cloud and provision a ClearDB or a Compose for MySQL database instance. ClearDB has a free tier for simple testing, while Compose has tiers for larger workloads.
For ClearDB, log into the ClearDB dashboard, and select the default database created for you. Get the user, password and host information under "Endpoint Information".
For Compose, get the information from the Service Credentials
tab in the IBM Cloud console.
Copy template.local.env
to a new file named local.env
and update the MYSQL_HOSTNAME
, MYSQL_USERNAME
, MYSQL_PASSWORD
and MYSQL_DATABASE
for your MySQL instance.
deploy.sh
is a convenience script reads the environment variables from local.env
and creates the OpenWhisk actions and API mappings on your behalf. Later you will run these commands yourself.
./deploy.sh --install
Note: If you see any error messages, refer to the Troubleshooting section below. You can also explore Alternative deployment methods.
There are four helper scripts that simulate HTTP API clients to create, get, update and delete entities against the /v1/cat
endpoint.
# POST /v1/cat {"name": "Tarball", "color": "Black"}
client/cat-post.sh Tarball Black
# GET /v1/cat?id=1
client/cat-get.sh 1 # Or whatever integer ID was returned by the command above
# PUT /v1/cat {"id": 1, "name": "Tarball", "color": "Gray"}
client/cat-put.sh 1 Tarball Gray
# DELETE /v1/cat?id=1
client/cat-delete.sh 1
Use deploy.sh
again to tear down the OpenWhisk actions and mappings. You will recreate them step-by-step in the next section.
./deploy.sh --uninstall
This section provides a deeper look into what the deploy.sh
script executes so that you understand how to work with OpenWhisk triggers, actions, rules, and packages in more detail.
Create four actions to manage cat data, one for each method (POST, PUT, GET, and DELETE) of our API. The code for the actions is located in /actions
. Let's start with the action action that creates a cat record first.
Note: There are a number of built-in packages available in the OpenWhisk Node.js runtime environment. If you need additional packages, you can upload them in a ZIP file along with your action file. More information on the single file versus zipped archive approaches is available in the getting started guide.
Because all of the actions rely on the MySQL database service, it's convenient to set the credentials once at the package level. This makes them available to all the actions in the package so we don't need to define them for each action at creation and run time.
source local.env
ibmcloud fn package create cat \
--param "MYSQL_HOSTNAME" $MYSQL_HOSTNAME \
--param "MYSQL_PORT" $MYSQL_PORT \
--param "MYSQL_USERNAME" $MYSQL_USERNAME \
--param "MYSQL_PASSWORD" $MYSQL_PASSWORD \
--param "MYSQL_DATABASE" $MYSQL_DATABASE
The JavaScript code for the POST action is in /actions/cat-post-action/index.js
. This function depends on the mysql
client npm package which we need to connect to the database. Install the package using npm install
(which parses package.json
) and create a ZIP file that includes both your application and its dependencies.
cd actions/cat-post-action
npm install
zip -rq action.zip *
Next use the OpenWhisk CLI to create an action from action.zip
.
# Create
ibmcloud fn action create cat/cat-post \
--kind nodejs:6 action.zip \
--web true
Then manually invoke the action using the ibmcloud fn
CLI to test.
# Test
ibmcloud fn action invoke \
--blocking \
--param name Tarball \
--param color Black \
cat/cat-post
Repeat the steps above to create and test the corresponding GET, PUT, and DELETE actions.
Note: Replace the number 1 in your tests below to reflect the actual id returned from the POST action result above.
# Create
cd ../../actions/cat-get-action
npm install
zip -rq action.zip *
ibmcloud fn action create cat/cat-get \
--kind nodejs:6 action.zip \
--web true
# Test
ibmcloud fn action invoke \
--blocking \
--param id 1 \
cat/cat-get
# Create
cd ../../actions/cat-put-action
npm install
zip -rq action.zip *
ibmcloud fn action create cat/cat-put \
--kind nodejs:6 action.zip \
--web true
# Test
ibmcloud fn action invoke \
--blocking \
--param name Tarball \
--param color Gray \
--param id 1 \
cat/cat-put
ibmcloud fn action invoke \
--blocking \
--param id 1 \
cat/cat-get
# Create
cd ../../actions/cat-delete-action
npm install
zip -rq action.zip *
ibmcloud fn action create cat/cat-delete \
--kind nodejs:6 action.zip \
--web true
# Test
ibmcloud fn action invoke \
--blocking \
--param id 1 \
cat/cat-delete
ibmcloud fn action invoke \
--blocking \
--param id 1 \
cat/cat-get
Now map a resource endpoint (/cat
) to the GET
, DELETE
, PUT
, and POST
HTTP methods, associate them with the corresponding OpenWhisk actions, and use the client scripts to test.
# Create
ibmcloud fn api create -n "Cats API" /v1 /cat post cat/cat-post
ibmcloud fn api create /v1 /cat put cat/cat-put
ibmcloud fn api create /v1 /cat get cat/cat-get
ibmcloud fn api create /v1 /cat delete cat/cat-delete
# Test
# POST /v1/cat {"name": "Tarball", "color": "Black"}
client/cat-post.sh Tarball Black
# GET /v1/cat?id=1
client/cat-get.sh 1 # Replace 1 with the id returned from the POST action above
# PUT /v1/cat {"id": 1, "name": "Tarball", "color": "Gray"}
client/cat-put.sh 1 Tarball Gray
# DELETE /v1/cat?id=1
client/cat-delete.sh 1
Remove the API mappings and delete the actions.
ibmcloud fn api delete /v1
ibmcloud fn action delete cat/cat-post
ibmcloud fn action delete cat/cat-put
ibmcloud fn action delete cat/cat-get
ibmcloud fn action delete cat/cat-delete
ibmcloud fn package delete cat
Check for errors first in the OpenWhisk activation log. Tail the log on the command line with ibmcloud fn activation poll
or drill into details visually with the monitoring console on the IBM Cloud.
If the error is not immediately obvious, make sure you have the latest version of the ibmcloud fn
CLI installed. If it's older than a few weeks, download an update.
ibmcloud fn property get --cliversion
deploy.sh
will be replaced with wskdeploy
in the future. wskdeploy
uses a manifest to deploy declared triggers, actions, and rules to OpenWhisk.
You can also use the following button to clone a copy of this repository and deploy to the IBM Cloud as part of a DevOps toolchain. Supply your OpenWhisk and MySQL credentials under the Delivery Pipeline icon, click Create
, then run the Deploy stage for the Delivery Pipeline.
This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the Developer Certificate of Origin, Version 1.1 (DCO) and the Apache Software License, Version 2.