diff --git a/api/v1/kustomization_types.go b/api/v1/kustomization_types.go
index 1f530647..ea6c92ae 100644
--- a/api/v1/kustomization_types.go
+++ b/api/v1/kustomization_types.go
@@ -99,6 +99,20 @@ type KustomizationSpec struct {
// +optional
HealthChecks []meta.NamespacedObjectKindReference `json:"healthChecks,omitempty"`
+ // NamePrefix will prefix the names of all managed resources.
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=200
+ // +kubebuilder:validation:Optional
+ // +optional
+ NamePrefix string `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
+
+ // NameSuffix will suffix the names of all managed resources.
+ // +kubebuilder:validation:MinLength=1
+ // +kubebuilder:validation:MaxLength=200
+ // +kubebuilder:validation:Optional
+ // +optional
+ NameSuffix string `json:"nameSuffix,omitempty" yaml:"nameSuffix,omitempty"`
+
// Strategic merge and JSON patches, defined as inline YAML objects,
// capable of targeting objects based on kind, label and annotation selectors.
// +optional
diff --git a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml
index 74a584f4..b069696d 100644
--- a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml
+++ b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml
@@ -221,6 +221,16 @@ spec:
required:
- secretRef
type: object
+ namePrefix:
+ description: NamePrefix will prefix the names of all managed resources.
+ maxLength: 200
+ minLength: 1
+ type: string
+ nameSuffix:
+ description: NameSuffix will suffix the names of all managed resources.
+ maxLength: 200
+ minLength: 1
+ type: string
patches:
description: |-
Strategic merge and JSON patches, defined as inline YAML objects,
diff --git a/docs/api/v1/kustomize.md b/docs/api/v1/kustomize.md
index d279ce3c..7a2281ad 100644
--- a/docs/api/v1/kustomize.md
+++ b/docs/api/v1/kustomize.md
@@ -222,6 +222,30 @@ bool
+namePrefix
+
+string
+
+ |
+
+(Optional)
+ NamePrefix will prefix the names of all managed resources.
+ |
+
+
+
+nameSuffix
+
+string
+
+ |
+
+(Optional)
+ NameSuffix will suffix the names of all managed resources.
+ |
+
+
+
patches
@@ -706,6 +730,30 @@ bool
|
+namePrefix
+
+string
+
+ |
+
+(Optional)
+ NamePrefix will prefix the names of all managed resources.
+ |
+
+
+
+nameSuffix
+
+string
+
+ |
+
+(Optional)
+ NameSuffix will suffix the names of all managed resources.
+ |
+
+
+
patches
diff --git a/docs/spec/v1/kustomizations.md b/docs/spec/v1/kustomizations.md
index 51b2d0ff..620291e4 100644
--- a/docs/spec/v1/kustomizations.md
+++ b/docs/spec/v1/kustomizations.md
@@ -401,6 +401,22 @@ should be applied to all the Kustomization's resources. It has two optional fiel
on an object. Any existing annotation will be overridden if it matches with a key
in this map.
+### Name Prefix and Suffix
+
+`.spec.namePrefix` and `.spec.nameSuffix` are optional fields used to specify a prefix and suffix
+to be added to the names of all the resources in the Kustomization.
+
+```yaml
+apiVersion: kustomize.toolkit.fluxcd.io/v1
+kind: Kustomization
+metadata:
+ name: app
+spec:
+ # ...omitted for brevity
+ namePrefix: "prefix-"
+ nameSuffix: "-suffix"
+```
+
### Patches
`.spec.patches` is an optional list used to specify [Kustomize `patches`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/)
diff --git a/go.mod b/go.mod
index 4a8db046..77f331ef 100644
--- a/go.mod
+++ b/go.mod
@@ -23,7 +23,7 @@ require (
github.com/fluxcd/pkg/apis/kustomize v1.4.0
github.com/fluxcd/pkg/apis/meta v1.4.0
github.com/fluxcd/pkg/http/fetch v0.10.0
- github.com/fluxcd/pkg/kustomize v1.9.0
+ github.com/fluxcd/pkg/kustomize v1.10.0
github.com/fluxcd/pkg/runtime v0.46.0
github.com/fluxcd/pkg/ssa v0.38.0
github.com/fluxcd/pkg/tar v0.6.0
diff --git a/go.sum b/go.sum
index 151b0160..d5485e1c 100644
--- a/go.sum
+++ b/go.sum
@@ -145,8 +145,8 @@ github.com/fluxcd/pkg/envsubst v1.0.0 h1:LD86BRNSCGJrvyrH2aX5/pit7RfbFpkzRXogwca
github.com/fluxcd/pkg/envsubst v1.0.0/go.mod h1:VAcb4OxcRdsDix1TRtr/mtTqFGHmNQaOvXQO2REArFQ=
github.com/fluxcd/pkg/http/fetch v0.10.0 h1:Uh1ZrPa4B4EDgi+NFrY7qP6g9vg1O6JHKg3+iJLtt1w=
github.com/fluxcd/pkg/http/fetch v0.10.0/go.mod h1:zZOsAqn7iODap40PVq29mcCPEKjDodYvamEaoN6tV/Q=
-github.com/fluxcd/pkg/kustomize v1.9.0 h1:bqS3mXiK1q5TpUtIO5I5b+v/0r96NGJBiearKGUhicA=
-github.com/fluxcd/pkg/kustomize v1.9.0/go.mod h1:PBerk0KzZN/IXaGociVp4MSMvsUQB0jR1P2SqSdixz0=
+github.com/fluxcd/pkg/kustomize v1.10.0 h1:5upGCY1wgC26chNBqKiaQjtDUm2qJQTDVFLvKNPQb4I=
+github.com/fluxcd/pkg/kustomize v1.10.0/go.mod h1:PBerk0KzZN/IXaGociVp4MSMvsUQB0jR1P2SqSdixz0=
github.com/fluxcd/pkg/runtime v0.46.0 h1:+pxFwTk8j8lZIS9Vyc8EJbgvmFp9JqeT6pfLo/0iP98=
github.com/fluxcd/pkg/runtime v0.46.0/go.mod h1:d9BaIjqoHL71fYeZsssrt08UFONGN2WQRaJ/Ay2d1Cc=
github.com/fluxcd/pkg/sourceignore v0.6.0 h1:kD6QXL/upPEX66UpR669yK1Bxr/GtjzmZiqBeYpunUQ=
diff --git a/internal/controller/kustomization_controller.go b/internal/controller/kustomization_controller.go
index 7022475d..0e313ed2 100644
--- a/internal/controller/kustomization_controller.go
+++ b/internal/controller/kustomization_controller.go
@@ -27,6 +27,7 @@ import (
"time"
securejoin "github.com/cyphar/filepath-securejoin"
+ "github.com/fluxcd/pkg/ssa/normalize"
ssautil "github.com/fluxcd/pkg/ssa/utils"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -293,6 +294,7 @@ func (r *KustomizationReconciler) reconcile(
obj *kustomizev1.Kustomization,
src sourcev1.Source,
patcher *patch.SerialPatcher) error {
+ log := ctrl.LoggerFrom(ctx)
// Update status with the reconciliation progress.
revision := src.GetArtifact().Revision
@@ -317,7 +319,11 @@ func (r *KustomizationReconciler) reconcile(
return err
}
- defer os.RemoveAll(tmpDir)
+ defer func(path string) {
+ if err := os.RemoveAll(path); err != nil {
+ log.Error(err, "failed to remove tmp dir", "path", path)
+ }
+ }(tmpDir)
// Download artifact and extract files to the tmp dir.
if err = fetch.NewArchiveFetcherWithLogger(
@@ -653,12 +659,12 @@ func (r *KustomizationReconciler) apply(ctx context.Context,
objects []*unstructured.Unstructured) (bool, *ssa.ChangeSet, error) {
log := ctrl.LoggerFrom(ctx)
- if err := ssa.SetNativeKindsDefaults(objects); err != nil {
+ if err := normalize.UnstructuredList(objects); err != nil {
return false, nil, err
}
- if meta := obj.Spec.CommonMetadata; meta != nil {
- ssautil.SetCommonMetadata(objects, meta.Labels, meta.Annotations)
+ if cmeta := obj.Spec.CommonMetadata; cmeta != nil {
+ ssautil.SetCommonMetadata(objects, cmeta.Labels, cmeta.Annotations)
}
applyOpts := ssa.DefaultApplyOptions()
diff --git a/internal/controller/kustomization_transformer_test.go b/internal/controller/kustomization_transformer_test.go
index e158de43..1ff2d3b0 100644
--- a/internal/controller/kustomization_transformer_test.go
+++ b/internal/controller/kustomization_transformer_test.go
@@ -146,6 +146,91 @@ data:
})
}
+func TestKustomizationReconciler_NamePrefixSuffix(t *testing.T) {
+ g := NewWithT(t)
+ id := "np-" + randStringRunes(5)
+ revision := "v1.0.0"
+ resultK := &kustomizev1.Kustomization{}
+
+ err := createNamespace(id)
+ g.Expect(err).NotTo(HaveOccurred(), "failed to create test namespace")
+
+ err = createKubeConfigSecret(id)
+ g.Expect(err).NotTo(HaveOccurred(), "failed to create kubeconfig secret")
+
+ manifests := func(name string) []testserver.File {
+ return []testserver.File{
+ {
+ Name: "config.yaml",
+ Body: fmt.Sprintf(`---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: %[1]s
+ annotations:
+ tenant: test
+data:
+ key: val
+`, name),
+ },
+ }
+ }
+
+ artifact, err := testServer.ArtifactFromFiles(manifests(id))
+ g.Expect(err).NotTo(HaveOccurred())
+
+ repositoryName := types.NamespacedName{
+ Name: fmt.Sprintf("cm-%s", randStringRunes(5)),
+ Namespace: id,
+ }
+
+ err = applyGitRepository(repositoryName, artifact, revision)
+ g.Expect(err).NotTo(HaveOccurred())
+
+ kustomizationKey := types.NamespacedName{
+ Name: fmt.Sprintf("cm-%s", randStringRunes(5)),
+ Namespace: id,
+ }
+ kustomization := &kustomizev1.Kustomization{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: kustomizationKey.Name,
+ Namespace: kustomizationKey.Namespace,
+ },
+ Spec: kustomizev1.KustomizationSpec{
+ Interval: metav1.Duration{Duration: 2 * time.Minute},
+ Path: "./",
+ KubeConfig: &meta.KubeConfigReference{
+ SecretRef: meta.SecretKeyReference{
+ Name: "kubeconfig",
+ },
+ },
+ SourceRef: kustomizev1.CrossNamespaceSourceReference{
+ Name: repositoryName.Name,
+ Namespace: repositoryName.Namespace,
+ Kind: sourcev1.GitRepositoryKind,
+ },
+ NamePrefix: "prefix-",
+ NameSuffix: "-suffix",
+ TargetNamespace: id,
+ },
+ }
+
+ g.Expect(k8sClient.Create(context.Background(), kustomization)).To(Succeed())
+
+ t.Run("sets name prefix and suffix", func(t *testing.T) {
+ g := NewWithT(t)
+ g.Eventually(func() bool {
+ _ = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), resultK)
+ return isReconcileSuccess(resultK)
+ }, timeout, time.Second).Should(BeTrue())
+ kstatusCheck.CheckErr(ctx, resultK)
+
+ name := fmt.Sprintf("prefix-%s-suffix", id)
+ var cm corev1.ConfigMap
+ g.Expect(k8sClient.Get(context.Background(), client.ObjectKey{Name: name, Namespace: id}, &cm)).To(Succeed())
+ })
+}
+
func TestKustomizationReconciler_KustomizeTransformer(t *testing.T) {
g := NewWithT(t)
id := "transformers-" + randStringRunes(5)
|