From 9376a5c4b78ada3bb3137a033c30e30b7589fe16 Mon Sep 17 00:00:00 2001 From: Niklas Wagner Date: Tue, 8 Jul 2025 11:07:06 +0200 Subject: [PATCH] Propagate Namespace correctly to Helm --- api/internal/builtins/NamespaceTransformer.go | 6 +++ api/internal/target/kusttarget.go | 10 ++-- .../target/kusttarget_configplugin.go | 5 ++ api/internal/target/kusttarget_test.go | 8 ++++ .../helmchartinflationgenerator_test.go | 48 +++++++++++++++++++ .../NamespaceTransformer.go | 6 +++ .../NamespaceTransformer_test.go | 43 +++++++++++++++++ 7 files changed, 121 insertions(+), 5 deletions(-) diff --git a/api/internal/builtins/NamespaceTransformer.go b/api/internal/builtins/NamespaceTransformer.go index d839fb975..a96465b9f 100644 --- a/api/internal/builtins/NamespaceTransformer.go +++ b/api/internal/builtins/NamespaceTransformer.go @@ -53,6 +53,12 @@ func (p *NamespaceTransformerPlugin) Transform(m resmap.ResMap) error { // Don't mutate empty objects? continue } + if origin, err := r.GetOrigin(); err == nil && origin != nil { + if origin.ConfiguredBy.Kind == "HelmChartInflationGenerator" { + // Don't apply namespace on Helm generated manifest. Helm should take care of it. + continue + } + } r.StorePreviousId() if err := r.ApplyFilter(namespace.Filter{ Namespace: p.Namespace, diff --git a/api/internal/target/kusttarget.go b/api/internal/target/kusttarget.go index 5f1d1095a..370fec1a9 100644 --- a/api/internal/target/kusttarget.go +++ b/api/internal/target/kusttarget.go @@ -127,11 +127,11 @@ func (kt *KustTarget) MakeCustomizedResMap() (resmap.ResMap, error) { } func (kt *KustTarget) makeCustomizedResMap() (resmap.ResMap, error) { - var origin *resource.Origin - if len(kt.kustomization.BuildMetadata) != 0 { - origin = &resource.Origin{} - } - kt.origin = origin + // Track origin for all resources so builtins can make decisions + // based on where resources originated from. + // Origin annotations will be stripped from the output if not + // requested via build metadata options. + kt.origin = &resource.Origin{} ra, err := kt.AccumulateTarget() if err != nil { return nil, err diff --git a/api/internal/target/kusttarget_configplugin.go b/api/internal/target/kusttarget_configplugin.go index 1ba028a36..0be848819 100644 --- a/api/internal/target/kusttarget_configplugin.go +++ b/api/internal/target/kusttarget_configplugin.go @@ -166,6 +166,11 @@ var generatorConfigurators = map[builtinhelpers.BuiltinPluginType]func( for _, chart := range kt.kustomization.HelmCharts { c.HelmGlobals = globals c.HelmChart = chart + // Pass kustomize namespace to helm + // Fixes https://github.com/kubernetes-sigs/kustomize/issues/5566 + if c.HelmChart.Namespace == "" && kt.kustomization.Namespace != "" { + c.HelmChart.Namespace = kt.kustomization.Namespace + } p := f() if err = kt.configureBuiltinPlugin(p, c, bpt); err != nil { return nil, err diff --git a/api/internal/target/kusttarget_test.go b/api/internal/target/kusttarget_test.go index 7993df5ac..beb95f807 100644 --- a/api/internal/target/kusttarget_test.go +++ b/api/internal/target/kusttarget_test.go @@ -300,6 +300,8 @@ metadata: require.NoError(t, expected.Append(r), "failed to append resource: %v") } expected.RemoveBuildAnnotations() + require.NoError(t, expected.RemoveTransformerAnnotations()) + require.NoError(t, expected.RemoveOriginAnnotations()) expYaml, err := expected.AsYaml() require.NoError(t, err) @@ -308,6 +310,8 @@ metadata: actual, err := kt.MakeCustomizedResMap() require.NoError(t, err) actual.RemoveBuildAnnotations() + require.NoError(t, actual.RemoveTransformerAnnotations()) + require.NoError(t, actual.RemoveOriginAnnotations()) actYaml, err := actual.AsYaml() require.NoError(t, err) assert.Equal(t, string(expYaml), string(actYaml)) @@ -411,6 +415,8 @@ metadata: require.NoError(t, err) } expected.RemoveBuildAnnotations() + require.NoError(t, expected.RemoveTransformerAnnotations()) + require.NoError(t, expected.RemoveOriginAnnotations()) expYaml, err := expected.AsYaml() require.NoError(t, err) @@ -419,6 +425,8 @@ metadata: actual, err := kt.MakeCustomizedResMap() require.NoError(t, err) actual.RemoveBuildAnnotations() + require.NoError(t, actual.RemoveTransformerAnnotations()) + require.NoError(t, actual.RemoveOriginAnnotations()) actYaml, err := actual.AsYaml() require.NoError(t, err) require.Equal(t, string(expYaml), string(actYaml)) diff --git a/api/krusty/helmchartinflationgenerator_test.go b/api/krusty/helmchartinflationgenerator_test.go index 7fc3f76e7..ec11d6f59 100644 --- a/api/krusty/helmchartinflationgenerator_test.go +++ b/api/krusty/helmchartinflationgenerator_test.go @@ -158,6 +158,54 @@ helmChartInflationGenerator: th.AssertActualEqualsExpected(m, expectedHelm) } +func TestHelmChartNamespacePropagation(t *testing.T) { + th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t) + defer th.Reset() + if err := th.ErrIfNoHelm(); err != nil { + t.Skip("skipping: " + err.Error()) + } + + chartDir := filepath.Join(th.GetRoot(), "charts", "service") + require.NoError(t, th.GetFSys().MkdirAll(filepath.Join(chartDir, "templates"))) + th.WriteF(filepath.Join(chartDir, "Chart.yaml"), ` +apiVersion: v2 +name: service +type: application +version: 1.0.0 +`) + th.WriteF(filepath.Join(chartDir, "values.yaml"), ``) + th.WriteF(filepath.Join(chartDir, "templates", "service.yaml"), ` +apiVersion: v1 +kind: Service +metadata: + name: the-bug + namespace: {{ .Release.Namespace }} + annotations: + this-service-is-deployed-in-namespace: {{ .Release.Namespace }} +`) + th.WriteF(filepath.Join(th.GetRoot(), "values.yaml"), ``) + + th.WriteK(th.GetRoot(), ` +helmGlobals: + chartHome: ./charts +namespace: the-actual-namespace +helmCharts: + - name: service + releaseName: service + valuesFile: values.yaml +`) + + m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled()) + th.AssertActualEqualsExpected(m, `apiVersion: v1 +kind: Service +metadata: + annotations: + this-service-is-deployed-in-namespace: the-actual-namespace + name: the-bug + namespace: the-actual-namespace +`) +} + func TestHelmChartInflationGenerator(t *testing.T) { th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t) defer th.Reset() diff --git a/plugin/builtin/namespacetransformer/NamespaceTransformer.go b/plugin/builtin/namespacetransformer/NamespaceTransformer.go index 9b395ef9f..43256d106 100644 --- a/plugin/builtin/namespacetransformer/NamespaceTransformer.go +++ b/plugin/builtin/namespacetransformer/NamespaceTransformer.go @@ -56,6 +56,12 @@ func (p *plugin) Transform(m resmap.ResMap) error { // Don't mutate empty objects? continue } + if origin, err := r.GetOrigin(); err == nil && origin != nil { + if origin.ConfiguredBy.Kind == "HelmChartInflationGenerator" { + // Don't apply namespace on Helm generated manifest. Helm should take care of it. + continue + } + } r.StorePreviousId() if err := r.ApplyFilter(namespace.Filter{ Namespace: p.Namespace, diff --git a/plugin/builtin/namespacetransformer/NamespaceTransformer_test.go b/plugin/builtin/namespacetransformer/NamespaceTransformer_test.go index 6fc510c13..660e46d03 100644 --- a/plugin/builtin/namespacetransformer/NamespaceTransformer_test.go +++ b/plugin/builtin/namespacetransformer/NamespaceTransformer_test.go @@ -8,7 +8,12 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "sigs.k8s.io/kustomize/api/provider" + "sigs.k8s.io/kustomize/api/resmap" + "sigs.k8s.io/kustomize/api/resource" kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest" + kyaml "sigs.k8s.io/kustomize/kyaml/yaml" ) const defaultFieldSpecs = ` @@ -762,3 +767,41 @@ subjects: `) }) } + +func TestNamespaceTransformer_SkipHelmOrigin(t *testing.T) { + th := kusttest_test.MakeEnhancedHarness(t). + PrepBuiltin("NamespaceTransformer") + defer th.Reset() + + rmF := resmap.NewFactory(provider.NewDefaultDepProvider().GetResourceFactory()) + rm, err := rmF.NewResMapFromBytes([]byte(`apiVersion: v1 +kind: Service +metadata: + name: svc + namespace: helm-ns +`)) + require.NoError(t, err) + r := rm.Resources()[0] + origin := &resource.Origin{ + ConfiguredBy: kyaml.ResourceIdentifier{ + TypeMeta: kyaml.TypeMeta{APIVersion: "builtin", Kind: "HelmChartInflationGenerator"}, + }, + } + require.NoError(t, r.SetOrigin(origin)) + + rm, err = th.RunTransformerFromResMap(` +apiVersion: builtin +kind: NamespaceTransformer +metadata: + name: notImportantHere + namespace: test +`+defaultFieldSpecs, rm) + require.NoError(t, err) + require.NoError(t, rm.RemoveOriginAnnotations()) + th.AssertActualEqualsExpectedNoIdAnnotations(rm, `apiVersion: v1 +kind: Service +metadata: + name: svc + namespace: helm-ns +`) +}