Can kubernetes-helm templates use variables?

3/16/2017

I have a generic template for a k8s resource that I want to expand n times (if you are curious, it is so that I can create n members of a mongo cluster and they are using the statefulset resource so that each member has a stable network name).

Obviously I need different values each time through the loop. I am looping over a series of indices generated by the Sprig "until" function. But the $index for the loop does not get set in the "." namespace. So I am unable to refer the the current iteration inside of my defined template in my _helpers.tpl file.

here is an example template w/full k8s resource yaml (I'm abbreviating most of it):

{{- define "mytest" -}} 
---
apiVersion: apps/v1beta1
kind: StatefulSet
  abbreviated...
  containers:
  - name: mongod-$index
  abbreviated...
{{- end -}}

caller:

{{ range $index, $e := until .Values.mongod_count }}
    {{include "mytest" .}}
{{ end}}

I just get: undefined variable "$index"

I have tried with blocks too, like this in my (caller) template:

{{ $foo := "somevalue" }}
{{ define "my_extra_labels" }} bla {{ .Values.test }}_{{$foo}}{{end}}
{{ template "mytest" . }}

And this in my _helpers.tpl

{{/* Test stuff */}} 
{{- define "mytest" -}}
hello: world_how_are_{{ block "my_extra_labels" . }}{{ end }}
{{- end -}} 

The variable $foo is not defined in the "define" body.

This template scoping feels so restrictive that at this point I can't see how to use it to solve my current scenario.

Is there some way to shove variables into the "." namespace? And if so (crossing my fingers) is there a way to merge namespaces in some way so that I can still access .Values and .Chart variables?

-- rideswitch
kubernetes-helm

2 Answers

8/10/2017

Templates in helm cannot access variables. However, the context handed to the template is a dictionary. The sprig library is accessible from within the Go templates and can be used to manipulate dictionaries.

Take this simplified template:

{{- define "mytest" -}} 
  - name: mongod-{{ .index }}
{{- end -}}

You can now call this template as an example:

{{ range $index := until 5 }}
  {{- $p := dict "index" $index }}
  {{include "mytest" $p}}
{{- end -}}

This will output:

- name: mongod-0
- name: mongod-1
- name: mongod-2
- name: mongod-3
- name: mongod-4

You can also add items to an existing or the current scoped dictionary:

{{- $_ := set . "index" "none" }}
{{include "mytest" .}}

The $_ is used to suppress undesired output as "set" returns the new dictionary. The above returns:

- name: mongod-none

Any values added to the dictionary will live beyond the call. If you want to avoid polluting an existing dictionary you can force a deep copy with:

{{-  $d := merge (dict) . -}}

Anything added to "$d" will not exist in ".".

-- kscoder
Source: StackOverflow

6/13/2018

I will left this here because some people might be trying to set a static value to a variable in Helm to re-use it in a template and they probably will find this SO question by its title. So, here is a trick:

Update:

There's a better way to do this:

{{- $_ := set . "appName" "app_name_one"-}}

---
apiVersion: v1
kind: Deployment
apiVersion: apps/v1beta2
metadata:
  name: {{ .appName }}

The old advice (don't use it)

Combined with the syntax from the answer above suggested by @kscoder

    ---
    # values.yml

    static_vars:
      app_name_one: app_name_one
      text_to_reuse: text_to_reuse

    ---    
    # templates/deployment.yml

    # now you don't need to copy-n-paste values, just set them here once
    {{- $text_to_reuse := index .Values "static_vars" "text_to_reuse" -}}
    {{- $app_name := index .Values "static_vars" "app_name_one" -}}
    {{- $_ := set . "app_name" $app_name -}}

    apiVersion: v1
    kind: Deployment
    apiVersion: apps/v1beta2
    metadata:
      name: {{ .app_name }}
    spec:
      selector:
        # https://github.com/kubernetes/kubernetes/issues/26202
        matchLabels:
          name: {{ .app_name }}
      template:
        metadata:
          labels:
            name: {{ .app_name }}
            name_alt: {{ $app_name }}
            other_label: {{ $text_to_reuse }}
    # and so on
-- kivagant
Source: StackOverflow