How to unpack a list of dictionaries in a Go template

108 views Asked by At

This is a toy example

{{/*Merge a list of objects*/}}
{{- define "mymerge" }}
    {{- toYaml (merge .) }}
{{- end }}

{{- define "mymergewrapper" }}
    {{- $dict1 := (dict "data" (dict "dict1key" "dict1val"))}}
    {{- $dict2 := (dict "data" (dict "dict2key" "dict2val"))}}
    {{- $dict3 := (dict "data" (dict "dict3key" "dict3val"))}}
    {{- $dict4 := (dict "data" (dict "dict3key" "dict4val"))}}
    {{- $arbitrary_list_of_dicts_of_unknown_length_and_content := (list $dict1 $dict2 $dict3 $dict4) }}
    {{- include "mymerge" $arbitrary_list_of_dicts_of_unknown_length_and_content }}
{{- end }}

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name | printf "%s-%s" .Chart.Name }}
data:
  myvalue: "Hello World"
  whatHappens:
  {{- include "mymergewrapper" . }}
 helm install myappchart2 myappchart2/ --debug --dry-run
Error: INSTALLATION FAILED: template: myappchart2/templates/deployment.yaml:22:6: executing "myappchart2/templates/deployment.yaml" at <include "mymergewrapper" .>: error calling include: template: myappchart2/templates/deployment.yaml:12:8: executing "mymergewrapper" at <include "mymerge" $arbitrary_list_of_dicts_of_unknown_length_and_content>: error calling include: template: myappchart2/templates/deployment.yaml:3:22: executing "mymerge" at <.>: wrong type for value; expected map[string]interface {}; got []interface {}
helm.go:84: [debug] template: myappchart2/templates/deployment.yaml:22:6: executing "myappchart2/templates/deployment.yaml" at <include "mymergewrapper" .>: error calling include: template: myappchart2/templates/deployment.yaml:12:8: executing "mymergewrapper" at <include "mymerge" $arbitrary_list_of_dicts_of_unknown_length_and_content>: error calling include: template: myappchart2/templates/deployment.yaml:3:22: executing "mymerge" at <.>: wrong type for value; expected map[string]interface {}; got []interface {}

I read "Merge two or more dictionaries into one..." a little too fast.

Is there a way to unpack my $objects list and pass the individual dicts to merge ?

1

There are 1 answers

1
Claude Gaye On BEST ANSWER

The merge function has a variadic argument. Templates do not support passing a slice as a variadic argument.

Use a loop to merge one by one:

{{- define "mymerge" }}
    {{- $dest := (dict) }}
    {{- range .}}{{merge $dest .}}{{end}}
    {{- toYaml $dest }}
{{- end }}