Unpack a Go map value in a Helm template

11/21/2019

I can't seem to find a simple and effective solution for what I imagine comes up a lot in Go templates / Helm. Basically, given a values.yaml like this:

ingress:
  hosts:
  - host: busy-a.local
    paths:
    - backend:
        serviceName:busy-a
        servicePort: 80
      path: /busy/[A-Z0-9]{1}

and a templates/ingress.yaml like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{.Values.project}}-ingress
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
  {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
        {{- range .paths }}
          - path: {{ .path }}
            backend:
              serviceName: {{ .backend.serviceName }} # this works
              servicePort: {{ .backend.servicePort }} # but can we shorthand backend?
        {{- end }}
  {{- end }}

But, wouldn't it be easier to "unpack" the backend map in the .paths range, like backend: {{.backend}}? However, it doesn't seem to work like that.

...
    paths:
      - path: /busy/[A-Z0-9]{3}
        backend: map[serviceName:busy-a servicePort:80]

What's the preferred way to unpack or assign a whole object like this in Go Templates or with Sprig extensions?

-- 4m1r
go
go-templates
kubernetes-helm

1 Answer

11/22/2019

Helm has a couple of barely-documented functions and one of those is a toYaml. This accepts an arbitrary object and writes it out in YAML format, unindented.

In your case you can achieve what you're trying for by combining toYaml and indent:

spec:
  ...
            backend:
{{ .backend | trim | indent 14 }}
{{/* above line intentionally at left margin */}}

Since toYaml can handle nested objects just fine, given your input and output, I might apply it higher up:

spec:
  rules:
  {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths: {{- .paths | toYaml | trim | nindent 10 }}
  {{- end }}

toYaml will always emit a trailing newline, so I tend to trim it off so I get a little more control over it. In the last example I use nindent to insert a leading newline to make the template a little bit more compact.

-- David Maze
Source: StackOverflow