I am trying to setup the ability to have a dynamic number of volume and volumeMounts in my helm chart. Here is how my deployment.yaml looks:
volumeMounts:
{{- if .Values.deployment.hostPath }} {{ $dict := split ":" .Values.deployment.hostPath }} {{ range $idx, $val := $dict }} {{ $mnt := split "," $val }}
- mountPath: {{ $mnt._1 }}
name: {{ $mnt._0 }}
{{ end }}
{{ end }}
volumes:
{{- if .Values.deployment.hostPath }} {{ $dict := split ":" .Values.deployment.hostPath }} {{ range $idx, $val := $dict }} {{ $mnt := split "," $val }}
- name: {{ $mnt._0 }}
hostPath:
path: {{ $mnt._2 }}
{{- if $mnt._3 }}
type: {{ $mnt._3 }}
{{ end }}
{{ end }}
{{ end }}
In the values.yaml I have something like this:
Deployment:
hostPath: test-host-path,/path/on/pod,/path/on/node,Directory
What I am doing is checking if there is anything definied for hostPath. If there is I create a dict, spltting items by ':'. In this first example, there is only one string of values, because the : delimeter isn't there. It then does a range to loop (in case there are mutiple sets of values separated by ':') and then it splits a set of values by commas.
So with this first example, it works just fine using helm install:
values.yaml --> hostPath: test-host-path,/path/on/pod,/path/on/node,Directory
volumeMounts:
- mountPath: /path/on/pod
name: test-host-path
volumes:
- name: test-host-path
hostPath:
path: /path/on/node
type: Directory
The type field is optional so I have a block to check if its defined, if not it doesnt render it in the yaml. So on my next example when I just have no value after the last comma it also works:
values.yaml --> hostPath: test-host-path,/path/on/pod,/path/on/node,
volumeMounts:
- mountPath: /path/on/pod
name: test-host-path
volumes:
- name: test-host-path
hostPath:
path: /path/on/node
But now if I try to add a second set of data, separated by a ':', it fails on helm install:
Deployment:
hostPath: test-host-path,/path/on/pod,/path/on/node,Directory:test-host-path-two,/path/on/pod/two,/path/on/node/two,Directory
Error: YAML parse error on chart/templates/deployment.yaml: error converting YAML to JSON: yaml: line 152: found a tab character that violates indentation
helm.go:94: [debug] error converting YAML to JSON: yaml: line 152: found a tab character that violates indentation
Of course it's mentioning a tab, but I can't quite figure out what the issue is. I have used this same code (dict,range,split) to populate multiple entries in a configmap so I think it can work. But clearly I am missing something here. Any help would be appreciated.
CodePudding user response:
It's not totally obvious where a tab character might be sneaking in. One thing that does jump out is there's some extra whitespace hanging out in the templating; for example, there's a space after the start of the {{ range }}
loop that potentially throws things off.
If you're having whitespace or indentation problems, one good thing to check is the helm template
output; Helm 3 will print "error converting YAML" as you've shown if it's really wrong, but adding a helm template --debug
option will print it anyways.
Other useful rules of thumb are to put only one templating construct on a line; to put a -
"swallow whitespace" marker inside opening but not closing curly braces; and generally put templating constructs at the first column. Those rules would get you something like
volumeMounts:
{{- if .Values.deployment.hostPath }}
{{- $dict := split ":" .Values.deployment.hostPath }}
{{- range $idx, $val := $dict }}
{{- $mnt := split "," $val }}
- mountPath: {{ $mnt._1 }}
name: {{ $mnt._0 }}
{{- end }}
{{- end }}
volumes:
{{- if .Values.deployment.hostPath }}
{{- $dict := split ":" .Values.deployment.hostPath }}
{{- range $idx, $val := $dict }}
{{- $mnt := split "," $val }}
- name: {{ $mnt._0 }}
hostPath:
path: {{ $mnt._2 }}
{{- if $mnt._3 }}
type: {{ $mnt._3 }}
{{- end }}
{{- end }}
{{- end }}
You should be able to tell by inspection with this layout that the indentation is correct. In the first example, there is a newline and spaces before - mountPath:
, for example, and a newline following the last {{- end }}
, but it should be clear there are not stray newlines or spaces between the templating code lines.