KRM Function Resource Transformation#
This article covers three interconnected mechanisms kpt uses when executing KRM functions: file path management (how resources are organized on disk after a function run), meta-resource skip lists (what gets excluded from mutation), and name back-reference fixing (how cross-resource name pointers stay consistent after renaming).
All three topics intersect in the ensure-name-substring function and in kpt's core render pipeline.
File Organization After Function Runs#
Resources carry their filesystem location in path annotations (internal.config.kubernetes.io/path and the legacy config.kubernetes.io/path). After a function pipeline executes, kpt performs three steps to reconcile the resource set with the filesystem:
-
Path adjustment —
adjustRelPath()translates each resource's path annotation from being relative to its source subpackage to being relative to the root package. It reads a temporaryinternal.config.kubernetes.io/package-pathannotation, callspathRelToRoot()to compute the new path, writes both the modern and legacy path annotations, then removes the package-path annotation. -
Output tracking —
trackOutputFiles()walks all post-hydration resources and records each file path in anoutputFilesset. A matchingtrackInputFiles()call recorded the pre-runinputFilesset earlier. -
Pruning —
pruneResources()deletes any file ininputFilesthat is not inoutputFiles, cleaning up resources removed by functions.
The practical effect is visible in the ensure-name-substring-advanced expected diff: after a prod- prefix is applied, resources.yaml (which contained multiple resources) is deleted, and each resource is re-written into its own namespaced file with the new name embedded in the filename (e.g., the-namespace/configmap_prod-the-map.yaml).
The MatchAllKRM glob pattern ensures the Kptfile is included when kpt reads resources from the filesystem via LocalPackageReadWriter.
Meta-Resource Skip List#
Since kpt v1.0.0-beta.15, meta-resources including Kptfile are included in the resource list passed to every function . Functions that do name transformation must explicitly guard against mutating them.
The ensure-name-substring function uses a hard-coded GVK skip list — prefixSuffixFieldSpecsToSkip — to prevent name mutations on meta-resources:
CustomResourceDefinition
apiregistration.k8s.io/APIService
Namespace
kpt.dev/Kptfile ← added in PR #796
The shouldSkip() function is called per-resource at the start of Transform() . The kpt.dev/Kptfile entry was added when kpt began including meta-resources by default .
At the kpt runtime level, per-function selectors and exclusions fields in the Kptfile provide a more general filtering mechanism via SelectInput(), which matches resources by name, namespace, kind, apiVersion, labels, and annotations. Resources excluded by a selector pass through untouched; MergeWithInput() uses an internal kpt-resource-id annotation (set by SetResourceIDs() and cleared by DeleteResourceIDs()) to merge the function's output back with the unmodified resources.
Name Back-Reference Fixing#
When a function renames a resource (e.g., prepending prod- to a Deployment), all resources that reference that name by value must also be updated. ensure-name-substring handles this in two places:
1. config.kubernetes.io/depends-on annotation — updateDependsOnAnnotation() updates the referenced resource's name within this annotation, but only if the target resource was part of the input set (tracked via resourceLookup, ).
2. General Kubernetes name references — FixNameBackReference() applies a Kustomize-derived transformer that walks a declarative map of known cross-resource name fields (nameReferenceConfig, loaded from NameReferenceFieldSpecs). For each renamed resource (the ReferralTarget), it finds all resources that reference it (the Referrers) and updates the referencing fields via nameref.Filter. It is called after Transform() completes, in EnsureNameSubstringProcessor.Process():
if err = ens.Transform(resMap); err != nil { ... }
err = nameref.FixNameBackReference(resMap)
The default configuration covers the most common Kubernetes cross-resource name pointers:
- HPA → Deployment/ReplicaSet/StatefulSet (
spec/scaleTargetRef/name) - Pod/workload volumes, env vars, envFrom → ConfigMap and Secret names
- StatefulSet → Service (
spec/serviceName) - RoleBinding/ClusterRoleBinding → Role/ClusterRole/ServiceAccount
- PersistentVolumeClaim → PersistentVolume, StorageClass
- Ingress → Service, Secret (TLS)
- ValidatingAdmissionPolicyBinding → ValidatingAdmissionPolicy
See namereference.go for the full field-spec list.
Key Source Files#
| File | Purpose |
|---|---|
pkg/lib/kptops/render_executor.go | adjustRelPath, trackOutputFiles, pruneResources |
pkg/fn/runtime/utils.go | SelectInput, MergeWithInput, SetResourceIDs |
pkg/lib/pkg/pkg.go | MatchAllKRM pattern |
functions/go/ensure-name-substring/ensure_name_substring.go | prefixSuffixFieldSpecsToSkip, shouldSkip, Transform |
functions/go/ensure-name-substring/main.go | Processor wiring; calls FixNameBackReference |
…/accumulator/namereferencetransformer.go | FixNameBackReference implementation |
…/builtinpluginconsts/namereference.go | NameReferenceFieldSpecs — cross-resource name back-ref map |