Command Functions

Page last updated:

This topic introduces Pivotal Function Service (PFS) command functions and provides an example built using the pfs CLI.

Command functions are functions that can be executed by themselves in PFS. They are either shell scripts, with the executable permission set, or a compiled binary program that doesn’t require any particular runtime or dynamic library to be present.

Command functions are handled by the riff command-function-invoker on GitHub.

Requirements

  • PFS has been installed and you have prepared a namespace.
  • The pfs CLI has been installed.
  • You have set REGISTRY and REGISTRY_USER environment variables.

    For GCR use gcr.io and your GCP Project ID.

    export REGISTRY=gcr.io
    export REGISTRY_USER=$(gcloud config get-value core/project)
    

    For the local registry used with Minikube or Docker Desktop, use registry name registry.pfs.svc.cluster.local:5000 and a dummy username.

    export REGISTRY=registry.pfs.svc.cluster.local:5000
    export REGISTRY_USER=testuser
    

How Command Functions Work

Command functions use standard input (stdin) and standard output (stdout) streams.

For each invocation, functions are expected to read stdin until the end of the stream (EOF) and provide a result on stdout.

Correct function execution is assumed if the exit code is zero. Any other value indicates an error.

Using the pfs CLI to Create a Command Function

This example uses the sample command-wordcount function from GitHub. It consists of a single executable file named wordcount.sh with the following content:

#!/bin/bash

tr [:punct:] ' ' | tr -s ' ' '\n' | tr [:upper:] [:lower:] | sort | uniq -c | sort -n

Create a wordcount function by running the CLI command below:

pfs function create wordcount \
--git-repo https://github.com/projectriff-samples/command-wordcount \
--artifact wordcount.sh \
--image $REGISTRY/$REGISTRY_USER/wordcount \
--verbose

The CLI output should show that the command invoker was selected.

For example:

-----> Process types:
web:      /workspace/io.projectriff.riff/riff-invoker-command/command-function-invoker
function: /workspace/io.projectriff.riff/riff-invoker-command/command-function-invoker

Now, let’s count the occurrences of words in the US Declaration of Independence by posting the contents of the document to the function using pfs service invoke:

curl -s https://raw.githubusercontent.com/projectriff-samples/command-wordcount/master/us-declaration-of-independence.txt \
    | pfs service invoke wordcount --text -- -d @- 
...
19 he
19 in
20 has
20 their
22 our
27 for
44 and
58 to
65 the
67 of

Creating a function from local source

This capability is currently only available when using Minikube or Docker Desktop with a local registry. It will be extended to work in other environments in a future release.

First you must prepare your environment for local builds by setting the PFS_BUILDER_IMAGE and PFS_PACKS_RUN_IMAGE environment variables. See Installing PFS on Minikube or on Docker Desktop for detailed instructions.

Setting these environment variables will affect both local and cluster builds. We suggest opening a new terminal window before changing to a different Kubernetes context.

Here we assume that you have created the pfs-local-path-env file in your download directory. Source the file with the environment settings using (if it is in a different location just change the path):

source ~/Downloads/pfs-local-path-env

To build a function from a local directory, use --local-path instead of --git-repo.

E.g. if you are in a directory with an executable file called wordcount.sh just like the one above:

pfs function create wordcount \
--local-path . \
--artifact wordcount.sh \
--image $REGISTRY/$REGISTRY_USER/wordcount \
--verbose

To update the function and deploy a new revision:

pfs function update wordcount \
  --local-path .