Search code examples
gokuberneteskubernetes-helmgo-templates

Flatten Dictionary with Helm


Is there a way to flatten a dictionary with helm? I want to provide environment variables to the application from the chart by flattening a YAML config located in values.yaml. The config can look like. (Not Actual)

config:
 server:
  port: 3333
 other:
  setting:
    name: test

And would like to provide environment variables as

- name: CONFIG_SERVER_PORT
  value: 3333
- name: CONFIG_OTHER_SETTING_NAME
  value: test

I have considered using Kubernetes config maps but this would mean deploying slightly different instances of the app with random release names so that the config is not overwritten. This library https://github.com/jeremywohl/flatten provides a way to flatten a map[string]interface{} with delimeters. Is there a way to provide a custom pipe for helm that uses the library or another way to flatten the config?


Solution

  • I'm not aware of anything like that built in. Sprig provides most of the useful functions for helm templates but the dict functions just cover the primitives.

    You could define a named template that does the business and recurses down the config dict/map. Then include the template where needed:

    {{- define "recurseFlattenMap" -}}
    {{- $map := first . -}}
    {{- $label := last . -}}
    {{- range $key, $val := $map -}}
      {{- $sublabel := list $label $key | join "_" | upper -}}
      {{- if kindOf $val | eq "map" -}}
        {{- list $val $sublabel | include "recurseFlattenMap" -}}
      {{- else -}}
    - name: {{ $sublabel | quote }}
      value: {{ $val | quote }}
    {{ end -}}
    {{- end -}}
    {{- end -}}
    

    Passing the config data in is a little complex here, via a list that is then separated back out into $map and $label. This is due to templates only accepting a single variable scope.

    env: {{ list .Values.config "CONFIG" | include "recurseFlattenMap" | nindent 2 }}   
    

    With the example values:

    config:
      server:
        port: 3333
      first: astr
      other:
        setting:
          name: test
    

    Results in

    $ helm template . 
    ---
    # Source: so61280873/templates/config.yaml
    env: 
      - name: "CONFIG_FIRST" 
        value: "astr"
      - name: "CONFIG_OTHER_SETTING_NAME" 
        value: "test"
      - name: "CONFIG_SERVER_PORT" 
        value: "3333"