Helm template - how to use "if exists at least one of" in array?

8/7/2019

I'm trying to make a list of env vars from a values.yaml become a single secret.yaml file containing the list of envs of the type "secret". The idea is to only create this secret file if at least one of the types equals "secret".

Eg:

values.yaml

env:
  - name: PLAIN_TEXT_ENV_VAR1
    type: plain
    value: text value
  - name: PLAIN_TEXT_ENV_VAR2
    type: plain
    value: text value
  - name: TOP_SECRET_ENV_VAR_1
    type: secret
  - name: TOP_SECRET_ENV_VAR_2
    type: secret
  - name: TOP_SECRET_ENV_VAR_3
    type: secret

resulting secret.yaml

kind: Secret
metadata:
  name: test
data:
    TOP_SECRET_ENV_VAR_1: change_me
    TOP_SECRET_ENV_VAR_2: change_me
    TOP_SECRET_ENV_VAR_3: change_me

I've already tried to create some flow control using range to iterate, boolean variables and if statements, but go template seems to ignore my ifs after I change it to another value. Now my secret template is like the one below.

{{ $flowcontrol := true -}}
{{ if $flowcontrol -}}
{{ range $env := $.Values.env -}}
{{ if eq $env.type "secret" -}}
apiVersion: v1
kind: Secret
metadata:
  name: testsecret
data:
    {{- range $env := $.Values.env }}
        {{- if eq $env.type "secret" }}
    {{ $env.name }}: "change_me" 
        {{- end }}
    {{- end }}
{{ $flowcontrol := false }}
{{ end -}}
{{ end -}}
{{ end -}}

It results in three replicated secret.yaml files with 3 variables:

$ helm template . 
---
# Source: teste/templates/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: testsecret
data:
    TOP_SECRET_ENV_VAR_1: "change_me"
    TOP_SECRET_ENV_VAR_2: "change_me"
    TOP_SECRET_ENV_VAR_3: "change_me"

apiVersion: v1
kind: Secret
metadata:
  name: testsecret
data:
    TOP_SECRET_ENV_VAR_1: "change_me"
    TOP_SECRET_ENV_VAR_2: "change_me"
    TOP_SECRET_ENV_VAR_3: "change_me"

apiVersion: v1
kind: Secret
metadata:
  name: testsecret
data:
    TOP_SECRET_ENV_VAR_1: "change_me"
    TOP_SECRET_ENV_VAR_2: "change_me"
    TOP_SECRET_ENV_VAR_3: "change_me"

How can one control the flow as: if the first one item of a list satisfies the condition, iterate through the rest of the same list only in another section after?

-- Edgar
go-templates
kubernetes-helm

1 Answer

8/8/2019

I've managed to create this feature! :D

Basicaly i've created a "template function" using define which iterates the env list from values.yaml and writes a string containing only the envs which the type property matches the word "secret". Then I call that function using include and assign it's output to a variable.

If the variable length is greater than 0 (meaning it's not an empty string), the secret file is created and then I use the same string to fill the data property.

Here's the code containing the function and the secret template:

{{- define "get-secrets-from-env-list" -}}
    {{- $allenv := index . 0 -}}
    {{- range $i, $scrts := $allenv -}}
        {{- if eq $scrts.type "secret" -}}
            {{- nindent 0 $scrts.name -}}: {{ "change_me" | b64enc -}}
        {{- end -}}
    {{- end -}}
{{- end -}}

{{ $secrets := include "get-secrets-from-env-list" (list .Values.env ) }}

{{- if gt (len $secrets) 0 -}}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: {{ include "awesome-chart.fullname" $ }}
  labels:
    app.kubernetes.io/name: {{ include "awesome-chart.name" $ }}
    helm.sh/chart: {{ include "awesome-chart.chart" $ }}
    app.kubernetes.io/instance: {{ $.Release.Name }}
    app.kubernetes.io/managed-by: {{ $.Release.Service }}
data:
    {{- nindent 2 $secrets -}}
{{- end -}}%                                                                                                                                                                                                         

Here's a sample output:

$ helm template .          
---
# Source: awesome-chart/templates/secret.yaml
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-app
  labels:
    app.kubernetes.io/name: awesome-chart
    helm.sh/chart: awesome-chart
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/managed-by: Tiller
data:

  TOP_SECRET_ENV_VAR_1: Y2hhbmdlX21l
  TOP_SECRET_ENV_VAR_2: Y2hhbmdlX21l
  TOP_SECRET_ENV_VAR_3: Y2hhbmdlX21l

Works like a charm! ;)

-- Edgar
Source: StackOverflow