Is there a way to keep randAlphaNum values consistent in subcharts in Helm?
Asked Answered
L

3

7

I have a main chart that generates a random password in _helpers.ptl. This random password needs to be used by several subcharts (db and app).

In _helpers.ptl of the main chart:

{{/* Generate db credentials */}}
{{- define "test.dbCredentials" -}}
dbUser: {{ randAlphaNum 16 | quote }}
dbPass: {{ randAlphaNum 32 | quote }}
{{- end }}

configmap.yml of the main chart:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  {{- include "test.dbCredentials" . | nindent 2 }}

configmap.yml of the subchart:

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  {{- include "test.dbCredentials" . | nindent 2 }}

When I debug this, the credentials for main and subcharts are different. Is there a way to generate random values in main, and pass the exact values to several subcharts?

Luckin answered 10/8, 2020 at 21:47 Comment(0)
C
3

I managed to find a solution by storing generated random string inside .Release object. Unlike .Values, it seems to remain the same for the main chart and subharts. Also, in my case it was the subchart who generated the password, but it think it should work either way:

{{- define "generate_static_password" -}}
{{- /* Create "tmp_vars" dict inside ".Release" to store various stuff. */ -}}
{{- if not (index .Release "tmp_vars") -}}
{{-   $_ := set .Release "tmp_vars" dict -}}
{{- end -}}
{{- /* Some random ID of this password, in case there will be other random values alongside this instance. */ -}}
{{- $key := printf "%s_%s" .Release.Name "password" -}}
{{- /* If $key does not yet exist in .Release.tmp_vars, then... */ -}}
{{- if not (index .Release.tmp_vars $key) -}}
{{- /* ... store random password under the $key */ -}}
{{-   $_ := set .Release.tmp_vars $key (randAlphaNum 20) -}}
{{- end -}}
{{- /* Retrieve previously generated value. */ -}}
{{- index .Release.tmp_vars $key -}}
{{- end -}}
Commensurable answered 13/3, 2023 at 14:26 Comment(3)
This works for me. I haven't found another way to reuse a random password in multiple charts, and the different password per release name is genius. Thank you!Bocanegra
How to use this code?Murray
What an ingenious workaround, solved my problem perfectlyPsephology
M
1

I found an answer that creates true random data and is consistant for every upgrade. You can use the lookup function:

{{- $secretName := printf "%s-%s" (include "mychart.fullname" .) "random" -}}
apiVersion: v1
kind: Secret
metadata:
  name: {{ $secretName }}
  labels:
    app: {{ template "mychart.fullname" . }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    release: "{{ .Release.Name }}"
data:
  {{- if (lookup "v1" "Secret" .Release.Namespace $secretName).data }}
  token: {{ (lookup "v1" "Secret" .Release.Namespace $secretName).data.token }}
  {{ else }}
  token: {{ randAlphaNum 16 | b64enc }}
  {{ end }}

It checks if the Secret already exists, if not it generates a random string.

NOTE: This does not work on dry-runs or helm template commands since it need access to the cluster. You also need to have access to read and modify secrets.

Mango answered 3/5 at 19:10 Comment(0)
P
0

I needed to do something very similar: generate a random password and then storing it as a secret, but at the same time hashing it with bcrypt for the deployment itself. After trying absolutely everything, including all the solutions described here and here, the only way i found to make this work is to use a single file. In my case i had to create the password, the hash, the secret and the deployment in the same chart. Here is an example extract of how i did it:

{{- $adminPassword := randAlphaNum 42 -}}

# This secret is used to store the user credentials generated.
apiVersion: v1
kind: Secret
metadata:
    name: "{{ include "app.fullname" . }}-passwords"
    labels:
    {{- include "app.labels" . | nindent 4 }}
type: Opaque
data:
    adminpassword: {{ $adminPassword | b64enc | quote }}

---

# Main Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
    name: "{{ include "app.fullname" . }}"
spec:
    replicas: 1
    template:
        spec:
            containers:
                - name: "{{ include "app.fullname" . }}-instance"
                  image: "{{ .Values.image.name }}"
                  env:
                      # Full admin user.  
                      - name: USERS_ADMIN_USERNAME
                        value: {{ .Values.authentication.users.adminUsername  | quote}}
                      - name: USERS_ADMIN_PASSWORD
                        value: {{(htpasswd "BCRYPT" $adminPassword )  | quote }}
Postmark answered 24/11, 2021 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.