Helm range without leaving global scope

3/18/2019

I need to loop through a list of instances and create 1 stateful set for every instance. However, inside range I then limit myself to the scope of that loop. I need to access some global values in my statefulset.

I've solved it by just putting all global objects I need in an env variable but... this very seems hacky.

What is the correct way to loop through ranges while still being able to reference global objects?

Example of my loop

{{- $values := .Values -}}
{{- $release := .Release -}}

{{- range .Values.nodes }}

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ $release.Name }} <-- Global Scope
  labels:
    .
    .
    .    
        env:
          - name: IP_ADDRESS
            value: {{ .ip_address }} <-- From range scope
    .
    .
    .
{{- end }}

Example of values

# Global
image:
  repository: ..ecr.....

# Instances
nodes:

  - node1:
    name: node-1
    iP: 1.1.1.1
  - node2:
    name: node-2
    iP: 1.1.1.1
-- LoganHenderson
kubernetes
kubernetes-helm

3 Answers

3/20/2019

When entering a loop block you lose your global context when using .. You can access the global context by using $. instead.

As written in the Helm docs -

there is one variable that is always global - $ - this variable will always point to the root context. This can be very useful when you are looping in a range and need to know the chart's release name.

In your example, using this would look something like:

{{- range .Values.nodes }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ $.Release.Name }}
  labels:
    .
    .
    .    
        env:
          - name: IP_ADDRESS
            value: {{ .ip_address }}
    .
    .
    .
{{- end }}
-- yanivoliver
Source: StackOverflow

12/31/2019

The question is about the global scope, but it is possible to keep access to any outer scope by storing it, like this:

{{- $outer := . -}}

Then, if you use named variables for the range, like this:

{{- range $idx, $node := .Values.nodes }}

You don't need ., so you can restore the outer scope, like this:

{{- with $outer -}}

In your example, using this would look something like:

{{- $outer := . -}}
{{- range $idx, $node := .Values.nodes }}
{{- with $outer -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ .Release.Name }}
  labels:
    .
    .
    .    
        env:
          - name: IP_ADDRESS
            value: {{ $node.ip_address }}
    .
    .
    .
{{- end }}
-- Lars Christian Jensen
Source: StackOverflow

3/18/2019

The best way is not to call many external objects inside the loop.

you can declare release name at the top in a variable to overcome this issue:

{{- $release_name := .Release.Name -}}
-- Abhi
Source: StackOverflow