Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

helm - how to iterate over map with complex values

In a helm chart want to iterate over a map that contains structured values.

I do know how to iterate over a map with simple string values. I also can iterate over an array that contains structured values (not shown here). But I did not manage to iterate over a map that contains structured values.

This is my directory structure containing 3 files:

templates/test.yaml
Chart.yaml
values.yaml

A simple file Chart.yaml (just for completing the showcase):

---
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: foochart
version: 0.1.0

The file values.yaml with a map that contains simple string values (label) and one that contains structured values (label1):

---
label:
  fook: foo
  bark: bar
label1:
  fook:
    name: foo
    value: foo1
  bark:
    name: bar
    value: bar2

This template test.yaml works:

---
env:
  {{- range $k, $v := .Values.label }}
  - name: {{ $k }}
    value: {{ $v }}
  {{- end }}

But when I substitute .Values.label by .Values.label1, it produces no output.

This is my command for testing:

helm template foochart

Question: Is it possible to process a map with structured values? I would like to use something like $v.name. If yes, how can I do that?

like image 520
Donat Avatar asked Sep 02 '25 09:09

Donat


1 Answers

You can in fact use syntax like $v.name, if you know that $v is a variable holding an object.

env:
{{- range $k, $v := .Values.label1 }}
  - name: {{ $k }}_{{ $v.name }}
    value: {{ $v.value }}
{{- end }}

If you know that it has exactly the syntax you want, there is an underdocumented toYaml function that takes an arbitrary object and returns it as unindented YAML. In your example, each of the values has the form of an env: item, and if you know (or specify) that, you can write out literally:

env:
{{- range .Values.label1 }}
  - {{ . | toYaml | indent 4 | trim }}
{{- else }}
  []
{{- end }}

(In this last example: I'm not assigning a variable, so . is temporarily reassigned to each value in the map, and the keys are lost; for each item, I convert it to YAML, indent it by 4 spaces, but then trim out leading and trailing whitespace; and if there are no values, I explicitly write out an empty list.)

It's usually easier to specify a format you want your values to be in, and work with that. If you for some reason can't be sure which form you have, the template language includes functions to test on a value's type, so in principle you can test:

env:
{{- range $k, $v := .Values.labelN }}
{{- if kindIs "string" $v }}
  - name: {{ $k }}
    value: {{ $v }}
{{- else }}
  - name: {{ $v.name }}
    value: {{ $v.value }}
{{- end }}
{{- else }}
  []
{{- end }}
like image 124
David Maze Avatar answered Sep 05 '25 01:09

David Maze