helm templating with toYaml

18,537

First, you have to know about the YAML syntax about string. You can find it by searching on the internet. For example: see YAML Multiline.

| enables multiline string and - chops the trailing \n from the end of the string.

The reason for appearing |- is the output of the script get_ports.sh (is being treated as a single string). You can test this,

port_list=$(get_ports.sh)
# pass this to the `--set` flag in both of the following ways
# 01: pass the var $port_list
--set ports=$port_list
# 02: directly pass the value of the var $port_list
--set ports="- 80
- 8080"

For both of the tests you have the same output as follows:

ports:
|-
  - 80
  - 8080

If you put a newline at the end of the output of your script, then you will see the - has disappeared.

--set ports="- 80
- 8080
"

The output is like as following:

ports:
|
  - 80
  - 8080

Now try in a different way. Change your template to like this one:

{{- if .Values.ports }}
  {{- print "ports:" | nindent 2 }}
  {{- range $_, $p := .Values.ports }}
    - number: {{ $p }}
      protocol: http
  {{- end }}
{{- end }}

This template expects the value of your ports in the --set flag as a list (not a string). According to my knowledge at the time of writing this answer, to provide a list value in --set flag either of the followings can be used:

  • --set ports={80\,8080}
  • --set ports[0]=80,ports[1]=8080

Now the output is same as you want.

$ helm template test . --set ports={80\,8080}
ports:
  - number: 80
    protocol: http
  - number: 8080
    protocol: http

So all you need to process the output of get_ports.sh. That's it.

You may need to adjust the indentation in the template

Share:
18,537

Related videos on Youtube

Jimmy Smith
Author by

Jimmy Smith

Updated on June 14, 2022

Comments

  • Jimmy Smith
    Jimmy Smith almost 2 years

    I have values.yml file that takes in a list of ports with this format and default values:

    Ports:
      - number: 443
        protocol: http
    

    The script that output the list of port to use as my input gives me this format:

    port_list=$(./get_ports.sh)

    output:

    - 80
    - 8080
    

    I want the resulting rendered template to be

    Ports:
      - number: 80
      - number: 8080
    

    How would I accomplish this? I tried the following in my template file:

    {{- with .Values.Ports }}
    Ports:
      {{- toYaml . | nindent 8 }}
    {{- end }}
    

    using helm template and setting values.Ports=$port_list, it ended up giving me a pipe and an extra dash like below, which I do not know where they come from, how do I accomplish getting to the format I want above based on the input?

    Ports:
    |-
      - number: 80
      - number: 8080
    

    As a bonus, I would also like to have a default protocol in my port list when the protocol isn't specified.

    Ports:
      - number: 80
        protocol: http
      - number: 8080
        protocol: http
    

    Is there a clean way to do this with just templating?

    • Mr. Llama
      Mr. Llama almost 3 years
      I know I'm a bit late here, but I strongly recommend against using toYaml because it means you suddenly have to care about indentation. Given that YAML is a superset of JSON, it's probably better to just use Ports: {{ toJson . }} instead. You will get the desired result without having to worry about whitespace or formatting issues.
  • Jimmy Smith
    Jimmy Smith almost 4 years
    Excellent answer, thank you. This was exactly what I needed.