Outputs
The outputs section of values-ui.yaml is what turns submitted form values into Helm values and Kubernetes Secrets. Inputs collect data from the user; outputs map that data into the shape Helm expects.
Two kinds of outputs:
outputs.values— an array describing where each piece of data ends up in the Helm values tree.outputs.secrets— a map describing which Kubernetes Secrets to create in the deployment's namespace, and what their contents should be.
outputs.values​
Each entry has a path (where in the Helm values tree) and a value (which input value to put there).
outputs:
values:
- path: [config, host]
value:
FieldValue:
input: hostname
- path: [config, port]
value:
FieldValue:
input: port
- path: [config, database, password_ref]
value:
FieldValue:
input: db_password_secret
Given user inputs hostname=api.example.com, port=8080, db_password_secret=db-creds.main, the resulting Helm values for helm install are:
config:
host: api.example.com
port: 8080
database:
password_ref: main
The path is an array of strings — each element is one level down in the YAML tree. Use as many levels as you need.
Value sources​
There are two ways to source a value:
FieldValue​
Takes the entire input value verbatim.
- path: [replicaCount]
value:
FieldValue:
input: replica_count
Use for plain inputs (text, number, checkbox), array inputs (the entire array lands at the path), and CollectionSelect inputs (the selected item's ID or name lands at the path).
FieldProperty​
Extracts a single property from a CollectionSelect input. Used when the user picks a thing (a deployment, a resource, a secret) and you want a specific attribute of that thing rather than its identifier.
- path: [config, database, hostname]
value:
FieldProperty:
input: database_deployment
property: ingress_hostname
- path: [config, database, port]
value:
FieldProperty:
input: database_deployment
property: port
database_deployment is a CollectionSelect over Deployments. When the user picks a postgres deployment, FieldProperty extracts the deployment's ingress_hostname and port and places them at the respective paths.
For arrays of CollectionSelect, FieldProperty produces an array of properties — one per selected item:
- id: regions
type: array
itemType: CollectionSelect
collection: regions
# in outputs:
- path: [region_hostnames]
value:
FieldProperty:
input: regions
property: hostname
If the user picks three regions, region_hostnames becomes a YAML array of three hostnames.
Which properties are available depends on the collection type:
- Env secrets —
value(the actual secret value). - Deployments —
id,name,kind,ingress_hostname,cluster_id, etc. (the deployment row's fields). - Deployment resources —
id,name, plus any fields defined in the resource'svalues-ui.yaml.
The exact list depends on the chart-ext crate version. Refer to platz_chart_ext::UiSchemaCollections for the canonical list.
Path syntax​
Paths are arrays of strings. Most strings are object keys, but a few special tokens manipulate arrays:
| Token | Meaning |
|---|---|
<key> | Object key — descend into the object at that key, creating an empty object if it doesn't exist. |
"[N]" | Array index (N is a number) — index into an array, creating empty entries up to N. |
"[+]" | Append — add a new element at the end of the array. Each [+] in the same output sequence creates a new element. |
"[=]" | Reference last appended element — descend into the most recently appended element (or create one if the array is empty). |
The bracket tokens must be quoted in YAML — "[+]", not [+] (the latter is YAML flow sequence syntax).
Example: building an array of objects from a CollectionSelect array.
inputs:
- id: tenants
type: array
itemType: CollectionSelect
collection: tenants
outputs:
values:
- path: [config, tenants, "[+]", id]
value:
FieldProperty:
input: tenants
property: id
- path: [config, tenants, "[=]", name]
value:
FieldProperty:
input: tenants
property: name
For each tenant the user picks, this appends {id: ..., name: ...} to config.tenants[]. The [+] appends, then [=] references the just-appended element.
The 1024-element ceiling: if your inputs produce more than 1024 array elements, the surplus is silently dropped. This is a safety net against runaway inputs, not a documented feature you should rely on.
outputs.secrets​
Each entry produces a Kubernetes Secret in the deployment's namespace.
outputs:
secrets:
db-credentials:
DB_HOST:
FieldValue:
input: db_hostname
DB_PORT:
FieldValue:
input: db_port
DB_PASSWORD:
FieldProperty:
input: db_password_secret
property: value
api-keys:
STRIPE_KEY:
FieldProperty:
input: stripe_secret
property: value
Result: two Kubernetes Secrets in the deployment's namespace.
db-credentialswith keysDB_HOST,DB_PORT,DB_PASSWORD.api-keyswith keySTRIPE_KEY.
The chart's templates reference these secrets by name and key (typically via envFrom: { secretRef: { name: db-credentials } } or by reading the keys individually).
Secret values are always serialized to strings. If the source is a number, it's converted via Rust's Display impl.
Optional secrets​
If a secret entry's source input is hidden (via showIf) and not required, the corresponding key is skipped — but the Secret itself is still created if any other key resolved. If all keys are skipped, the Secret is not created at all (Platz doesn't emit empty Kubernetes Secrets).
This means you can conditionally include keys:
inputs:
- id: use_tls
type: Checkbox
- id: tls_cert
type: text
sensitive: true
showIf:
"===":
- var: use_tls
- true
outputs:
secrets:
app-tls:
TLS_CERT:
FieldValue:
input: tls_cert
When use_tls is false, tls_cert is hidden, no TLS_CERT value resolves, and app-tls is not created. When use_tls is true, app-tls contains the cert.
Putting it together​
A realistic example: a chart that needs to know its host, point at a Postgres deployment, and store an API key.
apiVersion: platz.io/v1beta1
kind: ValuesUi
inputs:
- id: hostname
type: text
label: Hostname
required: true
- id: postgres_deployment
type: CollectionSelect
label: Postgres Deployment
collection:
Deployments:
filters:
kind: postgres
required: true
- id: api_key
type: CollectionSelect
label: API Key
collection: api-keys
outputs:
values:
- path: [hostname]
value:
FieldValue:
input: hostname
- path: [database, host]
value:
FieldProperty:
input: postgres_deployment
property: ingress_hostname
- path: [database, port]
value:
FieldProperty:
input: postgres_deployment
property: port
secrets:
app-config:
API_KEY:
FieldProperty:
input: api_key
property: value
What happens at install time:
- The user fills in the form, picking
payments-prodas the postgres deployment andstripe-prodas the API key. - Platz looks up
payments-prodand extracts itsingress_hostname(postgres-payments-prod.example.com) andport(5432). - Platz looks up
stripe-prodand extracts itsvalue(the actual API key). - Platz constructs the helm values:
{hostname: <user-input>, database: {host: "postgres-payments-prod.example.com", port: 5432}}. - Platz creates a Kubernetes Secret
app-configwith keyAPI_KEYset to the resolved Stripe key. - Platz runs
helm installwith the constructed values.
Caveats​
- Outputs are evaluated in order. Array operations (
[+],[=]) depend on this. Don't reorder entries unless you understand the consequences. - Outputs that reference hidden inputs silently skip. No error, no warning — the output just isn't produced. This is the right behavior for conditional outputs but a footgun for typos: if you write
input: hostnam(missing thee), the output is "skipped because input not provided" rather than a clear error. - Numeric values become strings in secrets. A
numberinput wired intooutputs.secretsends up as"5"not5. The chart's pod reads it as a string regardless. - Path components are strings, not paths. Don't write
path: ["a.b.c"]expecting Platz to split on dots — it won't. Usepath: [a, b, c]. - The default Helm
values.yamlis still in effect. Outputs don't replacevalues.yaml— they're a layer applied on top. If your chart has a default value atreplicaCount: 1invalues.yamland your outputs don't write to that path, the chart seesreplicaCount: 1. Outputs override defaults where they're written; they don't replace the whole values tree. values_overrideruns after outputs. The owner's raw YAML override sits on top of everything. If an override setsdatabase.host: <something>, it wins over the FieldProperty resolution. This is the design — it's the escape hatch.- Secret values can't reference other secrets. A
FieldPropertyof a secret extracts the secret's value, full stop. You can't chain (e.g., reference a secret whose value names another secret). Resolve fully in one step.