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

1

10

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?

Squires answered 7/8, 2019 at 20:17 Comment(0)
S
3

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! ;)

Squires answered 8/8, 2019 at 4:8 Comment(6)
any idea where this extra newline comes from between data: and first TOP_SECRET... ?Denby
@Denby I can't figure out why this newline is there. As you can see, I've used line chomping into the template like here {{- nindent 2 $secrets -}}, and also into the whole define "get-secrets-from-env-list" function. Good news is that k8s ignores this new line into manifests. It's annoying, but works. You can check out the whole template @ github: github.com/edgar-anascimento/awesome-chartSquires
the extra space is due to this line:{{ $secrets := include "get-secrets-from-env-list" (list .Values.env ) }} you could just do {{- $secrets := include "get-secrets-from-env-list" (list .Values.env ) -}}Everyday
@AnthonyPerot nor actually. I tried your suggestion, but nothing changed.Squires
Will replacing nindent by indent remove that annoying newline?Specular
yes @Specular with indent it doesn't add the newline! :D thanks for the suggestion!Squires

© 2022 - 2024 — McMap. All rights reserved.