Thinking Anew

Day 22 - 30 Days on the Oracle Cloud

All sorts of functions

Oracle Function was announced late last year (2018), with limited availability to select Oracle Cloud customers. The platform is built on Fn and is Oracle’s solution for developers wanting to deploy services using a Serverless Framework.

As succinctly explained by Kaslin Fields, a Fn function is a small embodiment of code that listens and speaks to HTTP streams. Ideally, each Fn function serves one, and only one purpose. It can be implemented in wide variety of programming languages and they are listed here (see the list of runtime options available).

Development Environment Setup

The Fn project provides a concise set of instructions on installing the Fn command line interface (CLI) utility. The CLI allows developers to run a Fn server locally, and perform developer and deployment client functions.

A rather recent version of Docker is required, and if you are on a Microsoft Windows machine, I highly recommend installing Virtual Box and running a Linux virtual machine (VM) for Fn development. You can create a VM manually, or you can install Vagrant and quickly stand up a suitable using Oracle’s official Vagrant build scripts (see Orace Linux 7 with Docker engine).

In a nutshell, assuming a Linux Operating System (OS), do the following:

  1. Install, configure and run Docker.

  2. Install Fn CLI using the command provided:

    1
    $ curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
  3. Open a console and start the Fn Server for local development:

    1
    $ fn start

    This pulls a Docker image and runs a container. The default server API URL is http://127.0.0.1:8080.

  4. Configure the VM to work with a local registry if you are planning to start out by developing serverless functions locally.

  5. Follow the quick tutorial on creating a simple “Helloworld” service, changing the runtime to use the programming language of your choice.

Oracle Cloud Setup

Oracle Functions is not 100% ready to go, right out of the box when your Oracle Cloud account is provisioned. The setup tasks and deployment instructions are already available in the official documentation. I shall attempt to summarise and highlight the important steps.

OCI Components Required

  1. A minimally functional Virtual Cloud Network (VCN)

  2. Policies that allows Oracle Functions (FaaS) to:
    a. Access the Oracle Cloud Infrastructure Registry (OCIR); and

    1
    Allow service FaaS to read repos in tenancy

    b. Use network components in the target compartment.

    1
    Allow service FaaS to use virtual-network-family in compartment <COMPARTMENT_NAME>

    One or two policies may be created, however, the first policy statement must be created in a policy within the root compartment.

Configure Environment for Oracle Functions

There are ten steps to perform for configuring the Fn development environment. The minimum you will need to invoke a simple “Helloworld” function are:

  1. Setting up the OCI API Signing key .

    1. Run openssl command to generate the private and public keys. Note down the paths and passphrase used.
    2. Add the public key to the OCI user’s API Keys and then noting the fingerprint.
  2. Create the OCI profile and configuration file (~/.oci/config). Make sure the values required are entered correctly, or API signing will fail and you will not be able to authenticate with the endpoint. Note the profile name. The end result is a profile like this:

    1
    2
    3
    4
    5
    6
    7
    [my_oci-profile]
    user=ocid1.user.oc1..**********
    fingerprint=**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**
    key_file=~/.oci/my-private-key.pem
    tenancy=ocid1.tenancy.oc1..**********
    region=us-ashburn-1
    pass_phrase=mysupersecretpassword
  3. Setup oci-curl, which isn’t really required to do a quick invocation test.

  4. If you already have a Fn development environment, then chances are, Docker and Fn CLI are already installed, configured and running.

  5. Setup the context (and this) for Fn CLI to work with Oracle Functions. After performing these steps, a context file will be created in ~/.fn/contexts, containing contents similar to this:

    1
    2
    3
    4
    5
    api-url: https://functions.us-ashburn-1.oraclecloud.com
    oracle.compartment-id: ocid1.compartment.oc1..**********
    oracle.profile: my-oci-profile
    provider: oracle
    registry: iad.ocir.io/<TENANT_NAMESPACE>/<REPOSITORY_NAME>
  6. Generate and note the Auth token, and then login to the OCIR.

Deploying to Oracle Function

The best way to check that the environment is configured (~/.oci/config) correctly, is to list the applications available:

1
2
3
$ fn list apps
No apps found
NAME ID

To create an application, either use the OCI console:

Oracle Functions - Create Application

Or, use the Fn CLI, specifying the name of the application, and the OCID of the subnet to attach to:

1
$ fn create app nodeapp --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.iad.**********"]'

List the applications again to ensure it was successfully created:

1
2
3
$ fn list apps
NAME ID
nodeapp ocid1.fnapp.oc1.iad.**********

Following the Fn tutorial, you would have created a directory containing the following artifacts required for a Fn function:

1
2
[/home/myuser/projects/nodefn]$ ls
func.js func.yaml package.json

Set your working directory here and then attempt to deploy the application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[/home/myuser/projects/nodefn]$ fn -v deploy --app nodeapp
Deploying nodefn to app: nodeapp
Bumped to version 0.0.5
Building image iad.ocir.io/**********/fndemo/nodefn:0.0.5
FN_REGISTRY: iad.ocir.io/**********/fndemo
Current Context: fboci05
Sending build context to Docker daemon 5.12kB
Step 1/9 : FROM fnproject/node:dev as build-stage
---> b557a05fec78
Step 2/9 : WORKDIR /function
---> Using cache
---> 80aba4e33a61
Step 3/9 : ADD package.json /function/
---> Using cache
---> ce7d7130e497
Step 4/9 : RUN npm install
---> Using cache
---> 622fc377f1a9
Step 5/9 : FROM fnproject/node
---> c8da69259495
Step 6/9 : WORKDIR /function
---> Using cache
---> e4ef6fe5e78e
Step 7/9 : ADD . /function/
---> 2d41667e41f6
Step 8/9 : COPY --from=build-stage /function/node_modules/ /function/node_modules/
---> 14abb279af71
Step 9/9 : ENTRYPOINT ["node", "func.js"]
---> Running in 60097a195252
Removing intermediate container 60097a195252
---> 9a54e9d7ef1d
Successfully built 9a54e9d7ef1d
Successfully tagged iad.ocir.io/**********/fndemo/nodefn:0.0.5

Parts: [iad.ocir.io ********** fndemo nodefn:0.0.5]
Pushing iad.ocir.io/**********/fndemo/nodefn:0.0.5 to docker registry...The push refers to repository [iad.ocir.io/**********/fndemo/nodefn]
a71bd36619f2: Pushed
e355820d7f01: Pushed
9682c276ebcb: Pushed
a0d7b4199dce: Pushed
8aed3db29123: Pushed
9c85c117f8f6: Pushed
a464c54f93a9: Pushed
0.0.5: digest: sha256:6dca91254ae9a404236e3ac5f486a9d0fb575b1589f987c146b9489b4900ffdf size: 1780
Updating function nodefn using image iad.ocir.io/**********/fndemo/nodefn:0.0.5...
Successfully created function: nodefn with iad.ocir.io/**********/fndemo/nodefn:0.0.5

Fn: [GET /triggers][500] ListTriggers default &{Fields: Message:Internal server error}

See 'fn <command> --help' for more information. Client version: 0.5.84

With increase verbosity, it is clear that Docker is used to containerize the service. I have not delved into the nuts and bolts of the deployment model, but from the little I know, a Docker image is first created and deployed to the OCIR. When a function is invoked, the platform creates a container, executes the function and then terminates, releasing any allocated resources.

To invoke the function, simply execute the command or use the oci-curl if available:

1
2
[/home/myuser/projects/nodefn]]$ fn invoke nodeapp nodefn
{"message":"Hello World"}

Summary

The tutorial’s “Helloworld” example doesn’t do much for now. However, as mentioned earlier in this article, Fn functions are wrapped up in a Docker container. By creating a custom Dockerfile for your Fn, the possibilities are endless.

Also in the tutorials, the authors provide a roadmap on how to create a custom Docker image that uses ImageMagick to perform image manipulations. Something that could be useful to us Oracle Application Express developers when Oracle Multimedia is completely removed in future Oracle Database versions.