Helm Chart environment from values file - kubernetes

I have the following values file:
MYVAR: 12123
MYVAR2: 214123
I want to iterate over them and use them as env variables in my deployment template:
env:
{{- range .Values.examplemap }}
- name: {{ .name }}
value: {{ .value }}
{{- end }}
I tried this

For iterate over a map in helm you can try put this in the values.yaml
extraEnvs:
- name: ENV_NAME_1
value: value123
- name: ENV_NAME_2
value: value123
So in your template you must iterate the extraEnvs like this:
extraEnvs:
{{- range .Values.image.extraEnvs }}
- name: {{ .name | quote }}
value: {{ .value | quote }}
{{- end }}

In the core Go text/template language, the range operator can iterate over either a list or a map. There's specific syntax to assign the key-value pairs in a map to local variables:
env:
{{- $k, $v := range .Values.examplemap }}
- name: {{ $k }}
value: {{ $v }}
{{- end }}

Related

how to loop through in Helm chart

I was trying to iterate through my values.yaml file objects
values.yaml
keyvault:
name: mykv
tenantId: ${tenantId}$
clientid: "#{spid}#"
clientsecret: "#{spsecret}#"
secrets:
- secret1
- secret2
- secret3
So here my requiremnt is to loopthrough each item of above "secrets" to below serviceproviderclass templates, "Data" and objectName fields. But its failing.
What I tried is as below.
{{- define "commonobject.secretproviderclass.tpl" -}}
{{- if eq .Values.secret.enabled true }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ $.Release.Name }}-secretproviderclass
labels:
app: {{ $.Release.Name }}
chart: "{{ $.Release.Name }}-{{ .Chart.Version }}"
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
provider: azure
secretObjects:
- data:
{{- range $key, $value := .Values.keyvault }}
{{- range $value.secret }}
- key: { . }
{{- end }}
{{- end }}
secretName: {{ .Values.secret.keyvault.name }}
type: opaque
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "false"
userAssignedIdentityID: ""
keyvaultName: {{ .Values.keyvault.name }}
objects: |
array:
{{- range $key, $value := .Values.keyvault }}
{{- range $value.secret }}
- |
objectName: {{ . }}
objectType: secret
{{- end }}
{{- end }}
tenantId: {{ .Values.keyvault.tenantid }}
{{- end }}
{{- end -}}
{{- define "commonobject.secretproviderclass" -}}
{{- template "commonobject.util.merge" (append . "commonobject.secretproviderclass.tpl") -}}
{{- end -}}
In your values.yaml file, .Values.keyvault is a single object that has keys name, secrets, etc. If you want to iterate through its secrets you just need a single range loop to do that.
secretObjects:
- data:
{{- range .Values.keyvault.secrets }}{{/* <-- only one range loop */}}
- key: { . }
{{- end }}
secretName: {{ .Values.secret.keyvault.name }}
type: opaque
In the double loop you have now, $key and $value get set to each pair from .Values.keyvault in sequence; clientid and #{spid}#, clientsecret and #{spsecret}#, and so on; and then you try to iterate through those (often string-valued) values. For this use you don't need the outer loop.

Helm pass range of properties

I'm tring to pass values ( the description can be ["First description","Second description"], but is the same).
templates:
description:
- First description
- Second description
name:
- First name
- Second name
references:
- First reference
- Second reference
for template property:
templates:
- description: First description
name: First name
references:
- First reference
- description: Second description
name: Second name
references:
- Second reference
I tried with
{{- range $key,$values := .Values.templates }}
- {{ $key }}: {{$values}}
{{ $key }}: {{$values}}
{{ $key }}: {{$values}}
{{- end }}
but I'm far from the result.
Need some logical judgment to achieve, this conversion is not a good solution
values.yaml
templates:
description:
- "First-description"
- "Second-description"
- "33333-description"
name:
- "First-name"
- "Second-name"
- "333-name"
references:
- "First-reference"
- "Second-reference"
- "3333-reference"
templateX.yaml
templates:
{{- if $.Values.templates }}
{{- range $i, $_ := $.Values.templates.name }}
{{- range $k, $v := $.Values.templates }}
{{- if eq $k "description" }}
- {{ $k }}: {{ index $v $i }}
{{- else if eq $k "references" }}
{{ $k }}:
- {{ index $v $i }}
{{- else }}
{{ $k }}: {{ index $v $i }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
A better way is to try to update the definition format of the data in values.yaml
like this:
values.yaml
templates:
- description: First-description
name: First-name
references:
- First-reference
- description: Second-description
name: Second-name
references:
- Second-reference
- description: 3333-description
name: 3333-name
references:
- 3333-reference
- description: 4444-description
name: 4444-name
references:
- 4444-reference
templateX.yaml
templates:
{{- toYaml $.Values.templates | nindent 2 }}
How to set these parameters with --set. Example:
I want when add --set number=First and
--set number=Second
This number to be set for all words where I have First and Second.
templates:
- description: First-description
name: First-name
references:
- First-reference
- description: Second-description
name: Second-name
references:
- Second-reference

Transform a helm dict into a list

I'm using a Helm chart to control what environment variables are set for a certain container in a deployment.
In my Values.yaml, I have an entry called env which is a dictionary:
image:
repository: xxxx.yyyyy.com/myimage
pullPolicy: IfNotPresent
# Enviroment variables that will be passed to the container.
env: {}
Now, I'll pass variables to the env dict using --set:
helm upgrade mydeployment chart --set env.VARIABLE=test
However, this must be transformed into a list to adhere to Kubernetes yaml:
spec:
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
# This should come from that dict
env:
- name: VARIABLE
value: "test"
I don't know how to use the template language from Helm (sprig / go) to achieve that. Is it even possible?
To iterate through the map, the core Go text/template language provides a range keyword that can iterate through maps or arrays.
{{ range $key, $value := .Values.env }}
...
{{ end }}
Inside of this you can put arbitrary text. Helm doesn't require this to be any particular kind of YAML construct, just so long as the final result is valid YAML. For this setup a typical loop would look like
env:
{{- range $key, $value := .Values.env }}
- name: {{ quote $key }}
value: {{ quote $value }}
{{- end }}
You do need to be careful with indentation here. As a rule of thumb it often will work to include a - "swallow whitespace" indicator inside the open {{ and to not include one inside the close }}. The - name: must be at least as indented as the env: above it (ignoring the range line), and value: must be aligned with name:. I might put all of the template-language lines (the range and end) starting at the first column, even if they're embedded in a structure that's nested more.
spec:
template:
spec:
containers:
- name: {{ template "chart.fullname" . }}
env:
{{- range $key, $value := .Values.env }}
- name: {{ quote $key }}
value: {{ quote $value }}
{{- end }}
image: {{ .Values.registry }}/{{ .Values.image }}:{{ .Values.tag }}

How do I get the name of a parent element from my values.yaml in a Helm template?

I have a section in my values.yaml that looks like this:
env:
normal:
ENV_VAR_1: value
ENV_VAR_2: otherValue
secret:
secret-location:
ENV_VAR_USERNAME: username
ENV_VAR_PASSWORD: password
different-secret:
ENV_CONN_STRING: my_conn_string
I have a _helpers.tpl function like so:
{{/*
Add environment variables
*/}}
{{- define "helpers.list-env-variables" }}
{{- range $key, $val := .Values.env.normal }}
- name: {{ $key }}
value: {{ $val }}
{{- end }}
{{- range $name := .Values.env.secret }}
{{- }}
{{- range $key, $val := $name }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ $name }}
key: {{ $val }}
{{- end }}
{{- end }}
{{- end }}
and it's called in the deployment.yaml like you'd expect:
env:
{{- include "helpers.list-env-variables" . | indent 12 }}
So the normal environment variables get added just fine, but the secret ones don't. It specifies the secretKeyRef.name: value as map[ENV_VAR_USERNAME:username ENV_VAR_PASSWORD:password] instead of secret-key-ref.
helm debug output:
...
env:
- name: ENV_VAR_1
value: value
- name: ENV_VAR_2
value: otherValue
- name: ENV_VAR_PASSWORD
valueFrom:
secretKeyRef:
name: map[ENV_VAR_USERNAME:username ENV_VAR_PASSWORD:password]
key: password
- name: ENV_VAR_USERNAME
valueFrom:
secretKeyRef:
name: map[ENV_VAR_USERNAME:username ENV_VAR_PASSWORD:password]
key: username
- name: ENV_CONN_STRING
valueFrom:
secretKeyRef:
name: map[ENV_CONN_STRING:my_conn_string]
key: my_conn_string
I've already got all these secrets loaded into my K8s cluster (they get shared across a number of microservices, so I don't need to add new secrets which is what the default Helm template seems to want to do) - I just need to reference existing secrets.
My assumption here is that there's something I'm missing in my function to get the value of an element (e.g. "secret-location"), I just can't figure out what it is. If there's a different way I can structure my values.yaml to accomplish this, I'm game for that as well.
When obtaining secret data, it can also be obtained in the form of key-val.
Try replacing _helpers.tpl with the following
{{/*
Add environment variables
*/}}
{{- define "helpers.list-env-variables" }}
{{- range $key, $val := .Values.env.normal }}
- name: {{ $key }}
value: {{ $val }}
{{- end }}
{{- range $k, $v := .Values.env.secret }}
{{- }}
{{- range $key, $val := $v }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ $k }}
key: {{ $val }}
{{- end }}
{{- end }}
{{- end }}

Helm iterate over keys

I'm trying to iterate over list of secrets in my values files and mount it as env variables on the pods but having hard time with it.
The helm template command which spits the sample template lists the keys & value as I expect it to be but when i deploy only the "name" key gets mounted on the pods but nothing after that like the valuefrom and secretkeyref. Really appreciate any help on this :)
**DEPLOYMENT YAML**
{{- if $root.Values.secrets }}
{{- range $secrets := $root.Values.secrets }}
{{- range $data := $secrets.data }}
- name: {{ $data.name }}
valuefrom:
secretKeyRef:
name: {{ $secrets.name }}
key: {{ $data.name }}
{{ end }}
{{ end }}
{{ end }}
secrets:
- name: aws-secrets
data:
- key: "secret1"
name: DATABASE_HOST
- key: "secret2"
name: DATABASE_NAME
I fat fingered should be "valueFrom". 🤦