Reputation: 391
I have a helm template like this,
1 {{- range $device_type := include "example.supportedDevices" . }}
3 {{- $total_worker_sets := get $.Values.all_worker_sets $device_type }}
4 {{- range $item := $total_worker_sets }}
5 {{- if eq $device_type "cpu" }}
6 {{- $type := "cpu" }}
7 {{- else }}
8 {{- $type := $item.name }}
9 {{- end }}
10 {{- range $i, $e := until ($item.worker_sets|int) }}
11 ---
12 apiVersion: apps/v1
13 kind: StatefulSet
14 metadata:
15 name: {{ template "example.fullname" $ }}-worker-{{ $type }}-{{ $i }}
16 spec:
...
{{- end }}
{{- end }}
{{- end }}
and helm lint
returns:
[ERROR] templates/: parse error at (example/templates/worker.yaml:15): undefined variable "$type"
Upvotes: 3
Views: 2730
Reputation: 159495
As @KamolHasan notes in their answer, if you try to define a variable inside an {{ if }}...{{ end }}
block, the scope of the variable is that block. Helm (and more specifically the Sprig extension template library) provides a ternary
extension function to work around this.
ternary
takes three arguments; in order, the true-value, the false-value, and the condition. This specific ordering lets you use template pipeline syntax to provide the condition. It's similar in spirit to the ? :
inline-conditional operators in C-like languages
{{ $value := ternary "if-true" "if-false" $condition }}
const char *value = condition ? "if-true" : "if-false";
That would let you promote $type
out of the conditional block
{{- range $item := $total_worker_sets }}
{{- $type := eq $device_type "cpu" | ternary "cpu" $item.name }}
{{- range $i, $e := until ($item.worker_sets|int) }}
name: {{ template "example.fullname" $ }}-worker-{{ $type }}-{{ $i }}
{{- end }}
{{- end }}
Upvotes: 1
Reputation: 13516
When you assigned the $type
with :=
inside an if-block
, the scope is limited only to that if-block
. Define the variable outside the if-block
so that you can use it later.
1 {{- range $device_type := include "example.supportedDevices" . }}
3 {{- $total_worker_sets := get $.Values.all_worker_sets $device_type }}
x {{- $type := "" }} ### <----define here
4 {{- range $item := $total_worker_sets }}
5 {{- if eq $device_type "cpu" }}
6 {{- $type = "cpu" }} ### <--- replace := with = to avoid re-declaration
7 {{- else }}
8 {{- $type = $item.name }} ### <--- replace := with =
9 {{- end }}
10 {{- range $i, $e := until ($item.worker_sets|int) }}
11 ---
12 apiVersion: apps/v1
13 kind: StatefulSet
14 metadata:
15 name: {{ template "example.fullname" $ }}-worker-{{ $type }}-{{ $i }}
16 spec:
...
{{- end }}
{{- end }}
{{- end }}
Upvotes: 4
Reputation: 4379
You can use $
to get to the root scope. So instead of .type
you can use $.type
. Here you used $type
, that is why it's showing undefined (undefined variable "$type"
, rather it would be $.type
.
Upvotes: 3