Key Features#
Two template engines#
A Template exposes exactly one of two engines, enforced by an API-level validation rule (has(self.gotemplate) != has(self.helm)).
Go template#
spec.gotemplate is a string parsed with Go's text/template plus Sprig functions. The output may emit one or more Kubernetes manifests separated by YAML document markers. The following Sprig functions are removed for safety: env, expandenv, getHostByName.
Helm#
spec.helm references a chart by repository URL, chart name, and SemVer 2 version:
HTTP/HTTPSrepositories:url: https://charts.example.com- OCI registries:
url: oci://ghcr.io/org/charts
Both Helm v3 and v4 SDKs are bundled. Pick with spec.helm.version: v3 or v4. When omitted, v3 is the default. Optional spec.helm.valuesTemplate is itself a Go template that, after rendering, is parsed as YAML and merged over the chart's default values.
Private repositories are supported via spec.helm.chart.repository.auth.secretRef, which references a Secret in the Template's namespace (not the consumer's).
Available data#
Both engines see the same context object:
.parameters, the resolved parameter map..instance.name,.instance.namespace,.instance.labels, metadata of the consumingTemplateInstance.
Important
If a rendered manifest omits metadata.namespace, the operator sets it to the TemplateInstance's namespace before applying.
Dynamic parameter resolution#
TemplateInstance parameter overrides may resolve their value at render time:
| Source | Field | Reads |
|---|---|---|
| Secret | valueFrom.secretKeyRef |
A specific key, base64-decoded |
| ConfigMap | valueFrom.configMapKeyRef |
A specific key |
| Any resource | valueFrom.objectFieldRef |
A JSONPath expression evaluated against the resource (GET mode) or against a list of resources (LIST mode, when name is omitted) |
objectFieldRef returns a scalar in GET mode; it always returns a list in LIST mode so templates can {{range}} safely. With sync.mode: revert or strict, the operator dynamically watches every resource referenced by valueFrom, and re-reconciles the TemplateInstance when the source changes.
A defaultValue may be set on each TemplateInstance parameter; it is used only when paired with valueFrom, and applies whenever the valueFrom resolution fails (missing resource, missing key, JSONPath error, and so on).
Target namespace control#
Template.spec.targetNamespaces decides which consumer namespaces are allowed to instantiate the Template:
- Omitted entirely → same namespace as the
Templateonly (default). explicit.allow.literal: ["*"]→ all namespaces.explicit.allow.literal: [...]→ explicit allow-list.selector→ namespaces whose labels match theLabelSelector.- A namespace is permitted if it matches the explicit list or the selector.
If a TemplateInstance is created in a non-permitted namespace, the controller sets the TargetNamespaceAllowed condition to False and refuses to render.
Lifecycle and clean-up#
- Every rendered resource carries a finalizer (
templates.v2.stakater.com/template-instance-resource) so the operator can clean up before the API server garbage-collects. Templatedeletion is blocked while anyTemplateInstancereferences it, the controller publishes theDeletingcondition with reasonDeletionBlocked.TemplateInstancedeletion sweeps every resource recorded instatus.renderedResources, removes the finalizer, then removes its own finalizer.
Status reporting#
Every CR exposes:
status.phase,Valid/Invalid/ErrorforTemplate;Ready/FailedforTemplateInstance.status.observedGeneration, lastmetadata.generationreconciled.status.conditions[], Kubernetes-standard withType,Status,Reason,Message,LastTransitionTime,ObservedGeneration.
TemplateInstance additionally exposes:
status.resolvedParameters, the source map for each parameter after merging defaults and overrides.status.renderedResources, identity (apiVersion/kind/name/namespace) plus per-resourceobservedGenerationandstatus(empty for successfully applied,Failedwhen the operator is retrying) for every applied resource.status.resolvedTemplateRef, thename/namespace/generationof theTemplatethat was actually rendered.
Validation at template-creation time#
The Template controller dry-run renders new and updated templates as soon as they are created. For Helm templates this includes pulling the chart, verifying the source is reachable, and rendering with the valuesTemplate output. The result is reported via:
Valid, template spec parses and renders.SourceAccessible, for Helm: chart could be pulled.DryRunRendered, render produces valid YAML.
Dry-run is skipped when any parameter has no literal default value (since the runtime type cannot be guessed safely).