Functions


Red Hat OpenShift Serverless 1.37

Setting up and using OpenShift Serverless Functions

Red Hat OpenShift Documentation Team

Abstract

This document provides information about getting started with OpenShift Serverless Functions and about developing and deploying functions by using Quarkus, Node.js, TypeScript, and Python.

Chapter 1. Getting started with functions

Function lifecycle management includes creating and deploying a function, after that you can call it. Use the kn func tool to perform these operations on OpenShift Serverless.

To enable the use of OpenShift Serverless Functions on your cluster, you must complete the following steps:

  • You have installed the OpenShift Serverless Operator and Knative Serving on your cluster.

    Note

    Functions are deployed as a Knative service. If you want to use event-driven architecture with your functions, you must also install Knative Eventing.

  • You have installed the oc CLI.
  • You have the Knative (kn) CLI installed. Installing the Knative CLI enables the use of kn func commands which you can use to create and manage functions.
  • You have installed Docker Container Engine or Podman version 3.4.7 or higher.
  • You have access to an available image registry, such as the OpenShift Container Registry.
  • If you are using Quay.io as the image registry, you must ensure that either the repository is not private, or that you have followed the OpenShift Container Platform documentation on Allowing pods to reference images from other secured registries.
  • If you are using the OpenShift Container Registry, a cluster administrator must expose the registry.

1.2. Creating, deploying, and invoking a function

On OpenShift Serverless, you can use the kn func to create, deploy, and call a function.

Procedure

  1. Create a function project by running the following command:

    $ kn func create -l <runtime> -t <template> <path>

    You get an output similar to the following example command:

    $ kn func create -l typescript -t cloudevents examplefunc

    You get an output similar to the following example:

    Created typescript function in /home/user/demo/examplefunc
  2. Navigate to the function project directory by running the following command:

    You get an output similar to the following example command:

    $ cd examplefunc
  3. Build and run the function locally by running the following command:

    You get an output similar to the following example command:

    $ kn func run
  4. Deploy the function to your cluster by running the following command:

    $ kn func deploy

    You get an output similar to the following example:

    Function deployed at: http://func.example.com
  5. Call the function by running the following command:

    $ kn func invoke

    This invokes either a locally or remotely running function. If both are running, the local one is invoked.

Chapter 2. Creating functions

Before you can build and deploy a function, you must create it. You can create functions by using the Knative (kn) CLI.

2.1. Creating a function by using the Knative CLI

You can specify the path, runtime, template, and image registry for a function as flags on the command line, or use the -c flag to start the interactive experience in the terminal.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.

Procedure

  1. Create a function project:

    $ kn func create -r <repository> -l <runtime> -t <template> <path>
    • Accepted runtime values include quarkus, node, typescript, go, python, springboot, and rust.
    • Accepted template values include http and cloudevents.

      You get an output similar to the following example:

      $ kn func create -l typescript -t cloudevents examplefunc

      You get an output similar to the following example:

      Created typescript function in /home/user/demo/examplefunc
  2. Specify a repository that has a custom template.

    You get an output similar to the following example:

    $ $ kn func create -r <templates_repository> -l node -t hello-world examplefunc

    Replace <templates_repository> with the repository that has the function templates.

    You get an output similar to the following example:

    Created node function in /home/user/demo/examplefunc

2.2. Creating a function in the web console

You can create a function from a Git repository by using the OpenShift Container Platform web console.

Prerequisites

  • Before you can create a function by using the web console, a cluster administrator must complete the following steps:

    • Install the OpenShift Serverless Operator and Knative Serving on the cluster.
    • Install the OpenShift Pipelines Operator on the cluster.
    • Create the following pipeline tasks so that they are available for all namespaces on the cluster:

      $ kn func tkn-tasks | oc apply -f -
      $ oc apply -f https://raw.githubusercontent.com/openshift-knative/kn-plugin-func/serverless-1.34/pkg/pipelines/resources/tekton/pipeline/dev-console/0.1/nodejs-pipeline.yaml
  • You must log in to the OpenShift Container Platform web console.
  • You must create a project or have access to a project with the appropriate roles and permissions to create applications and other workloads in OpenShift Container Platform.
  • You must create or have access to a Git repository that has the code for your function. The repository must contain a func.yaml file and use the s2i build strategy.

Procedure

  1. Navigate to +AddCreate Serverless function. The Create Serverless function page is displayed.
  2. Enter a Git Repo URL that points to the Git repository that has the code for your function.
  3. In the Pipelines section:

    1. Select the Build, deploy and configure a Pipeline Repository radio button to create a new pipeline for your function.
    2. Select the Use Pipeline from this cluster radio button to connect your function to an existing pipeline in the cluster.
  4. Click Create.

Verification

  • After you have created a function, you can view it in the Topology view.

Chapter 3. Running functions locally

You can run a function locally by using the kn func tool. This can be useful, for example, for testing the function before deploying it to the cluster.

3.1. Running a function locally

You can run a function locally by using the kn func run command in the current directory or by specifying a directory with the --path flag.

If you run the function for the first time, or if you change the project files, the kn func run command builds the function before running it.

You can run a function in the current directory by using the following command:

$ kn func run

You can run a function in a specific directory by specifying the path with the --path flag:

$ kn func run --path=<directory_path>

You can also force a rebuild of an existing image before running the function, even if there have been no changes to the project files, by using the --build flag:

You can run a function and trigger a build by using the --build flag:

$ kn func run --build

If you set the build flag as false, this disables building of the image, and runs the function by using the previously built image:

You can run a function without building it by using the --build=false flag:

$ kn func run --build=false

You can use the help command to learn more about kn func run command options:

$ kn func help run

Chapter 4. Deploying functions

You can deploy your functions to the cluster by using the kn func tool.

4.1. Deploying a function

You can deploy a function to your cluster as a Knative service by using the kn func deploy command. If you have already deployed the function, the command pushes a new container image to a container image registry and updates the Knative service.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a project or have access to a project with the appropriate roles and permissions to create applications and other workloads in OpenShift Container Platform.
  • You must have already created and initialized the function that you want to deploy.

Procedure

  • Deploy a function by running the following command:

    $ kn func deploy [-n <namespace> -p <path> -i <image>]

    You get an output similar to the following example:

    Function deployed at: http://func.example.com
    • If you do not specify a namespace, the command deploys the function in the current namespace.
    • The command deploys the function from the current directory unless you specify a path.
    • The command derives the Knative service name from the project name. You cannot change the service name by using this command.
Note

You can create a serverless function with a Git repository URL by using Import from Git or Create Serverless Function in the +Add view.

Chapter 5. Building functions

To run a function, you first must build the function project. This happens automatically when using the kn func run command, but you can also build a function without running it.

5.1. Building a function

Before you can run a function, you must build the function project. When you run the kn func run command, the system builds the function automatically. However, you can use the kn func build command to build a function without running it, which can be useful for advanced users or debugging scenarios.

You can run the kn func build command to create an OCI container image that you can run locally on your computer or on an OpenShift Container Platform cluster. This command uses the function project name and the image registry name to construct a fully qualified image name for your function.

5.1.1. Image container types

By default, kn func build creates a container image by using Red Hat Source-to-Image (S2I) technology.

You can build a function by using Red Hat Source-to-Image (S2I):

$ kn func build

5.1.2. Image registry types

By default, the system stores function images in the OpenShift Container Registry.

You can build a function by using the OpenShift Container Registry:

$ kn func build

You get an output similar to the following example:

Building function image
Function image has been built, image: registry.redhat.io/example/example-function:latest

You can override using OpenShift Container Registry as the default image registry by using the --registry flag:

$ kn func build --registry quay.io/username

You get an output similar to the following example:

Building function image
Function image has been built, image: quay.io/username/example-function:latest

5.1.3. Push flag

You can add the --push flag to a kn func build command to automatically push the function image after it is successfully built:

$ kn func build --push

5.1.4. Help command

You can use the help command to learn more about kn func build command options:

$ kn func help build

Chapter 6. Listing existing functions

You can list existing functions. You can do it using the kn func tool.

6.1. Listing existing functions

You can list existing functions by running kn func list command. To list functions that you deployed as Knative services, run kn service list command.

Procedure

  • List existing functions by running the following command:

    $ kn func list [-n <namespace> -p <path>]

    You get an output similar to the following example:

    NAME           NAMESPACE  RUNTIME  URL                                                                                      READY
    example-function  default    node     http://example-function.default.apps.ci-ln-g9f36hb-d5d6b.origin-ci-int-aws.dev.rhcloud.com  True
  • List functions deployed as Knative services by running the following command:

    $ kn service list -n <namespace>

    You get an output similar to the following example:

    NAME            URL                                                                                       LATEST                AGE   CONDITIONS   READY   REASON
    example-function   http://example-function.default.apps.ci-ln-g9f36hb-d5d6b.origin-ci-int-aws.dev.rhcloud.com   example-function-gzl4c   16m   3 OK / 3     True

Chapter 7. Invoking functions

You can test a deployed function by invoking it. You can do it using the kn func tool.

You can use the kn func invoke CLI command to send a test request to invoke a function either locally or on your OpenShift Container Platform cluster. You can use this command to test that a function is working and able to receive events correctly. Invoking a function locally is useful for a quick test during function development. Invoking a function on the cluster is useful for testing that is closer to the production environment.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a project or have access to a project with the appropriate roles and permissions to create applications and other workloads in OpenShift Container Platform.
  • You must have already deployed the function that you want to call.

Procedure

  • Start a function by running the following command:

    $ kn func invoke
    • The kn func invoke command only works when there is either a local container image currently running, or when there is a function deployed in the cluster.
    • The kn func invoke command executes on the local directory by default, and assumes that this directory is a function project.

Chapter 8. Deleting functions

You can delete a function. You can do it using the kn func tool.

8.1. Deleting a function

You can delete a function by using the kn func delete command. This is useful when a function is no longer required, and can help to save resources on your cluster.

Procedure

  • Delete a function by running the following command:

    $ kn func delete [<function_name> -n <namespace> -p <path>]
    • If you do not specify the name or path of the function to delete, the system searches the current directory for a func.yaml file and uses it to decide which function to delete.
    • If the namespace is not specified, it defaults to the namespace value in the func.yaml file.

Instead of building a function locally, you can build a function directly on the cluster. When using this workflow on a local development machine, you only need to work with the function source code. This is useful, for example, when you cannot install on-cluster function building tools, such as docker or Podman.

You can use the Knative (kn) CLI to start a function project build and then deploy the function directly on the cluster. To build a function project in this way, the source code for your function project must exist in a Git repository branch that is accessible to your cluster.

Prerequisites

  • You have installed the Red Hat OpenShift Pipelines on your cluster.
  • You have installed the OpenShift CLI (oc).
  • You have installed the Knative (kn) CLI.

Procedure

  1. Create a function by running the following command:

    $ kn func create <function_name> -l <runtime>
  2. Implement the business logic of your function. Then, use Git to commit and push the changes.
  3. Deploy your function by running the following command:

    $ kn func deploy --remote

    If you are not logged into the container registry referenced in your function configuration, you are prompted to give credentials for the remote container registry that hosts the function image:

    You get an output similar to the following example:

    🕕 Creating Pipeline resources
    Please provide credentials for image registry used by Pipeline.
    ? Server: https://index.docker.io/v1/
    ? Username: my-repo
    ? Password: ********
       Function deployed at URL: http://test-function.default.svc.cluster.local
  4. To update your function, commit and push new changes by using Git, then run the kn func deploy --remote command again.
  5. Optional. You can configure your function to be built on the cluster after every Git push by using pipelines-as-code:

    1. Generate the Tekton Pipelines and PipelineRuns configuration for your function by running the following command:

      $ kn func config git set

      Apart from generating configuration files, this command connects to the cluster and verifies the pipeline installation. By using the token, it also creates a webhook on the function repository on behalf of the user. That webhook triggers the pipeline on the cluster every time you push changes to the repository.

      You need to have a valid GitHub personal access token with the repository access to use this command.

    2. Commit and push the generated .tekton/pipeline.yaml and .tekton/pipeline-run.yaml files by running the following commands:

      $ git add .tekton/pipeline.yaml .tekton/pipeline-run.yaml
      $ git commit -m 'Add the Pipelines and PipelineRuns configuration'
      $ git push
    3. After you make a change to your function, commit and push it. The function is rebuilt automatically by using the created pipeline.

9.2. Specifying function revision

When building and deploying a function on the cluster, you must specify the location of the function code by specifying the Git repository, branch, and subdirectory within the repository. You do not need to specify the branch if you use the main branch. Similarly, you do not need to specify the subdirectory if your function is at the root of the repository. You can specify these parameters in the func.yaml configuration file, or by using flags with the kn func deploy command.

Prerequisites

  • You have installed the Red Hat OpenShift Pipelines on your cluster.
  • You have installed the OpenShift (oc) CLI.
  • You have installed the Knative (kn) CLI.

Procedure

  • Deploy your function:

    $ kn func deploy --remote \
                     --git-url <repo_url> \
                     [--git-branch <branch>] \
                     [--git-dir <function_dir>]
    --remote
    With the --remote flag, the build runs remotely.
    git-url <repo_url>
    Substitute <repo_url> with the URL of the Git repository.
    --git-branch <branch>
    Substitute <branch> with the Git branch, tag, or commit. If using the latest commit on the main branch, you can skip this flag.
    --git-dir <function_dir>
    Substitute <function_dir> with the directory containing the function if it is different from the repository root directory.

    Similar to the following example:

    $ kn func deploy --remote \
                     --git-url https://example.com/alice/myfunc.git \
                     --git-branch my-feature \
                     --git-dir functions/example-func/

9.3. Setting custom volume size

For projects that require a volume with a larger size to build, you might need to customize the persistent volume claim (PVC) when building on the cluster. The default PVC size is 256 mebibytes.

Prerequisites

  • You have installed the Red Hat OpenShift Pipelines on your cluster.
  • You have installed the OpenShift (oc) CLI.
  • You have installed the Knative (kn) CLI.

Procedure

  • Deploy your function with the --pvc-size flag and PVC size specification by running the following command:

    $ kn func deploy --remote --pvc-size='2Gi'

    In this example, PVC is set to two gibibytes.

9.4. Testing a function in the web console

You can test a deployed serverless function by invoking it in the OpenShift Container Platform web console.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on your OpenShift Container Platform cluster.
  • You have logged in to the web console.
  • You have created and deployed a function.

Procedure

  1. Navigate to Topology.
  2. Click a function, then click Test Serverless Function from the Actions drop-down list in the Details panel. This opens the Test Serverless Function dialog box.
  3. In the Test Serverless Function dialog box, change the settings for your test as required:

    1. Choose the Format for your test. This can be either CloudEvent or HTTP.
    2. The Content-Type defaults to the Content-Type HTTP header value.
    3. You can use the Advanced Settings to change the Type or Source for CloudEvent tests, or to add optional headers.
    4. You can change the input data for the test.
  4. Click Test to run your test.
  5. After the test is complete, the Test Serverless Function dialog box displays a status code and a message that informs you whether your test was succesful.
  6. Click Back to perform another test, or Close to close the testing dialog box.

When you deploy functions, the platform creates Knative services on an OpenShift Container Platform cluster. You can connect these functions to Knative Eventing components to receive incoming events.

10.1. Connect an event source to a function

Functions run as Knative services on an OpenShift Container Platform cluster. When you create an event source in the OpenShift Container Platform web console, specify a deployed function to receive events from that source.

Prerequisites

  • You have installed the OpenShift Serverless Operator, Knative Serving, and Knative Eventing are on your OpenShift Container Platform cluster.
  • You have logged in to the web console.
  • You have created a project or have access to a project with the appropriate roles and permissions to create applications and other workloads in OpenShift Container Platform.
  • You have created and deployed a function.

Procedure

  1. Create an event source of any type, by navigating to +AddEvent Source and selecting the event source type that you want to create.
  2. In the Target section of the Create Event Source form view, select your function in the Resource list.
  3. Click Create.

Verification

  1. Verify that the event source exists and connects to the function by viewing the Topology page.
  2. Navigate to Topology.
  3. View the event source and click the connected function to see the function details in the right panel.

Chapter 11. Subscribing functions to CloudEvents

You can subscribe a function to a set of events. This links your function to CloudEvent objects defined by your filters and enables automated responses.

11.1. Subscribing a function to CloudEvents

The subscribe command connects the function to events by matching filters for CloudEvent metadata and using a Knative Broker as the source. The function then consumes events from the broker.

Prerequisites

  • You have installed Knative Eventing on the cluster.
  • You have configured a Knative Broker.
  • You have installed the Knative (kn) CLI.

Procedure

  1. Subscribe the function to events for a given broker by running the following command:

    You get an output similar to the following example command:

    $ kn func subscribe --filter type=com.example.Hello --source my-broker

    Use the --source flag to specify the broker and one or more --filter flags to specify your filters.

    You can also omit the --source flag to use the default broker:

    You get an output similar to the following example command:

    $ kn func subscribe --filter type=com.example --filter extension=my-extension-value
  2. Deploy the function with Knative Triggers:

    You get an output similar to the following example command:

    $ kn func deploy

    You get an output similar to the following example:

    🙌 Function image built: <registry>/hello:latest
    🎯 Creating Triggers on the cluster
    ✅ Function deployed in namespace "default" and exposed at URL:
    http://hello.default.my-cluster.example.com

Chapter 12. Functions development reference guide

12.1. Developing Go functions

After you have created a Go function project, you can change the template files provided to add business logic to your function. This includes configuring function invocation and the returned headers and status codes.

Important

OpenShift Serverless Functions with Go is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

12.1.1. Go function template structure

When you create a Go function by using the Knative (kn) CLI, the project directory looks like a typical Go project. The only exception is the additional func.yaml configuration file, which is used for specifying the image.

Note

Before you can develop functions, you must configure the function.

Go functions have few restrictions. The only requirements are that your project must be defined in a function module, and must export the function Handle().

Both http and event trigger functions have the same template structure:

fn
├── README.md
├── func.yaml
├── go.mod
├── go.sum
├── handle.go
└── handle_test.go
func.yaml
The func.yaml configuration file is used to decide the image name and registry.
go.mod
You can add any required dependencies to the go.mod file, which can include additional local Go files. When the project is built for deployment, these dependencies are included in the resulting runtime container image.
$ go get gopkg.in/yaml.v2@v2.4.0

12.1.2. About invoking Go functions

When you use the Knative (kn) CLI to create a function project, you can generate a project that responds to CloudEvents or simple HTTP requests. Different methods call Go functions, depending on whether an HTTP request or a CloudEvent triggers them.

12.1.2.1. Functions triggered by an HTTP request

When a function receives an incoming HTTP request, the runtime calls it with a standard Go Context as the first parameter, followed by the http.ResponseWriter and http.Request parameters. You can use standard Go techniques to access the request and set the HTTP response.

The following example displays the HTTP response:

func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
  // Read body
  body, err := ioutil.ReadAll(req.Body)
  defer req.Body.Close()
  if err != nil {
	http.Error(res, err.Error(), 500)
	return
  }
  // Process body and function logic
  // ...
}
12.1.2.2. Functions triggered by a cloud event

When an incoming cloud event is received, the event is invoked by the CloudEvents Go SDK. The invocation uses the Event type as a parameter.

You can use the Go Context as an optional parameter in the function contract, as shown in the list of supported function signatures:

The following example displays supported function signatures:

Handle()
Handle() error
Handle(context.Context)
Handle(context.Context) error
Handle(cloudevents.Event)
Handle(cloudevents.Event) error
Handle(context.Context, cloudevents.Event)
Handle(context.Context, cloudevents.Event) error
Handle(cloudevents.Event) *cloudevents.Event
Handle(cloudevents.Event) (*cloudevents.Event, error)
Handle(context.Context, cloudevents.Event) *cloudevents.Event
Handle(context.Context, cloudevents.Event) (*cloudevents.Event, error)

The following example displays CloudEvent trigger:

A cloud event is received which contains a JSON string in the data property:

{
  "customerId": "0123456",
  "productId": "6543210"
}

To access this data, a structure must be defined which maps properties in the cloud event data, and retrieves the data from the incoming event. The following example uses the Purchase structure:

type Purchase struct {
  CustomerId string `json:"customerId"`
  ProductId  string `json:"productId"`
}
func Handle(ctx context.Context, event cloudevents.Event) (err error) {

  purchase := &Purchase{}
  if err = event.DataAs(purchase); err != nil {
	fmt.Fprintf(os.Stderr, "failed to parse incoming CloudEvent %s\n", err)
	return
  }
  // ...
}

A Go encoding/json package could be used to access the cloud event directly as JSON in the form of a bytes array:

func Handle(ctx context.Context, event cloudevents.Event) {
  bytes, err := json.Marshal(event)
  // ...
}

12.1.3. Go function return values

Functions triggered by HTTP requests can set the response directly. You can configure the function to do this by using the Go http.ResponseWriter parameter.

The following example displays HTTP response:

func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
  // Set response
  res.Header().Add("Content-Type", "text/plain")
  res.Header().Add("Content-Length", "3")
  res.WriteHeader(200)
  _, err := fmt.Fprintf(res, "OK\n")
  if err != nil {
	fmt.Fprintf(os.Stderr, "error or response write: %v", err)
  }
}

Functions triggered by a cloud event might return nothing, error, or CloudEvent to push events into the Knative Eventing system. In this case, you must set a unique ID, proper Source, and a Type for the cloud event. The data can be populated from a defined structure, or from a map.

The following example displays CloudEvent response:

func Handle(ctx context.Context, event cloudevents.Event) (resp *cloudevents.Event, err error) {
  // ...
  response := cloudevents.NewEvent()
  response.SetID("example-uuid-32943bac6fea")
  response.SetSource("purchase/getter")
  response.SetType("purchase")
  // Set the data from Purchase type
  response.SetData(cloudevents.ApplicationJSON, Purchase{
	CustomerId: custId,
	ProductId:  prodId,
  })
  // OR set the data directly from map
  response.SetData(cloudevents.ApplicationJSON, map[string]string{"customerId": custId, "productId": prodId})
  // Validate the response
  resp = &response
  if err = resp.Validate(); err != nil {
	fmt.Printf("invalid event created. %v", err)
  }
  return
}

12.1.4. Testing Go functions

Go functions can be tested locally on your computer. In the default project that is created when you create a function by using kn func create, there is a handle_test.go file, which has some basic tests. These tests can be extended as needed.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  1. Navigate to the test folder for your function.
  2. Run the tests by running the following command:

    $ go test

12.2. Developing Quarkus functions

After you have created a Quarkus function project, you can change the template files provided to add business logic to your function. This includes configuring function invocation and the returned headers and status codes.

12.2.1. Quarkus function template structure

When you create a Quarkus function by using the Knative (kn) CLI, the project directory looks similar to a typical Maven project. Additionally, the project has the func.yaml file, which is used for configuring the function.

Note

Before you can develop functions, you must configure the function.

Both http and event trigger functions have the same template structure:

.
├── func.yaml 
1

├── mvnw
├── mvnw.cmd
├── pom.xml 
2

├── README.md
└── src
    ├── main
    │   ├── java
    │   │   └── functions
    │   │       ├── Function.java 
3

    │   │       ├── Input.java
    │   │       └── Output.java
    │   └── resources
    │       └── application.properties
    └── test
        └── java
            └── functions 
4

                ├── FunctionTest.java
                └── NativeFunctionIT.java
func.yaml
Used to find the image name and registry.
pom.xml
The Project Object Model (POM) file has project configuration, such as information about dependencies. You can add additional dependencies by modifying this file.
Function.java
The function project must contain a Java method annotated with @Funq. You can place this method in the Function.java class.
functions
Contains simple test cases that can be used to test your function locally.

You get an output similar to the following example:

...
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>3.8.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
...

Dependencies are downloaded during the first compilation.

12.2.2. About invoking Quarkus functions

You can create a Quarkus project that responds to cloud events, or one that responds to simple HTTP requests. Cloud events in Knative are transported over HTTP as a POST request, so either function type can listen and respond to incoming HTTP requests.

When an incoming request is received, Quarkus functions are invoked with an instance of a permitted type.

The following table displays function invocation options:

Expand
Invocation methodData type contained in the instanceExample of data

HTTP POST request

JSON object in the body of the request

{ "customerId": "0123456", "productId": "6543210" }

HTTP GET request

Data in the query string

?customerId=0123456&productId=6543210

CloudEvent

JSON object in the data property

{ "customerId": "0123456", "productId": "6543210" }

The following example shows a function that receives and processes the customerId and productId buy data that is listed in the earlier table:

You get an output similar to the following example:

public class Functions {
    @Funq
    public void processPurchase(Purchase purchase) {
        // process the purchase
    }
}

The corresponding Purchase JavaBean class that has the purchase data looks as follows:

You get an output similar to the following example:

public class Purchase {
    private long customerId;
    private long productId;
    // getters and setters
}
12.2.2.1. Invocation examples

The following example code defines three functions named withBeans, withCloudEvent, and withBinary;

You get an output similar to the following example:

import io.quarkus.funqy.Funq;
import io.quarkus.funqy.knative.events.CloudEvent;

public class Input {
    private String message;

    // getters and setters
}

public class Output {
    private String message;

    // getters and setters
}

public class Functions {
    @Funq
    public Output withBeans(Input in) {
        // function body
    }

    @Funq
    public CloudEvent<Output> withCloudEvent(CloudEvent<Input> in) {
        // function body
    }

    @Funq
    public void withBinary(byte[] in) {
        // function body
    }
}

The withBeans function of the Functions class can be invoked by:

  • An HTTP POST request with a JSON body:

    $ curl "http://localhost:8080/withBeans" -X POST \
        -H "Content-Type: application/json" \
        -d '{"message": "Hello there."}'
  • An HTTP GET request with query parameters:

    $ curl "http://localhost:8080/withBeans?message=Hello%20there." -X GET
  • A CloudEvent object in binary encoding:

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/json" \
      -H "Ce-SpecVersion: 1.0" \
      -H "Ce-Type: withBeans" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      -d '{"message": "Hello there."}'
  • A CloudEvent object in structured encoding:

    $ curl http://localhost:8080/ \
        -H "Content-Type: application/cloudevents+json" \
        -d '{ "data": {"message":"Hello there."},
              "datacontenttype": "application/json",
              "id": "42",
              "source": "curl",
              "type": "withBeans",
              "specversion": "1.0"}'

The withCloudEvent function of the Functions class can be invoked by using a CloudEvent object, similarly to the withBeans function. However, unlike withBeans, withCloudEvent cannot be invoked with a plain HTTP request.

The withBinary function of the Functions class can be invoked by:

  • A CloudEvent object in binary encoding:

    $ curl "http://localhost:8080/" -X POST \
      -H "Content-Type: application/octet-stream" \
      -H "Ce-SpecVersion: 1.0"\
      -H "Ce-Type: withBinary" \
      -H "Ce-Source: cURL" \
      -H "Ce-Id: 42" \
      --data-binary '@img.jpg'
  • A CloudEvent object in structured encoding:

    $ curl http://localhost:8080/ \
      -H "Content-Type: application/cloudevents+json" \
      -d "{ \"data_base64\": \"$(base64 --wrap=0 img.jpg)\",
            \"datacontenttype\": \"application/octet-stream\",
            \"id\": \"42\",
            \"source\": \"curl\",
            \"type\": \"withBinary\",
            \"specversion\": \"1.0\"}"

12.2.3. CloudEvent attributes

If you need to read or write the attributes of a CloudEvent, such as type or subject, you can use the CloudEvent<T> generic interface and the CloudEventBuilder builder. The <T> type parameter must be one of the permitted types.

In the following example, CloudEventBuilder is used to return success or failure of processing the purchase:

public class Functions {

    private boolean _processPurchase(Purchase purchase) {
        // do stuff
    }

    public CloudEvent<Void> processPurchase(CloudEvent<Purchase> purchaseEvent) {
        System.out.println("subject is: " + purchaseEvent.subject());

        if (!_processPurchase(purchaseEvent.data())) {
            return CloudEventBuilder.create()
                    .type("purchase.error")
                    .build();
        }
        return CloudEventBuilder.create()
                .type("purchase.success")
                .build();
    }
}

12.2.4. Quarkus function return values

Functions can return an instance of any type from the list of permitted types. Or, they can return the Uni<T> type, where the <T> type parameter can be of any type from the permitted types.

The Uni<T> type is useful if a function calls asynchronous APIs, because the returned object is serialized in the same format as the received object. For example:

  • If a function receives an HTTP request, then the returned object is sent in the body of an HTTP response.
  • If a function receives a CloudEvent object in binary encoding, then the returned object is sent in the data property of a binary-encoded CloudEvent object.

The following example shows a function that fetches a list of purchases:

public class Functions {
    @Funq
    public List<Purchase> getPurchasesByName(String name) {
      // logic to retrieve purchases
    }
}
  • Invoking this function through an HTTP request produces an HTTP response that has a list of purchases in the body of the response.
  • Invoking this function through an incoming CloudEvent object produces a CloudEvent response with a list of purchases in the data property.
12.2.4.1. Permitted types

The input and output of a function can be any of the void, String, or byte[] types. Additionally, they can be primitive types and their wrappers, for example, int and Integer. They can also be the following complex objects: Javabeans, maps, lists, arrays, and the special CloudEvents<T> type.

Maps, lists, arrays, the <T> type parameter of the CloudEvents<T> type, and attributes of Javabeans can only be of types listed here.

Similar to the following example:

public class Functions {
    public List<Integer> getIds();
    public Purchase[] getPurchasesByName(String name);
    public String getNameById(int id);
    public Map<String,Integer> getNameIdMapping();
    public void processImage(byte[] img);
}

12.2.5. Testing Quarkus functions

You can test Quarkus functions locally on your computer. The default project that kn func create creates has a src/test/ directory with basic Maven tests. You can extend these tests as needed.

Prerequisites

  • You have created a Quarkus function.
  • You have installed the Knative (kn) CLI.

Procedure

  1. Navigate to the project folder for your function.
  2. Run the Maven tests:

    $ ./mvnw test

You can override liveness and readiness probe values for your Quarkus functions. Configure these probes to define how the platform performs health checks on the function.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  1. Override the /health/liveness and /health/readiness paths with your own values. You can do this either by changing properties in the function source or by setting the QUARKUS_SMALLRYE_HEALTH_LIVENESS_PATH and QUARKUS_SMALLRYE_HEALTH_READINESS_PATH environment variables on func.yaml file.

    1. To override the paths using the function source, update the path properties in the src/main/resources/application.properties file:

      quarkus.smallrye-health.root-path=/health
      quarkus.smallrye-health.liveness-path=alive
      quarkus.smallrye-health.readiness-path=ready
      quarkus.smallrye-health.root-path=/health
      The root path, which is automatically prepended to the liveness and readiness paths.
      quarkus.smallrye-health.liveness-path=alive
      The liveness path, set to /health/alive here.
      quarkus.smallrye-health.readiness-path=ready
      The readiness path, set to /health/ready here.
    2. To override the paths using environment variables, define the path variables in the build block of the func.yaml file:

      build:
        builder: s2i
        buildEnvs:
        - name: QUARKUS_SMALLRYE_HEALTH_LIVENESS_PATH
          value: alive 
      1
      
        - name: QUARKUS_SMALLRYE_HEALTH_READINESS_PATH
          value: ready 
      2
      value: alive
      The liveness path, set to /health/alive here.
      value: ready
      The readiness path, set to /health/ready here.
  2. Add the new endpoints to the func.yaml file, so that they are properly bound to the container for the Knative service:

    deploy:
      healthEndpoints:
        liveness: /health/alive
        readiness: /health/ready

12.3. Developing Node.js functions

After you have created a Node.js function project, you can change the template files provided to add business logic to your function. This includes configuring function invocation and the returned headers and status codes.

12.3.1. Node.js function template structure

When you create a Node.js function by using the Knative (kn) CLI, the project directory looks like a typical Node.js project. The only exception is the additional func.yaml file, which is used to configure the function.

Note

Before you can develop functions, you must configure the function.

Both http and event trigger functions have the same template structure:

.
├── func.yaml 
1

├── index.js 
2

├── package.json 
3

├── README.md
└── test 
4

    ├── integration.js
    └── unit.js
func.yaml
The func.yaml configuration file is used to determine the image name and registry.
index.js
Your project must contain an index.js file which exports a single function.
package.json
You are not restricted to the dependencies provided in the template package.json file. You can add additional dependencies as you would in any other Node.js project.
test
Integration and unit test scripts are provided as part of the function template.

You get an output similar to the following example:

npm install --save opossum

When the project is built for deployment, these dependencies are included in the created runtime container image.

12.3.2. About invoking Node.js functions

When using the Knative (kn) CLI to create a function project, you can generate a project that responds to CloudEvents, or one that responds to simple HTTP requests. CloudEvents in Knative are transported over HTTP as a POST request, so both function types listen for and respond to incoming HTTP events.

Node.js functions can be invoked with a simple HTTP request. When an incoming request is received, functions are invoked with a context object as the first parameter.

12.3.2.1. Node.js context objects

Functions are invoked by providing a context object as the first parameter. This object provides access to the incoming HTTP request information.

This information includes the HTTP request method, any query strings or headers sent with the request, the HTTP version, and the request body. Incoming requests that contain a CloudEvent attach the incoming instance of the CloudEvent to the context object so that it can be accessed by using context.cloudevent.

12.3.2.1.1. Context object methods

The context object has a single method, cloudEventResponse(), that accepts a data value and returns a CloudEvent.

In a Knative system, if a function deployed as a service is invoked by an event broker sending a CloudEvent, the broker examines the response. If the response is a CloudEvent, this event is handled by the broker.

The following example displays the context object method:

// Expects to receive a CloudEvent with customer data
function handle(context, customer) {
  // process the customer
  const processed = handle(customer);
  return context.cloudEventResponse(customer)
    .source('/handle')
    .type('fn.process.customer')
    .response();
}
12.3.2.1.2. CloudEvent data

If the incoming request is a CloudEvent, any data associated with the CloudEvent is extracted from the event and provided as a second parameter. For example, if a CloudEvent is received that has a JSON string in its data property that is similar to the following:

{
  "customerId": "0123456",
  "productId": "6543210"
}

When invoked, the second parameter to the function, after the context object, will be a JavaScript object that has customerId and productId properties.

You get an output similar to the following example:

function handle(context, data)

The data parameter in this example is a JavaScript object that has the customerId and productId properties.

12.3.2.1.3. Arbitrary data

A function can receive any data, not just CloudEvents. For example, you might want to call a function by using POST with an arbitrary object in the body:

{
  "id": "12345",
  "contact": {
    "title": "Mr.",
    "firstname": "John",
    "lastname": "Smith"
  }
}

In this case, you can define the function as follows:

function handle(context, customer) {
  return "Hello " + customer.contact.title + " " + customer.contact.lastname;
}

Supplying the contact object to the function would then return the following output:

Hello Mr. Smith
12.3.2.1.4. Supported data types

CloudEvents can contain various data types, including JSON, XML, plain text, and binary data. These data types are provided to the function in their dedicated formats:

  • JSON Data: Provided as a JavaScript object.
  • XML Data: Provided as an XML document.
  • Plain Text: Provided as a string.
  • Binary Data: Provided as a Buffer object.
12.3.2.1.5. Multiple data types in a function

Ensure your function can handle different data types by checking the Content-Type header and parsing the data. For example:

function handle(context, data) {
  if (context.headers['content-type'] === 'application/json') {
    // handle JSON data
  } else if (context.headers['content-type'] === 'application/xml') {
    // handle XML data
  } else {
    // handle other data types
  }
}

12.3.3. Node.js function return values

Functions can return any valid JavaScript type or can have no return value. When a function has no return value specified, and no failure is indicated, the caller receives a 204 No Content response.

Functions can also return a CloudEvent or a Message object to push events into the Knative Eventing system. In this case, the developer is not required to understand or implement the CloudEvent messaging specification. Headers and other relevant information from the returned values are extracted and sent with the response.

You get an output similar to the following example:

function handle(context, customer) {
  // process customer and return a new CloudEvent
  return new CloudEvent({
    source: 'customer.processor',
    type: 'customer.processed'
  })
}
12.3.3.1. Returning primitive types

Functions can return any valid JavaScript type, including primitives such as strings, numbers, and booleans:

You get an output similar to the following example:

function handle(context) {
  return "This function Works!"
}

Calling this function returns the following string:

$ curl https://myfunction.example.com
This function Works!

You get an output similar to the following example:

function handle(context) {
  let somenumber = 100
  return { body: somenumber }
}

Calling this function returns the following number:

$ curl https://myfunction.example.com
100

You get an output similar to the following example:

function handle(context) {
  let someboolean = false
  return { body: someboolean }
}

Calling this function returns the following boolean:

$ curl https://myfunction.example.com
false

Returning primitives directly without wrapping them in an object results in a 204 No Content status code with an empty body:

You get an output similar to the following example:

function handle(context) {
  let someboolean = false
  return someboolean
}

Calling this function returns the following:

$ http :8080
HTTP/1.1 204 No Content
Connection: keep-alive
...
12.3.3.2. Returning headers

You can set a response header by adding a headers property to the return object. These headers are extracted and sent with the response to the caller.

You get an output similar to the following example:

function handle(context, customer) {
  // process customer and return custom headers
  // the response will be '204 No content'
  return { headers: { customerid: customer.id } };
}
12.3.3.3. Returning status codes

You can set a status code that is returned to the caller by adding a statusCode property to the return object:

You get an output similar to the following example:

function handle(context, customer) {
  // process customer
  if (customer.restricted) {
    return { statusCode: 451 }
  }
}

Status codes can also be set for errors that are created and thrown by the function:

You get an output similar to the following example:

function handle(context, customer) {
  // process customer
  if (customer.restricted) {
    const err = new Error(‘Unavailable for legal reasons’);
    err.statusCode = 451;
    throw err;
  }
}

12.3.4. Testing Node.js functions

Node.js functions can be tested locally on your computer. In the default project that is created when you create a function by using kn func create, there is a test folder that has some simple unit and integration tests.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  1. Navigate to the test folder for your function.
  2. Run the tests:

    $ npm test

You can override liveness and readiness probe values for your Node.js functions. You can configure health checks performed on the function.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  • In your function code, create the Function object, which implements the following interface:
export interface Function {
  init?: () => any;

  shutdown?: () => any;

  liveness?: HealthCheck;

  readiness?: HealthCheck;

  logLevel?: LogLevel;

  handle: CloudEventFunction | HTTPFunction;
}
init?: () ⇒ any
The initialization function, called before the server is started. This function is optional and should be synchronous.
shutdown?: () ⇒ any;
The shutdown function, called after the server is stopped. This function is optional and should be synchronous.
liveness?: HealthCheck;
The liveness function, called to check if the server is alive. This function is optional and should return 200/OK if the server is alive.
readiness?: HealthCheck;
The readiness function, called to check if the server is ready to accept requests. This function is optional and should return 200/OK if the server is ready.
handle: CloudEventFunction | HTTPFunction;
The function to handle HTTP requests.

For example, add the following code to the index.js file:

const Function = {

  handle: (context, body) => {
    // The function logic goes here
    return 'function called'
  },

  liveness: () => {
    process.stdout.write('In liveness\n');
    return 'ok, alive';
  },

  readiness: () => {
    process.stdout.write('In readiness\n');
    return 'ok, ready';
  }
};

Function.liveness.path = '/alive';
Function.readiness.path = '/ready';

module.exports = Function;
Function.liveness.path = '/alive';
Custom liveness endpoint.
Function.readiness.path = '/ready';
Custom readiness endpoint.

As an alternative to Function.liveness.path and Function.readiness.path, you can specify custom endpoints by using the LIVENESS_URL and READINESS_URL environment variables:

run:
  envs:
  - name: LIVENESS_URL
    value: /alive
  - name: READINESS_URL
    value: /ready
value: /alive
The liveness path, set to /alive here.
value: /ready
The readiness path, set to /ready here.
  • Add the new endpoints to the func.yaml file, so that they are properly bound to the container for the Knative service:
deploy:
  healthEndpoints:
    liveness: /alive
    readiness: /ready

12.3.6. Node.js context object reference

The context object has several properties that can be accessed by the function developer. Accessing these properties can give information about HTTP requests and write output to the cluster logs.

12.3.6.1. Log

Provides a logging object that can be used to write output to the cluster logs. The log adheres to the Pino logging API.

function handle(context) {
  context.log.info(“Processing customer”);
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.function.com'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"Processing customer"}

You can change the log level to one of fatal, error, warn, info, debug, trace, or silent. To do that, change the value of logLevel by using one of these values to the environment variable FUNC_LOG_LEVEL by using the config command.

12.3.6.2. query

Returns the query string for the request, if any, as key-value pairs. These attributes are also found on the context object itself.

function handle(context) {
  // Log the 'name' query parameter
  context.log.info(context.query.name);
  // Query parameters are also attached to the context
  context.log.info(context.name);
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.com?name=tiger'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}
12.3.6.3. body

Returns the request body if any. If the request body contains JSON code, this will be parsed so that the attributes are directly available.

function handle(context) {
  // log the incoming request body's 'hello' parameter
  context.log.info(context.body.hello);
}

You can access the function by using the curl command to invoke it:

You get an output similar to the following example command:

$ kn func invoke -d '{"Hello": "world"}'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"world"}
12.3.6.4. headers

Returns the HTTP request headers as an object.

function handle(context) {
  context.log.info(context.headers["custom-header"]);
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.function.com'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"some-value"}
12.3.6.5. HTTP requests
method
Returns the HTTP request method as a string.
httpVersion
Returns the HTTP version as a string.
httpVersionMajor
Returns the HTTP major version number as a string.
httpVersionMinor
Returns the HTTP minor version number as a string.

12.4. Developing TypeScript functions

After you have created a TypeScript function project, you can change the template files provided to add business logic to your function. This includes configuring function invocation and the returned headers and status codes.

12.4.1. TypeScript function template structure

When you create a TypeScript function by using the Knative (kn) CLI, the project directory looks like a typical TypeScript project. The only exception is the additional func.yaml file, which is used for configuring the function.

Note

Before you can develop functions, you must configure the function.

Both http and event trigger functions have the same template structure:

.
├── func.yaml
├── package.json
├── package-lock.json
├── README.md
├── src
│   └── index.ts
├── test
│   ├── integration.ts
│   └── unit.ts
└── tsconfig.json
func.yaml
The func.yaml configuration file is used to find the image name and registry.
package.json
You are not restricted to the dependencies provided in the template package.json file. You can add additional dependencies as you would in any other TypeScript project.
index.ts
Your project must contain an src/index.js file that exports a function named handle.
test
Integration and unit test scripts are provided as part of the function template.

The following displays how to add npm dependencies:

npm install --save opossum

When the project is built for deployment, these dependencies are included in the created runtime container image.

12.4.2. About invoking TypeScript functions

When you use the Knative (kn) CLI to create a function project, you can generate a project that responds to CloudEvents or simple HTTP requests. Knative sends CloudEvents over HTTP as POST requests, so both function types listen for and respond to incoming HTTP events.

You can call TypeScript functions with a simple HTTP request. When a function receives a request, the runtime calls it with a context object as the first parameter.

12.4.2.1. TypeScript context objects

To call a function, pass a context object as the first parameter. Access its properties to get information about the incoming HTTP request.

The following example displayes context object:

function handle(context:Context): string

This information includes the HTTP request method, any query strings or headers sent with the request, the HTTP version, and the request body. Incoming requests that contain a CloudEvent attach the incoming instance of the CloudEvent to the context object so that it can be accessed by using context.cloudevent.

12.4.2.1.1. Context object methods

The context object has a single method, cloudEventResponse(), that accepts a data value and returns a CloudEvent.

In a Knative system, if a function deployed as a service is invoked by an event broker sending a CloudEvent, the broker examines the response. If the response is a CloudEvent, this event is handled by the broker.

The following example displayes context object method:

// Expects to receive a CloudEvent with customer data
export function handle(context: Context, cloudevent?: CloudEvent): CloudEvent {
  // process the customer
  const customer = cloudevent.data;
  const processed = processCustomer(customer);
  return context.cloudEventResponse(customer)
    .source('/customer/process')
    .type('customer.processed')
    .response();
}
12.4.2.1.2. Context types

The TypeScript type definition files export the following types for use in your functions.

The following example displayes exported type definitions:

// Invokable is the expeted Function signature for user functions
export interface Invokable {
    (context: Context, cloudevent?: CloudEvent): any
}

// Logger can be used for structural logging to the console
export interface Logger {
  debug: (msg: any) => void,
  info:  (msg: any) => void,
  warn:  (msg: any) => void,
  error: (msg: any) => void,
  fatal: (msg: any) => void,
  trace: (msg: any) => void,
}

// Context represents the function invocation context, and provides
// access to the event itself as well as raw HTTP objects.
export interface Context {
    log: Logger;
    req: IncomingMessage;
    query?: Record<string, any>;
    body?: Record<string, any>|string;
    method: string;
    headers: IncomingHttpHeaders;
    httpVersion: string;
    httpVersionMajor: number;
    httpVersionMinor: number;
    cloudevent: CloudEvent;
    cloudEventResponse(data: string|object): CloudEventResponse;
}

// CloudEventResponse is a convenience class used to create
// CloudEvents on function returns
export interface CloudEventResponse {
    id(id: string): CloudEventResponse;
    source(source: string): CloudEventResponse;
    type(type: string): CloudEventResponse;
    version(version: string): CloudEventResponse;
    response(): CloudEvent;
}
12.4.2.1.3. CloudEvent data

If the incoming request is a CloudEvent, any data associated with the CloudEvent is extracted from the event and provided as a second parameter. For example, if a CloudEvent is received that has a JSON string in its data property that is similar to the following:

{
  "customerId": "0123456",
  "productId": "6543210"
}

When invoked, the second parameter to the function, after the context object, will be a JavaScript object that has customerId and productId properties.

You get an output similar to the following example signature:

function handle(context: Context, cloudevent?: CloudEvent): CloudEvent

The cloudevent parameter in this example is a JavaScript object that has the customerId and productId properties.

12.4.3. TypeScript function return values

Functions can return any valid JavaScript type or can have no return value. When a function has no return value specified, and no failure is indicated, the caller receives a 204 No Content response.

Functions can also return a CloudEvent or a Message object to push events into the Knative Eventing system. In this case, the developer is not required to understand or implement the CloudEvent messaging specification. Headers and other relevant information from the returned values are extracted and sent with the response.

You get an output similar to the following example:

export const handle: Invokable = function (
  context: Context,
  cloudevent?: CloudEvent
): Message {
  // process customer and return a new CloudEvent
  const customer = cloudevent.data;
  return HTTP.binary(
    new CloudEvent({
      source: 'customer.processor',
      type: 'customer.processed'
    })
  );
};
12.4.3.1. Returning headers

You can set a response header by adding a headers property to the return object. These headers are extracted and sent with the response to the caller.

The following example displayes response header:

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, any> {
  // process customer and return custom headers
  const customer = cloudevent.data as Record<string, any>;
  return { headers: { 'customer-id': customer.id } };
}
12.4.3.2. Returning status codes

You can set a status code that is returned to the caller by adding a statusCode property to the return object:

The following example displayes status code:

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, any> {
  // process customer
  const customer = cloudevent.data as Record<string, any>;
  if (customer.restricted) {
    return {
      statusCode: 451
    }
  }
  // business logic, then
  return {
    statusCode: 240
  }
}

Status codes can also be set for errors that are created and thrown by the function:

The following example displayes error status code:

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, string> {
  // process customer
  const customer = cloudevent.data as Record<string, any>;
  if (customer.restricted) {
    const err = new Error(‘Unavailable for legal reasons’);
    err.statusCode = 451;
    throw err;
  }
}

12.4.4. Testing TypeScript functions

TypeScript functions can be tested locally on your computer. In the default project that is created when you create a function by using kn func create, there is a test folder that has some simple unit and integration tests.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  1. If you have not previously run tests, install the dependencies first by running the following command:

    $ npm install
  2. Navigate to the test folder for your function.
  3. Run the tests:

    $ npm test

You can override liveness and readiness probe values for your TypeScript functions. Use these probes to configure how the platform performs health checks on the function.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function by using kn func create.

Procedure

  1. In your function code, create the Function object, which implements the following interface:

    export interface Function {
      init?: () => any;
    
      shutdown?: () => any;
    
      liveness?: HealthCheck;
    
      readiness?: HealthCheck;
    
      logLevel?: LogLevel;
    
      handle: CloudEventFunction | HTTPFunction;
    }
    init?: () ⇒ any;
    The initialization function, called before the server is started. This function is optional and should be synchronous.
    shutdown?: () ⇒ any; <2>
    The shutdown function, called after the server is stopped. This function is optional and should be synchronous.
    liveness?: HealthCheck;
    The liveness function, called to check if the server is alive. This function is optional and should return 200/OK if the server is alive.
    readiness?: HealthCheck;
    The readiness function, called to check if the server is ready to accept requests. This function is optional and should return 200/OK if the server is ready.
    handle: CloudEventFunction | HTTPFunction;
    The function to handle HTTP requests.

    For example, add the following code to the index.js file:

    const Function = {
    
      handle: (context, body) => {
        // The function logic goes here
        return 'function called'
      },
    
      liveness: () => {
        process.stdout.write('In liveness\n');
        return 'ok, alive';
      },
    
      readiness: () => {
        process.stdout.write('In readiness\n');
        return 'ok, ready';
      }
    };
    
    Function.liveness.path = '/alive';
    Function.readiness.path = '/ready';
    
    module.exports = Function;
    liveness: () ⇒ {
    Custom liveness function.
    readiness: () ⇒ {
    Custom readiness function.
    Function.liveness.path = '/alive';
    Custom liveness endpoint.
    Function.readiness.path = '/ready';
    Custom readiness endpoint.

    As an alternative to Function.liveness.path and Function.readiness.path, you can specify custom endpoints by using the LIVENESS_URL and READINESS_URL environment variables:

    run:
      envs:
      - name: LIVENESS_URL
        value: /alive
      - name: READINESS_URL
        value: /ready
    value: /alive
    The liveness path, set to /alive here.
    value: /ready
    The readiness path, set to /ready here.
  2. Add the new endpoints to the func.yaml file, so that they are properly bound to the container for the Knative service:

    deploy:
      healthEndpoints:
        liveness: /alive
        readiness: /ready

12.4.6. TypeScript context object reference

The context object has several properties that can be accessed by the function developer. Accessing these properties can give information about incoming HTTP requests and write output to the cluster logs.

12.4.6.1. log

Provides a logging object that can be used to write output to the cluster logs. The log adheres to the Pino logging API.

You get an output similar to the following log example:

export function handle(context: Context): string {
    // log the incoming request body's 'hello' parameter
    if (context.body) {
      context.log.info((context.body as Record<string, string>).hello);
    } else {
      context.log.info('No data received');
    }
    return 'OK';
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.function.com'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"Processing customer"}

You can change the log level to one of fatal, error, warn, info, debug, trace, or silent. To do that, change the value of logLevel by assigning one of these values to the environment variable FUNC_LOG_LEVEL by using the config command.

12.4.6.2. query

Returns the query string for the request, if any, as key-value pairs. These attributes are also found on the context object itself.

You get an output similar to the following query example:

export function handle(context: Context): string {
      // log the 'name' query parameter
    if (context.query) {
      context.log.info((context.query as Record<string, string>).name);
    } else {
      context.log.info('No data received');
    }
    return 'OK';
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.function.com' --data '{"name": "tiger"}'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}
{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"tiger"}
12.4.6.3. body

Returns the request body, if any. If the request body contains JSON code, this will be parsed so that the attributes are directly available.

You get an output similar to the following body example:

export function handle(context: Context): string {
    // log the incoming request body's 'hello' parameter
    if (context.body) {
      context.log.info((context.body as Record<string, string>).hello);
    } else {
      context.log.info('No data received');
    }
    return 'OK';
}

You can access the function by using the kn func invoke command:

You get an output similar to the following example command:

$ kn func invoke --target 'http://example.function.com' --data '{"hello": "world"}'

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"world"}
12.4.6.4. headers

Returns the HTTP request headers as an object.

You get an output similar to the following headers example:

export function handle(context: Context): string {
    // log the incoming request body's 'hello' parameter
    if (context.body) {
      context.log.info((context.headers as Record<string, string>)['custom-header']);
    } else {
      context.log.info('No data received');
    }
    return 'OK';
}

You can access the function by using the curl command to call it:

You get an output similar to the following example command:

$ curl -H'x-custom-header: some-value’' http://example.function.com

You get an output similar to the following example:

{"level":30,"time":1604511655265,"pid":3430203,"hostname":"localhost.localdomain","reqId":1,"msg":"some-value"}
12.4.6.5. HTTP requests
method
Returns the HTTP request method as a string.
httpVersion
Returns the HTTP version as a string.
httpVersionMajor
Returns the HTTP major version number as a string.
httpVersionMinor
Returns the HTTP minor version number as a string.

12.5. Developing Python functions

After you have created a Python function project, you can change the template files provided to add business logic to your function. This includes configuring function invocation and the returned headers and status codes.

12.5.1. Python function template structure

When you create a Python function by using the Knative (kn) CLI, the project directory looks similar to a typical Python project. Python functions have very few restrictions. The only requirements are that your project contains a func.py file that contains a main() function, and a func.yaml configuration file.

Note

Before you can develop functions, you must configure the function.

Developers are not restricted to the dependencies provided in the template requirements.txt file. Additional dependencies can be added as they would be in any other Python project. When the project is built for deployment, these dependencies will be included in the created runtime container image.

Both http and event trigger functions have the same template structure:

Template structure

fn
├── func.py 
1

├── func.yaml 
2

├── requirements.txt 
3

└── test_func.py 
4

1 1 1 1
Contains a main() function.
2 2 2 2
Used to determine the image name and registry.
3 3 3
Additional dependencies can be added to the requirements.txt file as they are in any other Python project.
4 4 4
Contains a simple unit test that can be used to test your function locally.

12.5.2. About invoking Python functions

You can call Python functions with a simple HTTP request. When a function receives a request, the runtime calls it with a context object as the first parameter.

The context object is a Python class with two attributes:

  • The request attribute is always present, and has the Flask request object.
  • The second attribute, cloud_event, is populated if the incoming request is a CloudEvent object.

Developers can access any CloudEvent data from the context object.

You get an output similar to the following example:

def main(context: Context):
    """
    The context parameter contains the Flask request object and any
    CloudEvent received with the request.
    """
    print(f"Method: {context.request.method}")
    print(f"Event data {context.cloud_event.data}")
    # ... business logic here

12.5.3. Python function return values

Functions can return any value supported by Flask. This is because the invocation framework proxies these values directly to the Flask server.

You get an output similar to the following example:

def main(context: Context):
    body = { "message": "Howdy!" }
    headers = { "content-type": "application/json" }
    return body, 200, headers

Functions can set both headers and response codes as secondary and tertiary response values from function invocation.

12.5.3.1. Returning CloudEvents

Developers can use the @event decorator to tell the invoker that the function return value must be converted to a CloudEvent before sending the response.

You get an output similar to the following example:

@event("event_source"="/my/function", "event_type"="my.type")
def main(context):
    # business logic here
    data = do_something()
    # more data processing
    return data

This example sends a CloudEvent as the response value, with a type of "my.type" and a source of "/my/function". The CloudEvent data property is set to the returned data variable. The event_source and event_type decorator attributes are both optional.

12.5.4. Testing Python functions

You can test Python functions locally on your computer. The default project has a test_func.py file, which provides a simple unit test for functions.

Note

The default test framework for Python functions is unittest. You can use a different test framework if you prefer.

Prerequisites

  • To run Python functions tests locally, you must install the required dependencies:

    $ pip install -r requirements.txt

Procedure

  1. Navigate to the folder for your function that has the test_func.py file.
  2. Run the tests:

    $ python3 test_func.py

Chapter 13. Configuring functions

After you deploy functions to the cluster, they can access data in secrets and config maps. Mount this data as volumes or assign it to environment variables. Configure this access by using the Knative CLI or by editing the function configuration YAML file.

You can use the kn func config interactive utility to manage the secrets and config maps that your function accesses. You can list, add, and remove values stored as environment variables, and list, add, and remove volumes. Control which cluster data your function can access.

Important

To access secrets and config maps, deploy the function on the cluster. A function running locally cannot access them.

If the function cannot access a secret or config map value, the deployment fails and reports the inaccessible values.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Run the following command in the function project directory:

    $ kn func config

    You can also specify the function project directory by using the --path or -p option.

  2. Use the interactive interface to perform the necessary operation. For example, using the utility to list configured volumes produces an output similar to this:

    $ kn func config
    ? What do you want to configure? Volumes
    ? What operation do you want to perform? List
    Configured Volumes mounts:
    - Secret "mysecret" mounted at path: "/workspace/secret"
    - Secret "mysecret2" mounted at path: "/workspace/secret2"

    This scheme shows all operations available in the interactive utility and how to go to them:

    kn func config
       ├─> Environment variables
       │               ├─> Add
       │               │    ├─> ConfigMap: Add all key-value pairs from a config map
       │               │    ├─> ConfigMap: Add value from a key in a config map
       │               │    ├─> Secret: Add all key-value pairs from a secret
       │               │    └─> Secret: Add value from a key in a secret
       │               ├─> List: List all configured environment variables
       │               └─> Remove: Remove a configured environment variable
       └─> Volumes
               ├─> Add
               │    ├─> ConfigMap: Mount a config map as a volume
               │    └─> Secret: Mount a secret as a volume
               ├─> List: List all configured volumes
               └─> Remove: Remove a configured volume
  3. Optional: Deploy the function to make the changes take effect:

    $ kn func deploy -p test

Every time you run the kn func config utility, you need to go to the entire dialogue to select the operation you need, as shown in the earlier section. To save steps, you can directly run a specific operation by running a more specific form of the kn func config command:

  • To list configured environment variables:

    $ kn func config envs [-p <function_project_path>]
  • To add environment variables to the function configuration:

    $ kn func config envs add [-p <function_project_path>]
  • To remove environment variables from the function configuration:

    $ kn func config envs remove [-p <function_project_path>]
  • To list configured volumes:

    $ kn func config volumes [-p <function_project_path>]
  • To add a volume to the function configuration:

    $ kn func config volumes add [-p <function_project_path>]
  • To remove a volume from the function configuration:

    $ kn func config volumes remove [-p <function_project_path>]

The func.yaml file has the configuration for your function project. The kn func command uses the values in func.yaml. For example, when you run kn func build, the command uses the value in the build field. You can override these values with command-line flags or environment variables.

If you want to avoid storing sensitive information such as an API key in the function configuration, you can add a reference to an environment variable available in the local environment. You can do this by modifying the envs field in the func.yaml file.

Prerequisites

  • You need to have the function project created.
  • The local environment needs to contain the variable that you want to reference.

Procedure

  • To refer to a local environment variable, use the following syntax:

    {{ env:ENV_VAR }}

    Substitute ENV_VAR with the name of the variable in the local environment that you want to use.

    For example, you might have the API_KEY variable available in the local environment. You can assign its value to the MY_API_KEY variable, which you can then directly use within your function:

    You get an output similar to the following example:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - name: MY_API_KEY
      value: '{{ env:API_KEY }}'
    ...

13.2.2. Adding annotations to functions

You can add Kubernetes annotations to a deployed Serverless function. Use annotations to attach arbitrary metadata to a function, for example, a note about the function’s purpose. Add annotations to the annotations section of the func.yaml configuration file.

The function annotation feature has the following limitations:

  • After an annotation propagates to the corresponding Knative service on the cluster, you cannot remove it from the service by deleting it from the func.yaml file. Remove the annotation by modifying the Knative service YAML directly or by using the OpenShift Container Platform web console.
  • You cannot set annotations that Knative sets, for example, the autoscaling annotations.

13.2.3. Adding annotations to a function

You can add annotations to a function. Similar to labels, annotations use a key-value map. Annotations are useful, for example, for providing metadata about a function, such as the function’s author.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For every annotation that you want to add, add the following YAML to the annotations section:

    name: test
    namespace: ""
    runtime: go
    ...
    annotations:
      <annotation_name>: "<annotation_value>" 
    1
    1
    Substitute <annotation_name>: "<annotation_value>" with your annotation.

    For example, to indicate that Alice authored the function, include the following annotation:

    name: test
    namespace: ""
    runtime: go
    ...
    annotations:
      author: "alice@example.com"
  3. Save the configuration.

The next time you deploy the function to the cluster, the system adds the annotations to the corresponding Knative service.

You can manually add configuration for accessing secrets and config maps to your function. This might be preferable to using the kn func config interactive utility and commands, for example when you have an existing configuration snippet.

13.3.1. Mounting a secret as a volume

You can mount a secret as a volume. After you mount it, access it from the function as a regular file. Store data on the cluster that the function needs, for example, a list of URIs that the function accesses.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For each secret you want to mount as a volume, add the following YAML to the volumes section:

    name: test
    namespace: ""
    runtime: go
    ...
    volumes:
    - secret: mysecret
      path: /workspace/secret
    • Substitute mysecret with the name of the target secret.
    • Substitute /workspace/secret with the path where you want to mount the secret.

      For example, to mount the addresses secret, use the following YAML:

      name: test
      namespace: ""
      runtime: go
      ...
      volumes:
      - configMap: addresses
        path: /workspace/secret-addresses
  3. Save the configuration.

13.3.2. Mounting a config map as a volume

You can mount a config map as a volume. After you mount it, access it from the function as a regular file. Store data on the cluster that the function needs, for example, a list of URIs that the function accesses.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For each config map you want to mount as a volume, add the following YAML to the volumes section:

    name: test
    namespace: ""
    runtime: go
    ...
    volumes:
    - configMap: myconfigmap
      path: /workspace/configmap
    • Substitute myconfigmap with the name of the target config map.
    • Substitute /workspace/configmap with the path where you want to mount the config map.

      For example, to mount the addresses config map, use the following YAML:

      name: test
      namespace: ""
      runtime: go
      ...
      volumes:
      - configMap: addresses
        path: /workspace/configmap-addresses
  3. Save the configuration.

You can set an environment variable from a key value defined as a secret. A value previously stored in a secret can then be accessed as an environment variable by the function at runtime. This can be useful for getting access to a value stored in a secret, such as the ID of a user.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For each value from a secret key-value pair that you want to assign to an environment variable, add the following YAML to the envs section:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - name: EXAMPLE
      value: '{{ secret:mysecret:key }}'
    • Substitute EXAMPLE with the name of the environment variable.
    • Substitute mysecret with the name of the target secret.
    • Substitute key with the key mapped to the target value.

      For example, to access the user ID that is stored in userdetailssecret, use the following YAML:

      name: test
      namespace: ""
      runtime: go
      ...
      envs:
      - value: '{{ configMap:userdetailssecret:userid }}'
  3. Save the configuration.

You can set an environment variable from a key value defined as a config map. A value previously stored in a config map can then be accessed as an environment variable by the function at runtime. This can be useful for getting access to a value stored in a config map, such as the ID of a user.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For each value from a config map key-value pair that you want to assign to an environment variable, add the following YAML to the envs section:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - name: EXAMPLE
      value: '{{ configMap:myconfigmap:key }}'
    • Substitute EXAMPLE with the name of the environment variable.
    • Substitute myconfigmap with the name of the target config map.
    • Substitute key with the key mapped to the target value.

      For example, to access the user ID that is stored in userdetailsmap, use the following YAML:

      name: test
      namespace: ""
      runtime: go
      ...
      envs:
      - value: '{{ configMap:userdetailsmap:userid }}'
  3. Save the configuration.

You can set an environment variable from all values defined in a secret. Values previously stored in a secret can then be accessed as environment variables by the function at runtime. This can be useful for simultaneously getting access to a collection of values stored in a secret, for example, a set of data pertaining to a user.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For every secret for which you want to import all key-value pairs as environment variables, add the following YAML to the envs section:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - value: '{{ secret:mysecret }}' 
    1
    1
    Substitute mysecret with the name of the target secret.

    For example, to access all user data that is stored in userdetailssecret, use the following YAML:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - value: '{{ configMap:userdetailssecret }}'
  3. Save the configuration.

You can set an environment variable from all values defined in a config map. Values previously stored in a config map can then be accessed as environment variables by the function at runtime. This can be useful for simultaneously getting access to a collection of values stored in a config map, for example, a set of data pertaining to a user.

Prerequisites

  • You have installed the OpenShift Serverless Operator and Knative Serving on the cluster.
  • You have installed the Knative (kn) CLI.
  • You have created a function.

Procedure

  1. Open the func.yaml file for your function.
  2. For every config map for which you want to import all key-value pairs as environment variables, add the following YAML to the envs section:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - value: '{{ configMap:myconfigmap }}'

    Substitute myconfigmap with the name of the target config map.

    For example, to access all user data that is stored in userdetailsmap, use the following YAML:

    name: test
    namespace: ""
    runtime: go
    ...
    envs:
    - value: '{{ configMap:userdetailsmap }}'
  3. Save the file.

13.4. Configurable fields in func.yaml

You can configure some of the func.yaml fields.

13.4.1. Configurable fields in func.yaml

Many of the fields in func.yaml are generated automatically when you create, build, and deploy your function. However, there are also fields that you change manually to change things, such as the function name or the image name.

13.4.1.1. buildEnvs

You can use the buildEnvs field to set environment variables for the build environment. Variables that you set by using buildEnvs are not available during function runtime, unlike variables set by using envs.

You can set a buildEnv variable directly from a value. In the following example, the buildEnv variable named EXAMPLE1 is directly assigned the one value:

buildEnvs:
- name: EXAMPLE1
  value: one

You can also set a buildEnv variable from a local environment variable. In the following example, the buildEnv variable named EXAMPLE2 is assigned the value of the LOCAL_ENV_VAR local environment variable:

buildEnvs:
- name: EXAMPLE1
  value: '{{ env:LOCAL_ENV_VAR }}'
13.4.1.2. envs

The envs field enables you to set environment variables to be available to your function at runtime. You can set an environment variable in several different ways:

  1. Directly from a value.
  2. From a value assigned to a local environment variable. See the section "Referencing local environment variables from func.yaml fields" for more information.
  3. From a key-value pair stored in a secret or config map.
  4. You can also import all key-value pairs stored in a secret or config map, with keys used as names of the created environment variables.

The following examples demonstrates the different ways to set an environment variable:

name: test
namespace: ""
runtime: go
...
envs:
- name: EXAMPLE1
  value: value
- name: EXAMPLE2
  value: '{{ env:LOCAL_ENV_VALUE }}'
- name: EXAMPLE3
  value: '{{ secret:mysecret:key }}'
- name: EXAMPLE4
  value: '{{ configMap:myconfigmap:key }}'
- value: '{{ secret:mysecret2 }}'
- value: '{{ configMap:myconfigmap2 }}'
  • name: EXAMPLE1: An environment variable set directly from a value.
  • name: EXAMPLE2: An environment variable set from a value assigned to a local environment variable.
  • name: EXAMPLE3: An environment variable assigned from a key-value pair stored in a secret.
  • name: EXAMPLE4: An environment variable assigned from a key-value pair stored in a config map.
  • secret:mysecret2: A set of environment variables imported from key-value pairs of a secret.
  • configMap:myconfigmap2: A set of environment variables imported from key-value pairs of a config map.
13.4.1.3. builder

The builder field specifies the strategy used by the function to build the image. It accepts values of pack or s2i.

13.4.1.4. build

The build field indicates how the function should be built. The value local indicates that the function is built locally on your machine. The value git indicates that the function is built on a cluster by using the values specified in the git field.

13.4.1.5. volumes

You can use the volumes field to mount secrets and config maps as volumes that the function can access at the specified path, as shown in the following example:

name: test
namespace: ""
runtime: go
...
volumes:
- secret: mysecret
  path: /workspace/secret
- configMap: myconfigmap
  path: /workspace/configmap
  • secret: mysecret: The system mounts the mysecret secret as a volume at /workspace/secret.
  • configMap: myconfigmap: The system mounts the myconfigmap config map as a volume at /workspace/configmap.
13.4.1.6. options

You can use the options field to change Knative Service properties for the deployed function, such as autoscaling. If you do not set these options, the system uses default values.

These options are available:

  • scale

    • min: The minimum number of replicas. Must be a non-negative integer. The default is 0.
    • max: The maximum number of replicas. Must be a non-negative integer. The default is 0, which means no limit.
    • metric: Defines which metric type is watched by the Autoscaler. It can be set to concurrency, which is the default, or rps.
    • target: Recommendation for when to scale up based on the number of concurrently incoming requests. The target option can be a float value greater than 0.01. The default is 100, unless the options.resources.limits.concurrency is set, in which case target defaults to its value.
    • utilization: Percentage of concurrent requests usage allowed before scaling up. It can be a float value between 1 and 100. The default is 70.
  • resources

    • requests

      • cpu: A CPU resource request for the container with deployed function.
      • memory: A memory resource request for the container with deployed function.
    • limits

      • cpu: A CPU resource limit for the container with deployed function.
      • memory: A memory resource limit for the container with deployed function.
      • concurrency: Hard Limit of concurrent requests to be processed by a single replica. It can be integer value greater than or equal to 0, default is 0 - meaning no limit.

This is an example configuration of the scale options:

name: test
namespace: ""
runtime: go
...
options:
  scale:
    min: 0
    max: 10
    metric: concurrency
    target: 75
    utilization: 75
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
    limits:
      cpu: 1000m
      memory: 256Mi
      concurrency: 100
13.4.1.7. image

The image field sets the image name for your function after it has been built. You can change this field. If you do, the next time you run kn func build or kn func deploy, the function image will be created with the new name.

13.4.1.8. imageDigest

The imageDigest field contains the SHA256 hash of the image manifest when the function is deployed. Do not change this value.

13.4.1.9. labels

The labels field enables you to set labels on a deployed function.

You can set a label directly from a value. In the following example, the label with the role key is directly assigned the value of backend:

labels:
- key: role
  value: backend

You can also set a label from a local environment variable. In the following example, the label with the author key is assigned the value of the USER local environment variable:

labels:
- key: author
  value: '{{ env:USER }}'
13.4.1.10. name

The name field defines the name of your function. This value is used as the name of your Knative service when it is deployed. You can change this field to rename the function on next deployments.

13.4.1.11. namespace

The namespace field specifies the namespace in which your function is deployed.

13.4.1.12. runtime

The runtime field specifies the language runtime for your function, for example, python.

Legal Notice

Copyright © Red Hat.
Except as otherwise noted below, the text of and illustrations in this documentation are licensed by Red Hat under the Creative Commons Attribution–Share Alike 3.0 Unported license . If you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, the Red Hat logo, JBoss, Hibernate, and RHCE are trademarks or registered trademarks of Red Hat, LLC. or its subsidiaries in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
XFS is a trademark or registered trademark of Hewlett Packard Enterprise Development LP or its subsidiaries in the United States and other countries.
The OpenStack® Word Mark and OpenStack logo are trademarks or registered trademarks of the Linux Foundation, used under license.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top