diff --git a/pkg/app/piped/cloudprovider/kubernetes/helm.go b/pkg/app/piped/cloudprovider/kubernetes/helm.go index f2a5f51501..b17c0fa563 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/helm.go +++ b/pkg/app/piped/cloudprovider/kubernetes/helm.go @@ -45,7 +45,7 @@ func NewHelm(version, path string, logger *zap.Logger) *Helm { } } -func (c *Helm) TemplateLocalChart(ctx context.Context, appName, appDir, chartPath string, opts *config.InputHelmOptions) (string, error) { +func (c *Helm) TemplateLocalChart(ctx context.Context, appName, appDir, namespace, chartPath string, opts *config.InputHelmOptions) (string, error) { releaseName := appName if opts != nil && opts.ReleaseName != "" { releaseName = opts.ReleaseName @@ -57,6 +57,11 @@ func (c *Helm) TemplateLocalChart(ctx context.Context, appName, appDir, chartPat releaseName, chartPath, } + + if namespace != "" { + args = append(args, fmt.Sprintf("--namespace=%s", namespace)) + } + if opts != nil { for _, v := range opts.ValueFiles { args = append(args, "-f", v) @@ -88,7 +93,7 @@ type helmRemoteGitChart struct { Path string } -func (c *Helm) TemplateRemoteGitChart(ctx context.Context, appName, appDir string, chart helmRemoteGitChart, gitClient gitClient, opts *config.InputHelmOptions) (string, error) { +func (c *Helm) TemplateRemoteGitChart(ctx context.Context, appName, appDir, namespace string, chart helmRemoteGitChart, gitClient gitClient, opts *config.InputHelmOptions) (string, error) { // Firstly, we need to download the remote repositoy. repoDir, err := ioutil.TempDir("", "helm-remote-chart") if err != nil { @@ -109,7 +114,7 @@ func (c *Helm) TemplateRemoteGitChart(ctx context.Context, appName, appDir strin chartPath := filepath.Join(repoDir, chart.Path) // After that handle it as a local chart. - return c.TemplateLocalChart(ctx, appName, appDir, chartPath, opts) + return c.TemplateLocalChart(ctx, appName, appDir, namespace, chartPath, opts) } type helmRemoteChart struct { @@ -118,7 +123,7 @@ type helmRemoteChart struct { Version string } -func (c *Helm) TemplateRemoteChart(ctx context.Context, appName, appDir string, chart helmRemoteChart, opts *config.InputHelmOptions) (string, error) { +func (c *Helm) TemplateRemoteChart(ctx context.Context, appName, appDir, namespace string, chart helmRemoteChart, opts *config.InputHelmOptions) (string, error) { releaseName := appName if opts != nil && opts.ReleaseName != "" { releaseName = opts.ReleaseName @@ -131,6 +136,11 @@ func (c *Helm) TemplateRemoteChart(ctx context.Context, appName, appDir string, fmt.Sprintf("%s/%s", chart.Repository, chart.Name), fmt.Sprintf("--version=%s", chart.Version), } + + if namespace != "" { + args = append(args, fmt.Sprintf("--namespace=%s", namespace)) + } + if opts != nil { for _, v := range opts.ValueFiles { args = append(args, "-f", v) diff --git a/pkg/app/piped/cloudprovider/kubernetes/helm_test.go b/pkg/app/piped/cloudprovider/kubernetes/helm_test.go index d448397ea3..2b997427e0 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/helm_test.go +++ b/pkg/app/piped/cloudprovider/kubernetes/helm_test.go @@ -39,10 +39,37 @@ func TestTemplateLocalChart(t *testing.T) { require.NoError(t, err) helm := NewHelm("", helmPath, zap.NewNop()) - out, err := helm.TemplateLocalChart(ctx, appName, appDir, chartPath, nil) + out, err := helm.TemplateLocalChart(ctx, appName, appDir, "", chartPath, nil) require.NoError(t, err) out = strings.TrimPrefix(out, "---") manifests := strings.Split(out, "---") assert.Equal(t, 3, len(manifests)) } + +func TestTemplateLocalChart_WithNamespace(t *testing.T) { + var ( + ctx = context.Background() + appName = "testapp" + appDir = "testdata" + chartPath = "testchart" + namespace = "testnamespace" + ) + + // TODO: Preinstall a helm version inside CI runner to avoid installing. + helmPath, _, err := toolregistry.DefaultRegistry().Helm(ctx, "") + require.NoError(t, err) + + helm := NewHelm("", helmPath, zap.NewNop()) + out, err := helm.TemplateLocalChart(ctx, appName, appDir, namespace, chartPath, nil) + require.NoError(t, err) + + out = strings.TrimPrefix(out, "---") + + manifests, _ := ParseManifests(out) + for _, manifest := range manifests { + metadata, err := manifest.GetNestedMap("metadata") + require.NoError(t, err) + require.Equal(t, namespace, metadata["namespace"]) + } +} diff --git a/pkg/app/piped/cloudprovider/kubernetes/kubernetes.go b/pkg/app/piped/cloudprovider/kubernetes/kubernetes.go index aea9bf7249..470f609f48 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/kubernetes.go +++ b/pkg/app/piped/cloudprovider/kubernetes/kubernetes.go @@ -167,7 +167,13 @@ func (p *provider) LoadManifests(ctx context.Context) (manifests []Manifest, err Ref: p.input.HelmChart.Ref, Path: p.input.HelmChart.Path, } - data, err = p.helm.TemplateRemoteGitChart(ctx, p.appName, p.appDir, chart, sharedGitClient, p.input.HelmOptions) + data, err = p.helm.TemplateRemoteGitChart(ctx, + p.appName, + p.appDir, + p.input.Namespace, + chart, + sharedGitClient, + p.input.HelmOptions) case p.input.HelmChart.Repository != "": chart := helmRemoteChart{ @@ -175,10 +181,20 @@ func (p *provider) LoadManifests(ctx context.Context) (manifests []Manifest, err Name: p.input.HelmChart.Name, Version: p.input.HelmChart.Version, } - data, err = p.helm.TemplateRemoteChart(ctx, p.appName, p.appDir, chart, p.input.HelmOptions) + data, err = p.helm.TemplateRemoteChart(ctx, + p.appName, + p.appDir, + p.input.Namespace, + chart, + p.input.HelmOptions) default: - data, err = p.helm.TemplateLocalChart(ctx, p.appName, p.appDir, p.input.HelmChart.Path, p.input.HelmOptions) + data, err = p.helm.TemplateLocalChart(ctx, + p.appName, + p.appDir, + p.input.Namespace, + p.input.HelmChart.Path, + p.input.HelmOptions) } if err != nil { diff --git a/pkg/app/piped/cloudprovider/kubernetes/manifest.go b/pkg/app/piped/cloudprovider/kubernetes/manifest.go index b63c123b8d..4b19466ec8 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/manifest.go +++ b/pkg/app/piped/cloudprovider/kubernetes/manifest.go @@ -91,6 +91,15 @@ func (m Manifest) GetNestedStringMap(fields ...string) (map[string]string, error return sm, nil } +func (m Manifest) GetNestedMap(fields ...string) (map[string]interface{}, error) { + sm, _, err := unstructured.NestedMap(m.u.Object, fields...) + if err != nil { + return nil, err + } + + return sm, nil +} + // AddStringMapValues adds or overrides the given key-values into the string map // that can be found at the specified fields. func (m Manifest) AddStringMapValues(values map[string]string, fields ...string) error { diff --git a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/deployment.yaml b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/deployment.yaml index 9b5c700739..b9c4cf95df 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/deployment.yaml +++ b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/deployment.yaml @@ -4,6 +4,7 @@ metadata: name: {{ include "testchart.fullname" . }} labels: {{- include "testchart.labels" . | nindent 4 }} + namespace: {{.Release.Namespace}} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} diff --git a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/ingress.yaml b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/ingress.yaml index 4f349af257..7c17e022f3 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/ingress.yaml +++ b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/ingress.yaml @@ -15,6 +15,7 @@ metadata: annotations: {{- toYaml . | nindent 4 }} {{- end }} + namespace: {{.Release.Namespace}} spec: {{- if .Values.ingress.tls }} tls: diff --git a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/service.yaml b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/service.yaml index 86baf14821..d8c6e26de7 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/service.yaml +++ b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/service.yaml @@ -4,6 +4,7 @@ metadata: name: {{ include "testchart.fullname" . }} labels: {{- include "testchart.labels" . | nindent 4 }} + namespace: {{.Release.Namespace}} spec: type: {{ .Values.service.type }} ports: diff --git a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/serviceaccount.yaml b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/serviceaccount.yaml index f728deb2a6..4537db7747 100644 --- a/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/serviceaccount.yaml +++ b/pkg/app/piped/cloudprovider/kubernetes/testdata/testchart/templates/serviceaccount.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ include "testchart.serviceAccountName" . }} + namespace: {{.Release.Namespace}} labels: {{- include "testchart.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }}