how to replace numeric characters with their equivalent alphabetical strings, 0 replaced by Zero, 1 replaced by One and so on? - kubernetes-helm

im iterating over a list defined values.yaml, but the field im filling using the list contents doesn't accept numerical characters, so i want to replace numerical characters if found inside the range function, is there anyway to do that?
i didn't find a helm template function that offers this specific function
i tried ChatGPT lol ,it gave me examples of ways i can do it but it didn't work for me, kept saying that it can't recognize the functions used.
here's what it recommended
`
{{- import "strings" as strings -}}
{{- $newString := "" -}}
{{- $chars := "abcdefghijklmnopqrstuvwxyz" -}}
{{- range $i, $char := strings.split (string .Values.myString) "" -}}
{{- if reFind `[0-9]` $char -}}
{{- $newString = print $newString (index $chars (int $char)) -}}
{{- else -}}
{{- $newString = print $newString $char -}}
{{- end -}}
{{- end -}}
`

Related

Use defined variables from parent scope in a named template

I'm trying to provide idiomatic access to a value defined in a template to a named template being included. This much works:
# values.yml
versions:
- 1.2.3.4
- 5.6.7.8
# _helpers.tmpl
{{/*
Get the service path from the version string (passed as ".")
*/}}
{{- define "sample.servicePath" -}}
{{- $pat := "^[0-9]+\\.[0-9]+\\.([0-9]+)\\.[0-9]+$" }}
{{- $version := . | trimAll "\"" }}
{{- if regexMatch $pat $version }}
{{- regexReplaceAll $pat $version "${1}" }}
{{- else }}
{{- printf "Can't extract service number from version string %s" . | fail -}}
{{- end }}
{{- end }}
# sample.yml
{{- range $version := .Values.versions }}
{{- $servicePath := (include "sample.servicePath" $version) }}
# Here is the servicePath: {{ $servicePath }} which works
{{- end }}
But I imagined that this would also work:
# _helpers.tmpl (further down in the file)
{{- define "sample.labels" -}}
servicePath: {{ $servicePath }}
{{- end }}
# sample.yml
{{- range $version := .Values.versions }}
{{- $servicePath := (include "sample.servicePath" $version) }}
# Here is the servicePath: {{ $servicePath }} which still works
# but these labels: {{ include "sample.labels" . }} do not
{{- end }}
Ultimately I don't mind the implementation, I just need to be able to take a single list of values, range over them (to create multiple resources), and parse their value.
The Go text/template language, and by extension Helm charts, doesn't have global variables or dynamic scopes; you can't do this in the way you're suggesting. Each template invocation has its own scope, and the only things it can see are its single parameter . and any variables it declares locally.
However, Helm includes the Sprig extension library, which includes list and dict functions to create composite values. You can use these to pass multiple values into a template:
{{- define "sample.labels" -}}
{{- $top := index . 0 -}}
{{- $servicePath := index . 1 -}}
app.kubernetes.io/instance: {{ $top.Release.Name }}
servicePath: {{ $servicePath }}
{{ end -}}
{{- range $version := .Values.versions }}
{{- $servicePath := (include "sample.servicePath" $version) }}
{{- include "sample.labels" (list . $servicePath) }}
In the last line, we are invoking the template with a list of two parameters, the top-level Helm object (here as .) and the $servicePath local variable. The top of the sample.labels template then unpacks that back into two local variables within its own template, and then uses those to generate a reference set of labels.

helm template check for empty string

I have been asked to modify a Helm template to accommodate a few changes to check if a value is empty or not as in the code snippet below. I need to check $var.alias inside the printf in the code snippet and write custom logic to print a custom value. Any pointers around the same would be great.
{{- range $key, $value := .Values.testsConfig.keyVaults -}}
{{- range $secret, $var := $value.secrets -}}
{{- if nil $var.alias}}
{{- end -}}
{{ $args = append $args (printf "%s=/mnt/secrets/%s/%s" $var.alias $key $var.name | quote) }}
{{- end -}}
{{- end -}}
I decided to test what madniel wrote in his comment. Here are my files:
values.yaml
someString: abcdef
emptyString: ""
# nilString:
templates/test.yaml
{{ printf "someEmptyString=%q)" .Values.someString }}
{{ printf "emptyString=%q)" .Values.emptyString }}
{{ printf "nilString=%q)" .Values.nilString }}
{{- if .Values.someString }}
{{ printf "someString evaluates to true" }}
{{- end -}}
{{- if .Values.emptyString }}
{{ printf "emptyString evaluates to true" }}
{{- end -}}
{{- if .Values.nilString }}
{{ printf "nilString evaluates to true" }}
{{- end -}}
{{- if not .Values.emptyString }}
{{ printf "not emptyString evaluates to true" }}
{{- end -}}
{{- if not .Values.nilString }}
{{ printf "not nilString evaluates to true" }}
{{- end -}}
Helm template output:
➜ helm template . --debug
install.go:173: [debug] Original chart version: ""
install.go:190: [debug] CHART PATH: <REDACTED>
---
# Source: asd/templates/test.yaml
someEmptyString="abcdef")
emptyString="")
nilString=%!q(<nil>))
someString evaluates to true
not emptyString evaluates to true
not nilString evaluates to true
So yes, it should work if you use {{ if $var.alias }}

Use variable value with .Values in Helm

I've below parameters in values.yaml. I need to fetch the value of the schema but the database name may change
preparedDatabases:
a3s:
schemas:
a3s:
I'm using below functions in tpl to return the databasename and the schema name.
{{/* Return Databasename
*/}}
{{- define "databasename" }}
{{- range $key, $val := .Values.spec.preparedDatabases -}}
{{- $key | toYaml | trim }}
{{- end -}}
{{- end -}}
{{/* Return Schemaname
*/}}
{{- define "schema" }}
{{- $dbname := include "databasename" . }}
{{- range $key, $val := ( .Values.spec.preparedDatabases.{{ $dbname }}.schemas) -}}
{{- $key | toYaml | trim }}
{{- end -}}
{{- end -}}
But it returns the error bad character U+0024 '$'
Could you please help on how can i interpret the variable dbname to be used with .Values
Thanks in advance

Mapping a value in Helm 3 to another value

I'm building a Helm 3 library chart and would like to convert an input value to another value that's based on a preset map.
Say my values.yaml includes the following value:
global:
environment: production # (production/staging/test/development)
I have the following convention for converting a long environment name to a short one:
production => prod
staging => stage
test => test
development => dev
I would like to use the value stored in .Values.global.environment to generate a deployment name that is prefixed with the short environment name. In this case, it should be mapped to
prod-<application_name>.
How can this be achieved with Helm 3?
Add a helper function under templates/_helpers.tpl file.
Unfortunately, there's no switch functionality in go templates so it has to be "dirty" if else
{{/*
Environment name mapping
*/}}
{{- define "my-chart.environment" -}}
{{- if .Values.global.environment -}}
{{- if eq .Values.global.environment "production" -}}
{{- printf "prod" -}}
{{- else if eq .Values.global.environment "staging" -}}
{{- printf "stage" -}}
{{- else if eq .Values.global.environment "test" -}}
{{- printf "test" -}}
{{- else if eq .Values.global.environment "development" -}}
{{- printf "dev" -}}
{{- end -}}
{{- end -}}
{{- end -}}
then, use this template in the my-chart.fullname template
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "my-chart.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
##### ADDITIONAL LINES
{{- if .Values.global.environment -}}
{{- printf "%s-%s-%s" (include "my-chart.environment" .) .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
##### END ADDITIONAL LINES
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
Test:
/apps/my-chart # helm version
version.BuildInfo{Version:"v3.1.2", GitCommit:"d878d4d45863e42fd5cff6743294a11d28a9abce", GitTreeState:"clean", GoVersion:"go1.13.8"}
/apps/my-chart # cat ./values.yaml
# Default values for my-chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
global:
environment: development
Running helm template .
output:
...
...
# Source: my-chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dev-RELEASE-NAME-my-chart
...
...

Helm: generate comma separated list

Using Helm templates, I'm trying to generate a list of server names based on a number in values.yaml. The dot for this template is set to the number (its a float64).
{{- define "zkservers" -}}
{{- $zkservers := list -}}
{{- range int . | until -}}
{{- $zkservers := print "zk-" . ".zookeeper" | append $zkservers -}}
{{- end -}}
{{- join "," $zkservers -}}
{{- end -}}
For an input of, say, 3 I'm expecting this to produce:
zk-0.zookeeper,zk-1.zookeeper,zk-2.zookeeper
It produces nothing.
I understand that the line within the range block is a no-op since the variable $zkservers is a new variable each time the loop iterates. It is not the same variable as the $zkservers in the outer scope.
I hope the intention is clear of what I want to do. I am at a loss how to do it.
Anyone know how to do this with Helm templates?
For those from 2020+ it now can be achieved as simple as that:
{{ join "," .Values.some.array }}
It produces the correct output:
value: "test1,test2,test3"
At least it works with (more or less) recent versions of helm-cli:
Client: &version.Version{SemVer:"v2.16.2", GitCommit:"bbdfe5e7803a12bbdf97e94cd847859890cf4050", GitTreeState:"clean"}
Another quick way of doing it:
{{- define "helm-toolkit.utils.joinListWithComma" -}}
{{- $local := dict "first" true -}}
{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}}
{{- end -}}
If you give this input like:
test:
- foo
- bar
And call with:
{{ include "helm-toolkit.utils.joinListWithComma" .Values.test }}
You'll get the following rendered:
foo,bar
This is from OpenStack-Helm's Helm-toolkit chart, which is a collection of utilities for similar purposes.
I faced with the same problem and your solution with dictionary saved my day. It's a good workaround and it can be just a little simpler:
{{- define "zkservers" -}}
{{- $zk := dict "servers" (list) -}}
{{- range int . | until -}}
{{- $noop := printf "zk-%d.zookeeper" . | append $zk.servers | set $zk "servers" -}}
{{- end -}}
{{- join "," $zk.servers -}}
{{- end -}}
You're currently defining a new varialbe in the scope of the list while you want to alter the existing value.
In order to fix your bug, you only need to change the way you assign the value to $zkservers:
- {{- $zkservers := print "zk-" . ".zookeeper" | append $zkservers -}}
+ {{- $zkservers = print "zk-" . ".zookeeper" | append $zkservers -}}
which gives you the following script:
{{- define "zkservers" -}}
{{- $zkservers := list -}}
{{- range int . | until -}}
{{- $zkservers = print "zk-" . ".zookeeper" | append $zkservers -}}
{{- end -}}
{{- join "," $zkservers -}}
{{- end -}}
With this slight modification, {{ include "zkservers" 3 }}gives you the output zk-0.zookeeper,zk-1.zookeeper,zk-2.zookeeper
I was doing the same but on elasticsearch helm chart. Please find my example
values.yml:
...
replicaCount: 3
...
StatefulSets.yaml:
...
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.registry_address }}/{{ .Values.image.name }}:{{ .Chart.AppVersion }}"
env:
- name: ELASTICSEARCH_CLUSTER_NAME
value: "{{ .Values.env.ELASTICSEARCH_CLUSTER_NAME }}"
- name: ELASTICSEARCH_DISCOVERY_ZEN_PING_UNICAST_HOSTS
value: "{{ template "nodes" .Values }}"
...
_helpers.tpl:
{{/* vim: set filetype=mustache: */}}
{{- define "nodes" -}}
{{- $nodeCount := .replicaCount | int }}
{{- range $index0 := until $nodeCount -}}
{{- $index1 := $index0 | add1 -}}
elasticsearch-{{ $index0 }}.elasticsearch{{ if ne $index1 $nodeCount }},{{ end }}
{{- end -}}
{{- end -}}
This produces a comma separated list:
...
- name: ELASTICSEARCH_DISCOVERY_ZEN_PING_UNICAST_HOSTS
value: "elasticsearch-0.elasticsearch,elasticsearch-1.elasticsearch,elasticsearch-2.elasticsearch"
...
I got it working using:
{{- define "zkservers" -}}
{{- $dot := dict "nodes" (int .) "servers" (list) -}}
{{- template "genservers" $dot -}}
{{- join "," $dot.servers -}}
{{- end -}}
{{- define "genservers" -}}
{{- range until .nodes -}}
{{- $noop := print "zk-" . ".zookeeper" | append $.servers | set $ "servers" -}}
{{- end -}}
{{- end -}}
Seems a little bit verbose for what should normally be a simple one/two liner :)
How about just rendering and then trimming?
{{- include "template" . | trimSuffix "," -}}