<p>I'm trying to use a helm template helper to filter out values from a list in my <code>values.yaml</code> file, based on the value of one of the keys in each list member.</p>

<p>My chart is currently comprised of these files -<br>
values.yaml - </p>

<pre><code>namespaces:
- name: filter
  profiles:
  - nonProduction
- name: dont-filter
  profiles:
  - production  
clusterProfile: production
</code></pre>

<p>templates/namespaces.yaml</p>

<pre><code>apiVersion: v1
kind: List
items:
{{ $filteredList := include "filteredNamespaces" . }}
{{ range $filteredList }}
  {{ .name }}
{{- end -}}
</code></pre>

<p>templates/_profile-match.tpl</p>

<pre><code>{{/* vim: set filetype=mustache: */}}
{{- define "filteredNamespaces" -}}
  {{ $newList := list }}
  {{- range .Values.namespaces }}
    {{- if has $.Values.clusterProfile .profiles -}}
      {{ $newList := append $newList . }}
    {{- end -}}
  {{ end -}}
  {{ $newList }}
{{- end -}}
</code></pre>

<p>The problem is that within my helper file, the <code>$newList</code> variable is only populated within the scope of the <code>range</code> loop, and I end up with an empty list returning to the <code>namespaces.yaml</code> template.<br>
Is there any way around this issue? Am I taking the wrong approach for solving this?</p>

Yaron Idan
<p>For all that Go templates are <em>almost</em> general-purpose functions, they have a couple of limitations.  One of those limitations is that they only ever return a string; you can't write basic functional helpers like <code>map</code> or <code>filter</code> because you can't return the resulting list.</p>

<p>The more straightforward approach to doing filtering as you've shown is to move it up to the point of the caller (and possibly repeat the condition if it's needed in multiple places):</p>

<pre><code>items:
{{- range .Values.namespaces }}
{{- if has $.Values.clusterProfile .profiles }}
  - {{ .name }}
{{- end }}
{{- end }}
</code></pre>

<p>A hacky way to make this work as you have it is to marshal the list to some other string-based format, like JSON:</p>

<pre><code>{{- define "filteredNamespaces" -}}
...
{{ toJson $newList }}
{{- end -}}

{{- range include "filteredNamespaces" . | fromJson -}}...{{- end -}}
</code></pre>

<p>Also remember that you can inject Helm values files using the <code>helm install -f</code> option.  So rather than listing every permutation of option and then filtering out the ones you don't want, you could restructure this so that <code>namespaces:</code> only contains the list of namespaces you actually want to use, but then you use a different values file for each profile.</p>
