How to create helm variable with a comma - kubernetes-helm

I'm wanting to create a helm variable with just a comma. I'm not sure how I'd do it? I ran into syntax issues with the below.
{{- $asterisk := "*" }}
{{- $comma := ",\" }}
The result would be appended using printf.

Commas aren't special in the Go text/template language, and you don't need to escape them in strings.
{{- $comma := "," -}}
You can put literal text into printf and this may be easier for your uses
{{ printf "%s, %s" $var1 $var2 }}

Related

How to output template data line by line

I have some data which is a multiline string. And I don't want to modify it. Now I want to prefix each one with a character
{{- define "info.geological" -}}
iWater Well Completion Reports
Anatomy of a Water Well Report
Water table Altitudes
...
{{- end -}}
What I want
data:
- "iWater Well Completion Reports"
- "Anatomy of a Water Well Report"
- "Water table Altitudes"
...
Treat it as string in golang, split and print
template
{{- define "info.geological" -}}
iWater Well Completion Reports
Anatomy of a Water Well Report
Water table Altitudes
...
{{- end -}}
template/xxx.yaml
data:
{{- $dt := include "info.geological" . }}
{{- range ( split "\n" $dt) }}
- {{ . | quote }}
{{- end }}
output:
data:
- "iWater Well Completion Reports"
- "Anatomy of a Water Well Report"
- "Water table Altitudes"
...
Helm's template functions largely come from a library called Sprig. Sprig includes a small number of functions that operate on lists of strings, more specifically including a splitList function.
So, given your multi-line string, you can split it on newlines to get the list of lines
{{- $lines := include "info.geological" . | splitList "\n" -}}
Once you have that list, the easiest way to emit it as a YAML list is the underdocumented toYaml function; so
data:
{{ include "info.geological" . | splitList "\n" | toYaml | indent 2 }}
You can also manually iterate through it with a range loop if you'd like.
data:
{{- $lines := include "info.geological" . | splitList "\n" }}
{{- range $lines }}
- {{ quote . }}
{{- end }}

Passing Dictionary as an argument in Helm Template

I wonder if there is anyway for us to pass dictionary as an argument in Helm Templates. In Python, I could simply create some scripts like this but I am not sure how to translate this script into Helm.
>>> def display(d):
... for key in d:
... print("key:", key, "Value:", d[key])
...
>>> def func():
... D = {'a':1, 'b':2, 'c':3}
... display(D)
...
>>> func()
key: a Value: 1
key: b Value: 2
key: c Value: 3
I tried to implement some script like this but they seem does not solve out.
_helpers.tpl
{{- define "display"}}
{{- $d := .d -}}
{{- range $key, $value := $d -}}
{{- printf "%s-%s" $key $value-}}
{{- end -}}
_test.tpl
{{- define "func"}}
{{- $D = dict 'a' 1 'b' 2 'c' 3} -}}
{{- $res := include "display" (dict "d" $D) -}}
{{- $res -}}
{{- end -}}
Would you give me some working examples of how a dictionary is passed as an arguments in helm?
Thank you in advance for your help! I am much appreciate it!
A Go text/template template takes only one parameter. It has the special name . inside the template. That parameter can be any type, though, and in a Helm context there are extension functions like list and dict that can assemble the containers.
A template can only return a string, and if you need to capture that return value then you need to use the Helm include extension function rather than the standard template template directive. Anything the template outputs is part of that "return value" and there is not a specific "return" command.
So, for example, your display function is pretty easy to write: its one parameter is a dictionary and you use a range loop to iterate over its contents. (I'm dumping it out as a YAML list, which would be a more typical Kubernetes/Helm output.)
{{- define "display" -}}
{{- range $k, $v := . -}}
- key: {{ $k }}
value: {{ $v }}
{{ end -}}
{{ end -}}
And then to call it, you'd construct a dictionary with dict (or extract one from .Values) and pass that dictionary to the function.
{{- $d := dict "a" 1 "b" 2 "c" 3 }}
{{- include "display" $d -}}

Helm _helpers.yaml template with bool returning %!S(Bool=True) instead of string

I have the following Helm template definition:
{{- define "api.test-drive" -}}
{{- if not .Values.global.testDrive }}
{{- printf "%s" .Values.default.TEST_DRIVE | quote -}}
{{- else -}}
{{- printf "%s" .Values.global.testDrive | title | quote -}}
{{- end -}}
{{- end -}}
With the following in a configmap template:
TEST_DRIVE: {{ include "api.test-drive" . }}
And a global value of global.testDrive: true. However, when Helm executes this an inserts into the configmap, it is storing it as:
TEST_DRIVE:
----
%!S(Bool=True)
Shouldn't the printf be casting global.testDrive from a bool true to a string then applying the title and quote function? It is not clear what is happening here.
The Go text/template printf template function passes through directly to fmt.Printf(), but the fmt package defines its format strings a little bit differently from C's printf(3) function. In particular, the %s format modifier is only defined for string-type arguments, and you've passed it a bool-type argument; the %!s(...) output means there was an error processing a %s argument (see Format errors).
If you want to use printf here, %v will convert an arbitrary value to a string with a default syntax
{{- printf "%v" .Values.global.testDrive | title | quote -}}
{{/* ^^ */}}
Helm includes a generic toString helper which might be more convenient here.
{{- .Values.global.testDrive | toString | title | quote -}}
(...but under the hood in most cases toString does the equivalent of printf "%v".)

How can I apply template function to a range result in Helm?

My goal is to convert values in Values.yaml into the following:
CUSTOM_VARIABLE: "TEST_ENV_1=devil,TEST_ENV_2=god,TEST_ENV_3=angel"
### Values.yaml
env:
TEST_ENV_1: devil
TEST_ENV_2: god
TEST_ENV_3: angel
The below template almost does this but I'm getting comma at the end: TEST_ENV_1=devil,TEST_ENV_2=god,TEST_ENV_3=angel,.
### _envVars.tpl
{{ define "envVars" }}
...
- name: CUSTOM_VARIABLE
value: "
{{- range $key, $value := .Values.env -}}
{{- printf "%s=%s," $key $value -}}
{{- end -}}
"
...
{{- end }}
Is there a way to apply template function (e.g. trunc to remove last symbol) to a range result in my case?
try something like
{{range $i, $e := $}}
{{if $i}},{{end}}
{{$e}}{{end}}
If actually look for the index and if it's zero it's wont to add the , at last. here is if is not behave like normal it checks the index also.
{{- range $i, $e := . -}}
{{if $i}}, {{end}}prefix_{{$e}}
{{- end}}
above loop will give output like : prefix_one, prefix_two, prefix_three
https://play.golang.org/p/KuRh55BHna8
Read more at : https://groups.google.com/g/golang-nuts/c/XBScetK-guk/m/Bh7ZFz6R3wQJ
If you write the range call into a helper template, Helm has an include extension function that calls a template and captures its output as a string.
{{/* Render the map-type template parameter to a key=value,key=value,
list, ending with a trailing comma. */}}
{{- define "custom.variable.format" -}}
{{- range $key, $value := . -}}
{{ $key }}={{ $value }},
{{- end -}}
{{- end -}}
- name: CUSTOM_VARIABLE
value: {{ include "custom.variable.format" .Values.env | trimSuffix "," | quote }}
(It is probably cleaner to not generate the comma at all, as #HarshManvar's answer proposes.)

How to concatenate variables inside a ternary statement?

I'm trying to do this:
name: {{ $value.enable | ternary $value.prefix $.Release.Namespace $value.suffix $value.override }}
But that syntax is wrong. I can't find any examples for how I would concatenate these vars together: $value.prefix $.Release.Namespace $value.suffix
Edit
I thought I could use print like this:
name: {{ true | ternary (print $value.prefix $.Release.Namespace $value.suffix) $value.fullnameOverride }}
But if you don't specify one of the fields it prints <nil> instead of not printing anything which is what I want.
Helm includes the Sprig template library which includes many useful composable parts.
For the "true" half, you have the three components; you'd like them joined together; but you'd like nil parts to be removed. The Sprig list function constructs a list from arbitrary items; compact takes a list and returns a new list without empty items (either empty string or nil, anything that's a Go zero value); and then join combines the list together into a single string. You can assign that to a temporary variable, and use it in the ternary call:
{{- $qualifiedName := list $value.prefix $.Release.Namespace $value.suffix | compact | join "" }}
name: {{ $value.enable | ternary $qualifiedName $value.fullnameOverride }}
I find the ternary syntax a little hard to read (even if it matches the C-style expr ? t : f syntax) and in this context it's not necessary. A helper template that spelled this out could be easier to understand later.
{{-/* Generate the name of the thing. Call with a list containing
the top-level Helm object and an item from the values file.
(Indented for readability, the template engine removes all of
the whitespace.) */-}}
{{- define "name" -}}
{{- $top := index . 0 -}}
{{- $value := index . 1 -}}
{{- if $value.enable -}}
{{- with $value.prefix -}}{{- . -}}{{- end -}}
{{- with $top.Release.Namespace -}}{{- . -}}{{- end -}}
{{- with $value.suffix -}}{{- . -}}{{- end -}}
{{- else -}}
{{- $value.fullnameOverride -}}
{{- end -}}
{{- end -}}
name: {{ include "name" (list $ .) }}