From f4dda2c72f96bebaf0d612ce2b548e014c2bdcf1 Mon Sep 17 00:00:00 2001 From: Ethan Mosbaugh Date: Tue, 14 Dec 2021 01:54:51 +0000 Subject: [PATCH] Write helm midstream with HelmChart namespace --- pkg/base/base.go | 58 +++++++++++++++++ pkg/base/base_test.go | 55 ++++++++++++++++ pkg/base/helm.go | 3 + pkg/base/helm_test.go | 64 +++++++++++++++++++ pkg/base/replicated.go | 1 + pkg/pull/pull.go | 14 ++-- pkg/rewrite/rewrite.go | 14 ++-- .../pull/cases/configcontext/testcase.yaml | 1 + .../midstream/charts/test-chart/secret.yaml | 2 + .../overlays/midstream/secret.yaml | 2 + pkg/tests/pull/cases/simple/testcase.yaml | 1 + pkg/tests/pull/cases/subcharts/testcase.yaml | 1 + .../chart/charts/subchart-1/secret.yaml | 2 + .../subchart-2/charts/subsubchart/secret.yaml | 2 + .../chart/charts/subchart-2/secret.yaml | 2 + .../midstream/charts/chart/secret.yaml | 2 + .../overlays/midstream/secret.yaml | 2 + pkg/tests/pull/pull_test.go | 5 +- 18 files changed, 221 insertions(+), 10 deletions(-) diff --git a/pkg/base/base.go b/pkg/base/base.go index 811297b972..8d56e8cc98 100644 --- a/pkg/base/base.go +++ b/pkg/base/base.go @@ -26,12 +26,70 @@ type Base struct { Bases []Base } +func (in *Base) DeepCopyInto(out *Base) { + *out = *in + if in.Files != nil { + out.Files = make([]BaseFile, len(in.Files)) + for i, file := range in.Files { + out.Files[i] = *file.DeepCopy() + } + } + if in.ErrorFiles != nil { + out.ErrorFiles = make([]BaseFile, len(in.ErrorFiles)) + for i, file := range in.ErrorFiles { + out.ErrorFiles[i] = *file.DeepCopy() + } + } + if in.AdditionalFiles != nil { + out.AdditionalFiles = make([]BaseFile, len(in.AdditionalFiles)) + for i, file := range in.AdditionalFiles { + out.AdditionalFiles[i] = *file.DeepCopy() + } + } + if in.Bases != nil { + out.Bases = make([]Base, len(in.Bases)) + for i, base := range in.Bases { + out.Bases[i] = *base.DeepCopy() + } + } + return +} + +func (in *Base) DeepCopy() *Base { + if in == nil { + return nil + } + out := new(Base) + in.DeepCopyInto(out) + return out +} + +func (b *Base) SetNamespace(namespace string) { + b.Namespace = namespace + for i := range b.Bases { + b.Bases[i].SetNamespace(namespace) + } +} + type BaseFile struct { Path string Content []byte Error error } +func (in *BaseFile) DeepCopyInto(out *BaseFile) { + *out = *in +} + +func (in *BaseFile) DeepCopy() *BaseFile { + if in == nil { + return nil + } + out := new(BaseFile) + in.DeepCopyInto(out) + return out +} + type OverlySimpleGVK struct { APIVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` diff --git a/pkg/base/base_test.go b/pkg/base/base_test.go index 3f36aef22c..de92d9a569 100644 --- a/pkg/base/base_test.go +++ b/pkg/base/base_test.go @@ -498,3 +498,58 @@ func TestBaseFile_IsKotsKind(t *testing.T) { }) } } + +func TestBaseFile_DeepCopy(t *testing.T) { + var baseFile = &BaseFile{Path: "path", Content: []byte("content")} + baseFile2 := baseFile.DeepCopy() + baseFile2.Path = "change" + baseFile2.Content = []byte("change") + + assert.Equal(t, "path", baseFile.Path) + assert.Equal(t, []byte("content"), baseFile.Content) +} + +func TestBase_DeepCopy(t *testing.T) { + var subBase = &Base{ + Path: "path", + Namespace: "namespace", + Files: []BaseFile{{Path: "path7", Content: []byte("content7")}, {Path: "path10", Content: []byte("content10")}}, + ErrorFiles: []BaseFile{{Path: "path8", Content: []byte("content8")}, {Path: "path11", Content: []byte("content11")}}, + AdditionalFiles: []BaseFile{{Path: "path9", Content: []byte("content9")}, {Path: "path12", Content: []byte("content12")}}, + Bases: []Base{}, + } + var base = &Base{ + Path: "path", + Namespace: "namespace", + Files: []BaseFile{{Path: "path1", Content: []byte("content1")}, {Path: "path4", Content: []byte("content4")}}, + ErrorFiles: []BaseFile{{Path: "path2", Content: []byte("content2")}, {Path: "path5", Content: []byte("content5")}}, + AdditionalFiles: []BaseFile{{Path: "path3", Content: []byte("content3")}, {Path: "path6", Content: []byte("content6")}}, + Bases: []Base{*subBase}, + } + + base2 := base.DeepCopy() + base2.Path = "change" + base2.Files = nil + base2.ErrorFiles[0].Path = "change" + base2.ErrorFiles[0].Content = []byte("change") + base2.AdditionalFiles[1] = BaseFile{Path: "change", Content: []byte("change")} + base2.Bases[0].Path = "change" + base2.Bases[0].Files = nil + base2.Bases[0].ErrorFiles[0].Path = "change" + base2.Bases[0].ErrorFiles[0].Content = []byte("change") + base2.Bases[0].AdditionalFiles[1] = BaseFile{Path: "change", Content: []byte("change")} + + assert.Equal(t, "path", base.Path) + assert.Equal(t, "namespace", base.Namespace) + assert.Equal(t, []BaseFile{{Path: "path1", Content: []byte("content1")}, {Path: "path4", Content: []byte("content4")}}, base.Files) + assert.Equal(t, []BaseFile{{Path: "path2", Content: []byte("content2")}, {Path: "path5", Content: []byte("content5")}}, base.ErrorFiles) + assert.Equal(t, []BaseFile{{Path: "path3", Content: []byte("content3")}, {Path: "path6", Content: []byte("content6")}}, base.AdditionalFiles) + assert.Equal(t, []Base{{ + Path: "path", + Namespace: "namespace", + Files: []BaseFile{{Path: "path7", Content: []byte("content7")}, {Path: "path10", Content: []byte("content10")}}, + ErrorFiles: []BaseFile{{Path: "path8", Content: []byte("content8")}, {Path: "path11", Content: []byte("content11")}}, + AdditionalFiles: []BaseFile{{Path: "path9", Content: []byte("content9")}, {Path: "path12", Content: []byte("content12")}}, + Bases: []Base{}, + }}, base.Bases) +} diff --git a/pkg/base/helm.go b/pkg/base/helm.go index d45cb7c683..5f1b4cdd7e 100644 --- a/pkg/base/helm.go +++ b/pkg/base/helm.go @@ -99,6 +99,9 @@ func writeHelmBase(chartName string, baseFiles []BaseFile, renderOptions *Render base := &Base{ Path: path.Join("charts", chartName), } + if renderOptions.UseHelmInstall { + base.Namespace = renderOptions.Namespace + } for _, baseFile := range rest { fileBaseFiles, err := writeHelmBaseFile(baseFile, renderOptions) if err != nil { diff --git a/pkg/base/helm_test.go b/pkg/base/helm_test.go index b8b6131ce6..a876b34524 100644 --- a/pkg/base/helm_test.go +++ b/pkg/base/helm_test.go @@ -325,6 +325,70 @@ func Test_RenderHelm(t *testing.T) { }, }, }, + { + name: "test subcharts with namespace", + args: args{ + upstream: &upstreamtypes.Upstream{ + Name: "namespace-test", + Files: []upstreamtypes.UpstreamFile{ + { + Path: "Chart.yaml", + Content: []byte("name: test-chart\nversion: 0.1.0"), + }, + { + Path: "templates/deploy-1.yaml", + Content: []byte("apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: deploy-1"), + }, + { + Path: "charts/test-subchart/Chart.yaml", + Content: []byte("name: test-subchart\nversion: 0.2.0"), + }, + { + Path: "charts/test-subchart/templates/deploy-2.yaml", + Content: []byte("apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: deploy-2"), + }, + }, + }, + renderOptions: &RenderOptions{ + HelmVersion: "v3", + Namespace: "test-namespace", + UseHelmInstall: true, + }, + }, + want: &Base{ + Namespace: "test-namespace", + Files: []BaseFile{ + { + Path: "templates/deploy-1.yaml", + Content: []byte("apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: deploy-1\n namespace: test-namespace"), + }, + }, + AdditionalFiles: []BaseFile{ + { + Path: "Chart.yaml", + Content: []byte("name: test-chart\nversion: 0.1.0"), + }, + }, + Bases: []Base{ + { + Namespace: "test-namespace", + Path: "charts/test-subchart", + Files: []BaseFile{ + { + Path: "templates/deploy-2.yaml", + Content: []byte("apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: deploy-2\n namespace: test-namespace"), + }, + }, + AdditionalFiles: []BaseFile{ + { + Path: "Chart.yaml", + Content: []byte("name: test-subchart\nversion: 0.2.0"), + }, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/base/replicated.go b/pkg/base/replicated.go index 701f9da7a2..515e1dc199 100644 --- a/pkg/base/replicated.go +++ b/pkg/base/replicated.go @@ -284,6 +284,7 @@ func renderReplicatedHelmBase(u *upstreamtypes.Upstream, renderOptions *RenderOp return &Base{ Path: helmBase.Path, + Namespace: helmBase.Namespace, Files: helmBaseFiles, AdditionalFiles: helmBase.AdditionalFiles, Bases: helmBaseBases, diff --git a/pkg/pull/pull.go b/pkg/pull/pull.go index 9278216f35..cc1e2ffc02 100644 --- a/pkg/pull/pull.go +++ b/pkg/pull/pull.go @@ -369,6 +369,9 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { } for _, helmBase := range helmBases { + helmBaseCopy := helmBase.DeepCopy() + // strip namespace. helm render takes care of injecting the namespace + helmBaseCopy.SetNamespace("") writeBaseOptions := base.WriteOptions{ BaseDir: u.GetBaseDir(writeUpstreamOptions), SkippedDir: u.GetSkippedDir(writeUpstreamOptions), @@ -376,8 +379,8 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { ExcludeKotsKinds: pullOptions.ExcludeKotsKinds, IsHelmBase: true, } - if err := helmBase.WriteBase(writeBaseOptions); err != nil { - return "", errors.Wrapf(err, "failed to write helm base %s", helmBase.Path) + if err := helmBaseCopy.WriteBase(writeBaseOptions); err != nil { + return "", errors.Wrapf(err, "failed to write helm base %s", helmBaseCopy.Path) } } @@ -460,9 +463,12 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) { writeMidstreamOptions.MidstreamDir = filepath.Join(helmBase.GetOverlaysDir(writeBaseOptions), "midstream", helmBase.Path) writeMidstreamOptions.BaseDir = filepath.Join(u.GetBaseDir(writeUpstreamOptions), helmBase.Path) - helmBaseCopy := helmBase + helmBaseCopy := helmBase.DeepCopy() - helmMidstream, err := writeMidstream(writeMidstreamOptions, pullOptions, u, &helmBaseCopy, fetchOptions.License, identityConfig, u.GetUpstreamDir(writeUpstreamOptions), log) + pullOptionsCopy := pullOptions + pullOptionsCopy.Namespace = helmBaseCopy.Namespace + + helmMidstream, err := writeMidstream(writeMidstreamOptions, pullOptionsCopy, u, helmBaseCopy, fetchOptions.License, identityConfig, u.GetUpstreamDir(writeUpstreamOptions), log) if err != nil { return "", errors.Wrapf(err, "failed to write helm midstream %s", helmBase.Path) } diff --git a/pkg/rewrite/rewrite.go b/pkg/rewrite/rewrite.go index 9a8a089127..8cac3628c6 100644 --- a/pkg/rewrite/rewrite.go +++ b/pkg/rewrite/rewrite.go @@ -178,6 +178,9 @@ func Rewrite(rewriteOptions RewriteOptions) error { } for _, helmBase := range helmBases { + helmBaseCopy := helmBase.DeepCopy() + // strip namespace. helm render takes care of injecting the namespace + helmBaseCopy.SetNamespace("") writeBaseOptions := base.WriteOptions{ BaseDir: u.GetBaseDir(writeUpstreamOptions), SkippedDir: u.GetSkippedDir(writeUpstreamOptions), @@ -185,8 +188,8 @@ func Rewrite(rewriteOptions RewriteOptions) error { ExcludeKotsKinds: rewriteOptions.ExcludeKotsKinds, IsHelmBase: true, } - if err := helmBase.WriteBase(writeBaseOptions); err != nil { - return errors.Wrapf(err, "failed to write helm base %s", helmBase.Path) + if err := helmBaseCopy.WriteBase(writeBaseOptions); err != nil { + return errors.Wrapf(err, "failed to write helm base %s", helmBaseCopy.Path) } } @@ -270,9 +273,12 @@ func Rewrite(rewriteOptions RewriteOptions) error { writeMidstreamOptions.MidstreamDir = filepath.Join(helmBase.GetOverlaysDir(writeBaseOptions), "midstream", helmBase.Path) writeMidstreamOptions.BaseDir = filepath.Join(u.GetBaseDir(writeUpstreamOptions), helmBase.Path) - helmBaseCopy := helmBase + helmBaseCopy := helmBase.DeepCopy() - helmMidstream, err := writeMidstream(writeMidstreamOptions, rewriteOptions, &helmBaseCopy, fetchOptions.License, u.GetUpstreamDir(writeUpstreamOptions), log) + rewriteOptionsCopy := rewriteOptions + rewriteOptionsCopy.K8sNamespace = helmBaseCopy.Namespace + + helmMidstream, err := writeMidstream(writeMidstreamOptions, rewriteOptionsCopy, helmBaseCopy, fetchOptions.License, u.GetUpstreamDir(writeUpstreamOptions), log) if err != nil { return errors.Wrapf(err, "failed to write helm midstream %s", helmBase.Path) } diff --git a/pkg/tests/pull/cases/configcontext/testcase.yaml b/pkg/tests/pull/cases/configcontext/testcase.yaml index 105709b4ff..be90ac4472 100644 --- a/pkg/tests/pull/cases/configcontext/testcase.yaml +++ b/pkg/tests/pull/cases/configcontext/testcase.yaml @@ -1,5 +1,6 @@ Name: test helm pull PullOptions: + Namespace: app-namespace ExcludeAdminConsole: true IsAirgap: true Silent: true diff --git a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/secret.yaml b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/secret.yaml index 23fd331fa8..6f8bfc16f3 100644 --- a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/secret.yaml +++ b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/charts/test-chart/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-test-chart-registry + namespace: helmns type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: helmns type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/secret.yaml b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/secret.yaml index ba0e63b7e9..c012ed06b0 100644 --- a/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/secret.yaml +++ b/pkg/tests/pull/cases/configcontext/wantResults/overlays/midstream/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-registry + namespace: app-namespace type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: app-namespace type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/simple/testcase.yaml b/pkg/tests/pull/cases/simple/testcase.yaml index 1a47ea5868..ec8ecf7209 100644 --- a/pkg/tests/pull/cases/simple/testcase.yaml +++ b/pkg/tests/pull/cases/simple/testcase.yaml @@ -1,5 +1,6 @@ Name: test simple pull PullOptions: + Namespace: app-namespace ExcludeAdminConsole: true IsAirgap: true Silent: true diff --git a/pkg/tests/pull/cases/subcharts/testcase.yaml b/pkg/tests/pull/cases/subcharts/testcase.yaml index 56bf81e8c5..965e47845b 100644 --- a/pkg/tests/pull/cases/subcharts/testcase.yaml +++ b/pkg/tests/pull/cases/subcharts/testcase.yaml @@ -1,5 +1,6 @@ Name: test subcharts pull PullOptions: + Namespace: app-namespace ExcludeAdminConsole: true IsAirgap: true Silent: true diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/secret.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/secret.yaml index aa45b95b15..f09e62d9e0 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/secret.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-1/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-registry + namespace: helmns type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: helmns type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/secret.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/secret.yaml index aa45b95b15..f09e62d9e0 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/secret.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/charts/subsubchart/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-registry + namespace: helmns type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: helmns type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/secret.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/secret.yaml index aa45b95b15..f09e62d9e0 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/secret.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/charts/subchart-2/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-registry + namespace: helmns type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: helmns type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/secret.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/secret.yaml index 4bafad671c..4176677d4a 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/secret.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/charts/chart/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-chart-registry + namespace: helmns type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: helmns type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/secret.yaml b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/secret.yaml index aa45b95b15..9279d61b6e 100644 --- a/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/secret.yaml +++ b/pkg/tests/pull/cases/subcharts/wantResults/overlays/midstream/secret.yaml @@ -8,6 +8,7 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: my-app-registry + namespace: app-namespace type: kubernetes.io/dockerconfigjson --- @@ -21,4 +22,5 @@ metadata: helm.sh/hook-weight: "-9999" creationTimestamp: null name: kotsadm-replicated-registry + namespace: app-namespace type: kubernetes.io/dockerconfigjson diff --git a/pkg/tests/pull/pull_test.go b/pkg/tests/pull/pull_test.go index e1c9237327..67ea0ff073 100644 --- a/pkg/tests/pull/pull_test.go +++ b/pkg/tests/pull/pull_test.go @@ -11,6 +11,7 @@ import ( "github.com/ghodss/yaml" "github.com/replicatedhq/kots/pkg/pull" upstreamtypes "github.com/replicatedhq/kots/pkg/upstream/types" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -151,11 +152,11 @@ func TestKotsPull(t *testing.T) { if err != nil { fmt.Printf("unable to open file %s\n", path) } - require.NoError(t, err) + require.NoError(t, err, path) contentsString := string(contents) wantContentsString := string(wantContents) - require.Equal(t, wantContentsString, contentsString) + assert.Equal(t, wantContentsString, contentsString, path) return nil })