Convert YAML string to dict in Helm template

3/25/2019

I am creating a chart for a project that has a binary that when executed generates a configuration file in YAML format that looks like this:

---
PARAM_1: value1
PARAM_2: value2

My chart needs to read this file and and load all of its values into environment variables in a container, so I created a variable config in my values.yaml file and when the chart is installed I am passing the file content using --set-file:

helm install <CHART> --set-file config=/path/to/yaml/config/file

Next I create a ConfigMap withe the value of .Values.config:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  {{ .Values.config }}

The problem I am having is that I need to do two things with values of config:

  • prefix all keys with a predefined value (so in the example above I would MY_APP_PARAM_1 as key)
  • make sure the values are all string, otherwise the ConfigMap will fail

How can I parse the value of .Values.config in my template as a dict so that I can use a range loop do these changes?

-- Luiz Aoqui
go
kubernetes-helm

2 Answers

5/20/2020

If You need to work with more tricky YAML (map in a map) You can use this:

List Handler (list to comma separated string)

{{- define "helm-toolkit.utils.joinListWithComma" -}}
{{- $local := dict "first" true -}}
{{- range $k, $v := . -}}{{- if not $local.first -}}, {{ end -}}{{ $v -}}{{- $_ := set $local "first" false -}}{{- end -}}
{{- end -}}

Convert Yaml dict to the properties-like look

{{- define "utils.yaml2properties" }}
{{- $yaml := . -}}
{{- range $key, $value := $yaml }}
  {{- if kindIs "map" $value -}}
{{ $top:=$key }}
  {{- range $key, $value := $value }}
    {{- if kindIs "map" $value }}
    {{- $newTop := printf "%s.%s" $top $key }}
{{- include "utils.yaml2properties" (dict $newTop $value) }}
    {{- else if kindIs "slice" $value }}
{{ $top }}.{{ $key }}={{ include "helm-toolkit.utils.joinListWithComma" $value }}
    {{- else }}
{{ $top }}.{{ $key }}={{ $value }}
    {{- end }}
  {{- end }}
  {{- else if kindIs "slice" $value }}
{{ $key }}={{ include "helm-toolkit.utils.joinListWithComma" $value }}
  {{- else }}
{{ $key }}={{ $value }}
  {{- end }}
{{- end }}
{{- end }}

Use (example from K8s configMap)

{{- define "config.yaml" }}
vault.pki:
  enabled: {{.Values.vault.pki.enabled}}
  role: idverify
  common-name: idverify
  role:
    map:
      list:
        - one
        - two
{{- end }}

data:
  bootstrap.properties: |
{{ (include "utils.yaml2properties" (include "config.yaml" . | fromYaml )) | indent 4 }}
-- Vlad
Source: StackOverflow

3/26/2019

In the end I was able to do something like this:

{{ $lines := splitList "\n" .Values.config -}}
{{- range $lines }}
{{- if not (. | trim | empty) -}}
{{- $kv := . | splitn ":" 2 -}}
{{ printf "MY_APP_%s: %s" $kv._0 ($kv._1 | trim | quote) | indent 2 }}
{{ end -}}
{{- end -}}

I had a hard time getting the {{- vs {{ right, and helm install --debug --dry-run . help a lot in this part.

It's kind of messy, so I would be very interested in seeing if anyone has a better solution.

-- Luiz Aoqui
Source: StackOverflow