Dynamic Helm Configuration with Python Scripts
Enhance Helm deployments with dynamic configuration by using sandboxed Python scripts
Helm services can compute values and valuesFiles at render time with a Python script, as an alternative or a complement to Lua scripts. The script mutates two pre-defined globals, and the deployment agent merges the result into the Helm release:
{
"values": {
"key": "value"
},
"valuesFiles": ["file1.yaml", "file2.yaml"]
}apiVersion: deployments.plural.sh/v1alpha1
kind: ServiceDeployment
metadata:
name: my-app
namespace: infra
spec:
namespace: my-app
name: my-app
cluster: k3s
configuration:
environment: prod
helm:
version: 1.x.x
chart: my-app
url: https://example.invalid/charts
pythonScript: |
env = configuration.get("environment", "dev")
values["replicaCount"] = 3 if env == "prod" else 1
valuesFiles.append(f"values-{env}.yaml")The Python Runtime
Scripts are executed by Monty, a sandboxed Python interpreter written in Rust, embedded in the deployment agent through gomonty. It is not CPython: it implements a subset of Python 3.14 syntax and a small subset of the standard library, and it has no access to the host system.
The agent currently bundles gomonty v0.0.14, which pins Monty v0.0.9. Monty's upstream documentation tracks the latest Monty release, which supports more than the pinned version does (for example classes and str.format). Treat this page as the reference for what works in the agent.
Security Model
- No filesystem access:
opendoes not exist, and filesystem calls inosandpathlibraiseNotImplementedError. Unlike Lua, Python scripts cannot read files from the service tarball. UsevaluesFilesto have the agent load files on your behalf. - No environment or network access:
os.getenvandos.environraiseNotImplementedError, and there is no socket, HTTP, or subprocess module. - No third-party packages: there is no
sys.pathor site-packages, soimport yaml,import requests, and similar fail withModuleNotFoundError. YAML support is provided by theyaml_encodeandyaml_decodeglobals instead. - Limited host callbacks: the only way to reach the agent is
k8s_object_meta, a read-only lookup against the agent's object cache. The YAML andmergehelpers also run on the agent, but they only transform the data you pass them.warnis defined in the sandbox itself. - Fresh state on every render: each render gets a new interpreter. Nothing defined in one render, including functions and globals, is visible to the next.
Resource Limits
Limit | Value |
|---|---|
| Execution time | 10 seconds, including time spent waiting for a free interpreter |
| Memory | 100 MB |
| Recursion depth | 100 frames |