Deploy a function via API
Use Python's requests library to interact with the OpenFaaS REST API and manage functions and namespaces programmatically — useful for CI/CD pipelines, functions that manage other functions, or building self-service platforms on top of OpenFaaS.
Use-cases:
- Custom deployment tooling and CI/CD automation
- Functions that manage other functions and namespaces programmatically
- Building self-service platforms on top of OpenFaaS
This example creates a namespace if it does not already exist, then deploys a function into it.
Overview¶
handler.py:
import os
import json
import requests
def handle(event, context):
gateway = os.getenv("gateway_url", "http://gateway.openfaas:8080")
password = read_secret("openfaas-password")
auth = ("admin", password)
body = json.loads(event.body)
ns = body.get("namespace", "openfaas-fn")
namespaces = requests.get(
f"{gateway}/system/namespaces",
auth=auth,
).json()
if ns not in namespaces:
r = requests.post(
f"{gateway}/system/namespace/",
json={"name": ns, "annotations": {"openfaas": "1"}},
auth=auth,
)
if r.status_code not in (200, 201):
return {
"statusCode": r.status_code,
"body": f"Failed to create namespace: {r.text}",
}
r = requests.put(
f"{gateway}/system/functions",
json={
"service": body["name"],
"image": body["image"],
"namespace": ns,
},
auth=auth,
)
return {
"statusCode": r.status_code,
"body": r.text,
}
def read_secret(name):
with open("/var/openfaas/secrets/" + name, "r") as f:
return f.read().strip()
requirements.txt:
requests
stack.yaml:
functions:
deploy-function:
lang: python3-http
handler: ./deploy-function
image: ttl.sh/openfaas-examples/deploy-function:latest
secrets:
- openfaas-password
The requests package is pure Python, so the Alpine-based python3-http template works here.
- The gateway URL defaults to
http://gateway.openfaas:8080, the in-cluster address when running on Kubernetes. Override it with thegateway_urlenvironment variable if needed. - The handler authenticates with HTTP Basic Auth using the
adminusername and the password read from theopenfaas-passwordsecret. - Namespace creation is idempotent — the handler checks whether the namespace exists before attempting to create it.
Because this function can manage other functions and namespaces, its own endpoint should be protected. See Add authentication for how to do this.
Step-by-step walkthrough¶
Create the function¶
Pull the template and scaffold a new function:
faas-cli template store pull python3-http
faas-cli new --lang python3-http deploy-function \
--prefix ttl.sh/openfaas-examples
The example uses the public ttl.sh registry — replace the prefix with your own registry for production use.
Update deploy-function/handler.py and deploy-function/requirements.txt with the code from the overview above.
Create the openfaas-password secret¶
The gateway admin password is stored in a Kubernetes secret called basic-auth during installation. Retrieve it and create an OpenFaaS function secret named openfaas-password so the function can access it at runtime:
PASSWORD=$(kubectl get secret -n openfaas basic-auth \
-o jsonpath="{.data.basic-auth-password}" | base64 --decode)
faas-cli secret create openfaas-password --from-literal="$PASSWORD"
At runtime, the secret is mounted as a file under /var/openfaas/secrets/ inside the function container.
Deploy and invoke¶
Build, push and deploy the function with faas-cli up:
faas-cli up \
--filter deploy-function \
--tag digest
Deploy the env function into a staging namespace. The namespace is created automatically if it does not exist:
curl -X POST http://127.0.0.1:8080/function/deploy-function \
-H "Content-Type: application/json" \
--data '{
"name": "env",
"image": "ghcr.io/openfaas/alpine:latest",
"namespace": "staging"
}'
Add authentication¶
This function manages other functions and namespaces, so its endpoint should require authentication. You can implement authentication directly in the handler code, or use the built-in function authentication provided by OpenFaaS IAM.
Built-in function authentication with OpenFaaS IAM¶
OpenFaaS IAM provides built-in function authentication without any code changes. Set the jwt_auth environment variable on the function and configure a Role and Policy to control who can invoke it.
functions:
deploy-function:
lang: python3-http
handler: ./deploy-function
image: ttl.sh/openfaas-examples/deploy-function:latest
secrets:
- openfaas-password
environment:
jwt_auth: "true"
The watchdog enforces authentication automatically — callers must present a valid function access token in the Authorization: Bearer header. The request will never reaches the function handler if the token is missing or invalid.
See Function Authentication for how to configure Roles and Policies and obtain function access tokens.
Implement authentication in the handler¶
The handler can validate any credential that suits your use case — a pre-shared token, an API key, or any other scheme. The example below uses a pre-shared token stored as an OpenFaaS secret and compared against the Authorization: Bearer header — any request without a valid token is rejected before any API calls are made.
Add the valid_bearer helper and a token check at the top of the handler:
import os
import json
import requests
def handle(event, context):
+ token = read_secret("deploy-function-token")
+ if not valid_bearer(token, event.headers):
+ return {"statusCode": 401, "body": "Unauthorized"}
+
gateway = os.getenv("gateway_url", "http://gateway.openfaas:8080")
password = read_secret("openfaas-password")
auth = ("admin", password)
@@ ...
+def valid_bearer(token, headers):
+ if "Authorization" not in headers:
+ return False
+ authz = headers["Authorization"]
+ if not authz.startswith("Bearer "):
+ return False
+ return authz.split(" ", 1)[1] == token
+
def read_secret(name):
with open("/var/openfaas/secrets/" + name, "r") as f:
return f.read().strip()
Add the new secret to stack.yaml:
secrets:
- openfaas-password
+ - deploy-function-token
Generate and create the token secret:
faas-cli secret generate -o ./deploy-function-token.txt
faas-cli secret create deploy-function-token \
--from-file=./deploy-function-token.txt
Redeploy the function and invoke it with the token:
faas-cli up \
--filter deploy-function \
--tag digest
curl -X POST http://127.0.0.1:8080/function/deploy-function \
-H "Authorization: Bearer $(cat ./deploy-function-token.txt)" \
-H "Content-Type: application/json" \
--data '{
"name": "env",
"image": "ghcr.io/openfaas/alpine:latest",
"namespace": "staging"
}'
A request without a valid token returns 401 Unauthorized.