Merge pull request #5940 from Skaronator/propagate-namespaces

fix: Propagate Namespace correctly to Helm
This commit is contained in:
Kubernetes Prow Robot
2025-08-21 04:07:05 -07:00
committed by GitHub
7 changed files with 460 additions and 46 deletions

View File

@@ -51,6 +51,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,

View File

@@ -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
@@ -496,6 +496,11 @@ func (kt *KustTarget) accumulateDirectory(
}
subKt.kustomization.BuildMetadata = kt.kustomization.BuildMetadata
subKt.origin = kt.origin
// Propagate namespace to child kustomization if child doesn't have one
// This ensures Helm charts in base kustomizations inherit namespace from overlays
if subKt.kustomization.Namespace == "" && kt.kustomization.Namespace != "" {
subKt.kustomization.Namespace = kt.kustomization.Namespace
}
var bytes []byte
if openApiPath, exists := subKt.Kustomization().OpenAPI["path"]; exists {
bytes, err = ldr.Load(openApiPath)

View File

@@ -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

View File

@@ -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))

View File

@@ -21,10 +21,31 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
name: test-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
namespace: default
type: Opaque
---
apiVersion: v1
@@ -32,10 +53,14 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
namespace: default
spec:
ports:
- name: minecraft
@@ -150,7 +175,7 @@ func TestHelmChartInflationGeneratorOld(t *testing.T) {
helmChartInflationGenerator:
- chartName: minecraft
chartRepoUrl: https://itzg.github.io/minecraft-server-charts
chartVersion: 3.1.3
chartVersion: 4.26.4
releaseName: test
`)
@@ -158,6 +183,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()
@@ -169,7 +242,7 @@ func TestHelmChartInflationGenerator(t *testing.T) {
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test
`)
@@ -252,7 +325,7 @@ func TestHelmChartProdVsDev(t *testing.T) {
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test
`)
th.WriteK(dirProd, `
@@ -287,10 +360,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
name: myProd-test-minecraft-rcon
namespace: prod
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft-curseforge
namespace: prod
type: Opaque
---
@@ -299,7 +392,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
@@ -325,10 +421,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft
name: myDev-test-minecraft-rcon
namespace: dev
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft-curseforge
namespace: dev
type: Opaque
---
@@ -337,7 +453,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myDev-test-minecraft
@@ -359,10 +478,30 @@ kind: Secret
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
name: myProd-test-minecraft-rcon
namespace: prod
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft-curseforge
namespace: prod
type: Opaque
---
@@ -371,7 +510,10 @@ kind: Service
metadata:
labels:
app: test-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: myProd-test-minecraft
@@ -586,11 +728,11 @@ helmCharts:
skipTests: true
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.3
version: 4.26.4
releaseName: test-1
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 3.1.4
version: 4.26.4
releaseName: test-2
`)
@@ -621,10 +763,30 @@ kind: Secret
metadata:
labels:
app: test-1-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft
name: test-1-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-1-minecraft
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft-curseforge
namespace: default
type: Opaque
---
@@ -633,7 +795,10 @@ kind: Service
metadata:
labels:
app: test-1-minecraft
chart: minecraft-3.1.3
app.kubernetes.io/instance: test-1-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-1
name: test-1-minecraft
@@ -655,10 +820,30 @@ kind: Secret
metadata:
labels:
app: test-2-minecraft
chart: minecraft-3.1.4
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft
name: test-2-minecraft-rcon
namespace: default
type: Opaque
---
apiVersion: v1
data:
cf-api-key: Q0hBTkdFTUUh
kind: Secret
metadata:
labels:
app: test-2-minecraft
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft-curseforge
namespace: default
type: Opaque
---
@@ -667,7 +852,10 @@ kind: Service
metadata:
labels:
app: test-2-minecraft
chart: minecraft-3.1.4
app.kubernetes.io/instance: test-2-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test-2
name: test-2-minecraft
@@ -698,7 +886,7 @@ namespace: default
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 4.11.0
version: 4.26.4
releaseName: test
kubeVersion: "1.16"
valuesInline:
@@ -724,8 +912,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-rcon
@@ -741,8 +929,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
@@ -756,8 +944,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
@@ -779,8 +967,8 @@ metadata:
app: test-minecraft-map
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-map
@@ -794,7 +982,7 @@ namespace: default
helmCharts:
- name: minecraft
repo: https://itzg.github.io/minecraft-server-charts
version: 4.11.0
version: 4.26.4
releaseName: test
kubeVersion: "1.27"
valuesInline:
@@ -820,8 +1008,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-rcon
@@ -837,8 +1025,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-curseforge
@@ -852,8 +1040,8 @@ metadata:
app: test-minecraft
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft
@@ -875,8 +1063,8 @@ metadata:
app: test-minecraft-map
app.kubernetes.io/instance: test-minecraft
app.kubernetes.io/name: minecraft
app.kubernetes.io/version: 4.11.0
chart: minecraft-4.11.0
app.kubernetes.io/version: 4.26.4
chart: minecraft-4.26.4
heritage: Helm
release: test
name: test-minecraft-map
@@ -886,6 +1074,159 @@ spec:
`)
}
func TestHelmChartNamespacePropagationViaResources(t *testing.T) {
th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t)
defer th.Reset()
if err := th.ErrIfNoHelm(); err != nil {
t.Skip("skipping: " + err.Error())
}
// Create base directory with helm chart
baseDir := th.MkDir("base")
chartDir := filepath.Join(baseDir, "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: test-service
namespace: {{ .Release.Namespace }}
annotations:
deployed-in-namespace: {{ .Release.Namespace }}
`)
// Base kustomization with helmCharts
th.WriteK(baseDir, `
helmGlobals:
chartHome: ./charts
helmCharts:
- name: service
releaseName: service
`)
// Overlay that references base via resources and sets namespace
overlayDir := th.MkDir("overlay")
th.WriteK(overlayDir, `
namespace: production
resources:
- ../base
`)
m := th.Run(overlayDir, th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
deployed-in-namespace: production
name: test-service
namespace: production
`)
}
func TestHelmChartDifferentNamespaces(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: test-service
namespace: {{ .Release.Namespace }}
annotations:
helm-namespace: {{ .Release.Namespace }}
`)
// Test with different namespaces in transformer vs helmCharts.namespace
th.WriteK(th.GetRoot(), `
helmGlobals:
chartHome: ./charts
namespace: transformer-ns
helmCharts:
- name: service
releaseName: service
namespace: helm-ns
`)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
// helmCharts.namespace should take precedence
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
helm-namespace: helm-ns
name: test-service
namespace: helm-ns
`)
}
func TestHelmChartSameNamespace(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: test-service
namespace: {{ .Release.Namespace }}
annotations:
deployed-namespace: {{ .Release.Namespace }}
`)
// Test with same namespace in both places
th.WriteK(th.GetRoot(), `
helmGlobals:
chartHome: ./charts
namespace: shared-namespace
helmCharts:
- name: service
releaseName: service
namespace: shared-namespace
`)
m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled())
th.AssertActualEqualsExpected(m, `apiVersion: v1
kind: Service
metadata:
annotations:
deployed-namespace: shared-namespace
name: test-service
namespace: shared-namespace
`)
}
func copyValuesFilesTestChartsIntoHarness(t *testing.T, th *kusttest_test.HarnessEnhanced) {
t.Helper()