diff --git a/api/internal/target/kusttarget.go b/api/internal/target/kusttarget.go index 370fec1a9..2330e1429 100644 --- a/api/internal/target/kusttarget.go +++ b/api/internal/target/kusttarget.go @@ -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) diff --git a/api/krusty/helmchartinflationgenerator_test.go b/api/krusty/helmchartinflationgenerator_test.go index ec11d6f59..4a0d8bb96 100644 --- a/api/krusty/helmchartinflationgenerator_test.go +++ b/api/krusty/helmchartinflationgenerator_test.go @@ -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 `) @@ -217,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 `) @@ -300,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, ` @@ -335,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 --- @@ -347,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 @@ -373,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 --- @@ -385,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 @@ -407,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 --- @@ -419,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 @@ -634,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 `) @@ -669,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 --- @@ -681,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 @@ -703,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 --- @@ -715,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 @@ -746,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: @@ -772,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 @@ -789,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 @@ -804,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 @@ -827,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 @@ -842,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: @@ -868,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 @@ -885,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 @@ -900,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 @@ -923,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 @@ -934,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()