Skip to main content
Version: v1.0.0-rc.1 (pre-release)

Configuration Helper Functions

Configuration helpers are CEL extension functions that provide convenient methods to work with the configurations object in your templates. They help reduce boilerplate code and make templates more readable and maintainable.

Overview​

These helpers simplify working with container configurations, environment variables, and file mounts. All configuration helper functions are available on the configurations context object when working with ComponentType templates.

Helper Functions Reference​

toContainerEnvFrom()​

Generates an envFrom array for the container configuration, creating configMapRef and secretRef entries based on available environment variables.

Parameters: None

Returns: List of envFrom entries, each containing either:

FieldTypeDescription
configMapRefmapReference to ConfigMap (only present if container has config envs)
secretRefmapReference to Secret (only present if container has secret envs)

Examples:

# Using helper function
spec:
template:
spec:
containers:
- name: main
image: myapp:latest
envFrom: ${configurations.toContainerEnvFrom()}

# Equivalent manual implementation
envFrom: |
${(has(configurations.configs.envs) && configurations.configs.envs.size() > 0 ?
[{
"configMapRef": {
"name": oc_generate_name(metadata.name, "env-configs")
}
}] : []) +
(has(configurations.secrets.envs) && configurations.secrets.envs.size() > 0 ?
[{
"secretRef": {
"name": oc_generate_name(metadata.name, "env-secrets")
}
}] : [])}

# Combine with additional envFrom entries
envFrom: |
${configurations.toContainerEnvFrom() +
[{"configMapRef": {"name": "external-config"}}]}

toConfigEnvsByContainer()​

Generates a list of objects for creating ConfigMaps from environment variables. Each object contains the container name, generated resource name, and environment variables.

Parameters: None

Returns: List of objects, each containing:

FieldTypeDescription
containerstringName of the container
resourceNamestringGenerated ConfigMap name (componentName-environmentName-containerName-env-configs-hash)
envsarrayList of environment variable objects with name and value

Examples:

# Using helper function
- id: env-config
forEach: ${configurations.toConfigEnvsByContainer()}
var: envConfig
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${envConfig.resourceName}
namespace: ${metadata.namespace}
data: |
${envConfig.envs.transformMapEntry(index, env, {env.name: env.value})}

# Equivalent manual implementation
- id: env-config
forEach: |
${configurations.transformList(containerName, cfg,
{
"container": containerName,
"resourceName": oc_generate_name(metadata.name, containerName, "env-configs"),
"envs": cfg.configs.envs
}
)}
var: envConfig
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${envConfig.resourceName}
namespace: ${metadata.namespace}
data: |
${envConfig.envs.transformMapEntry(index, env, {env.name: env.value})}

Notes:

  • Only returns entries for containers that have config environment variables
  • Skips containers with no config envs or only secret envs
  • Generated resource names include container name and a hash for uniqueness

toSecretEnvsByContainer()​

Generates a list of objects for creating ExternalSecrets from secret environment variables. Each object contains the container name, generated resource name, and secret environment variables.

Parameters: None

Returns: List of objects, each containing:

FieldTypeDescription
containerstringName of the container
resourceNamestringGenerated ExternalSecret name (componentName-environmentName-containerName-env-secrets-hash)
envsarrayList of secret environment variable objects with name and remoteRef

Examples:

# Using helper function
- id: secret-env-external
forEach: ${configurations.toSecretEnvsByContainer()}
var: secretEnv
template:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: ${secretEnv.resourceName}
namespace: ${metadata.namespace}
spec:
refreshInterval: 15s
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: ${secretEnv.resourceName}
creationPolicy: Owner
data: |
${secretEnv.envs.map(secret, {
"secretKey": secret.name,
"remoteRef": {
"key": secret.remoteRef.key,
"property": has(secret.remoteRef.property) ? secret.remoteRef.property : oc_omit()
}
})}

# Equivalent manual implementation
- id: secret-env-external
forEach: |
${configurations.transformList(containerName, cfg,
{
"container": containerName,
"resourceName": oc_generate_name(metadata.name, containerName, "env-secrets"),
"envs": cfg.secrets.envs
}
)}
var: secretEnv
template:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: ${secretEnv.resourceName}
namespace: ${metadata.namespace}
spec:
refreshInterval: 15s
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: ${secretEnv.resourceName}
creationPolicy: Owner
data: |
${secretEnv.envs.map(secret, {
"secretKey": secret.name,
"remoteRef": {
"key": secret.remoteRef.key,
"property": has(secret.remoteRef.property) ? secret.remoteRef.property : oc_omit()
}
})}

Notes:

  • Only returns entries for containers that have secret environment variables
  • Skips containers with no secret envs or only config envs
  • Generated resource names include container name and a hash for uniqueness

toConfigFileList()​

Flattens configs.files from all containers into a single list. Each file includes a generated resourceName for creating ConfigMaps.

Parameters: None

Returns: List of file objects, each containing:

FieldTypeDescription
namestringFile name
mountPathstringMount path
valuestringFile content (empty string if using remoteRef)
resourceNamestringGenerated Kubernetes-compliant resource name (componentName-environmentName-containerName-config-fileName)
remoteRefmapRemote reference (only present if the file uses a secret reference)

Examples:

# Generate a ConfigMap for each config file
- id: file-configs
forEach: ${configurations.toConfigFileList()}
var: config
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${config.resourceName}
namespace: ${metadata.namespace}
data:
${config.name}: |
${config.value}

Equivalent CEL expression:

If you need additional fields (e.g., container name) or different behavior, use the underlying data directly:

forEach: |
${configurations.transformList(containerName, cfg,
cfg.configs.files.map(f, oc_merge(f, {
"container": containerName,
"resourceName": oc_generate_name(metadata.name, containerName, "config", f.name.replace(".", "-"))
}))
).flatten()}

toSecretFileList()​

Flattens secrets.files from all containers into a single list. Each file includes a generated resourceName for creating Secrets or ExternalSecrets.

Parameters: None

Returns: List of file objects, each containing:

FieldTypeDescription
namestringFile name
mountPathstringMount path
valuestringFile content (empty string if using remoteRef)
resourceNamestringGenerated Kubernetes-compliant resource name (componentName-environmentName-containerName-secret-fileName)
remoteRefmapRemote reference (only present if the file uses a secret reference)

Examples:

# Generate ExternalSecrets for secret files
- id: file-secrets
forEach: ${configurations.toSecretFileList()}
var: secret
includeWhen: ${has(secret.remoteRef)}
template:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ${secret.resourceName}
namespace: ${metadata.namespace}
spec:
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: ${secret.resourceName}
creationPolicy: Owner
data:
- secretKey: ${secret.name}
remoteRef:
key: ${secret.remoteRef.key}
property: ${secret.remoteRef.property}

# Generate Secrets for files with inline values
- id: inline-file-secrets
forEach: ${configurations.toSecretFileList()}
var: secret
includeWhen: ${!has(secret.remoteRef) && secret.value != ""}
template:
apiVersion: v1
kind: Secret
metadata:
name: ${secret.resourceName}
namespace: ${metadata.namespace}
data:
${secret.name}: ${base64.encode(secret.value)}

Equivalent CEL expression:

forEach: |
${configurations.transformList(containerName, cfg,
cfg.secrets.files.map(f, oc_merge(f, {
"container": containerName,
"resourceName": oc_generate_name(metadata.name, containerName, "secret", f.name.replace(".", "-"))
}))
).flatten()}

toContainerVolumeMounts()​

Generates a volumeMounts array for the container's config and secret files.

Parameters: None

Returns: List of volumeMount entries, each containing:

FieldTypeDescription
namestringVolume name (file-mount-{hash} format)
mountPathstringFull mount path (mountPath + "/" + filename)
subPathstringFilename to mount as subPath

Examples:

# Using helper function
spec:
template:
spec:
containers:
- name: main
image: myapp:latest
volumeMounts: ${configurations.toContainerVolumeMounts()}

# Equivalent manual implementation
volumeMounts: |
${has(configurations.configs.files) && configurations.configs.files.size() > 0 || has(configurations.secrets.files) && configurations.secrets.files.size() > 0 ?
(has(configurations.configs.files) && configurations.configs.files.size() > 0 ?
configurations.configs.files.map(f, {
"name": "file-mount-"+oc_hash(f.mountPath+"/"+f.name),
"mountPath": f.mountPath+"/"+f.name ,
"subPath": f.name
}) : []) +
(has(configurations.secrets.files) && configurations.secrets.files.size() > 0 ?
configurations.secrets.files.map(f, {
"name": "file-mount-"+oc_hash(f.mountPath+"/"+f.name),
"mountPath": f.mountPath+"/"+f.name,
"subPath": f.name
}) : [])
: oc_omit()}

# Combine with additional volume mounts
volumeMounts: |
${configurations.toContainerVolumeMounts() +
[{"name": "cache", "mountPath": "/cache"}]}

toVolumes()​

Generates a volumes array for all containers' config and secret files.

Parameters: None

Returns: List of volume entries, each containing:

FieldTypeDescription
namestringVolume name (generated using hash of mountPath and filename)
configMapmapConfigMap volume source (only present for config files)
secretmapSecret volume source (only present for secret files)

Examples:

# Using helper function
spec:
template:
spec:
containers:
- name: main
image: myapp:latest
volumeMounts: ${configurations.toContainerVolumeMounts()}
volumes: ${configurations.toVolumes()}

# Equivalent manual implementation
volumes: |
${has(configurations.configs.files) && configurations.configs.files.size() > 0 || has(configurations.secrets.files) && configurations.secrets.files.size() > 0 ?
(has(configurations.configs.files) && configurations.configs.files.size() > 0 ?
configurations.configs.files.map(f, {
"name": "file-mount-"+oc_hash(f.mountPath+"/"+f.name),
"configMap": {
"name": oc_generate_name(metadata.name, "config", f.name).replace(".", "-")
}
}) : []) +
(has(configurations.secrets.files) && configurations.secrets.files.size() > 0 ?
configurations.secrets.files.map(f, {
"name": "file-mount-"+oc_hash(f.mountPath+"/"+f.name),
"secret": {
"secretName": oc_generate_name(metadata.name, "secret", f.name).replace(".", "-")
}
}) : [])
: oc_omit()}

# Combine with inline volumes
volumes: |
${configurations.toVolumes() +
[{"name": "extra-volume", "emptyDir": {}}]}

Common Usage Patterns​

Complete Deployment with Configurations​

spec:
workloadType: deployment
resources:
- id: deployment
template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${metadata.name}
namespace: ${metadata.namespace}
spec:
replicas: ${parameters.replicas}
selector:
matchLabels: ${metadata.podSelectors}
template:
metadata:
labels: ${oc_merge(metadata.labels, metadata.podSelectors)}
spec:
containers:
- name: main
image: ${workload.container.image}
envFrom: ${configurations.toContainerEnvFrom()}
volumeMounts: ${configurations.toContainerVolumeMounts()}
volumes: ${configurations.toVolumes()}

# Generate ConfigMaps for environment variables
- id: env-configs
forEach: ${configurations.toConfigEnvsByContainer()}
var: envConfig
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${envConfig.resourceName}
namespace: ${metadata.namespace}
data: |
${envConfig.envs.transformMapEntry(i, e, {e.name: e.value})}

# Generate ExternalSecrets for secret environment variables
- id: env-secrets
forEach: ${configurations.toSecretEnvsByContainer()}
var: secretEnv
template:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: ${secretEnv.resourceName}
namespace: ${metadata.namespace}
spec:
refreshInterval: 15s
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: ${secretEnv.resourceName}
creationPolicy: Owner
data: |
${secretEnv.envs.map(e, {
"secretKey": e.name,
"remoteRef": {
"key": e.remoteRef.key,
"property": has(e.remoteRef.property) ? e.remoteRef.property : oc_omit()
}
})}

# Generate ConfigMaps for config files
- id: config-files
forEach: ${configurations.toConfigFileList()}
var: config
template:
apiVersion: v1
kind: ConfigMap
metadata:
name: ${config.resourceName}
namespace: ${metadata.namespace}
data:
${config.name}: |
${config.value}

# Generate ExternalSecrets for secret files
- id: secret-files
forEach: ${configurations.toSecretFileList()}
var: secret
includeWhen: ${has(secret.remoteRef)}
template:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ${secret.resourceName}
namespace: ${metadata.namespace}
spec:
secretStoreRef:
name: ${dataplane.secretStore}
kind: ClusterSecretStore
target:
name: ${secret.resourceName}
creationPolicy: Owner
data:
- secretKey: ${secret.name}
remoteRef:
key: ${secret.remoteRef.key}
property: ${secret.remoteRef.property}

Workload Helper Functions​

These helper functions are available on the workload context object to simplify working with endpoint configurations.

workload.toServicePorts()​

Converts a workload's endpoints into Kubernetes Service port definitions, automatically mapping endpoint configurations to the proper service port format.

Parameters: None (operates on workload.endpoints)

Returns: List of service port objects, each containing:

FieldTypeDescription
namestringPort name (derived from endpoint name, DNS-compliant)
portintegerService port number (from endpoint.port)
targetPortintegerTarget port on pods (from endpoint.targetPort or defaults to endpoint.port)
protocolstringProtocol (derived from endpoint.type, defaults to "TCP")

Endpoint Type Mapping:

Endpoint TypeService Protocol
HTTP, REST, GraphQLTCP
gRPCTCP
WebsocketTCP
TCPTCP
UDPUDP

Examples:

# Service resource using helper function
- id: service
template:
apiVersion: v1
kind: Service
metadata:
name: ${metadata.componentName}
namespace: ${metadata.namespace}
spec:
selector: ${metadata.podSelectors}
ports: ${workload.toServicePorts()}

# Equivalent manual implementation
ports: |
${workload.endpoints.map(name, ep, {
"name": oc_dns_label(name),
"port": ep.port,
"targetPort": has(ep.targetPort) ? ep.targetPort : ep.port,
"protocol": ep.type in ["UDP"] ? "UDP" : "TCP"
})}

Input Requirements:

  • workload.endpoints must be a map where each key is an endpoint name
  • Each endpoint must have a port field (integer, 1-65535)
  • Each endpoint should have a type field for protocol mapping
  • Each endpoint may have a targetPort field (integer, defaults to port value)
  • Each endpoint may have a visibility field (array of visibility levels: external, internal, namespace, project)
  • Each endpoint may have displayName and basePath fields for documentation and routing

Behavior:

  • Filters out any endpoints without a valid port field
  • Generates DNS-compliant port names using oc_dns_label()
  • Maps endpoint types to appropriate Kubernetes service protocols
  • Uses targetPort if specified, otherwise defaults to port value
  • Includes all endpoints regardless of visibility level (visibility is handled separately in routing resources)
  • Returns empty list if no valid endpoints are found

Edge Cases:

  • Empty workload.endpoints: Returns empty array []
  • Endpoint missing port: Endpoint is skipped
  • Endpoint missing type: Defaults to "TCP" protocol
  • Endpoint missing targetPort: Uses port value for targetPort
  • Invalid endpoint names: Converted to DNS-compliant format using oc_dns_label()

Usage in Templates:

# Basic service
spec:
selector: ${metadata.podSelectors}
ports: ${workload.toServicePorts()}

# Service with additional ports
spec:
selector: ${metadata.podSelectors}
ports: |
${workload.toServicePorts() + [
{"name": "metrics", "port": 9090, "targetPort": 9090}
]}

# Conditional service creation
- id: service
includeWhen: ${size(workload.endpoints) > 0}
template:
apiVersion: v1
kind: Service
metadata:
name: ${metadata.componentName}
spec:
ports: ${workload.toServicePorts()}

# HTTPRoute using endpoint details directly (not toServicePorts())
- id: httproute-external
forEach: '${workload.endpoints.transformList(name, ep, ("external" in ep.visibility) ? [name] : []).flatten()}'
var: endpoint
template:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ${oc_generate_name(metadata.componentName, endpoint)}
spec:
rules:
- matches:
- path:
type: PathPrefix
value: /${metadata.componentName}-${endpoint}
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: '${workload.endpoints[endpoint].?basePath.orValue("/")}'
backendRefs:
- name: ${metadata.componentName}
port: ${workload.endpoints[endpoint].port}

Notes:

  • This helper only works with Service resources; for HTTPRoute backend references, use workload.endpoints[endpointName].port directly
  • Port names are automatically generated and may differ from original endpoint names to ensure DNS compliance
  • The helper maintains a consistent mapping between endpoint configurations and service definitions
  • Visibility handling: The visibility attribute is not processed by this helper. Use visibility in routing resources (HTTPRoute, Gateway) to control endpoint exposure:
    • external: Accessible from outside the cluster
    • internal: Accessible within the cluster but not externally
    • namespace: Accessible only within the same namespace
    • project: Accessible only within the same project (implicit for all endpoints)
  • BasePath usage: For HTTPRoute path rewriting, use workload.endpoints[endpointName].basePath to configure URL path prefixes
  • TargetPort distinction: targetPort (container listening port) vs port (service port) - the helper uses the correct values for each

See Also​