Skip to content

Commit 2ab5e24

Browse files
author
Pierre-Gilles Mialon
committed
Add buildMetadata option to Kustomization spec
Allow users to configure kustomize buildMetadata per Kustomization resource. Supported values are 'originAnnotations' and 'transformerAnnotations' which add source origin and transformer tracking annotations to the built resources respectively. Signed-off-by: Pierre-Gilles Mialon <pmialon@users.noreply.github.com> Ref: #1579 Signed-off-by: Pierre-Gilles Mialon <pmialon@gmail.com> Signed-off-by: Pierre-Gilles Mialon <pierre-gilles.mialon@qube-rt.com>
1 parent b4e2b52 commit 2ab5e24

8 files changed

Lines changed: 219 additions & 3 deletions

File tree

api/v1/kustomization_types.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ type KustomizationSpec struct {
177177
// +optional
178178
Wait bool `json:"wait,omitempty"`
179179

180+
// BuildMetadata specifies which kustomize build metadata should be added
181+
// to the built resources. The allowed values are 'originAnnotations' to
182+
// annotate resources with their source origin, and 'transformerAnnotations'
183+
// to annotate resources with the transformers that produced them.
184+
// +optional
185+
BuildMetadata []BuildMetadataOption `json:"buildMetadata,omitempty"`
186+
180187
// Components specifies relative paths to kustomize Components.
181188
// +optional
182189
Components []string `json:"components,omitempty"`
@@ -194,6 +201,19 @@ type KustomizationSpec struct {
194201
HealthCheckExprs []kustomize.CustomHealthCheck `json:"healthCheckExprs,omitempty"`
195202
}
196203

204+
// BuildMetadataOption defines the supported buildMetadata options.
205+
// +kubebuilder:validation:Enum=originAnnotations;transformerAnnotations
206+
type BuildMetadataOption string
207+
208+
const (
209+
// BuildMetadataOriginAnnotations enables config.kubernetes.io/origin annotations
210+
// that track which file and path each resource was loaded from.
211+
BuildMetadataOriginAnnotations BuildMetadataOption = "originAnnotations"
212+
// BuildMetadataTransformerAnnotations enables internal.config.kubernetes.io annotations
213+
// that record which kustomize transformers modified each resource.
214+
BuildMetadataTransformerAnnotations BuildMetadataOption = "transformerAnnotations"
215+
)
216+
197217
// CommonMetadata defines the common labels and annotations.
198218
type CommonMetadata struct {
199219
// Annotations to be added to the object's metadata.

api/v1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ spec:
5353
KustomizationSpec defines the configuration to calculate the desired state
5454
from a Source using Kustomize.
5555
properties:
56+
buildMetadata:
57+
description: |-
58+
BuildMetadata specifies which kustomize build metadata should be added
59+
to the built resources. The allowed values are 'originAnnotations' to
60+
annotate resources with their source origin, and 'transformerAnnotations'
61+
to annotate resources with the transformers that produced them.
62+
items:
63+
description: BuildMetadataOption defines the supported buildMetadata
64+
options.
65+
enum:
66+
- originAnnotations
67+
- transformerAnnotations
68+
type: string
69+
type: array
5670
commonMetadata:
5771
description: |-
5872
CommonMetadata specifies the common labels and annotations that are

docs/api/v1/kustomize.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,23 @@ resources. When enabled, the HealthChecks are ignored. Defaults to false.</p>
385385
</tr>
386386
<tr>
387387
<td>
388+
<code>buildMetadata</code><br>
389+
<em>
390+
<a href="#kustomize.toolkit.fluxcd.io/v1.BuildMetadataOption">
391+
[]BuildMetadataOption
392+
</a>
393+
</em>
394+
</td>
395+
<td>
396+
<em>(Optional)</em>
397+
<p>BuildMetadata specifies which kustomize build metadata should be added
398+
to the built resources. The allowed values are &lsquo;originAnnotations&rsquo; to
399+
annotate resources with their source origin, and &lsquo;transformerAnnotations&rsquo;
400+
to annotate resources with the transformers that produced them.</p>
401+
</td>
402+
</tr>
403+
<tr>
404+
<td>
388405
<code>components</code><br>
389406
<em>
390407
[]string
@@ -444,6 +461,13 @@ KustomizationStatus
444461
</table>
445462
</div>
446463
</div>
464+
<h3 id="kustomize.toolkit.fluxcd.io/v1.BuildMetadataOption">BuildMetadataOption
465+
(<code>string</code> alias)</h3>
466+
<p>
467+
(<em>Appears on:</em>
468+
<a href="#kustomize.toolkit.fluxcd.io/v1.KustomizationSpec">KustomizationSpec</a>)
469+
</p>
470+
<p>BuildMetadataOption defines the supported buildMetadata options.</p>
447471
<h3 id="kustomize.toolkit.fluxcd.io/v1.CommonMetadata">CommonMetadata
448472
</h3>
449473
<p>
@@ -1018,6 +1042,23 @@ resources. When enabled, the HealthChecks are ignored. Defaults to false.</p>
10181042
</tr>
10191043
<tr>
10201044
<td>
1045+
<code>buildMetadata</code><br>
1046+
<em>
1047+
<a href="#kustomize.toolkit.fluxcd.io/v1.BuildMetadataOption">
1048+
[]BuildMetadataOption
1049+
</a>
1050+
</em>
1051+
</td>
1052+
<td>
1053+
<em>(Optional)</em>
1054+
<p>BuildMetadata specifies which kustomize build metadata should be added
1055+
to the built resources. The allowed values are &lsquo;originAnnotations&rsquo; to
1056+
annotate resources with their source origin, and &lsquo;transformerAnnotations&rsquo;
1057+
to annotate resources with the transformers that produced them.</p>
1058+
</td>
1059+
</tr>
1060+
<tr>
1061+
<td>
10211062
<code>components</code><br>
10221063
<em>
10231064
[]string

docs/spec/v1/kustomizations.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,41 @@ spec:
649649
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
650650
```
651651

652+
### Build metadata
653+
654+
`.spec.buildMetadata` is an optional list used to specify which
655+
[Kustomize `buildMetadata`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/buildmetadata/)
656+
options should be added to the built resources. The allowed values are:
657+
658+
- `originAnnotations`: Adds `config.kubernetes.io/origin` annotations that
659+
track which file and path each resource was loaded from.
660+
- `transformerAnnotations`: Adds `internal.config.kubernetes.io` annotations
661+
that record which kustomize transformers modified each resource.
662+
663+
```yaml
664+
apiVersion: kustomize.toolkit.fluxcd.io/v1
665+
kind: Kustomization
666+
metadata:
667+
name: podinfo
668+
namespace: flux-system
669+
spec:
670+
# ...omitted for brevity
671+
buildMetadata:
672+
- originAnnotations
673+
```
674+
675+
When `originAnnotations` is enabled, each resource gets an annotation like:
676+
677+
```yaml
678+
metadata:
679+
annotations:
680+
config.kubernetes.io/origin: |
681+
path: apps/deployment.yaml
682+
```
683+
684+
This is useful for debugging, auditing, and tooling that needs to trace
685+
resources back to their source files.
686+
652687
### Components
653688

654689
`.spec.components` is an optional list used to specify

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ require (
2727
github.com/fluxcd/pkg/auth v0.40.0
2828
github.com/fluxcd/pkg/cache v0.13.0
2929
github.com/fluxcd/pkg/http/fetch v0.22.0
30-
github.com/fluxcd/pkg/kustomize v1.28.0
30+
github.com/fluxcd/pkg/kustomize v1.29.0
3131
github.com/fluxcd/pkg/runtime v0.103.0
3232
github.com/fluxcd/pkg/ssa v0.70.0
3333
github.com/fluxcd/pkg/tar v0.17.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ github.com/fluxcd/pkg/envsubst v1.5.0 h1:S07mo+MkGhptdHA4pRze5HPKlc8tHxKswNdcMZi
219219
github.com/fluxcd/pkg/envsubst v1.5.0/go.mod h1:c3a8DYI855sZUubHFYQbjfjop6Wu4/zg1cLyf7SnCes=
220220
github.com/fluxcd/pkg/http/fetch v0.22.0 h1:FT8CfstPE/e7+KRxNrx8ZJ1Uj5rkR5wXOtvQJurNQ0U=
221221
github.com/fluxcd/pkg/http/fetch v0.22.0/go.mod h1:X+8wF3peP79TyyDSgCJiavz+fAcYaf7CRXSeu7ccsPA=
222-
github.com/fluxcd/pkg/kustomize v1.28.0 h1:0RuFVczJRabbt8frHZ/ql8aqte6BOOKk274O09l6/hE=
223-
github.com/fluxcd/pkg/kustomize v1.28.0/go.mod h1:cW08mnngSP8MJYb6mDmMvxH8YjNATdiML0udb37dk+M=
222+
github.com/fluxcd/pkg/kustomize v1.29.0 h1:B/5hr9wX6INwaQAZ6BGKVNvZm++A6qjgorUfoaBAwPw=
223+
github.com/fluxcd/pkg/kustomize v1.29.0/go.mod h1:cW08mnngSP8MJYb6mDmMvxH8YjNATdiML0udb37dk+M=
224224
github.com/fluxcd/pkg/runtime v0.103.0 h1:J5y5GPhWdkyqIUBlaI1FP2N02TtZmsjbWhhZubuTSFk=
225225
github.com/fluxcd/pkg/runtime v0.103.0/go.mod h1:mbo2f3azo3yVQgm7XZGxQB6/2zvzQ5Wgtd8TjRRwwAw=
226226
github.com/fluxcd/pkg/sourceignore v0.17.0 h1:Z72nruRMhC15zIEpWoDrAcJcJ1El6QDnP/aRDfE4WOA=

internal/controller/kustomization_transformer_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,3 +604,104 @@ func checkSecret(list *corev1.SecretList, name string) bool {
604604

605605
return false
606606
}
607+
608+
func TestKustomizationReconciler_BuildMetadata(t *testing.T) {
609+
g := NewWithT(t)
610+
id := "bm-" + randStringRunes(5)
611+
revision := "v1.0.0"
612+
resultK := &kustomizev1.Kustomization{}
613+
614+
err := createNamespace(id)
615+
g.Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
616+
617+
err = createKubeConfigSecret(id)
618+
g.Expect(err).NotTo(HaveOccurred(), "failed to create kubeconfig secret")
619+
620+
manifests := func(name string) []testserver.File {
621+
return []testserver.File{
622+
{
623+
Name: "config.yaml",
624+
Body: fmt.Sprintf(`---
625+
apiVersion: v1
626+
kind: ConfigMap
627+
metadata:
628+
name: %[1]s
629+
data:
630+
key: val
631+
`, name),
632+
},
633+
}
634+
}
635+
636+
artifact, err := testServer.ArtifactFromFiles(manifests(id))
637+
g.Expect(err).NotTo(HaveOccurred())
638+
639+
repositoryName := types.NamespacedName{
640+
Name: fmt.Sprintf("bm-%s", randStringRunes(5)),
641+
Namespace: id,
642+
}
643+
644+
err = applyGitRepository(repositoryName, artifact, revision)
645+
g.Expect(err).NotTo(HaveOccurred())
646+
647+
kustomizationKey := types.NamespacedName{
648+
Name: fmt.Sprintf("bm-%s", randStringRunes(5)),
649+
Namespace: id,
650+
}
651+
kustomization := &kustomizev1.Kustomization{
652+
ObjectMeta: metav1.ObjectMeta{
653+
Name: kustomizationKey.Name,
654+
Namespace: kustomizationKey.Namespace,
655+
},
656+
Spec: kustomizev1.KustomizationSpec{
657+
Interval: metav1.Duration{Duration: 2 * time.Minute},
658+
Path: "./",
659+
KubeConfig: &meta.KubeConfigReference{
660+
SecretRef: &meta.SecretKeyReference{
661+
Name: "kubeconfig",
662+
},
663+
},
664+
SourceRef: kustomizev1.CrossNamespaceSourceReference{
665+
Name: repositoryName.Name,
666+
Namespace: repositoryName.Namespace,
667+
Kind: sourcev1.GitRepositoryKind,
668+
},
669+
Prune: true,
670+
BuildMetadata: []kustomizev1.BuildMetadataOption{
671+
kustomizev1.BuildMetadataOriginAnnotations,
672+
},
673+
TargetNamespace: id,
674+
},
675+
}
676+
677+
g.Expect(k8sClient.Create(context.Background(), kustomization)).To(Succeed())
678+
679+
t.Run("sets origin annotations", func(t *testing.T) {
680+
g := NewWithT(t)
681+
g.Eventually(func() bool {
682+
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), resultK)
683+
return isReconcileSuccess(resultK)
684+
}, timeout, time.Second).Should(BeTrue())
685+
kstatusCheck.CheckErr(ctx, resultK)
686+
687+
var cm corev1.ConfigMap
688+
g.Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: id, Namespace: id}, &cm)).To(Succeed())
689+
g.Expect(cm.GetAnnotations()).To(HaveKey("config.kubernetes.io/origin"))
690+
})
691+
692+
t.Run("removes origin annotations", func(t *testing.T) {
693+
g := NewWithT(t)
694+
resultK.Spec.BuildMetadata = nil
695+
g.Expect(k8sClient.Update(context.Background(), resultK)).To(Succeed())
696+
697+
g.Eventually(func() bool {
698+
_ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), resultK)
699+
return isReconcileSuccess(resultK)
700+
}, timeout, time.Second).Should(BeTrue())
701+
kstatusCheck.CheckErr(ctx, resultK)
702+
703+
var cm corev1.ConfigMap
704+
g.Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: id, Namespace: id}, &cm)).To(Succeed())
705+
g.Expect(cm.GetAnnotations()).ToNot(HaveKey("config.kubernetes.io/origin"))
706+
})
707+
}

0 commit comments

Comments
 (0)