├── .gitignore ├── fdks ├── fdk-java │ ├── examples │ │ ├── qr-code │ │ │ ├── .gitignore │ │ │ ├── src │ │ │ │ ├── test │ │ │ │ │ ├── resources │ │ │ │ │ │ ├── qr-code-text-hello-world.jpg │ │ │ │ │ │ ├── qr-code-text-hello-world.png │ │ │ │ │ │ └── qr-code-number-0-12345-67890.png │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── fn │ │ │ │ │ │ └── QRGenTest.java │ │ │ │ └── main │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ └── QRGen.java │ │ │ ├── func.yaml │ │ │ ├── example.html │ │ │ ├── pom.xml │ │ │ └── README.md │ │ ├── async-thumbnails │ │ │ ├── .gitignore │ │ │ ├── test-image.png │ │ │ ├── setup │ │ │ │ ├── resize128 │ │ │ │ │ ├── func.yaml │ │ │ │ │ └── Dockerfile │ │ │ │ ├── resize256 │ │ │ │ │ ├── func.yaml │ │ │ │ │ └── Dockerfile │ │ │ │ ├── resize512 │ │ │ │ │ ├── func.yaml │ │ │ │ │ └── Dockerfile │ │ │ │ └── setup.sh │ │ │ ├── func.yaml │ │ │ ├── run.sh │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── fn │ │ │ │ │ │ └── ThumbnailsFunction.java │ │ │ │ └── test │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ └── ThumbnailsFunctionTest.java │ │ │ └── pom.xml │ │ ├── gradle-build │ │ │ ├── .dockerignore │ │ │ ├── func.yaml │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── fn │ │ │ │ │ │ └── HelloFunction.java │ │ │ │ └── test │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ └── HelloFunctionTest.java │ │ │ ├── Dockerfile │ │ │ ├── build.gradle │ │ │ └── README.md │ │ ├── configuration-variables │ │ │ ├── .settings │ │ │ │ ├── org.eclipse.m2e.core.prefs │ │ │ │ ├── org.eclipse.core.resources.prefs │ │ │ │ └── org.eclipse.jdt.core.prefs │ │ │ ├── func.yaml │ │ │ ├── .project │ │ │ ├── .classpath │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── fn │ │ │ │ │ │ └── Connection.java │ │ │ │ └── test │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ └── testing │ │ │ │ │ └── ConnectionTest.java │ │ │ ├── pom.xml │ │ │ └── README.md │ │ ├── string-reverse │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ └── java │ │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── fn │ │ │ │ │ │ └── StringReverse.java │ │ │ │ └── test │ │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ └── testing │ │ │ │ │ └── StringReverseTest.java │ │ │ ├── func.yaml │ │ │ ├── README.md │ │ │ └── pom.xml │ │ └── regex-query │ │ │ ├── func.yaml │ │ │ ├── src │ │ │ ├── main │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── fn │ │ │ │ │ ├── Query.java │ │ │ │ │ ├── Match.java │ │ │ │ │ ├── Response.java │ │ │ │ │ └── RegexQuery.java │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── fn │ │ │ │ └── RegexQueryTests.java │ │ │ ├── pom.xml │ │ │ └── README.md │ ├── SpringCloudFunctionSupport.md │ └── HTTPGatewayFunctions.md ├── README.md ├── fdk-python │ └── README.md ├── fdk-go │ └── README.md ├── fdk-ruby │ └── README.md └── fdk-node │ └── README.md ├── fn ├── assets │ ├── architecture.png │ ├── GrafanaDashboard.png │ ├── GrafanaDashboard2.png │ └── GrafanaDashboard3.png ├── general │ ├── images │ │ ├── fn-fdks.png │ │ ├── fn-architecture.png │ │ ├── fn-deploy-details.png │ │ └── fn-mono-to-funcs.png │ └── contributing.md ├── troubleshoot │ ├── images │ │ └── userinput.png │ ├── common │ │ ├── cannot-create-app.md │ │ └── cannot-deploy-app.md │ ├── README.md │ ├── debug-headers.md │ ├── known-issues │ │ └── 2019-08-fn-invoke-fails.md │ └── debug-loglevel.md ├── develop │ ├── clients.md │ ├── ce-example.json │ ├── triggers.md │ ├── README.md │ ├── cloudevents.md │ ├── packaging.md │ ├── podman.md │ ├── pagination.md │ ├── apps.md │ ├── fdks.md │ ├── func-file.md │ ├── extensions.md │ ├── configs.md │ └── annotations.md ├── operate │ ├── ui.md │ ├── databases │ │ ├── boltdb.md │ │ ├── mysql.md │ │ ├── postgres.md │ │ └── README.md │ ├── windows.md │ ├── selinux.md │ ├── docker.md │ ├── message-queues.md │ ├── metrics.md │ ├── README.md │ ├── extending.md │ ├── local-testing.md │ ├── logging.md │ ├── production.md │ ├── context-commands.md │ ├── variable-commands.md │ ├── private_registries.md │ └── options.md └── README.md ├── cli ├── ref │ ├── fn-help.md │ ├── fn-stop.md │ ├── fn-update-server.md │ ├── fn-version.md │ ├── fn-list-contexts.md │ ├── fn-update-context.md │ ├── fn-update-trigger.md │ ├── fn-list-apps.md │ ├── fn-create-context.md │ ├── fn-update-app.md │ ├── fn-list-triggers.md │ ├── fn-create-trigger.md │ ├── fn-migrate.md │ ├── fn-bump.md │ ├── fn-build.md │ ├── fn-use.md │ ├── fn-get.md │ ├── fn-push.md │ ├── fn-start.md │ ├── fn-invoke.md │ ├── fn-unset.md │ ├── fn-config.md │ ├── fn-create-app.md │ ├── fn-update-function.md │ ├── fn-get-config.md │ ├── fn-create-function.md │ ├── fn-list-config.md │ ├── fn-create.md │ ├── fn-update.md │ ├── fn-delete.md │ ├── fn-list.md │ ├── fn-inspect.md │ ├── README.md │ ├── fn-deploy.md │ └── fn-init.md ├── how-to │ ├── README.md │ ├── manage-server.md │ ├── create-run-fn.md │ └── create-init-image.md ├── script │ ├── fn-command-list.txt │ └── FnCliGen.rb └── README.md ├── examples └── README.md ├── community ├── README.md └── CODE_OF_CONDUCT.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .idea -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/.gitignore: -------------------------------------------------------------------------------- 1 | /data/ 2 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/.gitignore: -------------------------------------------------------------------------------- 1 | storage-upload 2 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/.dockerignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | .git 4 | build -------------------------------------------------------------------------------- /fn/assets/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/assets/architecture.png -------------------------------------------------------------------------------- /fn/general/images/fn-fdks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/general/images/fn-fdks.png -------------------------------------------------------------------------------- /fn/assets/GrafanaDashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/assets/GrafanaDashboard.png -------------------------------------------------------------------------------- /fn/assets/GrafanaDashboard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/assets/GrafanaDashboard2.png -------------------------------------------------------------------------------- /fn/assets/GrafanaDashboard3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/assets/GrafanaDashboard3.png -------------------------------------------------------------------------------- /fn/troubleshoot/images/userinput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/troubleshoot/images/userinput.png -------------------------------------------------------------------------------- /fn/general/images/fn-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/general/images/fn-architecture.png -------------------------------------------------------------------------------- /fn/general/images/fn-deploy-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/general/images/fn-deploy-details.png -------------------------------------------------------------------------------- /fn/general/images/fn-mono-to-funcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fn/general/images/fn-mono-to-funcs.png -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: gradle_build 3 | version: 0.0.41 4 | runtime: docker 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/test-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fdks/fdk-java/examples/async-thumbnails/test-image.png -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize128/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: resize128 3 | version: 0.0.8 4 | entrypoint: convert - -resize 128x128 - 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize256/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: resize256 3 | version: 0.0.8 4 | entrypoint: convert - -resize 256x256 - 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize512/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: resize512 3 | version: 0.0.11 4 | entrypoint: convert - -resize 512x512 - 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /fn/develop/clients.md: -------------------------------------------------------------------------------- 1 | # Client Libraries for the API 2 | 3 | * [Go](https://github.com/fnproject/fn_go) 4 | 5 | If we're missing your language, please create an issue and we'll try to get it made. -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize128/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian 2 | RUN apt-get update 3 | RUN apt-get install -y imagemagick 4 | ENTRYPOINT ["convert", "-", "-resize", "128x128", "-"] 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize256/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian 2 | RUN apt-get update 3 | RUN apt-get install -y imagemagick 4 | ENTRYPOINT ["convert", "-", "-resize", "256x256", "-"] 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/resize512/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian 2 | RUN apt-get update 3 | RUN apt-get install -y imagemagick 4 | ENTRYPOINT ["convert", "-", "-resize", "512x512", "-"] 5 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-text-hello-world.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-text-hello-world.jpg -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-text-hello-world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-text-hello-world.png -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-number-0-12345-67890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fnproject/docs/HEAD/fdks/fdk-java/examples/qr-code/src/test/resources/qr-code-number-0-12345-67890.png -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /cli/ref/fn-help.md: -------------------------------------------------------------------------------- 1 | # `fn help` 2 | 3 | ```c 4 | $ fn help 5 | 6 | 7 | - Shows a list of commands or help for one command 8 | 9 | USAGE 10 | fn [global options] [command] 11 | ``` 12 | 13 | [Some link](#) 14 | 15 | -------------------------------------------------------------------------------- /cli/how-to/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo CLI How-to 2 | 3 | [Manage Fn Servers](manage-server.md) 4 | [Create and Run Functions](create-run-fn.md) 5 | 6 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo Example 2 | Here are examples that show how to implement and use Fn. 3 | 4 | ### [FDK-Java Examples](../fdks/fdk-java/README.md) 5 | -------------------------------------------------------------------------------- /fn/operate/ui.md: -------------------------------------------------------------------------------- 1 | # User Interface for Fn 2 | 3 | ### Run Functions UI 4 | 5 | ```sh 6 | docker run --rm -it --link functions:api -p 4000:4000 -e "FN_API_URL=http://api:8080" fnproject/ui 7 | ``` 8 | 9 | For more information, see: https://github.com/fnproject/ui -------------------------------------------------------------------------------- /fdks/fdk-java/examples/string-reverse/src/main/java/com/example/fn/StringReverse.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | public class StringReverse { 4 | public String reverse(String str) { 5 | return new StringBuilder(str).reverse().toString(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /fn/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo Documentation by Area 2 | 3 | * [Introduction to Fn](general/introduction.md) 4 | * [For Developers](develop/README.md) 5 | * [For Operators](operate/README.md) 6 | -------------------------------------------------------------------------------- /cli/ref/fn-stop.md: -------------------------------------------------------------------------------- 1 | # `fn stop` 2 | 3 | ```c 4 | $ fn stop 5 | 6 | SERVER COMMANDS 7 | fn stop - Stop a function server 8 | 9 | USAGE 10 | fn [global options] stop 11 | 12 | DESCRIPTION 13 | This command stops a Fn server. 14 | ``` 15 | 16 | [Some link](#) 17 | 18 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: qr 3 | version: 0.0.17 4 | runtime: java 5 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.98 6 | run_image: fnproject/fn-java-fdk:jre11-1.0.98 7 | cmd: com.example.fn.QRGen::create 8 | triggers: 9 | - name: qr 10 | type: http 11 | source: /qr 12 | -------------------------------------------------------------------------------- /fn/operate/databases/boltdb.md: -------------------------------------------------------------------------------- 1 | # Fn using SQLite3 2 | 3 | SQLite3 is the default database, you just need to run the API. 4 | 5 | ## Persistent 6 | 7 | To keep it persistent, add a volume flag to the command: 8 | 9 | ```sh 10 | docker run --rm -it --privileged -v $PWD/fn.db:/app/fn.db -p 8080:8080 fnproject/fnserver 11 | ``` 12 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: connection 3 | version: 0.0.14 4 | runtime: java 5 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.99 6 | run_image: fnproject/fn-java-fdk:jre11-1.0.99 7 | cmd: com.example.fn.Connection::getConnection 8 | config: 9 | DB_DRIVER: mysqlDriver 10 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/src/main/java/com/example/fn/HelloFunction.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | public class HelloFunction { 4 | 5 | public String handleRequest(String input) { 6 | String name = (input == null || input.isEmpty()) ? "world" : input; 7 | return "Hello, " + name + "!"; 8 | } 9 | 10 | } -------------------------------------------------------------------------------- /cli/ref/fn-update-server.md: -------------------------------------------------------------------------------- 1 | # `fn update server` 2 | 3 | ```c 4 | $ fn update server 5 | 6 | MANAGEMENT COMMAND 7 | fn update server - Pulls latest functions server 8 | 9 | USAGE 10 | fn [global options] update server 11 | 12 | DESCRIPTION 13 | This command updates the latest Fn server 14 | ``` 15 | 16 | [Some link](#) 17 | 18 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: query 3 | version: 0.0.4 4 | runtime: java 5 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.96 6 | run_image: fnproject/fn-java-fdk:jre11-1.0.96 7 | cmd: com.example.fn.RegexQuery::query 8 | triggers: 9 | - name: query 10 | type: http 11 | source: /query 12 | -------------------------------------------------------------------------------- /fn/operate/windows.md: -------------------------------------------------------------------------------- 1 | # Running on Windows 2 | 3 | Windows doesn't support Docker in Docker so you'll change the run command to the following: 4 | 5 | ```sh 6 | docker run --privileged --rm --name functions -it -v /var/run/docker.sock:/var/run/docker.sock -v ${pwd}/data:/app/data -p 8080:8080 fnproject/fnserver 7 | ``` 8 | 9 | Then everything should work as normal. 10 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/string-reverse/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: string-reverse 3 | version: 0.0.2 4 | runtime: java 5 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.87 6 | run_image: fnproject/fn-java-fdk:jre11-1.0.87 7 | cmd: com.example.fn.StringReverse::reverse 8 | triggers: 9 | - name: string-reverse 10 | type: http 11 | source: /string-reverse 12 | -------------------------------------------------------------------------------- /cli/ref/fn-version.md: -------------------------------------------------------------------------------- 1 | # `fn version` 2 | 3 | ```c 4 | $ fn version 5 | 6 | 7 | fn version - Display Fn CLI and Fn Server versions 8 | 9 | USAGE 10 | fn [global options] version 11 | 12 | DESCRIPTION 13 | This command shows the version of the Fn CLI being used and the version of the Fn Server referenced by the current context, if available. 14 | ``` 15 | 16 | [Some link](#) 17 | 18 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/func.yaml: -------------------------------------------------------------------------------- 1 | schema_version: 20180708 2 | name: async-thumbnails 3 | version: 0.0.6 4 | runtime: java 5 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.98 6 | run_image: fnproject/fn-java-fdk:jre11-1.0.98 7 | cmd: com.example.fn.ThumbnailsFunction::handleRequest 8 | timeout: 120 9 | triggers: 10 | - name: async-thumbnails 11 | type: http 12 | source: /async-thumbnails 13 | -------------------------------------------------------------------------------- /fdks/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo FDK Documentation 2 | 3 | FDKs are language kits designed to help make working with Fn easier in each language. 4 | 5 | Select one of the FDK folders above to view documentation on that specific FDK. 6 | 7 | For general information on our FDK's, go here: https://github.com/fnproject/docs/blob/master/fn/develop/fdks.md -------------------------------------------------------------------------------- /cli/ref/fn-list-contexts.md: -------------------------------------------------------------------------------- 1 | # `fn list contexts` 2 | 3 | ```c 4 | $ fn list contexts 5 | 6 | MANAGEMENT COMMAND 7 | fn list contexts - List contexts 8 | 9 | USAGE 10 | fn [global options] list contexts [command options] 11 | 12 | DESCRIPTION 13 | This command returns a list of contexts. 14 | 15 | COMMAND OPTIONS 16 | --output value Output format (json) 17 | 18 | ``` 19 | 20 | [Some link](#) 21 | 22 | -------------------------------------------------------------------------------- /cli/ref/fn-update-context.md: -------------------------------------------------------------------------------- 1 | # `fn update context` 2 | 3 | ```c 4 | $ fn update context 5 | 6 | MANAGEMENT COMMAND 7 | fn update context - Update context files 8 | 9 | USAGE 10 | fn [global options] update context [command options] [value] 11 | 12 | DESCRIPTION 13 | This command updates the current context file. 14 | 15 | COMMAND OPTIONS 16 | --delete Delete key=value pair from context file. 17 | 18 | ``` 19 | 20 | [Some link](#) 21 | 22 | -------------------------------------------------------------------------------- /cli/ref/fn-update-trigger.md: -------------------------------------------------------------------------------- 1 | # `fn update trigger` 2 | 3 | ```c 4 | $ fn update trigger 5 | 6 | MANAGEMENT COMMAND 7 | fn update trigger - Update a trigger 8 | 9 | USAGE 10 | fn [global options] update trigger [command options] 11 | 12 | DESCRIPTION 13 | This command updates a created trigger. 14 | 15 | COMMAND OPTIONS 16 | --annotation value trigger annotations 17 | 18 | ``` 19 | 20 | [Some link](#) 21 | 22 | -------------------------------------------------------------------------------- /fn/develop/ce-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "cloudEventsVersion": "0.1", 3 | "eventID": "6480da1a-5028-4301-acc3-fbae628207b3", 4 | "source": "http://example.com/repomanager", 5 | "eventType": "com.example.repro.create", 6 | "eventTypeVersion": "v1.5", 7 | "eventTime": "2018-04-01T23:12:34Z", 8 | "schemaURL": "https://product.example.com/schema/repo-create", 9 | "contentType": "application/json", 10 | "data": { 11 | "name": "travis" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | fn --verbose deploy --app myapp --local 5 | 6 | 7 | echo "Calling function" 8 | curl -v -X POST --data-binary @test-image.png -H "Content-type: application/octet-stream" "http://localhost:8080/t/myapp/async-thumbnails" 9 | 10 | echo "Contents of bucket" 11 | mc ls -r example-storage-server 12 | echo "Sleeping for 5 seconds to allow flows to complete" 13 | sleep 5 14 | echo "Contents of bucket" 15 | mc ls -r example-storage-server 16 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 3 | org.eclipse.jdt.core.compiler.compliance=11 4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 7 | org.eclipse.jdt.core.compiler.release=disabled 8 | org.eclipse.jdt.core.compiler.source=11 9 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/src/main/java/com/example/fn/Query.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Query { 7 | public final String regex; 8 | public final String text; 9 | 10 | @JsonCreator 11 | public Query(@JsonProperty("regex") String regex, @JsonProperty("text") String text) { 12 | this.regex = regex; 13 | this.text = text; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fn/general/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing Documentation 2 | 3 | When creating a Pull Request, make sure that you also update the documentation 4 | accordingly. 5 | 6 | Most of the time, when making some behavior more explicit or adding a feature, 7 | documentation update is necessary. 8 | 9 | You will either update a file inside docs/ or create one. Prefer the former over 10 | the latter. If you are unsure, do not hesitate to open a PR with a comment 11 | asking for suggestions on how to address the documentation part. 12 | -------------------------------------------------------------------------------- /cli/ref/fn-list-apps.md: -------------------------------------------------------------------------------- 1 | # `fn list apps` 2 | 3 | ```c 4 | $ fn list apps 5 | 6 | MANAGEMENT COMMAND 7 | fn list apps - List all created applications 8 | 9 | USAGE 10 | fn [global options] list apps [command options] 11 | 12 | DESCRIPTION 13 | This command provides a list of defined applications. 14 | 15 | COMMAND OPTIONS 16 | --cursor value Pagination cursor 17 | -n value Number of apps to return (default: 100) 18 | --output value Output format (json) 19 | 20 | ``` 21 | 22 | [Some link](#) 23 | 24 | -------------------------------------------------------------------------------- /cli/ref/fn-create-context.md: -------------------------------------------------------------------------------- 1 | # `fn create context` 2 | 3 | ```c 4 | $ fn create context 5 | 6 | MANAGEMENT COMMAND 7 | fn create context - Create a new context 8 | 9 | USAGE 10 | fn [global options] create context [command options] 11 | 12 | DESCRIPTION 13 | This command creates a new context for a created application. 14 | 15 | COMMAND OPTIONS 16 | --provider value Context provider 17 | --api-url value Context api url 18 | --registry value Context registry 19 | 20 | ``` 21 | 22 | [Some link](#) 23 | 24 | -------------------------------------------------------------------------------- /cli/ref/fn-update-app.md: -------------------------------------------------------------------------------- 1 | # `fn update app` 2 | 3 | ```c 4 | $ fn update app 5 | 6 | MANAGEMENT COMMAND 7 | fn update app - Update an application 8 | 9 | USAGE 10 | fn [global options] update app [command options] 11 | 12 | DESCRIPTION 13 | This command updates a created application. 14 | 15 | COMMAND OPTIONS 16 | --config value, -c value Application configuration 17 | --annotation value Application annotations 18 | --syslog-url value Syslog URL to send application logs to 19 | 20 | ``` 21 | 22 | [Some link](#) 23 | 24 | -------------------------------------------------------------------------------- /cli/ref/fn-list-triggers.md: -------------------------------------------------------------------------------- 1 | # `fn list triggers` 2 | 3 | ```c 4 | $ fn list triggers 5 | 6 | MANAGEMENT COMMAND 7 | fn list triggers - List all triggers 8 | 9 | USAGE 10 | fn [global options] list triggers [command options] [function-name] 11 | 12 | DESCRIPTION 13 | This command returns a list of all created triggers for an 'app' or for a specific 'function' of an application. 14 | 15 | COMMAND OPTIONS 16 | --cursor value pagination cursor 17 | -n value number of triggers to return (default: 100) 18 | 19 | ``` 20 | 21 | [Some link](#) 22 | 23 | -------------------------------------------------------------------------------- /fn/develop/triggers.md: -------------------------------------------------------------------------------- 1 | # Trigger 2 | 3 | A Trigger represents an entry point for function invocations. Each type of Trigger requires specific configuration. They should be defined within the func.yaml file, as specified in [function file rules](func-file.md). 4 | 5 | ## Types 6 | 7 | ### http 8 | 9 | Configures a http endpoint for function invocation. 10 | 11 | ``` 12 | name: triggerOne 13 | type: http 14 | source: /trigger-path 15 | ``` 16 | 17 | This will cause the system to route requests arriving at the fn service at `/trigger-path` to the function specified in the func.yaml file. 18 | -------------------------------------------------------------------------------- /cli/ref/fn-create-trigger.md: -------------------------------------------------------------------------------- 1 | # `fn create trigger` 2 | 3 | ```c 4 | $ fn create trigger 5 | 6 | MANAGEMENT COMMAND 7 | fn create trigger - Create a new trigger 8 | 9 | USAGE 10 | fn [global options] create trigger [command options] 11 | 12 | DESCRIPTION 13 | This command creates a new trigger. 14 | 15 | COMMAND OPTIONS 16 | --source value, -s value trigger source 17 | --type value, -t value Todo 18 | --annotation value fn annotation (can be specified multiple times) 19 | 20 | ``` 21 | 22 | [Some link](#) 23 | 24 | -------------------------------------------------------------------------------- /cli/script/fn-command-list.txt: -------------------------------------------------------------------------------- 1 | fn build 2 | fn bump 3 | fn config 4 | fn create 5 | fn create app 6 | fn create context 7 | fn create function 8 | fn create trigger 9 | fn delete 10 | fn deploy 11 | fn get 12 | fn get config 13 | fn help 14 | fn init 15 | fn inspect 16 | fn invoke 17 | fn list 18 | fn list apps 19 | fn list config 20 | fn list contexts 21 | fn list triggers 22 | fn migrate 23 | fn push 24 | fn start 25 | fn stop 26 | fn unset 27 | fn update 28 | fn update app 29 | fn update context 30 | fn update function 31 | fn update server 32 | fn update trigger 33 | fn use 34 | fn version 35 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/src/main/java/com/example/fn/Match.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Match { 7 | public final int start; 8 | public final int end; 9 | public final String match; 10 | 11 | @JsonCreator 12 | public Match(@JsonProperty("start") int start, @JsonProperty("end") int end, @JsonProperty("match") String match) { 13 | this.start = start; 14 | this.end = end; 15 | this.match = match; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cli/ref/fn-migrate.md: -------------------------------------------------------------------------------- 1 | # `fn migrate` 2 | 3 | ```c 4 | $ fn migrate 5 | 6 | DEVELOPMENT COMMANDS 7 | fn migrate - Migrate a local func.yaml file to the latest version 8 | 9 | USAGE 10 | fn [global options] migrate 11 | 12 | DESCRIPTION 13 | This command will detect the version of a func.yaml file and update it to match the latest version supported by the Fn CLI. 14 | Any old or unsupported attributes will be removed, and any new ones may be added. 15 | The current func.yaml will be renamed to func.yaml.bak and a new func.yaml created. 16 | ``` 17 | 18 | [Some link](#) 19 | 20 | -------------------------------------------------------------------------------- /cli/ref/fn-bump.md: -------------------------------------------------------------------------------- 1 | # `fn bump` 2 | 3 | ```c 4 | $ fn bump 5 | 6 | DEVELOPMENT COMMANDS 7 | fn bump - Bump function version 8 | 9 | USAGE 10 | fn [global options] bump [command options] 11 | 12 | DESCRIPTION 13 | This command bumps the version of the func.yaml. 14 | 15 | COMMAND OPTIONS 16 | --major bumps major version 17 | --minor bumps minor version 18 | --verbose, -v verbose mode 19 | --working-dir value, -w value Specify the working directory to bump a function, must be the full path. 20 | 21 | ``` 22 | 23 | [Some link](#) 24 | 25 | -------------------------------------------------------------------------------- /cli/ref/fn-build.md: -------------------------------------------------------------------------------- 1 | # `fn build` 2 | 3 | ```c 4 | $ fn build 5 | 6 | DEVELOPMENT COMMANDS 7 | fn build - Build function version 8 | 9 | USAGE 10 | fn [global options] build [command options] [function-subdirectory] 11 | 12 | DESCRIPTION 13 | This command builds a new function. 14 | 15 | COMMAND OPTIONS 16 | --verbose, -v Verbose mode 17 | --no-cache Don't use docker cache 18 | --build-arg value Set build-time variables 19 | --working-dir value, -w value Specify the working directory to build a function, must be the full path. 20 | 21 | ``` 22 | 23 | [Some link](#) 24 | 25 | -------------------------------------------------------------------------------- /fn/troubleshoot/common/cannot-create-app.md: -------------------------------------------------------------------------------- 1 | # Cannot create application with Fn client 2 | 3 | ### Error Messages 4 | `fn create app app-name` fails with error message. 5 | 6 | * "Fn: Post http://localhost:8080/v2/apps: dial tcp [::1]:8080: connect: connection refused" 7 | 8 | ### Problem 9 | The most common causes of this error message is: 10 | 11 | * The fn server has not been started. 12 | * Another service is using port 8080. 13 | 14 | ### Solution 15 | To solve this problem: 16 | 17 | * Start Fn server 18 | * If Fn server does not start 19 | * Run `netstat -a` to see if there is a server on port 8080. 20 | * Stop the other server. 21 | * Start Fn server. 22 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/src/main/java/com/example/fn/Response.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | import java.util.List; 7 | 8 | public class Response { 9 | public final String regex; 10 | public final String text; 11 | public final List matches; 12 | 13 | @JsonCreator 14 | public Response(@JsonProperty("regex") String regex, @JsonProperty("text") String text, @JsonProperty("matches") List matches) { 15 | this.regex = regex; 16 | this.text = text; 17 | this.matches = matches; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cli/ref/fn-use.md: -------------------------------------------------------------------------------- 1 | # `fn use` 2 | 3 | ```c 4 | $ fn use 5 | 6 | MANAGEMENT COMMAND 7 | fn use - Select context for further commands 8 | 9 | USAGE 10 | fn [global options] use [command options] 11 | 12 | DESCRIPTION 13 | This command uses a selected object ('context') for further invocations. 14 | 15 | SUBCOMMANDS 16 | context, ctx Use context for future invocations 17 | help, h Shows a list of commands or help for one command 18 | 19 | COMMAND OPTIONS 20 | --help, -h show help 21 | 22 | FURTHER HELP: See 'fn use --help' for more information about a command. 23 | ``` 24 | 25 | [Some link](#) 26 | 27 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | configuration-variable 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /fn/troubleshoot/common/cannot-deploy-app.md: -------------------------------------------------------------------------------- 1 | # Cannot Deploy a Function with Fn client 2 | 3 | ### Error Messages 4 | `fn --verbose deploy --app app-name --local` fails with error message. 5 | 6 | * "Fn: Get http://localhost:8080/v2/apps?name=nodeapp: dial tcp [::1]:8080: connect: connection refused" 7 | 8 | ### Problem 9 | The most common causes of this error message is: 10 | 11 | * The Fn server has not been started. 12 | * Another service is using port 8080. 13 | 14 | ### Solution 15 | To solve this problem: 16 | 17 | * Start Fn server 18 | * If Fn server does not start 19 | * Run `netstat -a` to see if there is a server on port 8080. 20 | * Stop the other server. 21 | * Start Fn server. 22 | -------------------------------------------------------------------------------- /fn/operate/databases/mysql.md: -------------------------------------------------------------------------------- 1 | # Fn using MySQL DB 2 | 3 | Let's presuppose you don't have even a MySQL DB ready. 4 | 5 | ### 1. Let's start a MySQL instance: 6 | 7 | ``` 8 | docker run --name func-mysql \ 9 | -e MYSQL_DATABASE=funcs -e MYSQL_USER=func -e MYSQL_PASSWORD=funcpass -e MYSQL_RANDOM_ROOT_PASSWORD=yes -d mysql 10 | ``` 11 | 12 | For more configuration options, see [docker mysql docs](https://hub.docker.com/_/mysql/). 13 | 14 | ### 2. Now let's start Functions connecting to our new mysql instance 15 | 16 | ``` 17 | docker run --rm --privileged --link "func-mysql:mysql" \ 18 | -e "FN_DB_URL=mysql://func:funcpass@tcp(mysql:3306)/funcs" \ 19 | -it -p 8080:8080 fnproject/fnserver 20 | ``` 21 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Response from Default URL

4 | 5 | 6 |

Hello

7 | 8 | 9 |

Make a Call to 01234-567890

10 | 11 | 12 |

Open https://www.google.com URL

13 | 14 | 15 |

Create a Text Message from a QR Code

16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /cli/ref/fn-get.md: -------------------------------------------------------------------------------- 1 | # `fn get` 2 | 3 | ```c 4 | $ fn get 5 | 6 | 7 | fn get - Get an object to retrieve its information 8 | 9 | USAGE 10 | fn [global options] get [command options] 11 | 12 | DESCRIPTION 13 | This command gets a 'call', 'configuration' or 'log' to retrieve information for an object ('app' or 'function'). 14 | 15 | SUBCOMMANDS 16 | config, config, cf Get configurations for apps and functions 17 | help, h Shows a list of commands or help for one command 18 | 19 | COMMAND OPTIONS 20 | --help, -h show help 21 | 22 | FURTHER HELP: See 'fn get --help' for more information about a command. 23 | ``` 24 | 25 | [Some link](#) 26 | 27 | -------------------------------------------------------------------------------- /fn/operate/selinux.md: -------------------------------------------------------------------------------- 1 | # Running on SELinux systems 2 | 3 | Systems such as Oracle Linux 7 where SELinux is enabled and the security policies are set to "Enforcing" will restrict Fn from 4 | running containers and mounting volumes. 5 | 6 | For local development, you can relax SELinux constraints by running this command in a root shell: 7 | 8 | ```sh 9 | setenforce permissive 10 | ``` 11 | 12 | Then you will be able to run `fn start` as normal. 13 | 14 | Alternatively, use the docker-in-docker deployment that a production system would use: 15 | 16 | ```sh 17 | docker run --privileged --rm --name fns -it -v $PWD/data:/app/data -p 8080:8080 fnproject/fnserver 18 | ``` 19 | 20 | Check the [operating options](options.md) for further details about this. 21 | -------------------------------------------------------------------------------- /cli/ref/fn-push.md: -------------------------------------------------------------------------------- 1 | # `fn push` 2 | 3 | ```c 4 | $ fn push 5 | 6 | DEVELOPMENT COMMANDS 7 | fn push - Push function to docker registry 8 | 9 | USAGE 10 | fn [global options] push [command options] 11 | 12 | DESCRIPTION 13 | This command pushes the created image to the Docker registry. 14 | 15 | COMMAND OPTIONS 16 | --verbose, -v Verbose mode 17 | --registry --registry username Set the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. 18 | eg: --registry username will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner. 19 | 20 | ``` 21 | 22 | [Some link](#) 23 | 24 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gradle:5.6.2-jdk11 as build-stage 2 | 3 | WORKDIR /function 4 | # needed for gradle? 5 | USER root 6 | ENV GRADLE_USER_HOME /function/.gradle 7 | 8 | # Code build 9 | # Copy any build files into the build container and build 10 | COPY *.gradle /function/ 11 | RUN ["gradle", "-s", "--no-daemon","--console","plain","cacheDeps"] 12 | 13 | # Copies build source into build container 14 | COPY src /function/src 15 | 16 | RUN ["gradle", "-s", "--no-daemon","--console","plain","build"] 17 | # Container build 18 | FROM fnproject/fn-java-fdk:jre11-1.0.98 19 | WORKDIR /function 20 | COPY --from=build-stage /function/build/libs/*.jar /function/build/deps/*.jar /function/app/ 21 | CMD ["com.example.fn.HelloFunction::handleRequest"] 22 | -------------------------------------------------------------------------------- /cli/ref/fn-start.md: -------------------------------------------------------------------------------- 1 | # `fn start` 2 | 3 | ```c 4 | $ fn start 5 | 6 | SERVER COMMANDS 7 | fn start - Start a local Fn server 8 | 9 | USAGE 10 | fn [global options] start [command options] 11 | 12 | DESCRIPTION 13 | This command starts a local Fn server by downloading its docker image. 14 | 15 | COMMAND OPTIONS 16 | --log-level value --log-level debug to enable debugging 17 | --detach, -d Run container in background. 18 | --env-file value Path to Fn server configuration file. 19 | --version value Specify a specific fnproject/fnserver version to run, ex: '1.2.3'. (default: "latest") 20 | --port value, -p value Specify port number to bind to on the host. (default: 8080) 21 | 22 | ``` 23 | 24 | [Some link](#) 25 | 26 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/src/test/java/com/example/fn/HelloFunctionTest.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | 8 | import com.fnproject.fn.testing.FnResult; 9 | import com.fnproject.fn.testing.FnTestingRule; 10 | 11 | 12 | 13 | public class HelloFunctionTest { 14 | 15 | @Rule 16 | public final FnTestingRule testing = FnTestingRule.createDefault(); 17 | 18 | @Test 19 | public void shouldReturnGreeting() { 20 | testing.givenEvent().enqueue(); 21 | testing.thenRun(HelloFunction.class, "handleRequest"); 22 | 23 | FnResult result = testing.getOnlyResult(); 24 | assertEquals("Hello, world!", result.getBodyAsString()); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /fn/operate/docker.md: -------------------------------------------------------------------------------- 1 | # Docker Configuration 2 | 3 | To get the best performance, you'll want to ensure that Docker is configured properly. These are the environments known to produce the best results: 4 | 5 | 1. Linux 4.7 or newer with aufs or overlay2 module. 6 | 2. Ubuntu 16.04 LTS or newer with aufs or overlay2 module. 7 | 3. Docker 17.10 or newer to be available. 8 | 9 | It is important to reconfigure host's Docker with this filesystem module. Thus, in your Docker start scripts you must do as following: 10 | 11 | ``` 12 | docker daemon [...] --storage-driver=overlay2 13 | ``` 14 | 15 | In case you are using Ubuntu, you can reconfigure Docker easily by updating `/etc/docker/daemon.json` and restarting Docker: 16 | 17 | ```json 18 | { 19 | "storage-driver": "overlay2" 20 | } 21 | ``` -------------------------------------------------------------------------------- /cli/ref/fn-invoke.md: -------------------------------------------------------------------------------- 1 | # `fn invoke` 2 | 3 | ```c 4 | $ fn invoke 5 | 6 | DEVELOPMENT COMMANDS 7 | fn invoke - Invoke a remote function 8 | 9 | USAGE 10 | fn [global options] invoke [command options] [app-name] [function-name] 11 | 12 | DESCRIPTION 13 | This command invokes a function. Users may send input to their function by passing input to this command via STDIN. 14 | 15 | COMMAND OPTIONS 16 | --endpoint value Specify the function invoke endpoint for this function, the app-name and func-name parameters will be ignored 17 | --content-type value The payload Content-Type for the function invocation. 18 | --display-call-id whether display call ID or not 19 | --output value Output format (json) 20 | 21 | ``` 22 | 23 | [Some link](#) 24 | 25 | -------------------------------------------------------------------------------- /cli/ref/fn-unset.md: -------------------------------------------------------------------------------- 1 | # `fn unset` 2 | 3 | ```c 4 | $ fn unset 5 | 6 | MANAGEMENT COMMAND 7 | fn unset - Unset elements of a created object 8 | 9 | USAGE 10 | fn [global options] unset [command options] 11 | 12 | DESCRIPTION 13 | This command unsets elements ('configurations') for a created object ('app', 'function' or 'context'). 14 | 15 | SUBCOMMANDS 16 | config, config, cf Unset configurations for apps and functions 17 | context, ctx Unset current-context 18 | help, h Shows a list of commands or help for one command 19 | 20 | COMMAND OPTIONS 21 | --help, -h show help 22 | 23 | FURTHER HELP: See 'fn unset --help' for more information about a command. 24 | ``` 25 | 26 | [Some link](#) 27 | 28 | -------------------------------------------------------------------------------- /cli/ref/fn-config.md: -------------------------------------------------------------------------------- 1 | # `fn config` 2 | 3 | ```c 4 | $ fn config 5 | 6 | MANAGEMENT COMMAND 7 | fn config - Set configuration for an object 8 | 9 | USAGE 10 | fn [global options] config [command options] 11 | 12 | DESCRIPTION 13 | This command sets a configuration key for an 'app' or 'function'. 14 | 15 | SUBCOMMANDS 16 | app, apps, a Store a configuration key for this application 17 | function, func, f, fn Store a configuration key for this function 18 | help, h Shows a list of commands or help for one command 19 | 20 | COMMAND OPTIONS 21 | --help, -h show help 22 | 23 | FURTHER HELP: See 'fn config --help' for more information about a command. 24 | ``` 25 | 26 | [Some link](#) 27 | 28 | -------------------------------------------------------------------------------- /cli/ref/fn-create-app.md: -------------------------------------------------------------------------------- 1 | # `fn create app` 2 | 3 | ```c 4 | $ fn create app 5 | 6 | MANAGEMENT COMMAND 7 | fn create app - Create a new application 8 | 9 | USAGE 10 | fn [global options] create app [command options] 11 | 12 | DESCRIPTION 13 | This command creates a new application. 14 | Fn supports grouping functions into a set that defines an application (or API), making it easy to organize and deploy. 15 | Applications define a namespace to organize functions and can contain configuration values that are shared across all functions in that application. 16 | 17 | COMMAND OPTIONS 18 | --config value Application configuration 19 | --annotation value Application annotations 20 | --syslog-url value Syslog URL to send application logs to 21 | 22 | ``` 23 | 24 | [Some link](#) 25 | 26 | -------------------------------------------------------------------------------- /cli/ref/fn-update-function.md: -------------------------------------------------------------------------------- 1 | # `fn update function` 2 | 3 | ```c 4 | $ fn update function 5 | 6 | MANAGEMENT COMMAND 7 | fn update function - Update a function in application 8 | 9 | USAGE 10 | fn [global options] update function [command options] 11 | 12 | DESCRIPTION 13 | This command updates a function in an application. 14 | 15 | COMMAND OPTIONS 16 | --memory value, -m value Memory in MiB (default: 0) 17 | --config value, -c value Function configuration 18 | --timeout value Function timeout (eg. 30) (default: 0) 19 | --idle-timeout value Function idle timeout (eg. 30) (default: 0) 20 | --annotation value Function annotation (can be specified multiple times) 21 | --image value Function image 22 | 23 | ``` 24 | 25 | [Some link](#) 26 | 27 | -------------------------------------------------------------------------------- /cli/ref/fn-get-config.md: -------------------------------------------------------------------------------- 1 | # `fn get config` 2 | 3 | ```c 4 | $ fn get config 5 | 6 | MANAGEMENT COMMAND 7 | fn get config - Get configurations for apps and functions 8 | 9 | USAGE 10 | fn [global options] get config [command options] 11 | 12 | DESCRIPTION 13 | This command unsets the configuration of created objects ('app' or 'function'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a Inspect configuration key for this application 17 | function, func, f, fn Inspect configuration key for this function 18 | help, h Shows a list of commands or help for one command 19 | 20 | COMMAND OPTIONS 21 | --help, -h show help 22 | 23 | FURTHER HELP: See 'fn get config --help' for more information about a command. 24 | ``` 25 | 26 | [Some link](#) 27 | 28 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/string-reverse/src/test/java/com/example/fn/testing/StringReverseTest.java: -------------------------------------------------------------------------------- 1 | package com.example.fn.testing; 2 | 3 | import com.example.fn.StringReverse; 4 | import org.junit.Test; 5 | 6 | import static junit.framework.TestCase.assertEquals; 7 | 8 | public class StringReverseTest { 9 | private StringReverse stringReverse = new StringReverse(); 10 | 11 | @Test 12 | public void reverseEmptyString() { 13 | assertEquals("", reverse("")); 14 | } 15 | 16 | @Test 17 | public void reverseOfSingleCharacter() { 18 | assertEquals("a", reverse("a")); 19 | } 20 | 21 | @Test 22 | public void reverseHelloIsOlleh() { 23 | assertEquals("olleh", reverse("hello")); 24 | } 25 | 26 | private String reverse(String str) { 27 | return stringReverse.reverse(str); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cli/ref/fn-create-function.md: -------------------------------------------------------------------------------- 1 | # `fn create function` 2 | 3 | ```c 4 | $ fn create function 5 | 6 | MANAGEMENT COMMAND 7 | fn create function - Create a function within an application 8 | 9 | USAGE 10 | fn [global options] create function [command options] 11 | 12 | DESCRIPTION 13 | This command creates a new function within an application. 14 | 15 | COMMAND OPTIONS 16 | --memory value, -m value Memory in MiB (default: 0) 17 | --config value, -c value Function configuration 18 | --timeout value Function timeout (eg. 30) (default: 0) 19 | --idle-timeout value Function idle timeout (eg. 30) (default: 0) 20 | --annotation value Function annotation (can be specified multiple times) 21 | --image value Function image 22 | 23 | ``` 24 | 25 | [Some link](#) 26 | 27 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/src/main/java/com/example/fn/RegexQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class RegexQuery { 9 | 10 | public Response query(Query query) { 11 | return new Response(query.regex, query.text, getMatches(query)); 12 | } 13 | 14 | private List getMatches(Query query) { 15 | Pattern pattern = Pattern.compile(query.regex); 16 | Matcher matcher = pattern.matcher(query.text); 17 | List matches = new ArrayList<>(); 18 | while (matcher.find()) { 19 | matches.add(new Match(matcher.start(), matcher.end(), query.text.substring(matcher.start(), matcher.end()))); 20 | } 21 | return matches; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cli/ref/fn-list-config.md: -------------------------------------------------------------------------------- 1 | # `fn list config` 2 | 3 | ```c 4 | $ fn list config 5 | 6 | MANAGEMENT COMMAND 7 | fn list config - List configurations for apps and functions 8 | 9 | USAGE 10 | fn [global options] list config [command options] 11 | 12 | DESCRIPTION 13 | This command unsets the configuration of created objects ('app' or 'function'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a List configuration key/value pairs for this application 17 | function, func, f, fn List configuration key/value pairs for this function 18 | help, h Shows a list of commands or help for one command 19 | 20 | COMMAND OPTIONS 21 | --help, -h show help 22 | 23 | FURTHER HELP: See 'fn list config --help' for more information about a command. 24 | ``` 25 | 26 | [Some link](#) 27 | 28 | -------------------------------------------------------------------------------- /fn/operate/message-queues.md: -------------------------------------------------------------------------------- 1 | # Message Queues 2 | 3 | A message queue is used to coordinate asynchronous function calls that run through Fn. 4 | 5 | We currently support the following message queues and they are passed in via the `FN_MQ_URL` environment variable. For example: 6 | 7 | ```sh 8 | docker run -e "FN_MQ_URL=redis://localhost:6379/" ... 9 | ``` 10 | 11 | ## [Bolt](https://github.com/boltdb/bolt) (default) 12 | 13 | URL: `bolt:///fn/data/functions-mq.db` 14 | 15 | See Bolt in databases above. The Bolt database is locked at the file level, so 16 | the file cannot be the same as the one used for the Bolt Datastore. 17 | 18 | ## [Redis](http://redis.io/) 19 | 20 | See Redis in databases above. 21 | 22 | ## What about message queue X? 23 | 24 | We're happy to add more and we love pull requests, so feel free to add one! Copy one of the implementations above as a starting point. -------------------------------------------------------------------------------- /cli/ref/fn-create.md: -------------------------------------------------------------------------------- 1 | # `fn create` 2 | 3 | ```c 4 | $ fn create 5 | 6 | MANAGEMENT COMMAND 7 | fn create - Create a new object 8 | 9 | USAGE 10 | fn [global options] create [command options] 11 | 12 | DESCRIPTION 13 | This command creates a new object ('app', 'context', 'function', or 'trigger'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a Create a new application 17 | context, ctx Create a new context 18 | function, func, f, fn Create a function within an application 19 | trigger, trig, t, tr Create a new trigger 20 | help, h Shows a list of commands or help for one command 21 | 22 | COMMAND OPTIONS 23 | --help, -h show help 24 | 25 | FURTHER HELP: See 'fn create --help' for more information about a command. 26 | ``` 27 | 28 | [Some link](#) 29 | 30 | -------------------------------------------------------------------------------- /cli/ref/fn-update.md: -------------------------------------------------------------------------------- 1 | # `fn update` 2 | 3 | ```c 4 | $ fn update 5 | 6 | MANAGEMENT COMMAND 7 | fn update - Update a created object 8 | 9 | USAGE 10 | fn [global options] update [command options] 11 | 12 | DESCRIPTION 13 | This command updates an object ('app', 'context', 'function', 'server' or 'trigger'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a Update an application 17 | context, ctx Update context files 18 | function, func, f, fn Update a function in application 19 | server, sv Pulls latest functions server 20 | trigger, trig, t, tr Update a trigger 21 | help, h Shows a list of commands or help for one command 22 | 23 | COMMAND OPTIONS 24 | --help, -h show help 25 | 26 | FURTHER HELP: See 'fn update --help' for more information about a command. 27 | ``` 28 | 29 | [Some link](#) 30 | 31 | -------------------------------------------------------------------------------- /cli/ref/fn-delete.md: -------------------------------------------------------------------------------- 1 | # `fn delete` 2 | 3 | ```c 4 | $ fn delete 5 | 6 | MANAGEMENT COMMAND 7 | fn delete - Delete an object 8 | 9 | USAGE 10 | fn [global options] delete [command options] 11 | 12 | DESCRIPTION 13 | This command deletes a created object ('app', 'context', 'function' or 'trigger'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a Delete an application 17 | config, config, cf Delete configurations for apps and functions 18 | context, ctx Delete a context 19 | function, func, f, fn Delete a function from an application 20 | trigger, trig, t, tr Delete a trigger 21 | help, h Shows a list of commands or help for one command 22 | 23 | COMMAND OPTIONS 24 | --help, -h show help 25 | 26 | FURTHER HELP: See 'fn delete --help' for more information about a command. 27 | ``` 28 | 29 | [Some link](#) 30 | 31 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | ext { 4 | fdkVersion = '1.0.98' 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | maven { 10 | url 'https://dl.bintray.com/fnproject/fnproject' 11 | } 12 | } 13 | 14 | dependencies { 15 | runtime "com.fnproject.fn:api:$fdkVersion" 16 | // runtime "com.fnproject.fn:runtime:$fdkVersion" // this is optional and included with its deps in the base image to reduce layer size 17 | 18 | testCompile "junit:junit:4.12" 19 | testCompile "com.fnproject.fn:testing-core:$fdkVersion" 20 | testCompile "com.fnproject.fn:testing-junit4:$fdkVersion" 21 | } 22 | 23 | task cacheDeps(type: Exec) { 24 | configurations.testCompile.files 25 | commandLine 'echo', 'Downloaded all dependencies' 26 | } 27 | 28 | 29 | task copyDeps(type: Copy) { 30 | from configurations.compile 31 | into "${project.buildDir}/deps" 32 | } 33 | 34 | build.dependsOn copyDeps 35 | -------------------------------------------------------------------------------- /cli/ref/fn-list.md: -------------------------------------------------------------------------------- 1 | # `fn list` 2 | 3 | ```c 4 | $ fn list 5 | 6 | MANAGEMENT COMMAND 7 | fn list - Return a list of created objects 8 | 9 | USAGE 10 | fn [global options] list [command options] 11 | 12 | DESCRIPTION 13 | This command returns a list of created objects ('app', 'call', 'context', 'function' or 'trigger') or configurations. 14 | 15 | SUBCOMMANDS 16 | apps, app, a List all created applications 17 | config, config, cf List configurations for apps and functions 18 | contexts, context, ctx List contexts 19 | functions, funcs, f, fn List functions for an application 20 | triggers, trigs, t, tr List all triggers 21 | help, h Shows a list of commands or help for one command 22 | 23 | COMMAND OPTIONS 24 | --help, -h show help 25 | 26 | FURTHER HELP: See 'fn list --help' for more information about a command. 27 | ``` 28 | 29 | [Some link](#) 30 | 31 | -------------------------------------------------------------------------------- /fn/operate/metrics.md: -------------------------------------------------------------------------------- 1 | # Metrics 2 | 3 | ## Zipkin 4 | 5 | You can use zipkin to gather traces from fn. 6 | 7 | Running a zipkin node is easy to get started, they have a docker container: 8 | 9 | [zipkin page](http://zipkin.io/pages/quickstart.html) 10 | 11 | With zipkin running you can point functions to it using an env var: 12 | 13 | `ZIPKIN_URL=http://zipkin:9411/api/v1/spans` 14 | 15 | Open your browser to observe: 16 | 17 | `http://localhost:9411` 18 | 19 | ## Jaeger 20 | 21 | We have support for Jaeger traces, as well. 22 | 23 | It is easy to get an all-in-one container of jaeger running to test: 24 | 25 | [jaeger](http://jaeger.readthedocs.io/en/latest/getting_started/#all-in-one-docker-image) 26 | 27 | And then point fn to jaeger with the environment variable: 28 | 29 | `JAEGER_URL=http://localhost:14268/api/traces?format=jaeger.thrift` 30 | 31 | Open browser to observe: 32 | 33 | `http://localhost:16686` 34 | 35 | ## Prometheus 36 | 37 | Fn offers a prometheus metrics endpoint at `/metrics` 38 | -------------------------------------------------------------------------------- /fn/operate/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo Documentation for Operators 2 | 3 | ## For Operators 4 | 5 | If you are operating Fn, this section is for you. 6 | 7 | ### Getting Started 8 | 9 | * [Running in Production](production.md) 10 | * [Databases for running Fn](databases/README.md) 11 | * [Logging](logging.md) 12 | * [Message Queues](message-queues.md) 13 | * [Metrics](metrics.md) 14 | * [Operating on Windows](windows.md) 15 | * [Private Registries](private_registries.md) 16 | * [Running an LB Pool of Runners](runner_pools.md) 17 | * [Running on SELinux Systems](selinux.md) 18 | * [Runtime Options](options.md) 19 | * [Testing Locally](local-testing.md) 20 | * [User Interface](ui.md) 21 | 22 | ### Advanced 23 | 24 | * [Docker Configuration](docker.md) 25 | * [Extending Fn](extending.md) 26 | * [Kubernetes Helm Chart for Fn](https://github.com/fnproject/fn-helm/) 27 | * [Setting up development environment with Docker compose](compose.md) 28 | -------------------------------------------------------------------------------- /fn/develop/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo Documentation for Developers 2 | 3 | ## For Developers 4 | 5 | If you are a developer using Fn through the API, this section is for you. 6 | 7 | ### Getting Started 8 | 9 | * [Quickstart](https://github.com/fnproject/fn#quickstart) 10 | * [Applications - groups of functions](apps.md) 11 | * [Cloud Events](cloudevents.md) 12 | * [Config Vars for Functions](configs.md) 13 | * [FAQ](faq.md) 14 | * [FDKs](fdks.md) 15 | * [Function file (func.yaml)](func-file.md) 16 | * [Triggers](triggers.md) 17 | 18 | ### Examples and Tutorials 19 | 20 | * [Examples](../examples) 21 | * [Tutorials](https://github.com/fnproject/tutorials) 22 | 23 | ### Advanced 24 | 25 | * [API Reference](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/fnproject/fn/master/docs/swagger.yml) 26 | * [API Clients](clients.md) 27 | * [CLI Source](https://github.com/fnproject/cli/) 28 | * [Packaging functions](packaging.md) 29 | -------------------------------------------------------------------------------- /fdks/fdk-python/README.md: -------------------------------------------------------------------------------- 1 | # FN development kit for Python 2 | 3 | Purpose of this library to provide simple interface to parse HTTP 1.1 requests. 4 | 5 | Following examples are showing how to use API of this library to work with streaming HTTP requests from Fn service. 6 | 7 | ## Handling JSON Functions 8 | 9 | A main loop is supplied that can repeatedly call a user function with a series of HTTP requests. 10 | In order to utilise this, you can write your `func.py` as follows: 11 | 12 | ```py 13 | import json 14 | import io 15 | 16 | from fdk import response 17 | 18 | 19 | def handler(ctx, data: io.BytesIO=None): 20 | name = "World" 21 | try: 22 | body = json.loads(data.getvalue()) 23 | name = body.get("name") 24 | except (Exception, ValueError) as ex: 25 | print(str(ex)) 26 | 27 | return response.Response( 28 | ctx, response_data=json.dumps( 29 | {"message": "Hello {0}".format(name)}), 30 | headers={"Content-Type": "application/json"} 31 | ) 32 | 33 | ``` 34 | -------------------------------------------------------------------------------- /fn/operate/databases/postgres.md: -------------------------------------------------------------------------------- 1 | # Fn using Postgres 2 | 3 | Let's suppose you don't have even a postgres DB ready. 4 | 5 | ## 1. Let's start a postgres instance 6 | 7 | ```sh 8 | docker run --name func-postgres \ 9 | -e POSTGRES_PASSWORD=funcpass -d postgres 10 | ``` 11 | 12 | ## 2. Now let's create a new database for Functions 13 | 14 | Creating database: 15 | 16 | ```sh 17 | docker run -it --rm --link func-postgres:postgres postgres \ 18 | psql -h postgres -U postgres -c "CREATE DATABASE funcs;" 19 | ``` 20 | 21 | Granting access to postgres user 22 | 23 | ```sh 24 | docker run -it --rm --link func-postgres:postgres postgres \ 25 | psql -h postgres -U postgres -c 'GRANT ALL PRIVILEGES ON DATABASE funcs TO postgres;' 26 | ``` 27 | 28 | ## 3. Now let's start Functions connecting to our new postgres instance 29 | 30 | ```sh 31 | docker run --rm --privileged --link "func-postgres:postgres" \ 32 | -e "FN_DB_URL=postgres://postgres:funcpass@postgres/funcs?sslmode=disable" \ 33 | -it -p 8080:8080 fnproject/fnserver 34 | ``` 35 | -------------------------------------------------------------------------------- /cli/ref/fn-inspect.md: -------------------------------------------------------------------------------- 1 | # `fn inspect` 2 | 3 | ```c 4 | $ fn inspect 5 | 6 | MANAGEMENT COMMAND 7 | fn inspect - Retrieve properties of an object 8 | 9 | USAGE 10 | fn [global options] inspect [command options] 11 | 12 | DESCRIPTION 13 | This command allows to inspect the properties of an object ('app', 'context', function' or 'trigger'). 14 | 15 | SUBCOMMANDS 16 | app, apps, a Retrieve one or all apps properties 17 | context, ctx Inspect the contents of a context, if no context is specified the current-context will be used. 18 | function, func, f, fn Retrieve one or all properties for a function 19 | trigger, trig, t, tr Retrieve one or all trigger properties 20 | help, h Shows a list of commands or help for one command 21 | 22 | COMMAND OPTIONS 23 | --help, -h show help 24 | 25 | FURTHER HELP: See 'fn inspect --help' for more information about a command. 26 | ``` 27 | 28 | [Some link](#) 29 | 30 | -------------------------------------------------------------------------------- /fn/develop/cloudevents.md: -------------------------------------------------------------------------------- 1 | # CloudEvents - EXPERIMENTAL 2 | 3 | Fn supports CloudEvents throughout the system, meaning on ingestion and/or as a function I/O format. 4 | 5 | To use as a function I/O format, set `format: cloudevent`. 6 | 7 | And to pass in a full cloud event to a function endpoint, you need to set the Content-Type to `application/cloudevents+json`. 8 | 9 | If that header is set, it is assumed that the function also supports the CloudEvents format (in other words, it will automatically set `format: cloudevent`). 10 | 11 | ## Trying it out 12 | 13 | The FDK for Ruby supports CloudEvents, so we'll use that: 14 | 15 | ```sh 16 | fn init --runtime ruby rfunc 17 | cd rfunc 18 | ``` 19 | 20 | Now edit the func.yaml file and change the format to `format: cloudevent`. 21 | 22 | Then deploy it: 23 | 24 | ``` 25 | fn deploy --app myapp 26 | ``` 27 | 28 | There's an example cloudevent in this directory so you can test it with this: 29 | 30 | ```sh 31 | curl -X POST -H "Content-Type: application/cloudevents+json" -d @ce-example.json http://localhost:8080/r/myapp/rfunc 32 | ``` 33 | -------------------------------------------------------------------------------- /fn/troubleshoot/README.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | This page lists solutions to problems you might encounter with Fn. If you want to learn more about troubleshooting, see [Troubleshooting and Logging with Fn](https://github.com/fnproject/tutorials/tree/master/Troubleshooting/README.md). 3 | 4 | ## Debug 5 | Learn how to get detailed information about what is happening in the Fn server. 6 | 7 | * [Enable DEBUG log-level on the Fn Server](debug-loglevel.md) 8 | * [Debug HTTP Headers with the Fn CLI](debug-headers.md) 9 | 10 | ## Common Problems 11 | Here is a list of common problems you might encounter while using Fn. 12 | 13 | * [Can't create an application with Fn client](common/cannot-create-app.md) 14 | * [Can't deploy a function with Fn client](common/cannot-deploy-app.md) 15 | 16 | ## Known Issues 17 | This is a list of known issues with Fn. The pages linked here provide detailed information about an issue. These pages are usually linked to a GitHub issue for a particular repo. 18 | 19 | * [Trying to invoke a function when using a CentOS based Linux fails with an error message](known-issues/2019-08-fn-invoke-fails.md) 20 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/gradle-build/README.md: -------------------------------------------------------------------------------- 1 | # Example Java Functions: Fn Gradle + FDK for Java 2 | 3 | This example shows you how to build a Java function by using a Dockerfile. 4 | 5 | 6 | ## Key points: 7 | 8 | * [Dockerfile](Dockerfile) - contains the containerized Docker build (based on dockerhub library/gradle images) and image build - this includes the gradle invocation 9 | * The `cacheDeps` task in `build.gradle` pulls down dependencies into the container gradle cache to speed up docker builds. 10 | * The `copyDeps` task in `build.gradle` copies the functions compile deps. 11 | * This uses JDK 11 by default 12 | 13 | ## Step by step 14 | 15 | Ensure you have the Fn server running to host your function: 16 | 17 | (1) Start the server 18 | 19 | ```sh 20 | $ fn start 21 | ``` 22 | 23 | (2) Create an app for the function 24 | 25 | ```sh 26 | $ fn create app gradle-build-app 27 | ``` 28 | 29 | (3) Deploy the function to your app from the `gradle-build` directory. 30 | 31 | ```sh 32 | fn deploy --app gradle-build-app --local 33 | ``` 34 | 35 | (4) Invoke the function 36 | 37 | ```sh 38 | fn invoke gradle-build-app gradle_build 39 | ``` 40 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /fn/develop/packaging.md: -------------------------------------------------------------------------------- 1 | # Packaging your Function 2 | 3 | ## Option 1 (recommended): Use the `fn` cli tool 4 | 5 | We recommend using the [fn cli tool](https://github.com/fnproject/fn#quickstart) which will handle all of this for you. But if you'd like to dig in 6 | and customize your images, look at Option 2. 7 | 8 | ## Option 2: Build your own images 9 | 10 | Packaging a function has two parts: 11 | 12 | * Create a Docker image for your function with an ENTRYPOINT 13 | * Push your Docker image to a registry (Docker Hub by default) 14 | 15 | Once it's pushed to a registry, you can use the image location when adding a route. 16 | 17 | ### Creating an image 18 | 19 | The basic Dockerfile for most languages is along these lines: 20 | 21 | ``` 22 | # Choose base image 23 | FROM node:alpine 24 | # Set the working directory 25 | WORKDIR /function 26 | # Add your binary or code to the working directory 27 | ADD . /function/ 28 | # Set what will run when a container is started for this image 29 | ENTRYPOINT ["node func.js"] 30 | ``` 31 | 32 | Then build your function image: 33 | 34 | ```sh 35 | fn build 36 | ``` 37 | 38 | ### Push your image 39 | 40 | ```sh 41 | fn push 42 | ``` 43 | 44 | Now you can use that image when creating or updating routes. -------------------------------------------------------------------------------- /fn/operate/databases/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Databases 3 | 4 | We currently support the following databases and they are passed in via the `FN_DB_URL` environment variable. For example: 5 | 6 | ```sh 7 | docker run -e "FN_DB_URL=postgres://user:pass@localhost:6212/mydb" ... 8 | ``` 9 | 10 | ## sqlite3 (default) 11 | 12 | URL: `sqlite3:///functions/data/functions.db` 13 | 14 | SQLite3 is an embedded database which stores to disk. If you want to use this, be sure you don't lose the data directory by mounting 15 | the directory on your host. eg: `docker run -v $PWD/data:/functions/data -e FN_DB_URL=sqlite3:///functions/data/fn.db ...` 16 | 17 | ## [PostgreSQL](http://www.postgresql.org/) 18 | 19 | URL: `postgres://user123:pass456@ec2-117-21-174-214.compute-1.amazonaws.com:6212/db982398` 20 | 21 | Use a PostgreSQL database. If you're using Functions in production, you should probably start here. 22 | 23 | [More on PostgreSQL](postgres.md) 24 | 25 | ## [MySQL](https://www.mysql.com/) 26 | 27 | URL: `mysql://user123:pass456@tcp(ec2-117-21-174-214.compute-1.amazonaws.com:3306)/funcs` 28 | 29 | [More on MySQL](mysql.md) 30 | 31 | ## What about database X? 32 | 33 | We're happy to add more and we love pull requests, so feel free to add one! Copy one of the implementations above as a starting point. 34 | 35 | -------------------------------------------------------------------------------- /cli/ref/README.md: -------------------------------------------------------------------------------- 1 | # Fn Command Reference 2 | 3 | [fn build](fn-build.md) 4 | [fn bump](fn-bump.md) 5 | [fn config](fn-config.md) 6 | [fn create](fn-create.md) 7 | [fn create app](fn-create-app.md) 8 | [fn create context](fn-create-context.md) 9 | [fn create function](fn-create-function.md) 10 | [fn create trigger](fn-create-trigger.md) 11 | [fn delete](fn-delete.md) 12 | [fn deploy](fn-deploy.md) 13 | [fn get](fn-get.md) 14 | [fn get config](fn-get-config.md) 15 | [fn help](fn-help.md) 16 | [fn init](fn-init.md) 17 | [fn inspect](fn-inspect.md) 18 | [fn invoke](fn-invoke.md) 19 | [fn list](fn-list.md) 20 | [fn list apps](fn-list-apps.md) 21 | [fn list config](fn-list-config.md) 22 | [fn list contexts](fn-list-contexts.md) 23 | [fn list triggers](fn-list-triggers.md) 24 | [fn migrate](fn-migrate.md) 25 | [fn push](fn-push.md) 26 | [fn start](fn-start.md) 27 | [fn stop](fn-stop.md) 28 | [fn unset](fn-unset.md) 29 | [fn update](fn-update.md) 30 | [fn update app](fn-update-app.md) 31 | [fn update context](fn-update-context.md) 32 | [fn update function](fn-update-function.md) 33 | [fn update server](fn-update-server.md) 34 | [fn update trigger](fn-update-trigger.md) 35 | [fn use](fn-use.md) 36 | [fn version](fn-version.md) 37 | 38 | version: 0.5.91 39 | -------------------------------------------------------------------------------- /fn/develop/podman.md: -------------------------------------------------------------------------------- 1 | # Using Fn with Podman instead of Docker 2 | 3 | By default, Fn Project assumes the use of Docker to build and deploy function images. However, Fn Project now supports Podman as an alternative to Docker. When using Fn CLI version 0.6.12 and above, you can specify a configuration setting to use Podman instead of Docker. 4 | 5 | Having installed the Fn CLI ([Install Fn](https://fnproject.io/tutorials/install/)), specify that you want to use Podman as follows: 6 | 7 | 1. Install Podman (version 3.4 or later) and add Podman to the system path. See [Podman Installation Instructions](https://podman.io/getting-started/installation). 8 | 9 | 2. Add the `container-enginetype` configuration setting to the `~/.fn/config.yaml` file as follows: 10 | 11 | ```yaml 12 | container-enginetype: podman 13 | ``` 14 | 15 | If you subsequently want to use Docker rather than Podman, do either of the following: 16 | 17 | * Remove the `container-enginetype` configuration setting from the `~/.fn/config.yaml` file. 18 | * Update the `container-enginetype` configuration setting in the `~/.fn/config.yaml` file to specify Docker rather than Podman, as follows: 19 | 20 | ```yaml 21 | container-enginetype: docker 22 | ``` 23 | 24 | **Note:** If Podman is chosen as the `container-enginetype`, Fn server does not work. You are not able to deploy your functions to a local Fn server. 25 | -------------------------------------------------------------------------------- /fn/troubleshoot/debug-headers.md: -------------------------------------------------------------------------------- 1 | # Use DEBUG=1 for Client Commands 2 | 3 | If you're interacting with functions via the `fn` CLI, you can enable debug 4 | mode to see the full details of the HTTP requests going to the Fn server and 5 | the responses. The `fn` CLI simply wraps the Fn API to make it easier to 6 | manage your applications and functions. You can always use `curl` but the CLI 7 | is much more convenient! 8 | 9 | You enable debug mode by adding `DEBUG=1` before `fn` on each command. For 10 | example try the following: 11 | 12 | ![user input](images/userinput.png) 13 | >```sh 14 | > DEBUG=1 fn ls apps 15 | >``` 16 | 17 | Which, with debugging turn on, returns the following: 18 | 19 | ```sh 20 | GET /v2/apps HTTP/1.1 21 | Host: localhost:8080 22 | User-Agent: Go-http-client/1.1 23 | Accept: application/json 24 | Accept-Encoding: gzip 25 | 26 | 27 | HTTP/1.1 200 OK 28 | Content-Length: 977 29 | Content-Type: application/json; charset=utf-8 30 | Date: Sun, 13 Oct 2019 16:45:56 GMT 31 | 32 | 33 | {"items":[{"id":"01DQ2STN6KNG8G00GZJ000001Q","name":"tutorial","syslog_url":"tcp://logs3.papertrailapp.com:NNNN","created_at":"2019-10-13T14:54:45.459Z","updated_at":"2019-10-13T15:55:50.628Z"}]} 34 | NAME ID 35 | tutorial 01DQ2STN6KNG8G00GZJ000001Q 36 | ``` 37 | 38 | All debug output is written to stderr while the normal response is written 39 | to stdout so it's easy to capture or pipe either for processing. 40 | -------------------------------------------------------------------------------- /fn/operate/extending.md: -------------------------------------------------------------------------------- 1 | # Building Custom Server with Extensions 2 | 3 | You can easily add any number of extensions to Fn and then build your own custom image. 4 | 5 | An example of fn w/ extensions may be found [here](https://github.com/fnproject/fn-ext-example). 6 | 7 | Simply create an `ext.yaml` file with the extensions you want added: 8 | 9 | ```yaml 10 | extensions: 11 | - name: github.com/treeder/fn-ext-example/logspam 12 | - name: github.com/treeder/fn-ext-example/logspam2 13 | ``` 14 | 15 | Build it: 16 | 17 | ```sh 18 | fn build-server -t imageuser/imagename 19 | ``` 20 | 21 | `-t` takes the same input as `docker build -t`, tagging your image. 22 | 23 | Now run your new server: 24 | 25 | ```sh 26 | docker run --rm --name fnserver -it -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/data:/app/data -p 8080:8080 imageuser/imagename 27 | ``` 28 | 29 | ## datastores / mqs / drivers 30 | 31 | Users that construct their own fn `main()` to build with extensions will need 32 | to import any pieces they need to configure a datastore, mq and drivers for 33 | the agent. `github.com/fnproject/fn/api/server/defaultexts` will import 34 | everything in core and allowing configuring them at runtime. To get a smaller 35 | binary, users may import only what they need. See the `defaultexts` file for 36 | import paths to various pieces that may be configured. It's also possible to 37 | use an entirely separate datastore, mq, or driver if a user wishes. 38 | -------------------------------------------------------------------------------- /fdks/fdk-java/SpringCloudFunctionSupport.md: -------------------------------------------------------------------------------- 1 | # Spring cloud functions with Fn 2 | 3 | [Spring cloud function](https://github.com/spring-cloud/spring-cloud-function) 4 | is a [Spring](https://spring.io/) project for building Java functions with the 5 | (optional) support of the spring framework. 6 | 7 | We support execution of Spring cloud functions through the 8 | `SpringCloudFunctionInvoker` which manages the discovery and invocation of your 9 | functions. 10 | 11 | ## Tutorial 12 | 13 | The minimal necessary function you must provide is: 14 | 15 | ```yaml 16 | cmd: com.example.fn.FunctionConfig::handleRequest 17 | ``` 18 | 19 | ```java 20 | package com.example.fn; 21 | 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.context.annotation.Import; 24 | 25 | 26 | @Configuration 27 | @Import(ContextFunctionCatalogAutoConfiguration.class) 28 | public class FunctionConfig { 29 | public static String consumedValue; 30 | public static String suppliedValue = "Hello"; 31 | 32 | @FnConfiguration 33 | public static void configure(RuntimeContext ctx) { 34 | ctx.setInvoker(new SpringCloudFunctionInvoker(FunctionConfig.class)); 35 | } 36 | 37 | 38 | // Blank entrypoint necessary to load the FunctionConfig class, this isn't invoked 39 | public void handleRequest() { } 40 | 41 | @Bean 42 | public Function upperCase(){ 43 | return String::toUpperCase; 44 | } 45 | } 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/src/main/java/com/example/fn/Connection.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fnproject.fn.api.FnConfiguration; 4 | import com.fnproject.fn.api.RuntimeContext; 5 | 6 | 7 | public class Connection { 8 | private String url; 9 | private String driver; 10 | private String user; 11 | private String password; 12 | 13 | @FnConfiguration 14 | public void config(RuntimeContext ctx) { 15 | //Set value at the application configuration level 16 | url = ctx.getConfigurationByKey("DB_URL") 17 | .orElse("jdbc:oracle"); 18 | //Set value in the func.yaml 19 | driver = ctx.getConfigurationByKey("DB_DRIVER") 20 | .orElse("OracleDriver"); 21 | //Set value at the application configuration level 22 | user = ctx.getConfigurationByKey("DB_USER") 23 | .orElse("admin"); 24 | } 25 | 26 | 27 | public String getUrl() { 28 | return url; 29 | } 30 | 31 | 32 | public String getDriver() { 33 | return driver; 34 | } 35 | 36 | 37 | public String getUser() { 38 | return user; 39 | } 40 | 41 | //Set value at the function configuration level 42 | public String getPassword() { 43 | password = System.getenv().getOrDefault("DB_PASSWORD", "admin"); 44 | return password; 45 | } 46 | 47 | public String getConnection() { 48 | return "driver: " + getDriver() + "; url: " + url + "; user: " + getUser() + "; password: " + getPassword(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cli/ref/fn-deploy.md: -------------------------------------------------------------------------------- 1 | # `fn deploy` 2 | 3 | ```c 4 | $ fn deploy 5 | 6 | DEVELOPMENT COMMANDS 7 | fn deploy - Deploys a function to the functions server (bumps, build, pushes and updates functions and/or triggers). 8 | 9 | USAGE 10 | fn [global options] deploy [command options] [function-subdirectory] 11 | 12 | DESCRIPTION 13 | This command deploys one or all (--all) functions to the function server. 14 | 15 | COMMAND OPTIONS 16 | --app value App name to deploy to 17 | --create-app Enable automatic creation of app if it doesn't exist during deploy 18 | --verbose, -v Verbose mode 19 | --no-cache Don't use Docker cache for the build 20 | --local, --skip-push Do not push Docker built images onto Docker Hub - useful for local development. 21 | --registry --registry username Set the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. eg: --registry username will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner. 22 | --all app.yaml If in root directory containing app.yaml, this will deploy all functions 23 | --no-bump Do not bump the version, assuming external version management 24 | --build-arg value Set build time variables 25 | --working-dir value, -w value Specify the working directory to deploy a function, must be the full path. 26 | 27 | ``` 28 | 29 | [Some link](#) 30 | 31 | -------------------------------------------------------------------------------- /fdks/fdk-java/HTTPGatewayFunctions.md: -------------------------------------------------------------------------------- 1 | # Accessing HTTP information from functions 2 | 3 | Functions can be used to handle events, RPC calls or HTTP requests. When you are writing a function that handles an HTTP request you frequently need access to the HTTP headers of the incoming request or need to set HTTP headers or the status code on the outbound respsonse. 4 | 5 | 6 | In Fn for Java, when your function is being served by an HTTP trigger (or another compatible HTTP gateway) you can get access to both the incoming request headers for your function by adding a 'com.fnproject.fn.api.httpgateway.HTTPGatewayContext' parameter to your function's parameters. 7 | 8 | 9 | Using this allows you to : 10 | 11 | * Read incoming headers 12 | * Access the method and request URL for the trigger 13 | * Write outbound headers to the response 14 | * Set the status code of the response 15 | 16 | 17 | For example this function reads a request header the method and request URL, sets an response header and sets the response status code to perform an HTTP redirect. 18 | 19 | ```java 20 | package com.fnproject.fn.examples; 21 | import com.fnproject.fn.api.httpgateway.HTTPGatewayContext; 22 | 23 | 24 | public class RedirectFunction { 25 | 26 | public void redirect(HTTPGatewayContext hctx) { 27 | System.err.println("Request URL is:" + hctx.getRequestURL()); 28 | System.err.println("Trace ID" + hctx.getHeaders().get("My-Trace-ID").orElse("N/A")); 29 | 30 | hctx.setResponseHeader("Location","http://example.com"); 31 | hctx.setStatusCode(302); 32 | 33 | } 34 | } 35 | 36 | ``` 37 | -------------------------------------------------------------------------------- /fn/troubleshoot/known-issues/2019-08-fn-invoke-fails.md: -------------------------------------------------------------------------------- 1 | # `fn invoke` fails with the error message "kernel memory accounting disabled in this runc build" 2 | Date Reported: 7/2/19 Issue: 3 | 4 | ### Error messages 5 | * CentOS: "kernel memory accounting disabled in this runc build" 6 | * Oracle Linux: "API error (500): starting container process caused process_linux.go:402: container init caused process_linux.go:367: setting cgroup config for procHooks process caused kernel memory accounting disabled in this runc build: unknown" fn_id=01DHQC8C5YNG8G00GZJ0000002 idle_timeout=30 image="javafn:0.0.3" memory=128 7 | 8 | **Reproduced with:** 9 | 10 | * Docker:18.09(Git commit:e32a1bd) 11 | * Fn Server:0.3.728(latest) 12 | * Fn Client :0.5.84(latest) 13 | * Oracle Linux 7.x 14 | 15 | ### Problem 16 | CentOS 7.x enables kernel memory limit by default even though it's a experimental feature(not sure why), and RunC uses this feature without checking. This is causing a problem with Docker. 17 | 18 | **See:** 19 | 20 | * [Fn Issue](https://github.com/fnproject/fn/issues/1520) 21 | * [Enabling kmem accounting can break applications on CentOS7 #1725](https://github.com/opencontainers/runc/issues/1725) 22 | * [cgroups documenation](https://lwn.net/Articles/529927/) 23 | 24 | ### Workaround 25 | There seems to be three options: 26 | 27 | * Downgrade your system's containerd.io to containerd.io-1.2.2-3.3.el7 (a version not built with nokmem) and hope you don't run into the same issue. 28 | * Don't run Fn server on a CentOS based Linux kernel 3.x system. 29 | * Downgrade Docker to v18.0 30 | -------------------------------------------------------------------------------- /fn/develop/pagination.md: -------------------------------------------------------------------------------- 1 | # Pagination 2 | 3 | The Fn api utilizes "cursoring" to paginate large result sets on endpoints 4 | that list resources. The parameters are read from query parameters on incoming 5 | requests, and a cursor will be returned to the user if they receive a full 6 | page of data to use to retrieve the next page. We'll walk through with a 7 | concrete example in just a minute. 8 | 9 | To begin paging through a results set, a user should provide a `?cursor` with an 10 | empty string or omit the cursor query parameter altogether. A user may specify 11 | how many results per page they would like to receive with the `?per_page` 12 | query parameter, which defaults to 30 and has a max of 100. After calling a 13 | list endpoint, a user may receive a `response.next_cursor` value in the 14 | response, next to the list of resources. If `next_cursor` is an empty string, 15 | then there is no further data to retrieve and the user may stop paging. If 16 | `next_cursor` is a non-empty string, the user may provide it in the next 17 | request's `?cursor` parameter to receive the next page. 18 | 19 | Briefly, what this means, is user code should look similar to this: 20 | 21 | ``` 22 | req = "http://my.fn.com/v2/apps/" 23 | cursor = "" 24 | 25 | for { 26 | req_with_cursor = req + "?" + cursor 27 | resp = call_http(req_with_cursor) 28 | do_things_with_apps(resp["apps"]) 29 | 30 | if resp["next_cursor"] == "" { 31 | break 32 | } 33 | cursor = resp["next_cursor"] 34 | } 35 | 36 | # done! 37 | ``` 38 | 39 | Client libraries will have variables for each of these variables in their 40 | respective languages to make this a bit easier. 41 | -------------------------------------------------------------------------------- /cli/ref/fn-init.md: -------------------------------------------------------------------------------- 1 | # `fn init` 2 | 3 | ```c 4 | $ fn init 5 | 6 | DEVELOPMENT COMMANDS 7 | fn init - Create a local func.yaml file 8 | 9 | USAGE 10 | fn [global options] init [command options] [function-subdirectory] 11 | 12 | DESCRIPTION 13 | This command creates a func.yaml file in the current directory. 14 | 15 | COMMAND OPTIONS 16 | --name value Name of the function. Defaults to directory name in lowercase. 17 | --force Overwrite existing func.yaml 18 | --runtime value Choose an existing runtime - go, java, java11, java8, kotlin, node, python, python3.6, python3.7.1, ruby 19 | --init-image value A Docker image which will create a function template 20 | --entrypoint value Entrypoint is the command to run to start this function - equivalent to Dockerfile ENTRYPOINT. 21 | --cmd value Command to run to start this function - equivalent to Dockerfile CMD. 22 | --version value Set initial function version (default: "0.0.1") 23 | --working-dir value, -w value Specify the working directory to initialise a function, must be the full path. 24 | --trigger value Specify the trigger type - permitted values are 'http'. 25 | --memory value, -m value Memory in MiB (default: 0) 26 | --config value, -c value Function configuration 27 | --timeout value Function timeout (eg. 30) (default: 0) 28 | --idle-timeout value Function idle timeout (eg. 30) (default: 0) 29 | --annotation value Function annotation (can be specified multiple times) 30 | 31 | ``` 32 | 33 | [Some link](#) 34 | 35 | -------------------------------------------------------------------------------- /fn/troubleshoot/debug-loglevel.md: -------------------------------------------------------------------------------- 1 | # Log to Fn Server Terminal Window with DEBUG 2 | When working with Fn locally, you have the option to turn on the DEBUG log-level using the `fn start` command. This causes detailed information about functions to be output to the terminal after Fn server is started. 3 | 4 | To enable DEBUG logging for Fn server, restart the server with the following command: 5 | 6 | ![user input](images/userinput.png) 7 | >```sh 8 | > fn start --log-level DEBUG 9 | >``` 10 | 11 | ```sh 12 | 2019/12/19 09:26:27 ¡¡¡ 'fn start' should NOT be used for PRODUCTION !!! see https://github.com/fnproject/fn-helm/ 13 | time="2019-12-19T16:26:28Z" level=info msg="Setting log level to" fields.level=DEBUG 14 | ... 15 | ``` 16 | Notice in the first couple of messages state that the log level is set to DEBUG. 17 | 18 | Here is an example of the kind of output generated when a Runtime Exception is encountered with Java. 19 | ```sh 20 | time="2019-12-19T16:27:55Z" level=debug msg="Caused by: java.lang.RuntimeException: Something went horribly wrong! ...\n" action="server.handleFnInvokeCall)-fm" app_id=01DWFFR290NG8G00GZJ0000001 call_id=01DWFFS7QZNG8G00GZJ0000003 fn_id=01DWFFRQVQNG8G00GZJ0000002 image="fndemouser/trouble:0.0.2" user_log=true 21 | time="2019-12-19T16:27:55Z" level=debug msg=" at com.example.fn.HelloFunction.handleRequest(HelloFunction.java:7)\n" action="server.handleFnInvokeCall)-fm" app_id=01DWFFR290NG8G00GZJ0000001 call_id=01DWFFS7QZNG8G00GZJ0000003 fn_id=01DWFFRQVQNG8G00GZJ0000002 image="fndemouser/trouble:0.0.2" user_log=true 22 | ``` 23 | A Runtime Exception was thrown on line 7 of the HelloFunction. 24 | 25 | Running the Fn server with the DEBUG log level is a great way to track down any issues you are having with your functions. 26 | -------------------------------------------------------------------------------- /fn/operate/local-testing.md: -------------------------------------------------------------------------------- 1 | # Testing a running Fn locally 2 | 3 | Running functions that call other functions in a local testing environment can 4 | be challenging. This document will outline best practices in functions to make 5 | this work more easily between deployments as well as some tips to help testing 6 | locally. 7 | 8 | ### Best Practices 9 | 10 | Included in each function invocation will be the request url for how the 11 | function was invoked. In FDKs, this will be exposed in the context object for each language. 12 | If your function invokes other functions, it's recommended to either configure 13 | the host that your function should use to invoke the other functions yourself 14 | (by sending it in the payload, or elsewhere), or to parse the `request_url` 15 | that Fn includes in a function invocation and use that. This makes it easy to 16 | switch between e.g. `localhost:8080` and `fn.my-company.com`. 17 | 18 | ### Configuring functions to invoke locally 19 | 20 | When running functions that call other functions locally, they will need to be 21 | able to address the fn server to do so. Since functions run in a docker 22 | container, this can be more challenging when using a `localhost` url. One 23 | option is to use something more heavyweight like [ngrok](https://ngrok.com/), 24 | and this will work. It is also possible in a local environment to start `fn` 25 | with the option `FN_DOCKER_NETWORKS=host`, this is equivalent to running each 26 | function container with `--net=host`, where each function can address the 27 | locally running `fn` server to invoke functions against on `localhost`; this 28 | setting is not recommended for production and any behaviors therein should not 29 | be expected in production, it is extremely convenient for testing locally 30 | nonetheless. 31 | -------------------------------------------------------------------------------- /community/README.md: -------------------------------------------------------------------------------- 1 | # Fn Project Logo Project Community 2 | 3 | ## Welcome! 4 | 5 | Before proceeding, please review the Fn [Code of Conduct](CODE_OF_CONDUCT.md). 6 | 7 | Welcome to the Fn Project Community! You will find all the resources you need here to join our community, whether as a user, contributor, speaker, partner, or just observer. 8 | 9 | 10 | ## Bi-Weekly Fn Community Call 11 | 12 | The Fn Project community calls take place every other Tuesday and are open to anyone. You can find the date of the next call, dial-in information, and past meeting notes here: [http://comcall.fnproject.io](http://comcall.fnproject.io) 13 | 14 | 15 | ## For Contributors 16 | 17 | If you are working on the Fn Project, want to work on it or are creating extensions, start with our [contributing guidelines](CONTRIBUTING.md) page. 18 | 19 | 20 | ## Workstreams 21 | 22 | This list is unordered and simply a placeholder to start the conversation. May move to a GitHub Project per issue [1070](https://github.com/fnproject/fn/issues/1070)) 23 | 24 | 1. Fn Server core performance work 25 | 26 | 2. Terraform scripts for full "prod" deployment on multiple clouds 27 | 28 | 3. Tighter Kubernetes integration 29 | - Using CRD's to manage funcs 30 | - Accessing secrets 31 | - Using pods to schedule work 32 | - Possible integrations with Knative build, serve, or eventing 33 | 34 | 4. Additional triggers 35 | - Kafka (in progress) 36 | - OracleDB 37 | - MySQL 38 | - Scheduled (CRON like) 39 | 40 | 5. Update and Fix UI (might be complete rewrite) 41 | 42 | 6. [Fn Flow](https://github.com/fnproject/flow) 43 | 44 | To start using the Fn Project, visit our main repo here: [https://github.com/fnproject/fn](https://github.com/fnproject/fn) 45 | -------------------------------------------------------------------------------- /fn/operate/logging.md: -------------------------------------------------------------------------------- 1 | # Logging 2 | 3 | There are a few things to note about what Fn logs. 4 | 5 | ## Logspout 6 | 7 | We recommend using [logspout](https://github.com/gliderlabs/logspout) to forward your logs to a log aggregator of your choice. 8 | 9 | ## Format 10 | 11 | All logs are emitted in [logfmt](https://godoc.org/github.com/kr/logfmt) format for easy parsing. 12 | 13 | Each line contains timestamp, app id, and function id. Here's a sample: 14 | 15 | ```txt 16 | 2018-11-21T13:50:28-05:00 linuxkit-025000000001 app_id=01CV2SYZ9NNG8G00RZJ0000001,fn_id=01CWVSNBD0NG8G00RZJ00000 Caused by: java.lang.RuntimeException: Something went horribly wrong! 17 | ``` 18 | 19 | ## Remote syslog for functions 20 | 21 | You may add a syslog url to any function application and all functions that 22 | exist under that application will ship all of their logs to it. You may 23 | provide a comma separated list, if desired. Currently, we support `tcp`, 24 | `udp`, and `tcp+tls`, and this will not work if behind a proxy [yet?] (this is 25 | my life now). 26 | 27 | An example syslog url is: 28 | 29 | ``` 30 | tcp+tls://logs.papertrailapp.com:1 31 | ``` 32 | 33 | We log in a syslog format, with some variables added in logfmt format. If you 34 | find logfmt format offensive, please open an issue and we will consider adding 35 | more formats (or open a PR that does it, with tests, and you will receive 1 36 | free cookie along with the feature you want). The logs from the functions 37 | themselves are not formatted, only our pre-amble, thus, if you'd like a fully 38 | logfmt line, you must use a logfmt logger to log from your function. 39 | 40 | * All log lines are sent as level error w/ the current time and `fnrunner` as hostname. 41 | * app_id will prefix every log line. 42 | 43 | ``` 44 | <11>2 1982-06-25T12:00:00Z fnrunner - - - - app_id=54321 this is your log line 45 | ``` 46 | -------------------------------------------------------------------------------- /fn/develop/apps.md: -------------------------------------------------------------------------------- 1 | # Applications 2 | 3 | In `fn`, an application is a group of functions with path mappings (routes) to each function ([learn more](model.md)). 4 | We've tried to make it easy to work with full applications by providing tools that work with all the applications functions. 5 | 6 | ## Creating an Application 7 | 8 | All you have to do is create a file called `app.yaml` in your applications root directory, and the only required field is a name: 9 | 10 | ```yaml 11 | name: myawesomeapp 12 | ``` 13 | 14 | Once you have that file in place, the `fn` commands will work in the context of that application. 15 | 16 | ## The Index Function (aka: Root Function) 17 | 18 | The root app directory can also contain a `func.yaml` which will be the function access at `/`. 19 | 20 | ## Function paths 21 | 22 | By default, the function name and path will be the same as the directory structure. For instance, if you 23 | have a structure like this: 24 | 25 | ```txt 26 | - app.yaml 27 | - func.yaml 28 | - func.go 29 | - hello/ 30 | - func.yaml 31 | - func.js 32 | - users/ 33 | - func.yaml 34 | - func.rb 35 | ``` 36 | 37 | The URL's to access those functions will be: 38 | 39 | ``` 40 | http://abc.io/ -> root function 41 | http://abc.io/hello -> function in hello/ directory 42 | http://abc.io/users -> function in users/ directory 43 | ``` 44 | 45 | ## Deploying an entire app at once 46 | 47 | ```sh 48 | fn deploy --all 49 | ``` 50 | 51 | If you're just testing locally, you can speed it up with the `--local` flag. Or if you want to deploy to a different app, use the `--app APPNAME` flag. 52 | 53 | ## Deploying a single function in the app 54 | 55 | To deploy the `hello` function only, from the root dir, run: 56 | 57 | ```sh 58 | fn deploy hello 59 | ``` 60 | 61 | ## Example app 62 | 63 | See https://github.com/treeder/fn-app-example for a simple example. Just clone it and run `fn deploy --all` to see it in action. -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/src/test/java/com/example/fn/testing/ConnectionTest.java: -------------------------------------------------------------------------------- 1 | package com.example.fn.testing; 2 | 3 | import static junit.framework.TestCase.assertEquals; 4 | import java.util.List; 5 | 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | 10 | import com.example.fn.Connection; 11 | import com.fnproject.fn.testing.FnResult; 12 | import com.fnproject.fn.testing.FnTestingRule; 13 | 14 | 15 | public class ConnectionTest { 16 | 17 | @Rule 18 | public FnTestingRule fn; 19 | List results; 20 | 21 | @Before 22 | public void setUp() { 23 | fn = FnTestingRule.createDefault(); 24 | fn.givenEvent().enqueue(); 25 | fn.thenRun(Connection.class, "config"); 26 | } 27 | 28 | @Test 29 | public void getUrlDefaultValue() { 30 | fn.thenRun(Connection.class, "getUrl"); 31 | results = fn.getResults(); 32 | String url = results.get(1).getBodyAsString(); 33 | assertEquals("jdbc:oracle", url); 34 | } 35 | 36 | @Test 37 | public void getDriverDetaultValue() { 38 | fn.thenRun(Connection.class, "getDriver"); 39 | results = fn.getResults(); 40 | String driver = results.get(1).getBodyAsString(); 41 | assertEquals("OracleDriver", driver); 42 | } 43 | 44 | @Test 45 | public void getUsernameDefaultValue() { 46 | fn.thenRun(Connection.class, "getUser"); 47 | results = fn.getResults(); 48 | String user = results.get(1).getBodyAsString(); 49 | assertEquals("admin", user); 50 | } 51 | 52 | @Test 53 | public void getPasswordDefaultValue() { 54 | fn.thenRun(Connection.class, "getPassword"); 55 | results = fn.getResults(); 56 | String password = results.get(1).getBodyAsString(); 57 | assertEquals("admin", password); 58 | } 59 | 60 | 61 | 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /cli/how-to/manage-server.md: -------------------------------------------------------------------------------- 1 | # Manage an Fn Server 2 | The first step to using Fn it to start the Fn server. The Fn Command Line Interface (CLI) provides a number of commands for doing this. 3 | 4 | ### Start and Stopping the Fn Server 5 | To start the Fn server, open a terminal window and issue the following command: 6 | 7 | fn start 8 | 9 | This starts the server on the default listening port of `8080`. The server starts in current window and displays server information in that window. Your output should look similar to this: 10 | 11 | ```ini 12 | ... 13 | time="2018-07-12T20:46:22Z" level=info msg="available cpu" availCPU=4000 totalCPU=4000 14 | time="2018-07-12T20:46:22Z" level=info msg="sync and async cpu reservations" cpuAsync=3200 cpuAsyncHWMark=2560 cpuSync=800 15 | 16 | ______ 17 | / ____/___ 18 | / /_ / __ \ 19 | / __/ / / / / 20 | /_/ /_/ /_/ 21 | v0.3.482 22 | 23 | time="2018-07-12T20:46:22Z" level=info msg="Fn serving on `:8080`" type=full 24 | ``` 25 | 26 | To stop the Fn server, open a new terminal window and type: 27 | 28 | fn stop 29 | 30 | The server you started in the original window stops. 31 | 32 | #### Server Data 33 | When the server starts, data the Fn server needs to persist while running is stored in the `.fn/data` directory found in your home directory. 34 | 35 | #### Starting the the Background 36 | To start the Fn server in the background, use the following command: 37 | 38 | fn start -d 39 | 40 | ### Change the Fn Server Listening Port 41 | By default, the Fn server starts listening on port `8080`. If you need the Fn server to listen on a different port, make the following changes. 42 | 43 | For example, to start the Fn server on port 8081, issue the following start command: 44 | 45 | fn start -p 8081 46 | 47 | Additionally, you need to set an Fn environment variable to point the Fn client to the correct port. Set the `FN_API_URL` variable to `http://127.0.0.1:8081`, for example: 48 | 49 | export FN_API_URL=http://127.0.0.1:8081 50 | 51 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/src/test/java/com/example/fn/RegexQueryTests.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fnproject.fn.testing.FnTestingRule; 4 | import org.json.JSONException; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.skyscreamer.jsonassert.JSONAssert; 8 | 9 | public class RegexQueryTests { 10 | @Rule 11 | public FnTestingRule fn = FnTestingRule.createDefault(); 12 | 13 | @Test 14 | public void matchingSingleCharacter() throws JSONException { 15 | String text = "a"; 16 | String regex = "."; 17 | fn.givenEvent() 18 | .withBody(String.format("{\"text\": \"%s\", \"regex\": \"%s\"}", text, regex)) 19 | .enqueue(); 20 | 21 | fn.thenRun(RegexQuery.class, "query"); 22 | 23 | JSONAssert.assertEquals(String.format("{\"text\":\"%s\"," + 24 | "\"regex\":\"%s\"," + 25 | "\"matches\":[" + 26 | "{\"start\": 0, \"end\": 1, \"match\": \"a\"}" + 27 | "]}", text, regex), 28 | fn.getOnlyResult().getBodyAsString(), false); 29 | } 30 | 31 | @Test 32 | public void matchingSingleCharacterMultipleTimes() throws JSONException { 33 | String text = "abc"; 34 | String regex = "."; 35 | fn.givenEvent() 36 | .withBody(String.format("{\"text\": \"%s\", \"regex\": \"%s\"}", text, regex)) 37 | .enqueue(); 38 | 39 | fn.thenRun(RegexQuery.class, "query"); 40 | 41 | JSONAssert.assertEquals(String.format("{\"text\":\"%s\"," + 42 | "\"regex\":\"%s\"," + 43 | "\"matches\":[" + 44 | "{\"start\": 0, \"end\": 1, \"match\": \"a\"}," + 45 | "{\"start\": 1, \"end\": 2, \"match\": \"b\"}," + 46 | "{\"start\": 2, \"end\": 3, \"match\": \"c\"}" + 47 | "]}", text, regex), 48 | fn.getOnlyResult().getBodyAsString(), false); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/string-reverse/README.md: -------------------------------------------------------------------------------- 1 | # Example Java Function: String Reverse 2 | 3 | This example provides an HTTP trigger endpoint for reversing strings. 4 | 5 | ```bash 6 | $ curl -d "Hello World" http://localhost:8080/t/string-reverse-app/string-reverse 7 | dlroW olleH 8 | ``` 9 | 10 | 11 | ## Demonstrated FDK features 12 | 13 | This example uses **none** of the Fn FDK for Java features, in fact it doesn't 14 | have any dependency on the FDK for Java. It is just plain old Java code. 15 | 16 | ## Step by step 17 | 18 | Ensure you have the Fn server running to host your function and provide the HTTP endpoint that invokes it: 19 | 20 | (1) Start the server 21 | 22 | ```sh 23 | $ fn start 24 | ``` 25 | 26 | (2) Create an app for the function 27 | 28 | ```sh 29 | $ fn create app string-reverse-app 30 | ``` 31 | 32 | (3) Deploy the function to your app from the `string-reverse` directory. 33 | 34 | ```sh 35 | fn deploy --app string-reverse-app --local 36 | ``` 37 | 38 | (4) Invoke the function and reverse the string. 39 | 40 | ```sh 41 | echo "Hello World" | fn invoke string-reverse-app string-reverse 42 | dlroW olleH 43 | ``` 44 | 45 | (5) Invoke the function using curl and a trigger to reverse a string. 46 | 47 | ```bash 48 | $ curl -d "Hello World" http://localhost:8080/t/string-reverse-app/string-reverse 49 | dlroW olleH 50 | ``` 51 | 52 | 53 | ## Code walkthrough 54 | 55 | The entrypoint to the function is specified in `func.yaml` in the `cmd` key. 56 | It is set to `com.example.fn.StringReverse::reverse`. The whole class 57 | `StringReverse` is shown below: 58 | 59 | 60 | ```java 61 | package com.example.fn; 62 | 63 | public class StringReverse { 64 | public String reverse(String str) { 65 | return new StringBuilder(str).reverse().toString(); 66 | } 67 | } 68 | ``` 69 | 70 | As you can see, this is plain Java with no references to the Fn API. The 71 | Fn FDK for Java handles the marshalling of the HTTP body into the `str` 72 | parameter as well as the marshalling of the returned reversed string into the HTTP 73 | response body (see [Data Binding](../../DataBinding.md) for more 74 | information on how marshalling is performed). 75 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo CLI Guide 2 | 3 | 4 | 5 | Table of Contents
6 | CLI Source Code
7 | Fn Command Reference
8 | Fn CLI How-to Guides 9 |
10 | 11 | ### CLI Source Code 12 | 13 | * [https://github.com/fnproject/cli/](https://github.com/fnproject/cli/) 14 | 15 | ### Fn Command Reference 16 | 17 | [fn build](ref/fn-build.md) 18 | [fn bump](ref/fn-bump.md) 19 | [fn config](ref/fn-config.md) 20 | [fn create](ref/fn-create.md) 21 | [fn create app](ref/fn-create-app.md) 22 | [fn create context](ref/fn-create-context.md) 23 | [fn create function](ref/fn-create-function.md) 24 | [fn create trigger](ref/fn-create-trigger.md) 25 | [fn delete](ref/fn-delete.md) 26 | [fn deploy](ref/fn-deploy.md) 27 | [fn get](ref/fn-get.md) 28 | [fn get config](ref/fn-get-config.md) 29 | [fn help](ref/fn-help.md) 30 | [fn init](ref/fn-init.md) 31 | [fn inspect](ref/fn-inspect.md) 32 | [fn invoke](ref/fn-invoke.md) 33 | [fn list](ref/fn-list.md) 34 | [fn list apps](ref/fn-list-apps.md) 35 | [fn list config](ref/fn-list-config.md) 36 | [fn list contexts](ref/fn-list-contexts.md) 37 | [fn list triggers](ref/fn-list-triggers.md) 38 | [fn migrate](ref/fn-migrate.md) 39 | [fn push](ref/fn-push.md) 40 | [fn start](ref/fn-start.md) 41 | [fn stop](ref/fn-stop.md) 42 | [fn unset](ref/fn-unset.md) 43 | [fn update](ref/fn-update.md) 44 | [fn update app](ref/fn-update-app.md) 45 | [fn update context](ref/fn-update-context.md) 46 | [fn update function](ref/fn-update-function.md) 47 | [fn update server](ref/fn-update-server.md) 48 | [fn update trigger](ref/fn-update-trigger.md) 49 | [fn use](ref/fn-use.md) 50 | [fn version](ref/fn-version.md) 51 | 52 | version: 0.5.96 53 | 54 | 55 | ### [Fn CLI How-to Guides](how-to/README.md) 56 | 57 | #### Deploy Apps with Fn 58 | * [Manage an Fn Server](how-to/manage-server.md) 59 | * [Create and Run Functions with Fn](how-to/create-run-fn.md) 60 | * [Create an init-image for Fn](how-to/create-init-image.md) 61 | -------------------------------------------------------------------------------- /fn/develop/fdks.md: -------------------------------------------------------------------------------- 1 | # Function Development Kits (FDKs) 2 | 3 | FDKs are language kits designed to help make working with Fn easier in each language. 4 | 5 | Using the `fn init` CLI command will produce a boilerplate function along with the FDK imported and ready to go for runtime specified using `--runtime`. (eg `fn init --runtime go`). 6 | 7 | The Fn team has chosen a set of FDKs to initially support, while other FDKs will be labeled as "experimental". 8 | 9 | ## Officially Supported FDKs 10 | 11 | * [C#](https://fnproject.io/tutorials/csharp/intro/) 12 | * [Go](https://github.com/fnproject/docs/tree/master/fdks/fdk-go) 13 | * [Java](https://github.com/fnproject/docs/blob/master/fdks/fdk-java/README.md) 14 | * [Python](https://github.com/fnproject/docs/blob/master/fdks/fdk-python/README.md) 15 | * [Ruby](https://github.com/fnproject/docs/tree/master/fdks/fdk-ruby) 16 | * [NodeJS](https://github.com/fnproject/docs/tree/master/fdks/fdk-node) 17 | 18 | To search for all FDK work, you can [search the fnproject GitHub org](https://github.com/fnproject?utf8=%E2%9C%93&q=FDK). 19 | 20 | ## Community Supported FDKs 21 | * [C# / .NET Core](https://github.com/Daniel15/fdk-dotnet) 22 | 23 | ## Bring your own Container 24 | 25 | Because the Fn Project can use any container, almost any language or package can be used to build functions. The following tutorial helps with this process: 26 | 27 | https://fnproject.io/tutorials/ContainerAsFunction/ 28 | 29 | Also read about the [Fn Container Contract](fn-format.md) for more information. 30 | 31 | ## Examples 32 | * FDK for Java 33 | * [Configuration Variables](https://github.com/fnproject/docs/tree/master/fdks/fdk-java/examples/configuration-variables): Set configuration values for applications, function, and in `func.yaml`. 34 | * [Gradle Build](https://github.com/fnproject/docs/tree/master/fdks/fdk-java/examples/gradle-build): Use a function to build and run a Java app using Gradle. 35 | * [Regex](https://github.com/fnproject/docs/tree/master/fdks/fdk-java/examples/regex-query): Pass a regex to a function. 36 | * [Simple Reverse String](https://github.com/fnproject/docs/tree/master/fdks/fdk-java/examples/string-reverse): Reverse the letters in a string. 37 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/src/main/java/com/example/fn/QRGen.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fnproject.fn.api.RuntimeContext; 4 | import com.fnproject.fn.api.httpgateway.HTTPGatewayContext; 5 | import net.glxn.qrgen.core.image.ImageType; 6 | import net.glxn.qrgen.javase.QRCode; 7 | 8 | import java.io.ByteArrayOutputStream; 9 | 10 | public class QRGen { 11 | private final String defaultFormat; 12 | 13 | public QRGen(RuntimeContext ctx) { 14 | defaultFormat = ctx.getConfigurationByKey("FORMAT").orElse("png"); 15 | } 16 | 17 | public byte[] create(HTTPGatewayContext hctx) { 18 | // If format or contents is empty, set default to png and Hello World 19 | ImageType type = getFormat(hctx.getQueryParameters().get("format").orElse(defaultFormat)); 20 | System.err.println("Format set to: " + type.toString()); 21 | 22 | String contents = hctx.getQueryParameters().get("contents").orElse("QRCode Hello World!"); 23 | System.err.println("QR code generated from contents: " + contents); 24 | 25 | ByteArrayOutputStream stream = QRCode.from(contents).to(type).stream(); 26 | 27 | hctx.setResponseHeader("Content-Type", getMimeType(type)); 28 | return stream.toByteArray(); 29 | } 30 | 31 | private ImageType getFormat(final String extension) { 32 | switch (extension.toLowerCase()) { 33 | case "png": 34 | return ImageType.PNG; 35 | case "jpg": 36 | case "jpeg": 37 | return ImageType.JPG; 38 | case "gif": 39 | return ImageType.GIF; 40 | case "bmp": 41 | return ImageType.BMP; 42 | default: 43 | return ImageType.PNG; 44 | } 45 | } 46 | 47 | private String getMimeType(final ImageType type) { 48 | switch (type) { 49 | case JPG: 50 | return "image/jpeg"; 51 | case GIF: 52 | return "image/gif"; 53 | case PNG: 54 | return "image/png"; 55 | case BMP: 56 | return "image/bmp"; 57 | default: 58 | return "image/png"; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /fn/operate/production.md: -------------------------------------------------------------------------------- 1 | # Running Fn in Production 2 | 3 | The [QuickStart guide](https://github.com/fnproject/fn#quickstart) is intended to quickly get started and kick the tires. To run in production and be ready to scale, you need 4 | to use more production ready components. 5 | 6 | * Put the Fn Servers (API) behind a load balancer. You can run several instances of them (the more the merrier). 7 | * Run a database that can scale. 8 | * Asynchronous functions require a message queue (preferably one that scales). 9 | 10 | Here's a rough diagram of what a production deployment looks like: 11 | 12 | ![FN Architecture Diagram](../assets/architecture.png) 13 | 14 | ## Load Balancer 15 | 16 | Any load balancer will work, put every instance of Fn that you run behind the load balancer. 17 | 18 | ## Database 19 | 20 | We've done our best to keep the database usage to a minimum. There are no writes during the request/response cycle which where most of the load will be. 21 | 22 | The database is pluggable and we currently support a few options that can be [found here](databases/README.md). We welcome pull requests for more! 23 | 24 | ## Message Queue 25 | 26 | The message queue is an important part of asynchronous functions, buffering requests for processing when resources are available. The reliability and scale of the message queue will play an important part in how well Fn runs, in particular if you use a lot of asynchronous function calls. 27 | 28 | The message queue is pluggable and we currently support a few options that can be [found here](../operate/message-queues.md). We welcome pull requests for more! 29 | 30 | ## Logging, Metrics and Monitoring 31 | 32 | Logging is a particularly important part of Fn, such that it emits both logs and metrics the same way. Ops teams can then decide how they want to use the logs and metrics without us prescribing a particular technology. For instance, you can use [logspout-statsd](https://github.com/treeder/logspout-statsd) to capture metrics from the logs and forward them to statsd. 33 | 34 | [More about Metrics](metrics.md) 35 | 36 | ## Scaling 37 | 38 | There are metrics emitted to the logs that can be used to notify you when to scale. The most important being the `wait_time` metrics for both the synchronous and asynchronous functions. If `wait_time` increases, you'll want to start more Fn instances. 39 | -------------------------------------------------------------------------------- /fdks/fdk-go/README.md: -------------------------------------------------------------------------------- 1 | # Go Fn Development Kit (FDK) 2 | 3 | [![GoDoc](https://godoc.org/github.com/fnproject/fdk-go?status.svg)](https://godoc.org/github.com/fnproject/fdk-go) 4 | 5 | fdk-go provides convenience functions for writing Go fn code 6 | 7 | For getting started with fn, please refer to https://github.com/fnproject/fn/blob/master/README.md 8 | 9 | # Installing fdk-go 10 | 11 | ```sh 12 | go get github.com/fnproject/fdk-go 13 | ``` 14 | 15 | or your favorite vendoring solution :) 16 | 17 | # Examples 18 | 19 | For a simple getting started, see the [examples](https://github.com/fnproject/fdk-go/tree/master/examples) and follow 20 | the [README](https://github.com/fnproject/fdk-go/tree/master/examples). If you already have `fn` set up it 21 | will take 2 minutes! 22 | 23 | # Advanced example 24 | 25 | TODO going to move to [examples](examples/) too :) 26 | 27 | ```go 28 | package main 29 | 30 | import ( 31 | "context" 32 | "fmt" 33 | "io" 34 | "encoding/json" 35 | 36 | fdk "github.com/fnproject/fdk-go" 37 | "net/http" 38 | ) 39 | 40 | func main() { 41 | fdk.Handle(fdk.HandlerFunc(myHandler)) 42 | } 43 | 44 | func myHandler(ctx context.Context, in io.Reader, out io.Writer) { 45 | fnctx := fdk.Context(ctx) 46 | 47 | contentType := fnctx.Header.Get("Content-Type") 48 | if contentType != "application/json" { 49 | fdk.WriteStatus(out, 400) 50 | fdk.SetHeader(out, "Content-Type", "application/json") 51 | io.WriteString(out, `{"error":"invalid content type"}`) 52 | return 53 | } 54 | 55 | if fnctx.Method != "PUT" { 56 | fdk.WriteStatus(out, 404) 57 | fdk.SetHeader(out, "Content-Type", "application/json") 58 | io.WriteString(out, `{"error":"route not found"}`) 59 | return 60 | } 61 | 62 | var person struct { 63 | Name string `json:"name"` 64 | } 65 | json.NewDecoder(in).Decode(&person) 66 | 67 | // you can write your own headers & status, if you'd like to 68 | fdk.WriteStatus(out, 201) 69 | fdk.SetHeader(out, "Content-Type", "application/json") 70 | 71 | all := struct { 72 | Name string `json:"name"` 73 | Header http.Header `json:"header"` 74 | Config map[string]string `json:"config"` 75 | }{ 76 | Name: person.Name, 77 | Header: fnctx.Header, 78 | Config: fnctx.Config, 79 | } 80 | 81 | json.NewEncoder(out).Encode(&all) 82 | } 83 | ``` -------------------------------------------------------------------------------- /fdks/fdk-ruby/README.md: -------------------------------------------------------------------------------- 1 | # Function Development Kit for Ruby 2 | 3 | The Function Development Kit for Ruby (FDK for Ruby) provides a Ruby framework for developing `functions` for us with [Fn](https://fnproject.github.io). 4 | 5 | ## Function Handler 6 | 7 | To use this FDK, you simply need to require this gem. 8 | 9 | ```ruby 10 | require 'fdk` 11 | ``` 12 | 13 | Then create a function with with the following syntax: 14 | 15 | ```ruby 16 | def myfunc(context, input) 17 | # Do some work here 18 | return output 19 | end 20 | ``` 21 | 22 | * context - provides runtime information for your function, such as configuration values, headers, etc. 23 | * input – This parameter is a string containing body of the request. 24 | * output - is where you can return data back to the caller. Whatever you return will be sent back to the caller. 25 | * Default output format should be in JSON, as Content-Type header will be `application/json` by default. You can be more flexible if you create and return 26 | an FDK::Response object instead of a string. 27 | 28 | Then simply pass that function to the FDK: 29 | 30 | ```ruby 31 | FDK.handle(myfunction) 32 | ``` 33 | 34 | ## Full Example 35 | 36 | ```ruby 37 | require 'fdk' 38 | 39 | def myfunction(context:, input:) 40 | input_value = input.respond_to?(:fetch) ? input.fetch('name') : input 41 | name = input_value.to_s.strip.empty? ? 'World' : input_value 42 | { message: "Hello #{name}!" } 43 | end 44 | 45 | FDK.handle(function: :myfunction) 46 | ``` 47 | 48 | ## Running the example that is in the root directory of this repo 49 | 50 | ```sh 51 | $ echo '{"name":"coolio"}' | fn run 52 | {"message":"Hello coolio!"} 53 | ``` 54 | 55 | You can also specify the format (the default is JSON) 56 | 57 | ```sh 58 | $ echo '{"name":"coolio"}' | fn run --format json 59 | {"message":"Hello coolio!"} 60 | ``` 61 | 62 | If you want to just pass plain text to the function, specify a format of __default__: 63 | 64 | ```sh 65 | $ echo 'coolio' | fn run --format default 66 | {"message":"Hello coolio!"} 67 | ``` 68 | 69 | Deploy: 70 | 71 | ```sh 72 | fn deploy --app myapp --local && echo '{"name":"coolio"}' | fn call myapp /fdk-ruby 73 | ``` 74 | 75 | Change to hot: 76 | 77 | Update func.yaml: `format: json` 78 | 79 | ```sh 80 | fn deploy --app myapp --local && echo '{"name":"coolio"}' | fn call myapp /fdk-ruby 81 | ``` 82 | 83 | ## Compare cold and hot 84 | 85 | Run 86 | 87 | ```sh 88 | ruby loop.rb 89 | ``` 90 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | UTF-8 8 | 1.0.99 9 | 10 | com.example.fn 11 | connection 12 | 1.0.0 13 | 14 | 15 | 16 | fn-release-repo 17 | https://dl.bintray.com/fnproject/fnproject 18 | 19 | true 20 | 21 | 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | com.fnproject.fn 30 | api 31 | ${fdk.version} 32 | 33 | 34 | com.fnproject.fn 35 | testing-core 36 | ${fdk.version} 37 | test 38 | 39 | 40 | com.fnproject.fn 41 | testing-junit4 42 | ${fdk.version} 43 | test 44 | 45 | 46 | junit 47 | junit 48 | 4.12 49 | test 50 | 51 | 52 | com.fnproject.fn 53 | flow-testing 54 | ${fdk.version} 55 | test 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-compiler-plugin 64 | 3.3 65 | 66 | 11 67 | 11 68 | 69 | 70 | 71 | 72 | connection string 73 | 74 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/string-reverse/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | UTF-8 8 | 1.0.87 9 | 10 | com.example.fn 11 | string-reverse 12 | 1.0.0 13 | 14 | 15 | 16 | fn-release-repo 17 | https://dl.bintray.com/fnproject/fnproject 18 | 19 | true 20 | 21 | 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | com.fnproject.fn 30 | api 31 | ${fdk.version} 32 | 33 | 34 | com.fnproject.fn 35 | testing-core 36 | ${fdk.version} 37 | test 38 | 39 | 40 | com.fnproject.fn 41 | testing-junit4 42 | ${fdk.version} 43 | test 44 | 45 | 46 | junit 47 | junit 48 | 4.12 49 | test 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-compiler-plugin 58 | 3.3 59 | 60 | 8 61 | 8 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-surefire-plugin 67 | 2.22.1 68 | 69 | false 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /fn/operate/context-commands.md: -------------------------------------------------------------------------------- 1 | # Fn Context Commands 2 | The Fn context is a configuration file stored in the `~/fn/contexts` directory. Each context file stores all the information needed to make a connection to an Fn server. The Fn context determines where the CLI will find an Fn server which allow you to issue command for that server. 3 | 4 | 5 | ## Sample Context File 6 | When you run Fn the first time, a default context YAML file is created (`~./fn/contexts/default.yaml`). A sample Fn default context file looks like this. 7 | 8 | ```yaml 9 | api-url: http://localhost:8080 10 | provider: default 11 | registry: fndemouser 12 | ``` 13 | 14 | * `api-url` - URL location of the Fn server. 15 | * `provider` - Service provider for Fn. Contains the name of the provider or "default" by default. 16 | * `registry` - Login name for the Docker registry used with this context. In this example, `fndemouser` (fn demo user) is a made up name which causes Docker to store image data locally. If you wish to use Docker Hub to store your images, you will put your Docker Hub login ID in this field. 17 | 18 | ## Fn Context Command Reference 19 | The following sections provide definitions and examples of all the Fn commands related to the Fn context. 20 | 21 | ### Cheat Sheet 22 | * Create: `fn c ctx --api-url http://: --registry ` 23 | * Delete: `fn d ctx ` 24 | * List: `fn i ctx ` 25 | * List all: `fn ls ctx` 26 | * Update (Add) Name/Value: `fn up ctx ` 27 | * Update (Delete) Name/Value: `fn up ctx --delete ` 28 | 29 | 30 | ## Usage: Setup a new Context 31 | Here are the steps to setup a new context. 32 | * Create context 33 | * `fn c ctx my-ctx --api-url http://localhost:8080 --registry yourGitHubUserName` 34 | * Use the new context: 35 | * `fn u ctx my-ctx` 36 | * Get list of contexts: 37 | * `fn ls ctx` 38 | * Should show all the contexts that exist with your new context selected. 39 | 40 | 41 | ### Usage Examples 42 | * Create: `fn c ctx my-ctx --api-url http://localhost:8080 --registry youridhere` 43 | * Delete: `fn d ctx my-ctx` 44 | * List: `fn i ctx my-ctx` 45 | * List all: `fn ls ctx` 46 | * Update (Add) Name/Value: `fn u ctx KEY value` 47 | * Update (Delete) Name/Value: `fn u ctx --delete KEY` 48 | 49 | 50 | 51 | ### Detailed Command Examples 52 | * **Create** a new Fn context with the name and data provided. 53 | * `fn create context --api-url http://: --registry ` 54 | * **Delete** an Fn context with the specified name. 55 | * `fn delete context ` 56 | * **List** a context's settings. 57 | * `fn inspect context ` 58 | * **List all** contexts on this system. 59 | * `fn list contexts` 60 | * **Add or Update** key/value data in your context. 61 | * `fn update context ` 62 | * **Update (Delete)** a name/value pair from your context. 63 | * `fn update context --delete ` 64 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | 9 | UTF-8 10 | 1.0.98 11 | 12 | 13 | com.example.fn 14 | qr-code 15 | 1.0.0 16 | 17 | 18 | 19 | com.github.kenglxn.qrgen 20 | javase 21 | 2.3.0 22 | 23 | 24 | 25 | com.fnproject.fn 26 | api 27 | ${fdk.version} 28 | 29 | 30 | 31 | junit 32 | junit 33 | 4.12 34 | test 35 | 36 | 37 | com.fnproject.fn 38 | testing 39 | ${fdk.version} 40 | test 41 | 42 | 43 | com.fnproject.fn 44 | testing-junit4 45 | ${fdk.version} 46 | test 47 | 48 | 49 | 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-compiler-plugin 54 | 3.3 55 | 56 | 8 57 | 8 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-surfire-plugin 63 | 2.22.1 64 | 65 | false 66 | 67 | 68 | 69 | 70 | 71 | 72 | jitpack.io 73 | https://jitpack.io 74 | 75 | 76 | fn-release-repo 77 | https://dl.bintray.com/fnproject/fnproject 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /fn/develop/func-file.md: -------------------------------------------------------------------------------- 1 | # Func files 2 | 3 | A func file contains metadata that help the fn project when you create a function. 4 | 5 | Example of a func file: 6 | 7 | ```yaml 8 | schema_version: 20180708 9 | name: fnproject/hello 10 | version: 0.0.1 11 | runtime: java 12 | build_image: x/y 13 | run_image: x/y 14 | cmd: com.example.fn.HelloFunction::handleRequest 15 | memory: 128 16 | timeout: 30 17 | config: 18 | key: value 19 | key2: value2 20 | keyN: valueN 21 | expects: 22 | config: 23 | - name: SECRET_1 24 | required: true 25 | - name: SECRET_2 26 | required: false 27 | triggers: 28 | - name: triggerOne 29 | type: http 30 | source: /trigger-path 31 | ``` 32 | **schema_version:** Represents the version of the specification for this file. 33 | 34 | **name:** Unique name for this function. 35 | 36 | **version:** Represents the current version of the function. After deploying, it is appended to the image as a tag. 37 | 38 | **runtime:** Represents programming language runtime, for example, 39 | 'go', 'python', 'java', etc. The runtime 'docker' will use the existing Dockerfile if one exists. Current valid values for runtime as of v0.5.86 are: go, java8, java9, java, java11, node, python, python3.6, python, python3.7, ruby, and kotlin. 40 | 41 | **build_image:** (Optional) Base Docker image used for building your function. Default images used are the `dev` tagged images from the [dockers repo](https://github.com/fnproject/dockers). 42 | 43 | **run_image:** (Optional) Base Docker image used for running your function, as part of a multi-stage build. Function will be built with `build_image` and run with `run_image`. Default images used from the [dockers repo](https://github.com/fnproject/dockers). 44 | 45 | **cmd:** (Optional) Execution command for jvm based runtimes. 46 | 47 | **entrypoint:** (Optional) Execution entry point for native runtimes. 48 | 49 | **memory:** (Optional) Maximum memory threshold for this 50 | function. If this function exceeds this limit during execution, it is stopped 51 | and error message is logged. Set this value in multiples of 64. The maximum memory value allowed is 8 (GB) and the default value is 128 (MB). 52 | 53 | **timeout:** (Optional) Maximum runtime allowed for this function in seconds. The maximum value is 300 and the default values is 30. 54 | 55 | **config:** (Optional) Set of configuration variables pass onto the function as environment variables. 56 | These configuration options override application configuration during functions execution. See [Configuration](configs.md) 57 | for more information. 58 | 59 | **expects:** (Optional) List of configuration environment variables required to run this function. These variables are used when you run or test locally. If these variables are not found in your local environment, then your local testing fails. 60 | 61 | **triggers:** (Optional) Array of `trigger` entities that specific triggers for the function. See [Trigger](triggers.md) for more information. 62 | 63 | **signing_details:** (Optional) Function image signing information. Supported only when Oracle Provider is used. See [Configure image signature](../../cli/how-to/create-run-fn.md) for mode details. -------------------------------------------------------------------------------- /cli/how-to/create-run-fn.md: -------------------------------------------------------------------------------- 1 | # Create and Run Functions with Fn 2 | This how-to covers how to create and test functions. 3 | 4 | ## Create a Boilerplate Function with Init 5 | Fn provides the `init` option to setup or create a function you can test. To created a "Hello World" function using boilerplate code type: 6 | 7 | fn init --runtime node nodefn 8 | 9 | The command generates four files: 10 | 11 | * `func.js` - A boilerplate Node.js JavaScript function. 12 | * `func.yaml` - A boilerplate YAML file containing boilerplate configuration options for the function. 13 | * `package.json` - A list of packages required for the function. 14 | * `test.json` - A file for running tests on your function. 15 | 16 | The key Fn configuration file here is the `func.yaml` file. The file created from the sample command would be: 17 | 18 | ```yaml 19 | name: nodefn 20 | version: 0.0.1 21 | runtime: node 22 | entrypoint: node func.js 23 | ``` 24 | 25 | For more information on possible value in the `func.yaml` file see **Link to funcfile doc**. 26 | 27 | ## Set the Version Number when Creating a Function 28 | By default, when the `func.yaml` file is created, the version is set to `0.0.1`. If you with to start with a different number use the version command. 29 | 30 | fn init --version 1.0.1 --runtime node t1 31 | 32 | This creates a `func.yaml` file with a version set to `1.01`. 33 | 34 | ```yaml 35 | name: t1 36 | version: 1.0.1 37 | runtime: node 38 | entrypoint: node func.js 39 | ``` 40 | 41 | ## Create a `func.yaml` using an Existing Function File 42 | You can create a `func.yaml` file from an existing function file. For example, if I have a function named `func.js` in a directory named `t3`. Run the init command: 43 | 44 | fn init 45 | 46 | Fn will find your function file, determine it is a type Node and generate a func.yaml for you. For example 47 | 48 | ```yaml 49 | name: t3 50 | version: 0.0.1 51 | runtime: node 52 | entrypoint: node func.js 53 | ``` 54 | 55 | ## Configure image signature details in `func.yaml` 56 | You can sign function images using Oracle OCI keys. This is supported only when Oracle Provider is used. For more details on signing images refer to [OCIR Image Signature.](https://docs.oracle.com/iaas/Content/Registry/Tasks/registrysigningimages_topic.htm) 57 | 58 | To sign the function image, add the following section to `func.yaml` before running the `fn deploy` command. The `fn deploy` command will push the function image to the [OCI Container Registry (OCIR)](https://docs.oracle.com/iaas/Content/Registry/home.htm) and use the signing details provided to sign the function image in OCIR. 59 | ```yaml 60 | signing_details: 61 | image_compartment_id: ocid1.tenancy.oc1..aaaaaaaaba3____dsq 62 | kms_key_id: ocid1.key.oc1.phx.bbqehaq3aadfa.abyh______qlj 63 | kms_key_version_id: ocid1.keyversion.oc1.phx.0.bbqehaq3aadfa.acy6______mbb 64 | signing_algorithm: SHA_224_RSA_PKCS_PSS 65 | ``` 66 | where: 67 | - `image_compartment_id`: [OCID of the tenant to which image repository belongs](https://docs.oracle.com/iaas/Content/General/Concepts/identifiers.htm#tenancy_ocid) 68 | - `kms_key_id`: OCID of the master encryption key to use to sign the image 69 | - `kms_key_version_id`: OCID of the key version to use to sign the image 70 | - `signing_algorithm`: [Signing Algorithm to use to sign the image](https://docs.oracle.com/iaas/api/#/en/key/release/datatypes/SignDataDetails) 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /fn/develop/extensions.md: -------------------------------------------------------------------------------- 1 | # Writing Extensions 2 | 3 | Fn is extensible so you can add custom functionality and extend the project without needing to modify the core. 4 | 5 | There are multiple ways to extend the functionality of Fn. 6 | 7 | 1. Listeners - listen to API events such as a route getting updated and react accordingly. 8 | 1. Middleware - a chain of middleware is executed before an API handler is called. 9 | 1. Add API Endpoints - extend the default Fn API. 10 | 11 | To create an extension, there are just a couple of rules to follow. 12 | 13 | * All config should be via ENV vars. 14 | 15 | ## Code 16 | 17 | Your extension code needs to register itself with an `init()` method which states it's name and a function 18 | to be called during setup: 19 | 20 | ```go 21 | func init() { 22 | server.RegisterExtension(&fnext.Extension{ 23 | Name: "github.com/treeder/fn-ext-example/logspam", // Should be the import name 24 | Setup: setup, // Fn will call this during startup 25 | }) 26 | } 27 | 28 | func setup(s *fnext.ExtServer) error { 29 | // Add all the hooks your extension needs here 30 | s.AddCallListener(&LogSpam{}) 31 | } 32 | ``` 33 | 34 | See https://github.com/treeder/fn-ext-example for full example. 35 | 36 | ## Listeners 37 | 38 | Listeners are the main way to extend Fn. 39 | 40 | The following listener types are supported: 41 | 42 | * App Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#AppListener) 43 | * Call Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#CallListener) 44 | 45 | ### Creating a Listener 46 | 47 | You can easily use add listeners by creating a struct with valid methods satisfying the interface 48 | for the respective listener, adding it to `main.go` then compiling. 49 | 50 | Example: 51 | 52 | ```go 53 | package main 54 | 55 | import ( 56 | "context" 57 | 58 | "github.com/fnproject/fn/api/server" 59 | "github.com/fnproject/fn/api/models" 60 | ) 61 | 62 | type myCustomListener struct{} 63 | 64 | func (c *myCustomListener) BeforeAppCreate(ctx context.Context, app *models.App) error { return nil } 65 | func (c *myCustomListener) AfterAppCreate(ctx context.Context, app *models.App) error { return nil } 66 | 67 | func (c *myCustomListener) BeforeAppUpdate(ctx context.Context, app *models.App) error { return nil } 68 | func (c *myCustomListener) AfterAppUpdate(ctx context.Context, app *models.App) error { return nil } 69 | 70 | func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil } 71 | func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil } 72 | 73 | function main () { 74 | srv := server.New(/* Here all required parameters to initialize the server */) 75 | 76 | srv.AddAppListener(myCustomListener) 77 | 78 | srv.Run() 79 | } 80 | ``` 81 | 82 | ## Middleware 83 | 84 | Middleware enables you to add functionality to every API request. For every request, the chain of Middleware will be called 85 | in order, allowing you to modify or reject requests, as well as write output and cancel the chain. 86 | 87 | NOTES: 88 | 89 | * middleware is responsible for writing output if it's going to cancel the chain. 90 | 91 | See examples of this in [examples/middleware/main.go](../../examples/middleware/main.go). 92 | 93 | ## Adding API Endpoints 94 | 95 | You can add API endpoints to the Fn server by using the `AddEndpoint` and `AddEndpointFunc` methods. 96 | 97 | See examples of this in [examples/extensions/main.go](../../examples/extensions/main.go). -------------------------------------------------------------------------------- /community/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team by messaging the [Fn Team on the Fn Project forums](https://forums.fnproject.io/groups/FnTeam). All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | -------------------------------------------------------------------------------- /fn/operate/variable-commands.md: -------------------------------------------------------------------------------- 1 | # Fn Variable Commands 2 | The Fn CLI can store config variable information in the following places: 3 | 4 | * **Applications:** Variables can be accessed by all functions in the application. 5 | * **Functions:** Variables that can only by accessed by a single function. 6 | 7 | 8 | ## Fn Variable Command Reference 9 | The following sections provide definitions and examples of all the Fn commands related to the Fn context. 10 | 11 | 12 | ### Fn Application Vars Cheat Sheet 13 | * Create: `fn cf a ` 14 | * Delete: `fn d cf a ` 15 | * List: `fn ls cf a ` 16 | * List all Apps: `fn ls a` 17 | * Update Name/Value: `fn cf a ` 18 | * Overwrites the value. 19 | 20 | 21 | ### Fn Function Vars Cheat Sheet 22 | * Create: `fn cf f ` 23 | * Delete: `fn d cf f ` 24 | * List: `fn ls cf f ` 25 | * List all Functions: `fn ls f ` 26 | * Update Name/Value: `fn cf f ` 27 | * Overwrites the value. 28 | 29 | 30 | ## Usage: Setup a new App and Variable 31 | Here are the steps to setup a new app and add a key/value pair. 32 | * Create new app. 33 | * `fn c a ` 34 | * Add a variable to your application. 35 | * `fn cf a ` 36 | * Get list of all the variables set for the application. 37 | * `fn ls cf a ` 38 | 39 | 40 | ## Usage: Setup a new Function and Variable 41 | Here are the steps to setup a function key/value pair. 42 | * Create new app. 43 | * `fn c a ` 44 | * Deploy your function to the application. 45 | * `fn dp --app --local` 46 | * Add a variable to your function. 47 | * `fn cf f ` 48 | * Get list of all the variables set for the application. 49 | * `fn ls cf f ` 50 | 51 | 52 | ## Fn Application Vars Usage Examples 53 | * Create: `fn cf a my-app DB_USER my-user-name` 54 | * Delete: `fn d cf a my-app DB_USER` 55 | * List: `fn ls cf a my-app` 56 | * List all Apps: `fn ls a` 57 | * Update Name/Value: `fn cf a my-app DB_USER my-different-user-name` 58 | * Overwrites the value. 59 | 60 | 61 | ## Fn Function Vars Usage Examples 62 | * Create: `fn cf f my-app my-func DB_HOST myhost` 63 | * Delete: `fn d cf f my-app my-func DB_HOST` 64 | * List: `fn ls cf f my-app my-func` 65 | * List all Functions: `fn ls f my-app` 66 | * Update Name/Value: `fn cf f my-app my-func DB_HOST mynewhost` 67 | * Overwrites the value. 68 | 69 | 70 | ## Detailed Fn Application Vars Command Examples 71 | * **Create** a new Fn app variable. 72 | * `fn config app ` 73 | * **Delete** an Fn app variable. 74 | * `fn delete config app ` 75 | * **List** all contexts on this system. 76 | * `fn list config app ` 77 | * **Update** key/value data for your application. 78 | * `fn config app ` 79 | 80 | 81 | ## Detailed Fn Function Vars Command Examples 82 | * Create: `fn config function ` 83 | * Delete: `fn delete config function ` 84 | * List: `fn list config function ` 85 | * List all Functions: `fn list functions ` 86 | * Update Name/Value: `fn config function ` 87 | * Overwrites the value. 88 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | UTF-8 9 | UTF-8 10 | 11 11 | 1.0.96 12 | 2.10.1 13 | 14 | 15 | com.example.fn 16 | regex-query 17 | 1.0.0 18 | 19 | 20 | 21 | com.fasterxml.jackson.core 22 | jackson-databind 23 | ${jackson.version} 24 | 25 | 26 | com.fasterxml.jackson.core 27 | jackson-annotations 28 | ${jackson.version} 29 | 30 | 31 | junit 32 | junit 33 | 4.12 34 | test 35 | 36 | 37 | com.fnproject.fn 38 | api 39 | ${fdk.version} 40 | 41 | 42 | com.fnproject.fn 43 | testing-core 44 | ${fdk.version} 45 | test 46 | 47 | 48 | com.fnproject.fn 49 | testing-junit4 50 | ${fdk.version} 51 | test 52 | 53 | 54 | org.skyscreamer 55 | jsonassert 56 | 1.5.0 57 | test 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.apache.maven.plugins 66 | maven-compiler-plugin 67 | 3.8.0 68 | 69 | 1.8 70 | 1.8 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-deploy-plugin 76 | 2.8.2 77 | 78 | true 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | fn-release-repo 87 | https://dl.bintray.com/fnproject/fnproject 88 | 89 | true 90 | 91 | 92 | false 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/src/test/java/com/example/fn/QRGenTest.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fnproject.fn.testing.FnTestingRule; 4 | import com.google.zxing.BinaryBitmap; 5 | import com.google.zxing.ChecksumException; 6 | import com.google.zxing.FormatException; 7 | import com.google.zxing.NotFoundException; 8 | import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 9 | import com.google.zxing.common.HybridBinarizer; 10 | import com.google.zxing.qrcode.QRCodeReader; 11 | import org.junit.Rule; 12 | import org.junit.Test; 13 | 14 | import javax.imageio.ImageIO; 15 | import java.awt.image.BufferedImage; 16 | import java.io.ByteArrayInputStream; 17 | import java.io.IOException; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | public class QRGenTest { 22 | @Rule 23 | public FnTestingRule fn = FnTestingRule.createDefault(); 24 | 25 | @Test 26 | public void textHelloWorld() { 27 | String content = "hello world"; 28 | String decodedImage = null; 29 | fn.givenEvent() 30 | .withHeader("Fn-Http-Request-Url", "http://www.example.com/qr?contents=hello+world&format=png") 31 | .withHeader("Fn-Http-Method","GET") 32 | .enqueue(); 33 | fn.thenRun(QRGen.class, "create"); 34 | 35 | try { 36 | decodedImage = decode(fn.getOnlyResult().getBodyAsBytes()); 37 | } catch(Exception e) { 38 | System.err.println("Failed to decode image: " + e.getStackTrace()); 39 | } 40 | 41 | assertEquals(content, decodedImage); 42 | } 43 | 44 | @Test 45 | public void phoneNumber() { 46 | String telephoneNumber = "tel:0-12345-67890"; 47 | String decodedImage = null; 48 | fn.givenEvent() 49 | .withHeader("Fn-Http-Request-Url", "http://www.example.com/qr?contents=tel:0-12345-67890") 50 | .withHeader("Fn-Http-Method","GET") 51 | .enqueue(); 52 | fn.thenRun(QRGen.class, "create"); 53 | 54 | try { 55 | decodedImage = decode(fn.getOnlyResult().getBodyAsBytes()); 56 | } catch(Exception e) { 57 | System.err.println("Failed to decode image: " + e.getStackTrace()); 58 | } 59 | 60 | assertEquals(telephoneNumber, decodedImage); 61 | 62 | } 63 | 64 | @Test 65 | public void formatConfigurationIsUsedIfNoFormatIsProvided() { 66 | String contents = "hello world"; 67 | String decodedImage = null; 68 | fn.setConfig("FORMAT", "jpg"); 69 | fn.givenEvent() 70 | .withHeader("Fn-Http-Request-Url", "http://www.example.com/qr?contents=hello+world") 71 | .withHeader("Fn-Http-Method","GET") 72 | .enqueue(); 73 | fn.thenRun(QRGen.class, "create"); 74 | 75 | try { 76 | decodedImage = decode(fn.getOnlyResult().getBodyAsBytes()); 77 | } catch(Exception e) { 78 | System.err.println("Failed to decode image: " + e.getStackTrace()); 79 | } 80 | 81 | assertEquals(contents, decodedImage); 82 | 83 | } 84 | 85 | private String decode(final byte[] imageBytes) throws IOException, NotFoundException, ChecksumException, FormatException { 86 | BinaryBitmap bitmap = readToBitmap(imageBytes); 87 | return new QRCodeReader().decode(bitmap).getText(); 88 | } 89 | 90 | private BinaryBitmap readToBitmap(final byte[] imageBytes) throws IOException { 91 | BufferedImage inputImage = ImageIO.read(new ByteArrayInputStream(imageBytes)); 92 | BufferedImageLuminanceSource luminanceSource = new BufferedImageLuminanceSource(inputImage); 93 | HybridBinarizer binarizer = new HybridBinarizer(luminanceSource); 94 | return new BinaryBitmap(binarizer); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/configuration-variables/README.md: -------------------------------------------------------------------------------- 1 | # Configuration Variables 2 | 3 | You can get configuration variables into a function and make them available as environment variables. 4 | 5 | The `configuration-variables` function creates a database connection string. This function has four variables: `DB_URL`, `DB_DRIVER`, `DB_USER`, and `DB_PASSWORD`. 6 | 7 | The `DB_URL`, `DB_DRIVER`, `DB_USER`, and `DB_PASSWORD` environment variables are set on different configuration levels. 8 | For example, the value of the `DB_DRIVER` variable is read from the `func.yaml` file in the `config` key. The `DB_URL` and `DB_USER` 9 | environment variables are set in the application configuration level, and the `DB_PASSWORD` environment variable is set in the 10 | function configuration level. 11 | 12 | ## Step by step: Set the configuration values 13 | Ensure you have the Fn server running to host your function. 14 | 15 | (1) Start the server. 16 | 17 | ```sh 18 | $ fn start 19 | ``` 20 | 21 | (2) Go to the `configuration-variables` directory. 22 | 23 | ```sh 24 | $ cd configuration-variables 25 | ``` 26 | 27 | (3) Create an app for the function. 28 | 29 | ```sh 30 | $ fn create app connection-app 31 | ``` 32 | 33 | (4) At the application level, configure the `DB_URL` environment variable. 34 | 35 | ```sh 36 | $ fn config app connection-app DB_URL jdbc:mysql 37 | ``` 38 | 39 | (5) At the application level, configure the `DB_USER` environment variable. 40 | 41 | ```sh 42 | $ fn config app connection-app DB_USER superadmin 43 | ``` 44 | 45 | (6) Deploy the application. 46 | 47 | ```sh 48 | $ fn deploy --app connection-app --local 49 | ``` 50 | (7) At the function level, configure the `DB_PASSWORD` environment variable. 51 | 52 | ```sh 53 | $ fn config function connection-app connection DB_PASSWORD superadmin 54 | ``` 55 | 56 | (8) Invoke the `connection` function. 57 | 58 | ```sh 59 | $ fn invoke connection-app connection 60 | driver: mysqlDriver; url: jdbc:mysql; user: superadmin; password: superadmin 61 | ``` 62 | 63 | ## Code walkthrough 64 | 65 | The entrypoint to the function is specified in `func.yaml` in the `cmd` key. 66 | It is set to `com.example.fn.Connection::getConnection`. The whole class 67 | `Connection` is shown below: 68 | 69 | ```java 70 | package com.example.fn; 71 | 72 | import com.fnproject.fn.api.FnConfiguration; 73 | import com.fnproject.fn.api.RuntimeContext; 74 | 75 | 76 | public class Connection { 77 | private String url; 78 | private String driver; 79 | private String user; 80 | private String password; 81 | 82 | @FnConfiguration 83 | public void config(RuntimeContext ctx) { 84 | //Set value at the application configuration level 85 | url = ctx.getConfigurationByKey("DB_URL") 86 | .orElse("jdbc:oracle"); 87 | //Set value in the func.yaml 88 | driver = ctx.getConfigurationByKey("DB_DRIVER") 89 | .orElse("OracleDriver"); 90 | //Set value at the application configuration level 91 | user = ctx.getConfigurationByKey("DB_USER") 92 | .orElse("admin"); 93 | } 94 | 95 | 96 | public String getUrl() { 97 | return url; 98 | } 99 | 100 | 101 | public String getDriver() { 102 | return driver; 103 | } 104 | 105 | 106 | public String getUser() { 107 | return user; 108 | } 109 | 110 | //Set value at the function configuration level 111 | public String getPassword() { 112 | password = System.getenv().getOrDefault("DB_PASSWORD", "admin"); 113 | return password; 114 | } 115 | 116 | public String getConnection() { 117 | return "driver: " + getDriver() + "; url: " + url + "; user: " + getUser() + "; password: " + getPassword(); 118 | } 119 | } 120 | 121 | ``` 122 | 123 | For more information see the [configuration vars documentaion page](https://github.com/fnproject/docs/blob/master/fn/develop/configs.md). 124 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/src/main/java/com/example/fn/ThumbnailsFunction.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.fnproject.fn.api.FnFeature; 4 | import com.fnproject.fn.api.Headers; 5 | import com.fnproject.fn.api.RuntimeContext; 6 | import com.fnproject.fn.api.flow.Flow; 7 | import com.fnproject.fn.runtime.flow.FlowFeature; 8 | import com.fnproject.fn.api.flow.Flows; 9 | import com.fnproject.fn.api.flow.HttpMethod; 10 | import io.minio.MinioClient; 11 | 12 | import java.io.ByteArrayInputStream; 13 | import java.io.Serializable; 14 | 15 | @FnFeature(FlowFeature.class) 16 | public class ThumbnailsFunction implements Serializable { 17 | 18 | private final String storageUrl; 19 | private final String storageAccessKey; 20 | private final String storageSecretKey; 21 | 22 | private final String resize128ID; 23 | private final String resize256ID; 24 | private final String resize512ID; 25 | 26 | public ThumbnailsFunction(RuntimeContext ctx) { 27 | storageUrl = ctx.getConfigurationByKey("OBJECT_STORAGE_URL") 28 | .orElseThrow(() -> new RuntimeException("Missing configuration: OBJECT_STORAGE_URL")); 29 | storageAccessKey = ctx.getConfigurationByKey("OBJECT_STORAGE_ACCESS") 30 | .orElseThrow(() -> new RuntimeException("Missing configuration: OBJECT_STORAGE_ACCESS")); 31 | storageSecretKey = ctx.getConfigurationByKey("OBJECT_STORAGE_SECRET") 32 | .orElseThrow(() -> new RuntimeException("Missing configuration: OBJECT_STORAGE_SECRET")); 33 | 34 | resize128ID = ctx.getConfigurationByKey("RESIZE_128_FN_ID") 35 | .orElseThrow(() -> new RuntimeException("Missing configuration: RESIZE_128_FN_ID")); 36 | resize256ID = ctx.getConfigurationByKey("RESIZE_256_FN_ID") 37 | .orElseThrow(() -> new RuntimeException("Missing configuration: RESIZE_256_FN_ID")); 38 | resize512ID = ctx.getConfigurationByKey("RESIZE_512_FN_ID") 39 | .orElseThrow(() -> new RuntimeException("Missing configuration: RESIZE_512_FN_ID")); 40 | 41 | } 42 | 43 | public class Response { 44 | Response(String imageId) { this.imageId = imageId; } 45 | public String imageId; 46 | } 47 | 48 | public Response handleRequest(byte[] imageBuffer) { 49 | String id = java.util.UUID.randomUUID().toString(); 50 | Flow runtime = Flows.currentFlow(); 51 | 52 | runtime.allOf( 53 | runtime.invokeFunction(resize128ID, HttpMethod.POST, Headers.emptyHeaders(), imageBuffer) 54 | .thenAccept((img) -> objectUpload(img.getBodyAsBytes(), id + "-128.png")), 55 | runtime.invokeFunction(resize256ID, HttpMethod.POST, Headers.emptyHeaders(), imageBuffer) 56 | .thenAccept((img) -> objectUpload(img.getBodyAsBytes(), id + "-256.png")), 57 | runtime.invokeFunction(resize512ID, HttpMethod.POST, Headers.emptyHeaders(), imageBuffer) 58 | .thenAccept((img) -> objectUpload(img.getBodyAsBytes(), id + "-512.png")), 59 | runtime.supply(() -> objectUpload(imageBuffer, id + ".png")) 60 | ); 61 | return new Response(id); 62 | } 63 | 64 | /** 65 | * Uploads the provided data to the storage server, as an object named as specified. 66 | * 67 | * @param imageBuffer the image data to upload 68 | * @param objectName the name of the remote object to create 69 | */ 70 | private void objectUpload(byte[] imageBuffer, String objectName) { 71 | try { 72 | MinioClient minioClient = new MinioClient(storageUrl, storageAccessKey, storageSecretKey); 73 | 74 | // Ensure the bucket exists. 75 | if(!minioClient.bucketExists("alpha")) { 76 | minioClient.makeBucket("alpha"); 77 | } 78 | 79 | // Upload the image to the bucket with putObject 80 | minioClient.putObject("alpha", objectName, new ByteArrayInputStream(imageBuffer), imageBuffer.length, "application/octet-stream"); 81 | } catch(Exception e) { 82 | System.err.println("Error occurred: " + e); 83 | e.printStackTrace(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /fn/develop/configs.md: -------------------------------------------------------------------------------- 1 | # Use of environment variables 2 | 3 | Do you want to use configuration variables into a function and make them available as environment variables? You can set configuration variables using the Fn CLI or the `func.yaml` file. 4 | 5 | By using the Fn CLI, your can set configuration variables on the application or function level. 6 | 7 | # Set environment variables 8 | 9 | The following three examples shows you how to set the configuration variables on different levels using the `connection-app` sample application. The configuration examples are listed in order of precedent, the later examples override the previous ones. For example, adding a function key/value pair overrides an application key/value pair with the same name. 10 | 11 | (1) Application level configuration 12 | 13 | Configuration variables set at the application level apply to all functions contained in that application. 14 | 15 | ```sh 16 | fn config app 17 | ``` 18 | For example, set the `DB_URL` configuration variable with value of `jdbc:mysql`. 19 | ```sh 20 | $ fn config app connection-app DB_URL jdbc:mysql 21 | ``` 22 | 23 | (2) Function configuration from `func.yaml` file 24 | 25 | Use the `func.yaml` file to define your configuration variables in the `config` key. For example: set the `DB_DRIVER` configuration variable with value of `mysqlDriver`. 26 | 27 | ```sh 28 | schema_version: 20180708 29 | name: connection 30 | version: 0.0.16 31 | runtime: java 32 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.99 33 | run_image: fnproject/fn-java-fdk:jre11-1.0.99 34 | cmd: com.example.fn.Connection::getConnection 35 | config: 36 | DB_DRIVER: mysqlDriver 37 | ``` 38 | See [Function file](func-file.md) for more info. 39 | 40 | (3) Function level configuration 41 | 42 | After you deploy your function, you can set function level configuration variables. The variables only apply to the specific function identified. 43 | ```sh 44 | fn config function 45 | ``` 46 | 47 | For example, set the `DB_PASSWORD` configuration variable with value of `superadmin`. 48 | ```sh 49 | $ fn config function connection-app connection DB_PASSWORD superadmin 50 | ``` 51 | 52 | 53 | 54 | # Get environment variables 55 | 56 | You can use your environment variable in your function by using a `RuntimeContext` instance or the `getenv()` method of the `System` class. 57 | 58 | 59 | The following example shows the `config` function configuration method, which is used to get the values of the `DB_URL`,`DB_DRIVER`, and `DB_USER` configuration variables. The `getPassword` method gets the value of the `DB_PASSWORD` configuration variable by using the `System` class. 60 | 61 | ```java 62 | package com.example.fn; 63 | 64 | import com.fnproject.fn.api.FnConfiguration; 65 | import com.fnproject.fn.api.RuntimeContext; 66 | 67 | 68 | public class Connection { 69 | private String url; 70 | private String driver; 71 | private String user; 72 | private String password; 73 | 74 | @FnConfiguration 75 | public void config(RuntimeContext ctx) { 76 | url = ctx.getConfigurationByKey("DB_URL") 77 | .orElse("jdbc:oracle"); 78 | driver = ctx.getConfigurationByKey("DB_DRIVER") 79 | .orElse("OracleDriver"); 80 | user = ctx.getConfigurationByKey("DB_USER") 81 | .orElse("admin"); 82 | } 83 | 84 | 85 | public String getUrl() { 86 | return url; 87 | } 88 | 89 | 90 | public String getDriver() { 91 | return driver; 92 | } 93 | 94 | 95 | public String getUser() { 96 | return user; 97 | } 98 | 99 | public String getPassword() { 100 | password = System.getenv().getOrDefault("DB_PASSWORD", "admin"); 101 | return password; 102 | } 103 | 104 | public String getConnection() { 105 | return "driver: " + getDriver() + "; url: " + url + "; user: " + getUser() + "; password: " + getPassword(); 106 | } 107 | } 108 | ``` 109 | 110 | See [configuration-variables example application](../../fdks/fdk-java/examples/configuration-variables) for more info. 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/setup/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | STORAGE_DIR="/tmp/example-storage-server-files" 5 | 6 | COMPLETER_IMAGE=fnproject/flow 7 | FUNCTIONS_IMAGE=fnproject/fnserver 8 | MINIO_IMAGE=minio/minio 9 | 10 | # Checks 11 | if docker ps &>/dev/null ; then 12 | echo "Docker is present." 13 | else 14 | echo "error: docker is not available." 15 | exit 1 16 | fi 17 | if fn --help &>/dev/null ; then 18 | echo "Fn is present." 19 | else 20 | echo "error: fn is not available." 21 | exit 1 22 | fi 23 | if type mc &>/dev/null ; then 24 | echo "mc is present." 25 | else 26 | echo "error: mc is not available, please install it from https://github.com/minio/mc" 27 | echo "mac os: brew install minio/stable/mc" 28 | echo "linux: sudo curl -sL https://dl.minio.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc && sudo chmod +x /usr/local/bin/mc" 29 | exit 1 30 | fi 31 | 32 | docker pull "$COMPLETER_IMAGE" 33 | docker pull "$FUNCTIONS_IMAGE" 34 | docker pull "$MINIO_IMAGE" 35 | 36 | # Set up the storage server and upload directory 37 | if [[ -z `docker ps | grep "example-storage-server"` ]]; then 38 | mkdir -p "$STORAGE_DIR" 39 | docker run -d --name example-storage-server \ 40 | -e "MINIO_ACCESS_KEY=alpha" \ 41 | -e "MINIO_SECRET_KEY=betabetabetabeta" \ 42 | -v "$STORAGE_DIR":/export \ 43 | -p 9000:9000 \ 44 | "$MINIO_IMAGE" server /export 45 | # Give it time to start up 46 | sleep 3 47 | else 48 | echo "Storage server is already up." 49 | fi 50 | 51 | STORAGE_SERVER_IP=`docker inspect --type container -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' example-storage-server` 52 | 53 | # Start functions server if not there 54 | if [[ -z `docker ps | grep "fnserver"` ]]; then 55 | fn start -d 56 | sleep 3 57 | else 58 | echo "Functions server is already up." 59 | fi 60 | # Get its IP 61 | FUNCTIONS_SERVER_IP=`docker inspect --type container -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' fnserver` 62 | 63 | # Start flow service if not there 64 | if [[ -z `docker ps | grep "flow-service"` ]]; then 65 | docker run -d --name flow-service \ 66 | -e LOG_LEVEL=debug \ 67 | -e NO_PROXY="$FUNCTIONS_SERVER_IP:$NO_PROXY" \ 68 | -e API_URL=http://$FUNCTIONS_SERVER_IP:8080/invoke \ 69 | -p 8081:8081 \ 70 | "$COMPLETER_IMAGE" 71 | # Give it time to start up 72 | sleep 3 73 | else 74 | echo "Flow Completer server is already up." 75 | fi 76 | # Get its IP 77 | COMPLETER_SERVER_IP=`docker inspect --type container -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' flow-service` 78 | 79 | # Create app and routes 80 | if [[ `fn list apps` == *"myapp"* ]]; then 81 | echo "App myapp is already there." 82 | else 83 | fn create app myapp 84 | fi 85 | 86 | 87 | fn config app myapp COMPLETER_BASE_URL http://${COMPLETER_SERVER_IP}:8081 88 | fn config app myapp OBJECT_STORAGE_URL http://${STORAGE_SERVER_IP}:9000 89 | fn config app myapp OBJECT_STORAGE_ACCESS alpha 90 | fn config app myapp OBJECT_STORAGE_SECRET betabetabetabeta 91 | 92 | ( 93 | cd ${SCRIPT_DIR}/resize128 94 | fn deploy --app myapp --local 95 | ) 96 | 97 | fn config app myapp RESIZE_128_FN_ID $(fn list functions myapp | grep resize128 | awk '{print $3}') 98 | 99 | ( 100 | cd ${SCRIPT_DIR}/resize256 101 | fn deploy --app myapp --local 102 | ) 103 | 104 | fn config app myapp RESIZE_256_FN_ID $(fn list functions myapp | grep resize256 | awk '{print $3}') 105 | 106 | 107 | ( 108 | cd ${SCRIPT_DIR}/resize512 109 | fn deploy --app myapp --local 110 | ) 111 | 112 | fn config app myapp RESIZE_512_FN_ID $(fn list functions myapp | grep resize512 | awk '{print $3}') 113 | 114 | 115 | 116 | 117 | if mc config host list | grep example-storage-server &>/dev/null ; then 118 | echo "mc example-storage-server configuration is already present" 119 | else 120 | echo "configuring mc example-storage-server host" 121 | mc config host add example-storage-server http://localhost:9000 alpha betabetabetabeta 122 | fi 123 | -------------------------------------------------------------------------------- /cli/how-to/create-init-image.md: -------------------------------------------------------------------------------- 1 | # Create an init-image for Fn 2 | This how-to shows how to create an init-image for Fn 3 | 4 | ## What is an init-image? 5 | 6 | An init-image can be used with `fn init --init-image=` to create a template for a function. Init-images 7 | can be used to create a HelloWorld function showing how to use a particular language, or for more complex 8 | templating. 9 | 10 | The requirements for an init-image are: 11 | 12 | - it will be run with `docker run -e FN_FUNCTION_NAME= init_image_name` 13 | - the output will be treated as a [tarball](https://en.wikipedia.org/wiki/Tar_(computing)) 14 | - the files in the tarball should form a valid function which can be run using `fn run`, with the exception of `func.yaml` 15 | - the output _should not_ contain a `func.yaml` file 16 | - the output _must_ contain a file called `func.init.yaml` which has a subset of the keys from a `func.yaml` 17 | - the `func.init.yaml` _must_ contain the following keys: `runtime` 18 | - the `func.init.yaml` _may_ also contain the following keys: `build`, `buildImage`, `cmd`, `content_type`, `entrypoint`, `expects`, `headers`, `runImage`, and `tests` 19 | 20 | 21 | The CLI will: 22 | - put the files in the archive on disk, owned by the current user and with correct permissions 23 | - merge the content of `func.init.yaml` with other properties such as `name` and `version` and create a `func.yaml` 24 | - remove the left-over `func.init.yaml` 25 | 26 | ## Creating an example init-image 27 | 28 | The easiest way to create an init-image is to base it on an existing function 29 | 30 | ### A simple function 31 | 32 | We'll use a really simple function as our example, one which we could create by hand that uses the string-reversing tool called `rev` that is bundled in Alpine Linux: 33 | 34 | ``` 35 | $ ls 36 | Dockerfile func.yaml 37 | ``` 38 | 39 | ``` 40 | $ cat Dockerfile 41 | FROM alpine:latest 42 | CMD ["rev"] 43 | ``` 44 | 45 | ``` 46 | $ cat func.yaml 47 | name: reverser 48 | version: 0.0.1 49 | runtime: docker 50 | ``` 51 | 52 | ``` 53 | $ echo HELLO | fn run 54 | Building image blah:0.0.1 55 | OLLEH 56 | ``` 57 | 58 | ### Creating the init-image 59 | 60 | Firstly we need to create `func.init.yaml`. It'll be the same as the existing `func.yaml` but without `name` and `version` (these are provided by the CLI when the init-image is used). 61 | 62 | ``` 63 | $ cat func.init.yaml 64 | runtime: docker 65 | ``` 66 | 67 | We need to create a tarball of the files we want the init-image to create: 68 | 69 | ``` 70 | $ tar -cf init.tar Dockerfile func.init.yaml 71 | ``` 72 | 73 | There is no need to use any compression here as Docker does that for us. 74 | 75 | We'll be creating the init-image here, so we need another Dockerfile to do that: 76 | 77 | ``` 78 | $ cat Dockerfile-init-image 79 | FROM alpine:latest 80 | COPY init.tar / 81 | CMD ["cat", "/init.tar"] 82 | ``` 83 | 84 | Now we can create our init-image: 85 | 86 | ``` 87 | $ docker build -t reverser-init -f Dockerfile-init-image . 88 | 89 | Sending build context to Docker daemon 15.36kB 90 | Step 1/3 : FROM alpine:latest 91 | ---> 3fd9065eaf02 92 | Step 2/3 : COPY init.tar / 93 | ---> 03ad6bc830c3 94 | Step 3/3 : CMD cat /init.tar 95 | ---> Running in b8dad41e966f 96 | ---> decb5e898b1d 97 | Removing intermediate container b8dad41e966f 98 | Successfully built decb5e898b1d 99 | Successfully tagged reverser-init:latest 100 | ``` 101 | 102 | And we are done. 103 | 104 | ### Testing out the init-image 105 | 106 | Move into an empty directory, and we can create a function from the init-image: 107 | 108 | ``` 109 | $ mkdir new && cd new 110 | $ fn init --init-image=reverser-init 111 | Building from init-image: reverser-init 112 | func.yaml created. 113 | ``` 114 | 115 | ``` 116 | $ echo "YES MATE" | fn run 117 | Building image new:0.0.1 118 | ETAM SEY 119 | ``` 120 | 121 | You can `docker push` this image to a registry to share it with others, and it should be clear how to create more complex init-images too. Remember that you are not limited to `COPY` for adding a tarball, you could create it on the fly within the init-image if you wanted to do some deeper customization. 122 | -------------------------------------------------------------------------------- /fn/operate/private_registries.md: -------------------------------------------------------------------------------- 1 | # Using a private registry with Fn 2 | 3 | For local development, or a team that wishes to keep their images off of the public Docker registry, a private 4 | registry may be useful. This can be hosted on your own server or local machine. See the Docker docs [here](https://docs.docker.com/registry/) for information on setting this up. A registry on localhost may greatly speed up iterative development in environments where the network is constrained. 5 | 6 | To set up your fn service with authentication for any registry, you must 7 | provide fn with `FN_DOCKER_AUTH` env var: 8 | 9 | ``` 10 | FN_DOCKER_AUTH='{"auths":{"http://my.registry.com:80":{"auth":"yourauthbase64here"}}}' 11 | ``` 12 | 13 | You may provide multiple auths in this way, it's also possible to run the `fn` 14 | docker container with a volume mounted `~/docker/config.json` or use a local 15 | version of `fn` against your locally configured `dockerd`. 16 | 17 | This is where the `FN_REGISTRY` environment variable or `--registry` setting comes into play. 18 | 19 | ## The `FN_REGISTRY` or `--registry` setting. 20 | 21 | This determines where your images will be pushed to or deployed from. It can follow one of the following schemes: 22 | 23 | - `myuser` -> `docker.io/myuser/:`. Used for interacting with the official docker registry. 24 | 25 | - `somedomain.com` -> `somedomain.com/:`. A custom registry hosted at the given domain. The image is not nested under a path. 26 | 27 | - `somedomain.com:port` -> `somedomain.com:port/:`. A custom registry hosted at the given port. (Useful for insecure http registries running on port 80/5000). 28 | 29 | - `somedomain.com[port?]/path` -> `somedomain.com[port?]/path/:`. The image will be nested under the given path. This path can be more than one element. 30 | 31 | ### Insecure HTTP registries 32 | 33 | If your registry is not hosted over https, your Docker daemon must be configured to treat the registry as http only. 34 | 35 | In most installations this will require adding the `:` to the `insecure_registries` configuration for the Docker daemon. See [here](https://docs.docker.com/registry/insecure/) for more details and troubleshooting. Docker-for-Mac will require changing a setting in the UI. 36 | 37 | ## Example of a private registry on localhost 38 | 39 | Starting a `registry:2` container: 40 | 41 | ```bash 42 | $ docker run -d -p 5000:5000 --name registry registry:2 43 | $ docker ps 44 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 45 | c18ac6172e0d registry:2 "/entrypoint.sh /e..." 2 seconds ago Up 2 seconds 0.0.0.0:5000->5000/tcp registry 46 | ``` 47 | 48 | Given a function called "dummy": 49 | 50 | ```sh 51 | $ ls ./dummy 52 | func.go func.yaml 53 | ``` 54 | 55 | ```sh 56 | $ cat ./dummy/func.yaml 57 | version: 0.0.1 58 | runtime: go 59 | entrypoint: ./func 60 | ``` 61 | 62 | Upload it to your registry (notice the use of `--registry`): 63 | 64 | ```bash 65 | $ fn deploy --app myapp --registry localhost:5000/some/path 66 | Deploying dummy to app: myapp at path: /dummy 67 | Bumped to version 0.0.2 68 | Building image localhost:5000/some/path/dummy:0.0.2 .. 69 | Pushing localhost:5000/some/path/dummy:0.0.2 to docker registry...The push refers to a repository [localhost:5000/some/path/dummy] 70 | 5fcef0dbce8b: Pushed 71 | ce4a1aad8bd7: Pushed 72 | 88229188f6e3: Pushed 73 | d82c387bddae: Pushed 74 | 0.0.2: digest: sha256:369e158767c89357142f4f394618838b04865af7ab6afc183b38b5f46a0ece3f size: 1155 75 | Updating route /dummy using image localhost:5000/some/path/dummy:0.0.2... 76 | ``` 77 | 78 | Now you can use the route and function named "dummy" as normal. 79 | 80 | ## Authenticating against private registries 81 | 82 | Pushing images to registries that require authentication (like Dockerhub) will require the use of `docker login` from your developer machine. This will be as similar for your private registry if you have authentication enabled. 83 | 84 | For pulling images you may also require your Docker daemon to be authenticated. This also needs to be done via `docker login` but the [official documentation](https://docs.docker.com/engine/reference/commandline/login/) demonstrates useful alternatives for automating credential usage via a config file or external credential providers which is suggested for larger fleets of machines. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Fn Project Logo Project Documentation 2 | 3 | **[Quickstart](https://github.com/fnproject/fn#quickstart)  |  [Tutorials](https://fnproject.io/tutorials)  |  [Docs](https://github.com/fnproject/docs)  |  [API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/fnproject/fn/master/docs/swagger_v2.yml)** 4 | 5 | Fn is an event-driven, open source, [Functions-as-a-Service (FaaS)](https://github.com/fnproject/docs/blob/master/fn/general/introduction.md) compute platform that you can run anywhere. 6 | 7 | ## Getting Started 8 | * [Quickstart Tutorial](https://github.com/fnproject/fn#quickstart) 9 | * [Fn Installation](https://fnproject.io/tutorials/install/) 10 | * [Fn Introduction](fn/general/introduction.md) 11 | * Using Fn with Java 12 | * [Java Tutorial](https://fnproject.io/tutorials/JavaFDKIntroduction/) 13 | * [Java Examples](fdks/fdk-java) 14 | * Using Fn with Node.js 15 | * [Node Tutorial](https://fnproject.io/tutorials/node/intro/) 16 | * [Node Examples](fdks/fdk-node) 17 | * Using Fn with Python 18 | * [Python Tutorial](https://fnproject.io/tutorials/python/intro/) 19 | * [Python Examples](fdks/fdk-python) 20 | * Creating Functions with Docker 21 | * [Create a Function with a Docker Container](https://fnproject.io/tutorials/ContainerAsFunction/) 22 | * [Create a Function from a Docker image that contains a Node.js app with Oracle DB Support](https://fnproject.io/tutorials/node/custom-db/) 23 | * [Create a Function with a Linux Command and HotWrap](https://fnproject.io/tutorials/docker/CustomLinuxContainer/) 24 | * [Logging and Debugging Tutorial](https://fnproject.io/tutorials/Troubleshooting/) 25 | * [Function Debugging](fn/troubleshoot/debug-loglevel.md) 26 | * [FAQ](fn/general/faq.md) 27 | * Using Fn with Other Languages 28 | * [Using Fn with C#](https://fnproject.io/tutorials/csharp/intro/) 29 | * [Using Fn with Go](https://fnproject.io/tutorials/Introduction/) 30 | * [Using Fn with Ruby](https://fnproject.io/tutorials/ruby/intro/) 31 | * Exploring Fn 32 | * [Create Apps with Fn](https://fnproject.io/tutorials/Apps/) 33 | * [Fn Dev with Muliple Contexts](https://fnproject.io/tutorials/basics/UsingContexts/) 34 | * [Using the Fn RuntimeContext with Functions](https://fnproject.io/tutorials/basics/UsingRuntimeContext/) 35 | * Popular Fn Topics 36 | * [Fn Function File Format](fn/develop/func-file.md): All the values that can be used in `func.yaml`. 37 | * [Fn FDKs](fn/develop/fdks.md): Function Development Kits for supported languages. 38 | * [Fn Runtime Options](fn/operate/options.md) 39 | * [Kubernetes Helm Chart for Fn](https://github.com/fnproject/fn-helm/) 40 | * Fn Sub-projects: [Flow](https://github.com/fnproject/flow), [UI](https://github.com/fnproject/ui) 41 | * [Running Fn in Production](fn/operate/production.md) 42 | * [Triggers](fn/develop/triggers.md): Using triggers. 43 | * [Troubleshooting](fn/troubleshoot/README.md): Solutions to common problems when working with Fn. 44 | * Known Issue: [Trying to invoke a function when using a CentOS based Linux fails with an error message](fn/troubleshoot/known-issues/2019-08-fn-invoke-fails.md) 45 | * [Using Fn with Podman instead of Docker](fn/develop/podman.md): Use Podman with the Fn client. 46 | * [Windows: Running Fn Client for Windows](fn/develop/running-fn-client-windows.md): Run the Fn client on Microsoft Windows. 47 | 48 | 49 | ## More Fn Docs 50 | **| [APIs](https://github.com/fnproject/docs/blob/master/fn/develop/README.md#advanced)  | 51 | [CLI Docs and Reference](https://github.com/fnproject/docs/tree/master/cli)  | 52 | [Fn Tips for Developers](https://github.com/fnproject/docs/tree/master/fn/develop)  | 53 | [Fn Tips for Operators](https://github.com/fnproject/docs/blob/master/fn/operate)  |** 54 | 55 | 56 | ## For Contributors 57 | We love contributions! To get started, please visit our [community page](community/README.md) and [contributing guidelines](community/CONTRIBUTING.md) page. 58 | 59 | 60 | ## Stay Connected to Fn 61 | **| [StackOverflow](https://stackoverflow.com/questions/tagged/fn)  | [Slack Community](http://slack.fnproject.io)  | 62 | [Blog](https://medium.com/fnproject)  | 63 | [Twitter](https://twitter.com/fnproject)  | 64 | [YouTube](https://www.youtube.com/channel/UCo3fJqEGRx9PW_ODXk3b1nw)  | 65 | [The Fn Project Presentation Master](http://deck.fnproject.io)  |** 66 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | UTF-8 9 | UTF-8 10 | 11 | 1.0.98 12 | 2.8.47 13 | 2.10.0.pr1 14 | 15 | 16 | com.example.fn 17 | async-thumbnails 18 | 1.0.0 19 | 20 | 21 | 22 | com.fnproject.fn 23 | api 24 | ${fdk.version} 25 | 26 | 27 | com.fnproject.fn 28 | flow-runtime 29 | ${fdk.version} 30 | 31 | 32 | commons-net 33 | commons-net 34 | 3.6 35 | 36 | 37 | com.fasterxml.jackson.core 38 | jackson-databind 39 | ${jackson.version} 40 | 41 | 42 | io.minio 43 | minio 44 | 5.0.1 45 | 46 | 47 | com.fnproject.fn 48 | testing-core 49 | ${fdk.version} 50 | test 51 | 52 | 53 | com.fnproject.fn 54 | flow-testing 55 | ${fdk.version} 56 | test 57 | 58 | 59 | com.fnproject.fn 60 | testing-junit4 61 | ${fdk.version} 62 | test 63 | 64 | 65 | junit 66 | junit 67 | 4.12 68 | test 69 | 70 | 71 | 72 | com.github.tomakehurst 73 | wiremock 74 | 2.19.0 75 | 76 | 77 | org.slf4j 78 | slf4j-simple 79 | 1.6.2 80 | test 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-compiler-plugin 89 | 3.3 90 | 91 | 8 92 | 8 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-surefire-plugin 98 | 2.22.1 99 | 100 | false 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | fn-release-repo 109 | https://dl.bintray.com/fnproject/fnproject 110 | 111 | true 112 | 113 | 114 | false 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/async-thumbnails/src/test/java/com/example/fn/ThumbnailsFunctionTest.java: -------------------------------------------------------------------------------- 1 | package com.example.fn; 2 | 3 | import com.example.fn.ThumbnailsFunction; 4 | import com.fnproject.fn.testing.FnTestingRule; 5 | import com.fnproject.fn.testing.flow.FlowTesting; 6 | import com.github.tomakehurst.wiremock.client.WireMock; 7 | import com.github.tomakehurst.wiremock.junit.WireMockRule; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | 11 | import static com.github.tomakehurst.wiremock.client.WireMock.*; 12 | 13 | public class ThumbnailsFunctionTest { 14 | 15 | @Rule 16 | public final FnTestingRule fn = FnTestingRule.createDefault(); 17 | private final FlowTesting flow = FlowTesting.create(fn); 18 | 19 | @Rule 20 | public final WireMockRule mockServer = new WireMockRule(0); 21 | 22 | @Test 23 | public void testThumbnail() { 24 | fn 25 | .setConfig("OBJECT_STORAGE_URL", "http://localhost:" + mockServer.port()) 26 | .setConfig("OBJECT_STORAGE_ACCESS", "alpha") 27 | .setConfig("OBJECT_STORAGE_SECRET", "betabetabetabeta") 28 | .setConfig("RESIZE_128_FN_ID","myapp/resize128") 29 | .setConfig("RESIZE_256_FN_ID","myapp/resize256") 30 | .setConfig("RESIZE_512_FN_ID","myapp/resize512"); 31 | 32 | 33 | flow 34 | .givenFn("myapp/resize128") 35 | .withAction((data) -> "128".getBytes()) 36 | .givenFn("myapp/resize256") 37 | .withAction((data) -> "256".getBytes()) 38 | .givenFn("myapp/resize512") 39 | .withAction((data) -> "512".getBytes()); 40 | 41 | fn 42 | .givenEvent() 43 | .withBody("fn".getBytes()) 44 | .enqueue(); 45 | 46 | // Mock the http endpoint 47 | mockMinio(); 48 | 49 | fn.thenRun(ThumbnailsFunction.class, "handleRequest"); 50 | 51 | // Check the final image uploads were performed 52 | mockServer.verify(putRequestedFor(urlMatching("/alpha/.*\\.png")).withRequestBody(containing("fn"))); 53 | mockServer.verify(putRequestedFor(urlMatching("/alpha/.*\\.png")).withRequestBody(containing("128"))); 54 | mockServer.verify(putRequestedFor(urlMatching("/alpha/.*\\.png")).withRequestBody(containing("256"))); 55 | mockServer.verify(putRequestedFor(urlMatching("/alpha/.*\\.png")).withRequestBody(containing("512"))); 56 | mockServer.verify(4, putRequestedFor(urlMatching(".*"))); 57 | } 58 | 59 | @Test 60 | public void anExternalFunctionFailure() { 61 | fn 62 | .setConfig("OBJECT_STORAGE_URL", "http://localhost:" + mockServer.port()) 63 | .setConfig("OBJECT_STORAGE_ACCESS", "alpha") 64 | .setConfig("OBJECT_STORAGE_SECRET", "betabetabetabeta") 65 | .setConfig("RESIZE_128_FN_ID","myapp/resize128") 66 | .setConfig("RESIZE_256_FN_ID","myapp/resize256") 67 | .setConfig("RESIZE_512_FN_ID","myapp/resize512");; 68 | 69 | flow 70 | .givenFn("myapp/resize128") 71 | .withResult("128".getBytes()) 72 | .givenFn("myapp/resize256") 73 | .withResult("256".getBytes()) 74 | .givenFn("myapp/resize512") 75 | .withFunctionError(); 76 | 77 | fn 78 | .givenEvent() 79 | .withBody("fn".getBytes()) 80 | .enqueue(); 81 | 82 | // Mock the http endpoint 83 | mockMinio(); 84 | 85 | fn.thenRun(ThumbnailsFunction.class, "handleRequest"); 86 | 87 | // Confirm that one image upload didn't happen 88 | mockServer.verify(0, putRequestedFor(urlMatching("/alpha/.*\\.png")).withRequestBody(equalTo("512"))); 89 | 90 | mockServer.verify(3, putRequestedFor(urlMatching(".*"))); 91 | 92 | } 93 | 94 | private void mockMinio() { 95 | 96 | mockServer.stubFor(get(urlMatching("/alpha.*")) 97 | .willReturn(aResponse().withBody( 98 | "\n" + 99 | "\n" + 100 | " alpha\n" + 101 | " \n" + 102 | " 0\n" + 103 | " 100\n" + 104 | " false\n" + 105 | ""))); 106 | 107 | mockServer.stubFor(WireMock.head(urlMatching("/alpha.*")).willReturn(aResponse().withStatus(200))); 108 | 109 | mockServer.stubFor(WireMock.put(urlMatching(".*")).willReturn(aResponse().withStatus(200))); 110 | 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /cli/script/FnCliGen.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'rubygems' 4 | require 'kramdown' 5 | require 'pathname' 6 | 7 | 8 | # Script to convert all the db directories into an index 9 | class FnCliGen 10 | 11 | attr_accessor :contentArr, :fileTemplateArr 12 | 13 | def initialize(aCmdListFile) 14 | @cmdListFile = aCmdListFile # Get command list 15 | @cmdListArr = Array.new # Array of commands from file 16 | @fileNameArr = Array.new # Array of output filenames 17 | @fnVersion = getFnVersion 18 | 19 | # @fileOutArr == Temp output array 20 | @cmdListArr = IO.readlines(File.expand_path(@cmdListFile)) 21 | @cmdListArr.each {|command| command.gsub!("\n", "")} 22 | @fileNameArr = Marshal.load(Marshal.dump(@cmdListArr)) 23 | 24 | end 25 | 26 | def getFnVersion 27 | # Get Current Fn Version 28 | tempArr = [] 29 | tempArr.push(`fn version`) 30 | tempOutStr = tempArr[0].match(/.*(version.*)/)[1] 31 | return tempOutStr 32 | end 33 | 34 | 35 | 36 | # createFileNameArr 37 | # Creates an array of file names replacing space with dash. 38 | 39 | def createFileNameArr 40 | # Build Mirror Array of Filenames 41 | @fileNameArr.each do |filename| 42 | filename.gsub!(" ", "-") 43 | end 44 | 45 | end 46 | 47 | def buildFnCmdCard 48 | x = 0 49 | fileOutArr = Array.new 50 | 51 | # Build each Fn Command Card 52 | @cmdListArr.each do |command| 53 | # Start markdown file 54 | fileOutArr.push "# `" + command + "`\n\n" #title 55 | fileOutArr.push "```c\n" # Start help text code block 56 | fileOutArr.push "$ " + command + "\n" # Command 57 | command = command + " --help" 58 | fileOutArr.push `#{command}` # Execute command, get result 59 | fileOutArr.push "```\n\n" # End Code block 60 | 61 | # Link code goes here 62 | fileOutArr.push "[Some link](#)\n\n" 63 | 64 | # Write .md file to disk 65 | puts "Writing: " + @fileNameArr[x] + ".md" 66 | File.open(@fileNameArr[x] + ".md", "w") do |f| 67 | f.puts(fileOutArr) 68 | end 69 | 70 | fileOutArr.clear # Clear array for next loop 71 | x = x + 1 # Counter for syncing arrays 72 | end 73 | end 74 | 75 | 76 | # Build README.md file for all commands. 77 | def buildReadMeIndex 78 | x = 0 79 | fileOutArr = Array.new 80 | 81 | # Build each Fn Command Card 82 | fileOutArr.push "# Fn Command Reference\n\n" 83 | @cmdListArr.each do |command| 84 | # Start markdown file 85 | fileOutArr.push "[" + command + "](" + @fileNameArr[x] + ".md" + ") \n" 86 | x = x + 1 # Counter for syncing arrays 87 | end 88 | 89 | # Add Fn Version 90 | fileOutArr.push("\n" + @fnVersion + "") 91 | 92 | # Write README.md file to disk 93 | puts "Writing: " + "README" + ".md" 94 | File.open("README.md", "w") do |f| 95 | f.puts(fileOutArr) 96 | end 97 | 98 | end 99 | 100 | # Build Markdown Parent index file REFLIST.md containting all the .md files 101 | def buildParentReadMeIndex 102 | x = 0 103 | fileOutArr = Array.new 104 | 105 | # Build list of reference pages 106 | fileOutArr.push "### Fn Command Reference\n\n" 107 | @cmdListArr.each do |command| 108 | # Add each command to output 109 | fileOutArr.push "[" + command + "](ref/" + @fileNameArr[x] + ".md" + ") \n" 110 | x = x + 1 # Counter for syncing arrays 111 | end 112 | 113 | # Add Fn Version 114 | fileOutArr.push("\n" + @fnVersion + "") 115 | 116 | 117 | # Write REFLIST.md file to disk 118 | puts "Writing: " + "REFLIST" + ".md" 119 | File.open("REFLIST.md", "w") do |f| 120 | f.puts(fileOutArr) 121 | end 122 | 123 | end 124 | 125 | def main 126 | createFileNameArr() 127 | buildFnCmdCard() 128 | buildReadMeIndex() 129 | buildParentReadMeIndex() 130 | end 131 | end 132 | 133 | 134 | # If the Ruby class is called from another file, the code in the if is ignored. 135 | # Works normally if called from the command line. 136 | if __FILE__ == $0 137 | 138 | if ARGV.length != 1 139 | puts "Usage: FnCliGen FnCommandList" 140 | exit 141 | end 142 | 143 | app = FnCliGen.new(ARGV[0]) 144 | app.main 145 | end 146 | -------------------------------------------------------------------------------- /fn/develop/annotations.md: -------------------------------------------------------------------------------- 1 | # App and Route Annotations 2 | 3 | App and Route annotations allow users building on the Fn platform to encode consumer-specific data inline with Apps and Routes. 4 | 5 | Annotations can be used to either communicate and carry information externally (only by API users) or to communicate between external applications and Fn extensions. 6 | 7 | ## Use cases/Examples: 8 | 9 | ### Externally defined/consumed annotations 10 | 11 | Software using Fn as a service, attaches non-identifying metadata annotations to Fn resources for subsequent reads (e.g. my reference for this function/app ) 12 | 13 | Writer : API user, Reader: API user 14 | 15 | E.g. platform "platX" creates/modifies functions, has an internal reference it wants to associate with an object for later retrieval (it can't query/search Fn by this attribute) 16 | 17 | ``` 18 | POST /v1/apps 19 | 20 | { 21 | ... 22 | "annotations" : { 23 | "platx.com/ref" : "adsfasdfads" 24 | } 25 | ... 26 | } 27 | ``` 28 | 29 | ### Extensions: Allow passing data from user or upstream input to extensions (configuration of extensions) 30 | 31 | Writer : API user, Reader: Fn platform extension (use), API user (informational) 32 | 33 | ``` 34 | POST /v1/apps 35 | ... 36 | { 37 | ... 38 | "annotations" : { 39 | "my_cloud_provider.com/network_id" : "network.id" 40 | } 41 | ... 42 | } 43 | ``` 44 | 45 | ### Extensions: Allow indicating internally derived/set values to user (API extension sets/generates annotations, prevents user from changing it) 46 | 47 | Writer : Internal platform extension, Reader: API user. 48 | 49 | 50 | ``` 51 | GET /v1/apps/myapp 52 | ... 53 | { 54 | ... 55 | "annotations" : { 56 | "my_cloud_provider.com/create_user" : "foo@foo.com" 57 | } 58 | ... 59 | } 60 | ``` 61 | 62 | 63 | 64 | ``` 65 | PATCH /v1/apps/myapp 66 | ... 67 | { 68 | ... 69 | "annotations" : { 70 | "my_cloud_provider.com/create_user" : "foo@foo.com" 71 | } 72 | ... 73 | } 74 | 75 | HTTP/1.1 400 Invalid operation 76 | 77 | { 78 | "error": "annotation key cannot be changed", 79 | } 80 | ``` 81 | 82 | ## Content Examples 83 | example : user attaches local annotations 84 | 85 | ``` 86 | PUT /v1/apps/foo 87 | 88 | { 89 | app: { 90 | ... 91 | "annotations": { 92 | "mylabel": "super-cool-fn", 93 | "myMetaData": { 94 | "k1": "foo", 95 | "number": 5000, 96 | "array": [1, 2, 3] 97 | } 98 | } 99 | ... 100 | } 101 | } 102 | ``` 103 | 104 | User sets extension-specific annotations: 105 | 106 | ``` 107 | PUT /v1/apps/foo 108 | { 109 | ... 110 | "annotations": { 111 | "example.extension.com/v1/myval" : "val" 112 | } 113 | ... 114 | } 115 | ``` 116 | 117 | ## Key Syntax and Namespaces 118 | 119 | A key consists of any printable (non-extended) ascii characters excluding whitespace characters. 120 | 121 | The maximum (byte) size of a key is 128 bytes (excluding quotes). 122 | 123 | Keys are stored as free text with the object. Normatively extensions and systems using annotations *must* use a namespace prefix based on an identified domain and followed by at least one '/' character. 124 | 125 | Systems *should* use independent annotation keys for any value that can be changed independently. 126 | 127 | Extensions *should not* interact with annotations keys that are not prefixed with a domain they own. 128 | 129 | ## Value syntax 130 | 131 | Values may contain any valid JSON value (object/array/string/number) except the empty string `""` and `null` 132 | 133 | The serialised JSON representation (rendered without excess whitespace as a string) of a single value must not exceed a 512 bytes. 134 | 135 | ## Modifying and deleting annotation keys 136 | 137 | A key can be modified by a PATCH operation containing a partial `annotations` object indicating the keys to update (or delete) 138 | 139 | A key can be deleted by a PATCH operation by setting its value to an empty string. 140 | 141 | For each element that of data that can be changed independently, you *should* use a new top-level annotation key. 142 | 143 | ## Maximum number of keys 144 | 145 | A user may not add keys in a PATCH or PUT operation if the total number of keys after changes exceeds 100 keys. 146 | 147 | Fn may return a larger number of keys. 148 | 149 | ## Extension interaction with resource modification 150 | 151 | An extension may prevent a PUT, PATCH or POST operation on a domain object based on the value of an annotation passed in by a user, in this case this should result in an HTTP 400 error with an informational message indicating that an error was present in the annotations and containing the exact key or keys which caused the error. 152 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/regex-query/README.md: -------------------------------------------------------------------------------- 1 | # Fn Java Example Project: Regex Query 2 | This example provides an HTTP endpoint for performing regex matching on strings. 3 | 4 | ```bash 5 | $ curl -d '{"text":"One, 2, Three, 4, Five", "regex":"\\d"}' 'http://localhost:8080/t/regex-query/query' 6 | {"regex":"\\d","text":"One, 2, Three, 4, Five","matches":[{"start":5,"end":6,"match":"2"},{"start":15,"end":16,"match":"4"}]} 7 | ``` 8 | 9 | 10 | ## FDK features 11 | 12 | The Function Development Kit for Java (FDK for Java) API supports JSON input and 13 | output through [Jackson](https://github.com/FasterXML/jackson). This example 14 | function demonstrates the input/output mapping through use of POJO data transfer 15 | objects. 16 | 17 | ## Step by step 18 | 19 | Ensure you have the functions server running using, this will host your 20 | function and provide the HTTP endpoints that invoke it: 21 | 22 | ```bash 23 | $ fn start 24 | ``` 25 | 26 | Create an app to host the function 27 | ```bash 28 | $ fn create app regex-query 29 | ``` 30 | 31 | Deploy the function to the Fn server. 32 | ```bash 33 | $ fn --verbose deploy --app regex-query --local 34 | ``` 35 | 36 | Invoke the function to perform a regex search 37 | ```bash 38 | $ curl -d '{ "text": "One, 2, Three, 4, Five", "regex": "\\\\d" }' 'http://localhost:8080/r/regex-query/query' 39 | {"regex":"\\d","text":"One, 2, Three, 4, Five","matches":[{"start":5,"end":6,"match":"2"},{"start":15,"end":16,"match":"4"}]} 40 | ``` 41 | 42 | 43 | ## Code walkthrough 44 | 45 | The entrypoint to the function is specified in `func.yaml` in the `cmd` key. 46 | This is set to be `com.example.fn.RegexQuery::query`. 47 | ```js 48 | schema_version: 20180708 49 | name: query 50 | version: 0.0.1 51 | runtime: java 52 | build_image: fnproject/fn-java-fdk-build:jdk11-1.0.96 53 | run_image: fnproject/fn-java-fdk:jre11-1.0.96 54 | cmd: com.example.fn.RegexQuery::query 55 | triggers: 56 | - name: query 57 | type: http 58 | source: /query 59 | ``` 60 | 61 | The class containing the function is shown below: 62 | 63 | ```java 64 | package com.fnproject.fn.examples; 65 | 66 | import java.util.*; 67 | import java.util.regex.Matcher; 68 | import java.util.regex.Pattern; 69 | 70 | public class RegexQuery { 71 | public Response query(Query query) { 72 | return new Response(query.regex, query.text, getMatches(query)); 73 | } 74 | 75 | private List getMatches(Query query) { 76 | Pattern pattern = Pattern.compile(query.regex); 77 | Matcher matcher = pattern.matcher(query.text); 78 | List matches = new ArrayList<>(); 79 | while (matcher.find()) { 80 | matches.add(new Match(matcher.start(), matcher.end(), query.text.substring(matcher.start(), matcher.end()))); 81 | } 82 | return matches; 83 | } 84 | } 85 | ``` 86 | 87 | The Fn FDK for Java has Jackson coercion support out of the box, annotate your 88 | objects with Jackson annotations or use POJOs and Jackson will attempt to coerce 89 | them to and from JSON. The FDK supports a variety of coercions and provides an 90 | extensibility point for you to inject your own custom coercions see [Extending 91 | Data Binding](../../ExtendingDataBinding.md). 92 | 93 | ### Testing 94 | 95 | The Fn FDK for Java provides a testing module in `com.fnproject.fn.testing` 96 | providing a DSL to easily functionally test your code 97 | 98 | `com.fnproject.fn.examples.RegexQueryTests` demonstrates the use 99 | of the `com.fnproject.fn.testing` module to functionally test your function. 100 | 101 | A [JUnit rule](https://github.com/junit-team/junit4/wiki/rules) 102 | field takes care of faking the `fn` server, the rule annotation manages 103 | the lifetime of the fake server. `fn.buildEvent()` create an event 104 | builder to construct and queue events into the function under test. 105 | 106 | ```java 107 | ... 108 | @Rule 109 | public FnTesting fn = FnTesting.createDefault(); 110 | ... 111 | ``` 112 | 113 | The function is invoked using `fn.thenRun(, 114 | )` and assertions use the familiar `Assert.assert*` family 115 | of static methods (we make use of the 116 | [JSONAssert](http://jsonassert.skyscreamer.org/) library to simplify testing 117 | JSON APIs). A variety of methods live on `FnTesting` to get a handle on 118 | result(s). 119 | 120 | ```java 121 | ... 122 | @Test 123 | public void matchingSingleCharacter() throws JSONException { 124 | String text = "a"; 125 | String regex = "."; 126 | fn.givenEvent() 127 | .withMethod("POST") 128 | .withBody(String.format("{\"text\": \"%s\", \"regex\": \"%s\"}", text, regex)) 129 | .enqueue(); 130 | 131 | fn.thenRun(RegexQuery.class, "query"); 132 | 133 | JSONAssert.assertEquals(String.format("{\"text\":\"%s\"," + 134 | "\"regex\":\"%s\"," + 135 | "\"matches\":[" + 136 | "{\"start\": 0, \"end\": 1, \"match\": \"a\"}" + 137 | "]}", text, regex), 138 | fn.getOnlyResult().getBodyAsString(), false); 139 | } 140 | ... 141 | ``` 142 | 143 | See the [Testing Functions](../../TestingFunctions.md) docs for more information 144 | on testing. 145 | -------------------------------------------------------------------------------- /fdks/fdk-node/README.md: -------------------------------------------------------------------------------- 1 | # Fn Function Development Kit for Node.js 2 | 3 | This Function Development Kit makes it easy to deploy Node.js functions to Fn. 4 | 5 | 6 | ## Creating a Node Function 7 | 8 | Writing a Node.js function is simply a matter of writing a handler function 9 | that you pass to the FDK to invoke each time your function is called. 10 | 11 | Start by creating a node function with `fn init` and installing the FDK: 12 | 13 | ```sh 14 | fn init --runtime node nodefunc 15 | cd nodefunc 16 | ``` 17 | 18 | This creates a simple hello world function in `func.js`: 19 | 20 | ```javascript 21 | var fdk = require('@fnproject/fdk'); 22 | 23 | fdk.handle(function(input) { 24 | var name = 'World'; 25 | if (input.name) { 26 | name = input.name; 27 | } 28 | response = {'message': 'Hello ' + name} 29 | return response 30 | }) 31 | ``` 32 | 33 | The handler function takes the string input that is sent to the function 34 | and returns a response string. Using the FDK you don't have to worry about reading 35 | input from standard input and writing to standard output to return your response. 36 | The FDK let's you focus on your function logic and not the mechanics. 37 | 38 | Now run it! 39 | 40 | ```sh 41 | fn run 42 | ``` 43 | 44 | Now you have a basic running Node function that you can modify and add what you want. 45 | 46 | From this point on, it's the same as any other function in any language. 47 | deploy the function: 48 | 49 | ```sh 50 | fn deploy --app fnfdk --local 51 | ``` 52 | 53 | Once deployed, you and invoke the function: 54 | 55 | ```sh 56 | echo -n "Tom" | fn call fdkdemo /hello 57 | ``` 58 | 59 | or 60 | 61 | ```sh 62 | curl -d "Tom" http://localhost:8080/r/fdkdemo/hello 63 | ``` 64 | 65 | In both cases you'll get the response: 66 | 67 | ```sh 68 | Hello Tom from Node! 69 | ``` 70 | 71 | ## Function Context 72 | 73 | Function invocation context details are available through an optional function argument. 74 | To receive a context object, simply add a second argument to your handler function. 75 | in the following example the `call_id` is obtained from the context and included in 76 | the response message: 77 | 78 | ```javascript 79 | var fdk = require('@fnproject/fdk'); 80 | 81 | fdk.handle(function(input, ctx) { 82 | var name = 'World'; 83 | if (input) { 84 | name = input; 85 | } 86 | return 'Hello ' + name + ' from Node call ' + ctx.callId + '!'; 87 | }) 88 | ``` 89 | 90 | In the case of `default` format functions the context give you access to all environment variables 91 | including those defined through function or app config as well as those automatically provided 92 | by Fn like `app_name`, `path`, `memory`, etc. 93 | 94 | 95 | ## Asynchronous function responses 96 | 97 | You return an asynchronous response from a function by returning a Javascript `Promise` from the function body: 98 | 99 | ```javascript 100 | var fdk = require('@fnproject/fdk'); 101 | 102 | fdk.handle(function(input, ctx) { 103 | return new Promise((resolve, reject) => { 104 | setTimeout(() => resolve("Hello"), 1000); 105 | }); 106 | }) 107 | ``` 108 | 109 | ## Handling non-json input and output 110 | 111 | By default the FDK will convert input with a content-type matching `application/json` into a JSON object as the function input, if the incoming content type is different from `application/json` then the input will be the raw string value of the input. In both cases, the raw (string) version of the input is also available in `ctx.body`. 112 | 113 | Likewise by default the output of a function will be treated as a JSON object and converted using JSON.stringify - you can change this behaviour by setting the content type of the response in the context using `ctx.responseContentType='application/text-plain'`. Changing the content type to non-json will result in the output being treated as a string. 114 | 115 | ## Using HTTP headers and setting HTTP status codes 116 | 117 | You can read http headers passed into a function invocation using `ctx.protocol.header(key)`, this returns the first header value of the header matching `key` (after canonicalization) and `ctx.protocol.headers` which returns an object containing all headers. 118 | 119 | ```javascript 120 | var fdk = require('@fnproject/fdk'); 121 | 122 | fdk.handle(function(input, ctx) { 123 | console.log("Authorization header:" , ctx.protocol.header("Authorization")) 124 | console.log( ctx.protocol.headers) // prints e.g. { "Content-Type": ["application/json"],"Accept":["application/json","text/plain"] } 125 | }) 126 | ``` 127 | 128 | Outbound headers and the HTTP status code can be modified when the function uses the `json` request format. 129 | 130 | To update the outbound status-code set `ctx.protocol.statusCode`. To modify outbound headers use `ctx.protocol.setHeader(k,v)` or `ctx.protocol.addHeader(k,v)` which set (overwriting existing headers) or add (preserving existing headers) headers to the response respectively. 131 | 132 | 133 | ```javascript 134 | var fdk = require('@fnproject/fdk'); 135 | 136 | fdk.handle(function(input, ctx) { 137 | ctx.protocol.setHeader("Location", "http://example.com") 138 | ctx.protocol.statusCode = 302 139 | }) 140 | ``` 141 | 142 | ## Fn and Node.js Dependencies 143 | Fn handles Node.js dependencies in the following way: 144 | 145 | * If a `package.json` is present without a `node_modules` directory, an Fn build runs an `npm install` within the build process and installs your dependencies. 146 | * If the `node_modules` is present, Fn assumes you have provided the dependencies yourself and no installation is performed. 147 | -------------------------------------------------------------------------------- /fdks/fdk-java/examples/qr-code/README.md: -------------------------------------------------------------------------------- 1 | # Java Fn Function Example: QR Code Gen 2 | 3 | This example provides an HTTP endpoint for generating QR Codes: 4 | 5 | ```bash 6 | $ curl "http://localhost:8080/t/qrcode/qr?contents=Hello%20world&format=png" -o hello.png 7 | ``` 8 | 9 | 10 | ## FDK features 11 | 12 | The Fn FDK for Java provides an `InputEvent` object, representing the function's 13 | input. Output should be returned as an `OutputEvent` instance where fine-grained 14 | control over the output (such as setting a MIME type) is needed. See [Data Binding](../../DataBinding.md) for further information. 15 | 16 | ## Step by step 17 | 18 | Ensure you have the Fn server running (`fn start`). The Fn server will host your 19 | function and provide the HTTP endpoints that invoke it: 20 | 21 | ```bash 22 | $ fn start 23 | ``` 24 | 25 | Create an app. 26 | ```bash 27 | $ fn create app qrcode 28 | ``` 29 | 30 | 31 | Deploy the function. 32 | 33 | ```bash 34 | $ fn --verbose deploy --app qrcode --local 35 | ``` 36 | 37 | Invoke the function to create a QR code 38 | 39 | ```bash 40 | $ curl "http://localhost:8080/t/qrcode/qr?contents=Hello%20World" -o hello.png 41 | $ open hello.png # or for linux: xdg-open hello.png 42 | ``` 43 | 44 | Checkout `example.html` which uses the function to present a variety of 45 | QR codes. The examples include: 46 | 47 | * The response from default URL 48 | * The text string Hello 49 | * Instructions phone to make a call to 01234-567890 50 | * Opens https://www.google.com URL 51 | * Creates a text message from a QR Code 52 | 53 | To try out the examples, point the camera of your iOS or Android device at the QRCode. The appropriate text and actions should just popup in the camera app. 54 | 55 | ## Code walkthrough 56 | 57 | The entry point to the function is specified in `func.yaml` in the `cmd` 58 | key. This is set to be `com.fnproject.fn.examples.QRGen::create`, the entrypoint 59 | of the example function. The body of the function is shown below: 60 | 61 | 62 | ```java 63 | public byte[] create(HTTPGatewayContext hctx) { 64 | // If format or contents is empty, set default to png and Hello World 65 | ImageType type = getFormat(hctx.getQueryParameters().get("format").orElse(defaultFormat)); 66 | System.err.println("Format set to: " + type.toString()); 67 | 68 | String contents = hctx.getQueryParameters().get("contents").orElse("QRCode Hello World!"); 69 | System.err.println("QR code generated from contents: " + contents); 70 | 71 | ByteArrayOutputStream stream = QRCode.from(contents).to(type).stream(); 72 | 73 | hctx.setResponseHeader("Content-Type", getMimeType(type)); 74 | return stream.toByteArray(); 75 | } 76 | ``` 77 | 78 | The Fn FDK for Java facilitates access to the HTTP context of events triggered 79 | from HTTP gateways via `HTTPGatewayContext`. The function response is a byte 80 | array. See [Data Binding](../../DataBinding.md) for further information on the 81 | types of input that the FDK provides. 82 | 83 | In this example we take the request URL from the `HTTPGatewayContext` and parse 84 | the query parameters present in the URL (using `QueryParameters`). 85 | A QR code is created using `net.glxn.qrgen.javase.QRCode` which is 86 | serialised to a byte array and returned in an HTTP response. 87 | 88 | Logs are written via `System.err` for processing by the `functions` server. 89 | When a QR code is generated the example logs `"QR code generated from contents: [...]"`. 90 | 91 | Function configuration is injected into the constructor optionally taking 92 | a `RuntimeContext` parameter giving access to parameters set for the 93 | application or the function. 94 | 95 | ```java 96 | ... 97 | private final String defaultFormat; 98 | 99 | public QRGen(RuntimeContext ctx) { 100 | defaultFormat = ctx.getConfigurationByKey("FORMAT").orElse("png"); 101 | } 102 | ... 103 | ``` 104 | 105 | ### Testing 106 | 107 | The Fn FDK for Java provides a `com.fnproject.fn.testing` package for simulating 108 | function invocations and inspecting function results. This is accomplished 109 | by a fake functions server, `FnTesting`, whose life cycle is managed by a [JUnit rule]( 110 | https://github.com/junit-team/junit4/wiki/rules). 111 | 112 | ```java 113 | ... 114 | @Rule 115 | public FnTesting fn = FnTesting.createDefault(); 116 | ... 117 | ``` 118 | 119 | A `FnTesting` object is used to simulate interactions with the function, 120 | this is setup as a JUnit . We will use 121 | this to handle invocations of functions and retrieving function results 122 | 123 | ```java 124 | ... 125 | @Test 126 | public void textHelloWorld() throws Exception { 127 | String content = "hello world"; 128 | fn.givenEvent() 129 | .withHeader("Fn-Http-Request-Url", "http://www.example.com/qr?contents=hello+world&format=png") 130 | .withHeader("Fn-Http-Method","GET") 131 | .enqueue(); 132 | fn.thenRun(QRGen.class, "create"); 133 | 134 | assertEquals(content, decode(fn.getOnlyResult().getBodyAsBytes())); 135 | } 136 | ``` 137 | 138 | Input events are constructed using `fn.givenEvent()` providing an 139 | `FnEventBuilder` interface for customising the input event which is then queued 140 | event using `enqueue`. The function is finally run by 141 | `fn.thenRun(.class, "")`. The results are 142 | retrieved by `fn.getOnlyResult().getBodyAsBytes()` to then compare with a 143 | pregenerated QR code read from disk. 144 | 145 | See [Function Testing](../../FunctionTesting.md) for further information 146 | on the features the testing package provides. 147 | -------------------------------------------------------------------------------- /fn/operate/options.md: -------------------------------------------------------------------------------- 1 | # Fn Runtime Options 2 | 3 | ## Default run command for production 4 | 5 | This will run with docker in docker. 6 | 7 | ```sh 8 | docker run --privileged \ 9 | --rm \ 10 | --name fns \ 11 | -it \ 12 | -v $PWD/data:/app/data \ 13 | -v $PWD/data/iofs:/iofs \ 14 | -e "FN_IOFS_DOCKER_PATH=$PWD/data/iofs" \ 15 | -e "FN_IOFS_PATH=/iofs" \ 16 | -p 80:8080 \ 17 | fnproject/fnserver 18 | ``` 19 | 20 | See below for starting without docker in docker. 21 | 22 | ## Configuration 23 | 24 | When starting Fn, you can pass in the following configuration variables as environment variables. Use `-e VAR_NAME=VALUE` in 25 | docker run. For example: 26 | 27 | ```sh 28 | docker run -e VAR_NAME=VALUE ... 29 | ``` 30 | 31 | Additionally you may desire to load the environment variables from files, for example if you are using Docker Secrets, in that case you may append 32 | `_FILE` to the end of any variable name and specify the file location. The variable will be filled with the file's contents. For example: 33 | 34 | ```sh 35 | docker run -e VAR_NAME_FILE=/path/to/secret ... 36 | ``` 37 | 38 | 39 | | Env Variables | Description | Default values | 40 | | --------------|-------------|----------------| 41 | | `FN_DB_URL` | The database URL to use in URL format. See [Databases](databases/README.md) for more information. | sqlite3:///app/data/fn.db | 42 | | `FN_MQ_URL` | The message queue to use in URL format. See [Message Queues](mqs/README.md) for more information. | bolt:///app/data/worker_mq.db | 43 | | `FN_API_URL` | The primary Fn API URL to that this instance will talk to. In a production environment, this would be your load balancer URL. | N/A | 44 | | `FN_PORT `| Sets the port to run on | 8080 | 45 | | `FN_LOG_LEVEL` | Set to DEBUG to enable debugging | INFO | 46 | | `FN_LOG_DEST` | Set a url to send logs to, instead of stderr. [scheme://][host][:port][/path]; default scheme to udp:// if none given, possible schemes: { udp, tcp, file } 47 | | `FN_LOG_PREFIX` | If supplying a syslog url in `FN_LOG_DEST`, a prefix to add to each log line 48 | | `FN_API_CORS_ORIGINS` | A comma separated list of URLs to enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for (or `*` for all domains). This corresponds to the allowed origins in the `Acccess-Control-Allow-Origin` header. | None | 49 | | `FN_API_CORS_HEADERS` | A comma separated list of Headers to enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for. This corresponds to the allowed headers in the `Access-Control-Allow-Headers` header. | Origin,Content-Length,Content-Type | 50 | | `FN_FREEZE_IDLE_MSECS` | Set this option to specify the amount of time to wait in milliseconds before pausing/freezing an idle container. Set to 0 to freeze idle containers without any delay. Set to negative integer to disable freeze/pause of idle hot containers. | 50 | 51 | | `FN_EJECT_IDLE_MSECS` | Set this option to specify the amount of time in milliseconds for an idle hot container to become eligible for eviction if the system is starved for CPU and Memory resources. Set to negative integer to disable this feature. | 1000 | 52 | | `FN_MAX_RESPONSE_SIZE` | Set this option to specify the http body or json response size in bytes from the containers. | 0 (off) | 53 | | `DOCKER_HOST` | Docker remote API URL. | /var/run/docker.sock | 54 | | `DOCKER_API_VERSION` | Docker remote API version. | 1.24 | 55 | | `DOCKER_TLS_VERIFY` | Set this option to enable/disable Docker remote API over TLS/SSL. | 0 | 56 | | `DOCKER_CERT_PATH` | Set this option to specify where CA cert placeholder. | ~/.docker/cert.pem | 57 | | `FN_MAX_FS_SIZE_MB` | Set this option in MB to pass a `size` option to Docker storage driver. This limits the file system size for all containers on the system. See [Docker storage driver options per container](https://docs.docker.com/engine/reference/commandline/run/#set-storage-driver-options-per-container) documentation for details. | None | 58 | | `FN_DOCKER_NETWORKS` | Set this option with a list of docker networks for function containers to use. If unset, default docker network is used. | None | 59 | | `FN_DISABLE_READONLY_ROOTFS` | Set this option to enable writable root filesystem. By default root filesystem is mounted read-only. | None | 60 | | `FN_DOCKER_LOAD_FILE` | Set this option with an absolute path to a tarball to load a set of docker images during fn server startup. The tarball can be generated using [docker save](https://docs.docker.com/engine/reference/commandline/save/). | None | 61 | 62 | ## Starting without Docker in Docker 63 | 64 | The default way to run Fn, as it is in the Quickstart guide, is to use docker-in-docker (dind). There are 65 | a couple reasons why we did it this way: 66 | 67 | * It's clean. Once the container exits, there is nothing left behind including all the function images. 68 | * You can set resource restrictions for the entire Fn instance. For instance, you can set `--memory` on the docker run command to set the max memory for the Fn instance AND all of the functions it's running. 69 | 70 | There are some reasons you may not want to use dind, such as using the image cache during testing or you're running 71 | [Windows](windows.md). 72 | 73 | ### Mount the Host Docker 74 | 75 | One way is to mount the host Docker. Everything is essentially the same except you add a `-v` flag: 76 | 77 | ```sh 78 | docker run --rm --name functions -it -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/data:/app/data -p 8080:8080 fnproject/fnserver 79 | ``` 80 | 81 | On Linux systems where SELinux is enabled and set to "Enforcing", SELinux will stop the container from accessing 82 | the host docker and the local directory mounted as a volume, so this method cannot be used unless security restrictions 83 | are disabled. 84 | 85 | ### Run outside Docker 86 | 87 | You can of course just run the binary directly, you'll just have to change how you set the environment variables above. 88 | 89 | See [contributing doc](../general/contributing.md) for information on how to build and run. 90 | --------------------------------------------------------------------------------