How to Use With and Range Flow Control in Helm

Aman Jaiswal
DevOps Learners
Published in
3 min readMar 20, 2022

In the last article we’ve seen how can we use if/else condition blocks. Let’s see how can we use “with” and “range” flow control to make more generic helm templates.

with

with helps us to modify the scope. In the template, the current scope is “.”

By using with we can set the current scope to a particular object. Here is the structure of with -

{{ with PIPELINE }}
# restricted scope
{{ end }}

Let’s see some examples:

Here is the part of our values.yaml file. In this, we have tags as kafka and database which includes some other variables and their values.

tags:
kafka:
uname: myKafka
topic: test
database:
uname: mongo
collection: users

These data we need to pass in our configmap.yaml. So our configmap.yaml will be:

apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
kafka-username: {{ .Values.tags.kafka.uname }}
kafka-topic: {{ .Values.tags.kafka.topic }}
database-username: {{ .Values.tags.database.uname }}
database-collection: {{ .Values.tags.database.collection }}

Here we can see the duplication of .Values.tags, we’ve written this 4 times. And we can avoid this by setting up the scope using with block. Let’s see how to do that.

If we convert tags block in values.yaml file to the tree structure, it will look like this:

Now let’s see how can we use with to change the scope and make our configmap.yaml more simple. We will change the current scope from “.” to tags.

apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
{{- with .Values.tags }}
kafka-username: {{ .kafka.uname }}
kafka-topic: {{ .kafka.topic }}
database-username: {{ .database.uname }}
database-collection: {{ .database.collection }}
{{- end }}

Here in the data block, the scope is .Values.tags

It looks simpler than before. But we can make it more simple by removing the duplication of kafka and database with the help of with block.

apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
{{- with .Values.tags }}
{{- with .kafka }}
kafka-username: {{ .uname }}
kafka-topic: {{ .topic }}
{{- end }}
{{- with .database }
database-username: {{ .uname }}
database-collection: {{ .collection }}
{{- end }}
{{- end }}

Here we have set the scope as kafka and database because we are already in scope .Values.tags (refer to the tree structure)

Now suppose if we want to pass the release name data, how can we do that?

If we just put it like this it will throw an error names nil pointer evaluating because we are currently in the scope .Values.tags and there is no Release object.

release: {{ .Release.Name }}

It means we can’t refer to any object outside the scope. Here Release object is in the root scope. Root scope is also represented by the $ sign. So we can use $ here before the . and it will take us to root scope.

release: {{ $.Release.Name }}

That’s all about with flow control. Let’s see about range.

range

range is as similar to for/foreach loops in any other programming language. We can use range to iterate through a collection one by one.

Let’s see an example. Here is the part of our values.yaml file.

secrets:
- mongo-secret
- kafka-secret
- redis-secret
- vault-secret

Now if we need to pass this data, our configmap.yaml looks like this:

apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
secrets:
- mongo-secret
- kafka-secret
- redis-secret
- vault-secret

It’s easy if we have two-three objects but it will become messy if there are a lot of. To avoid this range is helpful here. Let’s see how our configmap.yaml will look like using range:

apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
secrets:
{{- range .Values.secrets }}
- {{ . }}
{{- end }}

It looks simpler, isn’t it?

Again these are basic examples of with and range flow controls. Play around with this and implement it. That’s all about Flow Controls in Helm.

--

--