Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Helm range without leaving global scope

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
like image 671
LoganHenderson Avatar asked Mar 18 '19 01:03

LoganHenderson


People also ask

What does {{ }} mean in Helm?

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.

How do you define a variable in Helm chart?

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 .

Does Helm use Jinja?

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.


3 Answers

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 }}
like image 190
yanivoliver Avatar answered Oct 03 '22 18:10

yanivoliver


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 }}
like image 34
Lars Christian Jensen Avatar answered Oct 03 '22 20:10

Lars Christian Jensen


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 }}
like image 44
Terany Avatar answered Oct 03 '22 18:10

Terany