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

<pre><code>Ports:
  - number: 443
    protocol: http
</code></pre>

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

<p><code>port_list=$(./get_ports.sh)</code></p>

<p>output:</p>

<pre><code>- 80
- 8080
</code></pre>

<p>I want the resulting rendered template to be </p>

<pre><code>Ports:
  - number: 80
  - number: 8080
</code></pre>

<p>How would I accomplish this? I tried the following in my template file:               </p>

<pre><code>{{- with .Values.Ports }}
Ports:
  {{- toYaml . | nindent 8 }}
{{- end }}
</code></pre>

<p>using helm template and setting <code>values.Ports=$port_list</code>, 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?</p>

<pre><code>Ports:
|-
  - number: 80
  - number: 8080
</code></pre>

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

<pre><code>Ports:
  - number: 80
    protocol: http
  - number: 8080
    protocol: http
</code></pre>

<p>Is there a clean way to do this with just templating?</p>

<p>First, you have to know about the YAML syntax about string. You can find it by searching on the internet. For example: see <a href="https://yaml-multiline.info/" rel="noreferrer">YAML Multiline</a>.</p>

<p><code>|</code> enables multiline string and <code>-</code> chops the trailing <code>\n</code> from the end of the string.</p>

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

<pre class="lang-sh prettyprint-override"><code>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"
</code></pre>

<p>For both of the tests you have the same output as follows:</p>

<pre><code>ports:
|-
  - 80
  - 8080
</code></pre>

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

<pre class="lang-sh prettyprint-override"><code>--set ports="- 80
- 8080
"
</code></pre>

<p>The output is like as following:</p>

<pre><code>ports:
|
  - 80
  - 8080
</code></pre>

<p>Now try in a different way. Change your template to like this one:</p>

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

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

<ul>
<li><code>--set ports={80\,8080}</code></li>
<li><code>--set ports[0]=80,ports[1]=8080</code></li>
</ul>

<p>Now the output is same as you want.</p>

<pre class="lang-sh prettyprint-override"><code>$ helm template test . --set ports={80\,8080}
ports:
  - number: 80
    protocol: http
  - number: 8080
    protocol: http
</code></pre>

<p>So all you need to process the output of <code>get_ports.sh</code>. That's it.</p>

<blockquote>
  <p><strong>You may need to adjust the indentation in the template</strong></p>
</blockquote>
