<p>I have the following values.yaml</p>
<pre><code>ingresses:
  - name: public
    class: &quot;nginx&quot;
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: 122m
      nginx.ingress.kubernetes.io/proxy-connect-timeout: &quot;7&quot;
      nginx.ingress.kubernetes.io/proxy-read-timeout: &quot;60&quot;
      nginx.ingress.kubernetes.io/proxy-send-timeout: &quot;30&quot;
    labels: {}

    rules:
      - host: example.com
        http:
        paths:
        - path: /asd/as
          pathType: ImplementationSpecific
          backend:
            service:
              name: one
              port: 
                number: 8080
        - backend:
            service:
              name: log
              port:
                number: 8081
          path: /path/log
          pathType: ImplementationSpecific
        - backend:
            service:
              name: got
              port:
                number: 8082
          path: /api/got
          pathType: ImplementationSpecific
    tls:
    - hosts:
      - example.com
      secretName: cert
  
 - name: public
   annotations:
   labels: {}
   rules:
    - host: example1.com
      http:
      paths:
        - backend:
            service:
              name: web
              port:
                number: 8090
          pathType: ImplementationSpecific
      
    tls:
    - hosts:
      - example1.com
      secretName: qwe
</code></pre>
<p>and I have the following ingress file:</p>
<pre><code>{{- $top := . -}}
{{- range $ingress := .Values.ingresses }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ $ingress.name }}
  namespace: {{ $ingress.namespace }}
  {{- with $ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 8 }}
  {{- end }}
spec:
  {{- if and $ingress.class (semverCompare &quot;&gt;=1.18-0&quot; $.Capabilities.KubeVersion.GitVersion) }}
  ingressClassName: {{ $ingress.class }}
  {{- end }}
  {{- if $ingress.tls }}
  tls:
    {{- range $ingress.tls }}
    - hosts:
        {{- range .hosts }}
        - {{ . | quote }}
        {{- end }}
      secretName: {{ .secretName }}
    {{- end }}
  {{- end }}
  rules:
    {{- range $ingress.rules }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          {{- if and .path (semverCompare &quot;&gt;=1.18-0&quot; $.Capabilities.KubeVersion.GitVersion) }}
          - path: {{ .path }}
          {{ end }}
            {{- if and .pathType (semverCompare &quot;&gt;=1.18-0&quot; $.Capabilities.KubeVersion.GitVersion) }}
            pathType: {{ .pathType }}
            {{- end }}
            backend:
              service:
                name: {{ .backend.service.name }}
                port:
                  number: {{ .backend.service.port.number}}
          {{- end }}
    {{- end }}
    {{- end }}
</code></pre>
<p>This only generates one ingress (whichever is the last one in values files). I tried using <code>range $ingress := .Values.ingress</code> but it keeps giving me an error whenever I try $ingress.name . What changes do I make to the ingress.yaml to be able to deploy both these ingresses.</p>
<p>Edit: Made edits based on David's answer.</p>

<p>You need to break the two separate ingress configurations up in the Helm values somehow.  Right now they're in a single map object under <code>ingress:</code>, so <code>.Values.ingress.name</code> for example only has one value rather than being something you can iterate over.</p>
<p>A YAML list here makes sense:</p>
<pre class="lang-yaml prettyprint-override"><code># values.yaml
ingresses:
  - name: example-com
    class: nginx
    rules: [...]
  - name: example1-com
    class: nginx
    rules: [...]
</code></pre>
<p>Then you can iterate over this list with a <code>range</code> loop.  The important thing to know about a <code>range</code> loop is that it rebinds the <code>.</code> special variable, which is the base of constructs like <code>.Values</code>; that means that you need to save the original value of <code>.</code> outside the loop (the <code>$</code> special variable may work as well).  You can generate multiple Kubernetes objects in a single Helm template file so long as each begins with the YAML <code>---</code> start-of-document marker (and it's valid to generate no output at all).</p>
<pre class="lang-yaml prettyprint-override"><code>{{-/* save the original value of . */-}}
{{- $top := . -}}

{{-/* iterate over the ingress configurations */-}}
{{- range $ingress := .Values.ingresses }}
---
{{-/* your existing conditionals can go here, simplifying */}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  {{-/* this comes from the per-ingress config */}}
  {{- with $ingress.annotations }}
  annotations: {{- toYaml . | nindent 4 }}
  {{- end }}

  {{-/* if you need to use &quot;standard&quot; helper functions, make sure
        to pass the saved $top value as their parameter */}}
  name: {{ include &quot;mychart.fullname $top }}-{{ $ingress.name }}
spec: { ... }
{{- end }}
</code></pre>
<p>You also may want to reconsider how much of this is appropriate to include in arbitrarily-configurable values.  Rather than essentially write out the entire Ingress object in Helm values, you may find it easier to write out things like the path mappings in the template files themselves, and have a few high-level controls (&quot;enabled&quot;, &quot;host name&quot;, &quot;TLS secret name&quot;) exposed.  Things like the backend service name and port will correspond to other things in your chart and you may need to compute the service name; someone just installing your chart shouldn't need to configure this.</p>
