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
The Helm template syntax is based on the Go programming language's text/template package. The braces {{ and }} are the opening and closing brackets to enter and exit template logic.
In Helm templates, a variable is a named reference to another object. It follows the form $name . Variables are assigned with a special assignment operator: := . We can rewrite the above to use a variable for Release.Name .
Helm uses Go templates to define Kubernetes (yaml) manifests. We were already unsatisfied by using Jinja and we did not see a huge improvement from our previous system, the main reason being: YAML files are not suitable to be managed by text templating frameworks.
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 }}
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 }}
If you need to access the global scope only, simply add {{- with $ -}} will do.
{{- range $idx, $node := .Values.nodes }}
{{- with $ -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}
labels:
.
.
.
env:
- name: IP_ADDRESS
value: {{ $node.ip_address }}
.
.
.
{{- end }}
{{- end }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With