From 9510713d21ea0f16e6c4e7076ed1eb84a1e75b8d Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Tue, 24 Sep 2019 10:55:00 -0700 Subject: [PATCH 1/2] fix(chartutil): port over enhancements to `helm create` from Helm 2 Signed-off-by: Matthew Fisher --- cmd/helm/create.go | 1 + cmd/helm/create_test.go | 10 ++-- pkg/chartutil/create.go | 110 ++++++++++++++++++++++++++++++----- pkg/chartutil/create_test.go | 3 + 4 files changed, 104 insertions(+), 20 deletions(-) diff --git a/cmd/helm/create.go b/cmd/helm/create.go index 65e142097..dd8df8d1b 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -42,6 +42,7 @@ something like this: ├── values.yaml # The default values for your templates ├── charts/ # Charts that this chart depends on └── templates/ # The template files + └── tests/ # The test files 'helm create' takes a path for an argument. If directories in the given path do not exist, Helm will attempt to create them as it goes. If the given diff --git a/cmd/helm/create_test.go b/cmd/helm/create_test.go index d9b312262..0a9b7b9a5 100644 --- a/cmd/helm/create_test.go +++ b/cmd/helm/create_test.go @@ -106,8 +106,9 @@ func TestCreateStarterCmd(t *testing.T) { t.Errorf("Wrong API version: %q", c.Metadata.APIVersion) } - if l := len(c.Templates); l != 6 { - t.Errorf("Expected 5 templates, got %d", l) + expectedNumberOfTemplates := 8 + if l := len(c.Templates); l != expectedNumberOfTemplates { + t.Errorf("Expected %d templates, got %d", expectedNumberOfTemplates, l) } found := false @@ -173,8 +174,9 @@ func TestCreateStarterAbsoluteCmd(t *testing.T) { t.Errorf("Wrong API version: %q", c.Metadata.APIVersion) } - if l := len(c.Templates); l != 6 { - t.Errorf("Expected 5 templates, got %d", l) + expectedNumberOfTemplates := 8 + if l := len(c.Templates); l != expectedNumberOfTemplates { + t.Errorf("Expected %d templates, got %d", expectedNumberOfTemplates, l) } found := false diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index 023e3bb9a..329c0000e 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -39,6 +39,8 @@ const ( TemplatesDir = "templates" // ChartsDir is the relative directory name for charts dependencies. ChartsDir = "charts" + // TemplatesTestsDir is the relative directory name for tests. + TemplatesTestsDir = TemplatesDir + sep + "tests" // IgnorefileName is the name of the Helm ignore file. IgnorefileName = ".helmignore" // IngressFileName is the name of the example ingress file. @@ -47,10 +49,14 @@ const ( DeploymentName = TemplatesDir + sep + "deployment.yaml" // ServiceName is the name of the example service file. ServiceName = TemplatesDir + sep + "service.yaml" + // ServiceAccountName is the name of the example serviceaccount file. + ServiceAccountName = TemplatesDir + sep + "serviceaccount.yaml" // NotesName is the name of the example NOTES.txt file. NotesName = TemplatesDir + sep + "NOTES.txt" - // HelpersName is the name of the example NOTES.txt file. + // HelpersName is the name of the example helpers file. HelpersName = TemplatesDir + sep + "_helpers.tpl" + // TestConnectionName is the name of the example test file. + TestConnectionName = TemplatesTestsDir + sep + "test-connection.yaml" ) const sep = string(filepath.Separator) @@ -88,9 +94,28 @@ image: repository: nginx pullPolicy: IfNotPresent +imagePullSecrets: [] nameOverride: "" fullnameOverride: "" +serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + service: type: ClusterIP port: 80 @@ -103,11 +128,10 @@ ingress: hosts: - host: chart-example.local paths: [] - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local + # - secretName: chart-example-tls + # hosts: + # - chart-example.local resources: {} # We usually recommend not to specify default resources and to leave this as a conscious @@ -149,16 +173,13 @@ const defaultIgnore = `# Patterns to ignore when building packages. .project .idea/ *.tmproj +.vscode/ ` const defaultIngress = `{{- if .Values.ingress.enabled -}} {{- $fullName := include ".fullname" . -}} {{- $svcPort := .Values.service.port -}} -{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} kind: Ingress metadata: name: {{ $fullName }} @@ -210,8 +231,17 @@ spec: labels: {{- include ".selectorLabels" . | nindent 8 }} spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include ".serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: @@ -228,10 +258,10 @@ spec: port: http resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} + {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} @@ -259,6 +289,16 @@ spec: {{- include ".selectorLabels" . | nindent 4 }} ` +const defaultServiceAccount = `{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include ".serviceAccountName" . }} + labels: +{{ include ".labels" . | nindent 4 }} +{{- end -}} +` + const defaultNotes = `1. Get the application URL by running these commands: {{- if .Values.ingress.enabled }} {{- range $host := .Values.ingress.hosts }} @@ -267,16 +307,16 @@ const defaultNotes = `1. Get the application URL by running these commands: {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services {{ include ".fullname" . }}) - export NODE_IP=$(kubectl get nodes -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include ".fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc -w {{ include ".fullname" . }}' - export SERVICE_IP=$(kubectl get svc {{ include ".fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include ".fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include ".fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ .Values.service.port }} {{- else if contains "ClusterIP" .Values.service.type }} - export POD_NAME=$(kubectl get pods -l "app.kubernetes.io/name={{ include ".name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include ".name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80 {{- end }} @@ -334,6 +374,34 @@ Selector labels app.kubernetes.io/name: {{ include ".name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define ".serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include ".fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} +` + +const defaultTestConnection = `apiVersion: v1 +kind: Pod +metadata: + name: "{{ include ".fullname" . }}-test-connection" + labels: +{{ include ".labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include ".fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never ` // CreateFrom creates a new chart, but scaffolds it from the src chart. @@ -431,6 +499,11 @@ func Create(name, dir string) (string, error) { path: filepath.Join(cdir, ServiceName), content: transform(defaultService, name), }, + { + // serviceaccount.yaml + path: filepath.Join(cdir, ServiceAccountName), + content: transform(defaultServiceAccount, name), + }, { // NOTES.txt path: filepath.Join(cdir, NotesName), @@ -441,6 +514,11 @@ func Create(name, dir string) (string, error) { path: filepath.Join(cdir, HelpersName), content: transform(defaultHelpers, name), }, + { + // test-connection.yaml + path: filepath.Join(cdir, TestConnectionName), + content: transform(defaultTestConnection, name), + }, } for _, file := range files { diff --git a/pkg/chartutil/create_test.go b/pkg/chartutil/create_test.go index 87205cab0..82fde586c 100644 --- a/pkg/chartutil/create_test.go +++ b/pkg/chartutil/create_test.go @@ -55,8 +55,11 @@ func TestCreate(t *testing.T) { HelpersName, IgnorefileName, NotesName, + ServiceAccountName, ServiceName, TemplatesDir, + TemplatesTestsDir, + TestConnectionName, ValuesfileName, } { if _, err := os.Stat(filepath.Join(dir, f)); err != nil { From 223c8598672aad13c39170505fcf158c0c66e67d Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Thu, 3 Oct 2019 12:36:13 -0700 Subject: [PATCH 2/2] fix(create): convert tabs to spaces on help output Signed-off-by: Matthew Fisher --- cmd/helm/create.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/helm/create.go b/cmd/helm/create.go index dd8df8d1b..e9f71d0a7 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -36,13 +36,13 @@ directories used in a chart. For example, 'helm create foo' will create a directory structure that looks something like this: - foo/ - ├── .helmignore # Contains patterns to ignore when packaging Helm charts. - ├── Chart.yaml # Information about your chart - ├── values.yaml # The default values for your templates - ├── charts/ # Charts that this chart depends on - └── templates/ # The template files - └── tests/ # The test files + foo/ + ├── .helmignore # Contains patterns to ignore when packaging Helm charts. + ├── Chart.yaml # Information about your chart + ├── values.yaml # The default values for your templates + ├── charts/ # Charts that this chart depends on + └── templates/ # The template files + └── tests/ # The test files 'helm create' takes a path for an argument. If directories in the given path do not exist, Helm will attempt to create them as it goes. If the given