diff --git a/pkg/action/install.go b/pkg/action/install.go index b379d6873..47ba8ed59 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -70,6 +70,16 @@ const notesFileSuffix = "NOTES.txt" const defaultDirectoryPermission = 0755 +const createNamespaceTemplateName = "templates/helm-create-namespace.yaml" + +const createNamespaceTemplate = `apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Release.Namespace }} + labels: + name: {{ .Release.Namespace }} +` + // Install performs an installation operation. type Install struct { cfg *Configuration @@ -241,6 +251,21 @@ func (i *Install) installCRDs(crds []chart.CRD) error { return nil } +func addCreateNamespaceTemplate(chrt *chart.Chart) { + if chrt == nil { + return + } + for _, tmpl := range chrt.Templates { + if tmpl != nil && tmpl.Name == createNamespaceTemplateName { + return + } + } + chrt.Templates = append(chrt.Templates, &common.File{ + Name: createNamespaceTemplateName, + Data: []byte(createNamespaceTemplate), + }) +} + // Run executes the installation // // If DryRun is set to true, this will prepare the release, but not install it @@ -341,6 +366,10 @@ func (i *Install) RunWithContext(ctx context.Context, ch ci.Charter, vals map[st return nil, err } + if i.CreateNamespace && isDryRun(i.DryRunStrategy) && i.Namespace != "" { + addCreateNamespaceTemplate(chrt) + } + if driver.ContainsSystemLabels(i.Labels) { return nil, fmt.Errorf("user supplied labels contains system reserved label name. System labels: %+v", driver.GetSystemLabels()) } diff --git a/pkg/cmd/template_test.go b/pkg/cmd/template_test.go index 5bcccf5d0..32ff1af7d 100644 --- a/pkg/cmd/template_test.go +++ b/pkg/cmd/template_test.go @@ -96,6 +96,11 @@ func TestTemplateCmd(t *testing.T) { cmd: fmt.Sprintf("template '%s' --include-crds", chartPath), golden: "output/template-with-crds.txt", }, + { + name: "template with create-namespace", + cmd: fmt.Sprintf("template '%s' --create-namespace --namespace create-ns", chartPath), + golden: "output/template-create-namespace.txt", + }, { name: "template with show-only one", cmd: fmt.Sprintf("template '%s' --show-only templates/service.yaml", chartPath), diff --git a/pkg/cmd/testdata/output/template-create-namespace.txt b/pkg/cmd/testdata/output/template-create-namespace.txt new file mode 100644 index 000000000..574f27f5e --- /dev/null +++ b/pkg/cmd/testdata/output/template-create-namespace.txt @@ -0,0 +1,122 @@ +--- +# Source: subchart/templates/helm-create-namespace.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: create-ns + labels: + name: create-ns +--- +# Source: subchart/templates/subdir/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: subchart-sa +--- +# Source: subchart/templates/subdir/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: subchart-role +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["get","list","watch"] +--- +# Source: subchart/templates/subdir/rolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: subchart-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: subchart-role +subjects: +- kind: ServiceAccount + name: subchart-sa + namespace: default +--- +# Source: subchart/charts/subcharta/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: subcharta + labels: + helm.sh/chart: "subcharta-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: apache + selector: + app.kubernetes.io/name: subcharta +--- +# Source: subchart/charts/subchartb/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: subchartb + labels: + helm.sh/chart: "subchartb-0.1.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nginx + selector: + app.kubernetes.io/name: subchartb +--- +# Source: subchart/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: subchart + labels: + helm.sh/chart: "subchart-0.1.0" + app.kubernetes.io/instance: "release-name" + kube-version/major: "1" + kube-version/minor: "20" + kube-version/version: "v1.20.0" +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: nginx + selector: + app.kubernetes.io/name: subchart +--- +# Source: subchart/templates/tests/test-config.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: "release-name-testconfig" + annotations: + "helm.sh/hook": test +data: + message: Hello World +--- +# Source: subchart/templates/tests/test-nothing.yaml +apiVersion: v1 +kind: Pod +metadata: + name: "release-name-test" + annotations: + "helm.sh/hook": test +spec: + containers: + - name: test + image: "alpine:latest" + envFrom: + - configMapRef: + name: "release-name-testconfig" + command: + - echo + - "$message" + restartPolicy: Never