<p>I am  using <code>Helm</code> v3 and trying to iterate over a complex object/map in a YAML definition file for Kubernetes network policy with the following content:<br />
<code>values.yaml:</code></p>
<pre><code>networkPolicies:
  egress:
    - service: microservice-name
      destination:
        - podLabels:
            app=microservice-name
          namespaceLabels:
             company.com/microservices: microservice-name
      protocol: TCP
      ports:
        - 8444
</code></pre>
<p>At the k8s definition file, I have this code:<br />
<code>egress-networkpolicy.yaml:</code></p>
<pre><code>{{- range $v, $rule := .Values.networkPolicies.egress  }}---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-kong-to-{{ $rule.service }}-egress
  namespace: kong
  annotations:
    description: Kong egress policies
spec:
  podSelector:
    matchLabels:
      {{- range $label,$value := $rule.podSelector }}
      {{ $label }}: {{ $value }}
      {{- end }}
  egress:
    - to:
        {{- range $from := $rule.to }}
        - podSelector:
            matchLabels:
              {{- range $label,$value := $from.podLabels }}
              {{ $label }}: {{ $value }}
              {{- end }}
          {{- if has $from &quot;namespaceLabels&quot; }}
          namespaceSelector:
            {{- if eq ( len $from.namespaceLabels ) 0 }} {}
            {{- else }}
            matchLabels:
              {{- range $label,$value := $from.namespaceLabels }}
              {{ $label }}: {{ $value }}
              {{- end }}
            {{- end }}
          {{- end }}
        {{- end }}
      {{- if has $rule &quot;ports&quot; }}
      ports:
        {{- range $port := $rule.service.ports }}
        - protocol: {{ $port.protocol }}
        - port: {{ $port }}
        {{- end }}
      {{- end }}
    policyTypes:
      - Egress
{{ end -}}
</code></pre>
<p>Unfortunately when I run <code>helm template name-of-the-template</code> it throws the following error:</p>
<pre><code>❯ helm template name-of-the-template --debug
install.go:178: [debug] Original chart version: &quot;&quot;ate name-of-the-template --debug  

install.go:199: [debug] CHART PATH: /Users/user/charts/name-of-the-template


Error: template: name-of-the-template/templates/egress-networkpolicy.yaml:34:13: executing &quot;name-of-the-template/templates/egress-networkpolicy.yaml&quot; at &lt;has $rule &quot;ports&quot;&gt;: error calling has: Cannot find has on type string
helm.go:88: [debug] template: name-of-the-template/templates/egress-networkpolicy.yaml:34:13: executing &quot;name-of-the-template/templates/egress-networkpolicy.yaml&quot; at &lt;has $rule &quot;ports&quot;&gt;: error calling has: Cannot find has on type string
</code></pre>
<p>I can't find the reason for <code>Helm</code> throwing this error at that line, but not in similar code before that line.</p>

Ricardo Silva
<p>The <a href="https://docs.helm.sh/docs/chart_template_guide/function_list/#has-musthas" rel="nofollow noreferrer"><code>has</code></a> template function checks for membership in a list.  In this context <code>$rule</code> is a mapping or dictionary (it is one of the items in the list under <code>egress</code>) and for that type you need to use <a href="https://docs.helm.sh/docs/chart_template_guide/function_list/#haskey" rel="nofollow noreferrer"><code>hasKey</code></a> instead.</p>
<pre class="lang-yaml prettyprint-override"><code>{{- if hasKey $rule &quot;ports&quot; }}{{/* hasKey, not has */}}
ports:
  ...
{{- end }}
</code></pre>
<p>One thing that can simplify this slightly is to use the Go template <code>with</code> construct instead of <code>if</code> here.  <code>with</code> acts just like <code>if</code>, except it also rebinds the special variable <code>.</code> to the conditional value if it's truthy.  Accessing an undefined key in a map is okay but returns <code>nil</code>, which is falsey.  So in this context I might write</p>
<pre class="lang-yaml prettyprint-override"><code>{{- with $rule.ports }}
ports:
{{- range . }}
  - protocol: {{ $rule.protocol }}
    port: {{ . }}
{{- end }}
{{- end }}
</code></pre>
<p>(But note as I've written it that the <code>.</code> in the third and fifth lines are different variables, and that this usage also changes <code>.</code> as appears at the start of <code>.Values</code> or in <code>template &quot;name&quot; .</code>  In this little loop that's not going to be a practical problem.)</p>
