# Conditionals, Loops and Scope — Helm

Source: https://www.skillbyai.com/en/helm/t-control

> Write if, with and range blocks and keep access to the root context.

## Control structures and the dot

**`if` / `else if` / `else`** include blocks conditionally; empty strings, zero, `false`, `nil` and empty lists or maps count as false. **`with`** changes the **scope**: inside `{{ with .Values.ingress }}`, the dot `.` refers to `.Values.ingress`, and the block is skipped if the value is empty. **`range`** loops over lists or maps, again changing `.` to the current item; `{{ range $key, $value := .Values.env }}` gives you named variables. Because `with` and `range` change the dot, you can no longer write `.Release.Name` inside them; use **`$`**, which always points to the root context: `{{ $.Release.Name }}`. To embed a whole structure from values, such as `resources` or `nodeSelector`, use `{{- toYaml .Values.x | nindent N }}`, where N is the indentation the YAML needs at that position.

## Ingress rules from a list of hosts

Inside `range`, `$` reaches the release name and service port.

```yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "shop-api.fullname" . }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  ingressClassName: {{ .Values.ingress.className }}
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          - path: {{ .path | default "/" }}
            pathType: Prefix
            backend:
              service:
                name: {{ include "shop-api.fullname" $ }}
                port:
                  number: {{ $.Values.service.port }}
    {{- end }}
{{- end }}
```

## Changing rooms in a house

`with` and `range` walk you into a room, so "the table" now means the table in that room. `$` is the front door address: wherever you are, it still leads to the whole house.

**Quiz:** Inside a `range` block, how do you read the release name?

- [ ] .Release.Name
- [x] $.Release.Name
- [ ] range.Release.Name
- [ ] It is not possible

*Answer:* $.Release.Name. range rebinds the dot to the current item; $ always refers to the root context.
