Search code examples
goyamlkubernetes-helm

How to return a map object from template in Helm function?


I have a function that I want to call in another function. I want it to return a map, but instead it returns the toString representation of the map. It is an actual map inside the function, but not outside it.

{{- define "app.getSubKey" -}}
  {{- $name := .source }}
  {{- range $key, $value := .keys }}
    {{- if kindIs "int" $value }}
      {{- $name = index $name (int $value) }}
    {{- else }}
      {{- $name = index $name $value }}
    {{- end }}
  {{- end }}
  {{- if kindIs "string" $name }}
    {{- trim $name }}
  {{- else }}
    {{ $name }}
  {{- end }}
{{- end }}

When I call this function on the below YAML with {{- include "app.getSubKey" (dict "source" .Values.vars "keys" (list 0)) }}, inside the function $name is a map (I used kindOf to check this) but outside it's of kind string. How can I get it returned as a map?

vars:
  - name: something
    value: blah

Solution

  • To be precise: your app.getSubKey is not a function, it is a named template and as such, it does not return anything. On the other hand, include is a function. It takes as arguments a template name and its context, and returns rendered template as a string. You cannot change the type of the include function return value.

    Said that, I see two options:

    • if your goal is to get a properly formatted YAML from the include "app.getSubKey" call (still as a string) use toYaml function inside the named template, i.e.:
    {{- define "app.getSubKey" -}}
      ...
      {{- else }}
        {{- $name | toYaml | nindent 0 }}
      {{- end }}
    {{- end }}
    

    nindent 0 is necessary to get a properly left align YAML

    • if you want to get an actual dictionary (for further processing), you need to convert the string returned from the include call back to an object (the toYaml in the named template is still required):
      {{- $d := dict "source" .Values.vars "keys" (list 0) | include "app.getSubKey" | fromYaml -}}
    

    The function fromYaml is undocumented, so using it might be a bit risky. The only trace of it I found in the official docs is in the examples on the library charts page.

    BTW, the app.getSubKey logic doesn't seem correct: it will fail for the keys list with more then one element.


    If app.getSubKey returns an array, you must use fromYamlArray to "decode" the data.