how to loop through in Helm chart - kubernetes-helm

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.

Related

Helm iterate over nested list and added output in yaml with decoded value

I have a bunch of secretKey in values.yaml like below. I need to add each value of secretKey as a key and decoded value in template.data like as a value like below.
How can I achieve this ?
{{- range $externalSecretName, $externalSecret := .Values.externalSecrets }}
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ $externalSecretName }}
spec:
refreshInterval: 1m
secretStoreRef:
name: secret
kind: SecretStore
target:
name: {{ $externalSecretName }}
creationPolicy: Owner
template:
data:
## Needs to insert/add each secretKey value here like below
{
keyname1: "{{ .keyname1 | b64dec }}".
keyname2: "{{ .keyname2 | b64dec }}".
}
data:
{{- toYaml $externalSecret.data | nindent 4 }}
---
{{- end }}
values.yaml:
===========
extraEnvSecret:
fromSecret:
name: master-tf-address-handling
data:
PREFIX_KEYNAME1: keyname1
PREFIX_KEYNAME2: keyname2
externalSecrets:
demo-app:
data:
- secretKey: keyname1
remoteRef:
key: value1
- secretKey: keyname2
remoteRef:
key: value1
{{- range $externalSecretName, $externalSecret := .Values.externalSecrets }}
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ $externalSecretName }}
spec:
refreshInterval: 1m
secretStoreRef:
name: secret
kind: SecretStore
target:
name: {{ $externalSecretName }}
creationPolicy: Owner
template:
data:
{
{{- range $externalSecret.data }}
{{ .secretKey }}: "{{ .remoteRef.key | b64enc }}",
{{- end }}
}
data:
{{- toYaml $externalSecret.data | nindent 4 }}
{{- end }}

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 }}

Why helm template function is not resolveing $labels var?

I am defining a PrometheusRule as follow:
prometheusRule:
rules:
- alert: SSLCertExpiringSoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 10
for: 0m
labels:
severity: warning
annotations:
summary: Blackbox SSL certificate will expire soon (instance {{ $labels.instance }})
description: "SSL certificate expires in 30 days\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
And the template yml from helm chart:
{{- if .Values.prometheusRule.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ template "prometheus-blackbox-exporter.fullname" . }}
{{- with .Values.prometheusRule.namespace }}
namespace: {{ . }}
{{- end }}
labels:
{{- include "prometheus-blackbox-exporter.labels" . | nindent 4 }}
{{- with .Values.prometheusRule.additionalLabels -}}
{{- toYaml . | nindent 4 -}}
{{- end }}
spec:
{{- with .Values.prometheusRule.rules }}
groups:
- name: {{ template "prometheus-blackbox-exporter.name" $ }}
rules: {{ tpl (toYaml .) $ | nindent 8 }}
{{- end }}
{{- end }}
when I run helm template, tpl func it is not resolving the $labels and $values vars. When I remove annotations then the helm template is not complaining anymore. Where do fail?
error:
Error: template: prometheus-blackbox-exporter/templates/prometheusrule.yaml:18:16: executing "prometheus-blackbox-exporter/templates/prometheusrule.yaml" at <tpl (toYaml .) $>: error calling tpl: error during tpl function execution for "- alert: SSLCertExpiringSoon\n annotations:\n summary: Blackbox SSL certificate will expire soon (instance {{ $labels.instance\n }})\n expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 10\n for: 0m\n labels:\n release: prometheus\n severity: warning\n- alert: SSLCertExpiringSoon\n annotations: null\n expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 3\n for: 0m\n labels:\n severity: critical": parse error at (prometheus-blackbox-exporter/templates/prometheusrule.yaml:3): undefined variable "$labels"
Prometheus's alerting rules also use {{ ... $variable ... }} syntax, similar to Helm but with a different variant on the Go text/template syntax. When you pass this file through tpl, Helm tries to evaluate the embedded {{ ... }} template and evaluate any blocks there. Since $labels and $value aren't local variables defined at the Helm level, you get this error.
If you just want Prometheus to see this file as-is, and you don't need to replace anything at the Helm level (the file doesn't include references to .Values) then you don't need tpl
rules: {{ toYaml . | nindent 8 }}
If you do need tpl, then inside the included file you need to cause {{ to be emitted as a string and not processed as a template. One syntactic approach to it is to create a template block that prints out {{:
description: "VALUE = {{ "{{" }} $value }}"
# ^^^^^^^^^^ a {{ ... }} block that prints "{{"
The working version of syntax is as follow:
{{ `{{` }} $value }}

Helm Chart environment from values file

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 }}

Helm: overloading global variables on {{ include }} call?

I have a shared metadata block, based on the commons library that I would like to override a name for one specific instance. Is it possible?
metadata:
{{ include "common.metadata" (merge (dict ".Values.fullnameSuffix" "-redirect") .) }} # Doesn't work - How do I add a `-redirect` suffix?
name: {{ include "common.fullname" . }}-redirect # Causes two `name:` attributes
Within common.metadata there is a call to "fullname" as well:
{{ define "common.metadata" -}}
name: {{ template "common.fullname" . }}
namespace: {{ .Release.Namespace }}
{{- end -}}
Is there a way to pass-down a variable override from the first include so that I can override the name:? It's specific only to this chart.
Use set to add a new key/value pair to a dictionary and pass it to slightly modified common.metadata helper function.
values.yaml
fullnameSuffix: redirect
_helpers.tpl
{{- define "common.metadata" -}}
{{- if .suffix }}
name: {{ template "common.fullname" . }}-{{ .suffix }}
{{- else }}
name: {{ template "common.fullname" . }}
{{- end }}
namespace: {{ .Release.Namespace }}
{{- end -}}
manifest.yaml
metadata:
{{- include "common.metadata" (set . "suffix" .Values.fullnameSuffix ) }}
If your fullnameSuffix is empty, name without suffix will be used.