Search code examples
kuberneteskubernetes-helmgo-templates

helper function not resolving correctly


Hi I am having a helm chart named test-service. I have a helper chart named helm-common-templates. my chart has dependency on the helm-common-templates. it has a function named "helm-common-templates.certificate-enabled" defined in it . The following is the function.

{{- define "helm-common-templates.certificate-enabled" -}}
{{- $val := "false" }}
{{- if .Values.global -}}
{{- if .Values.global.pms -}}
{{- if .Values.global.pms.logstash -}}
{{- if .Values.global.pms.logstash.tls -}}
{{- if .Values.global.pms.logstash.tls.enabled -}}
{{- $val := "true" }}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{ $val }}
{{- end -}}

The function basically return true if the property global.pms.logstash.tls.enabled is set to true else return false. In my main chart I am calling the function in a file named certificate.yaml

The following is the content of the file certificate.yaml

{{ if eq (include "helm-common-templates.certificate-enabled" .) "true" }}

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: ls-secret
  annotations:
    "helm.sh/hook": "post-delete"
    "helm.sh/hook-delete-policy": "before-hook-creation, hook-succeeded"
data:

---
{{end}}

if i give dry run i get the following output

helm upgrade --install --debug  test --namespace bcc --wait --timeout "10m0s"  --set global.pms.logstash.tls.enabled=true  . --dry-run

output

history.go:56: [debug] getting history for release test
Release "test" does not exist. Installing it now.
install.go:192: [debug] Original chart version: ""
install.go:209: [debug] CHART PATH: /home/prabpras/filebeat-testing/test-service

NAME: test
LAST DEPLOYED: Wed Nov  1 14:50:28 2023
NAMESPACE: bcc
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
global:
  pms:
    logstash:
      tls:
        enabled: true

COMPUTED VALUES:
global:
  kubernetes: {}
  pms:
    logstash:
      tls:
        enabled: true
  tls:
    enabled: true
    truststore: {}
  tracing:
    type: NoOp
helm-common-templates:
  global:
    kubernetes: {}
    pms:
      logstash:
        tls:
          enabled: true
    tls:
      enabled: true
      truststore: {}
    tracing:
      type: NoOp
HOOKS:
MANIFEST:

I could see that the secret resource in the certificate.yaml is not rendered in the dry run output. basically the function helm-common-templates.certificate-enabled always returns false.

I am also attaching the directory structure of my chart

test-service]$ tree
.
|-- Chart.yaml
|-- charts
|   `-- helm-common-templates
|       |-- Chart.yaml
|       `-- templates
|           `-- _helpers.tpl
|-- requirements.yaml
|-- templates
|   |-- NOTES.txt
|   |-- _helpers.tpl
|   `-- certificate.yaml
`-- values.yaml

appreciate any help. thank you


Solution

  • The core problem you're running into are that variable assignments $var := val are block-scoped in the Go template language. At an absolute minimum, a template like

    {{ $var := "foo" }}
    {{ if true }}
    {{ $var := "bar" }}
    {{ end }}
    {{ $var }}
    

    will always print out foo: the assignment inside the if statement creates a new variable.

    The template language allows reassigning an existing variable. This is similar to the distinction between := that creates a new variable and = that assigns an existing one in Go. If you remove the colon at the inside of the conditional it will reassign the variable

    {{- $val := "false" }}
    {{- if ... -}}
    {{- $val = "true" }}
    {{/*-    ^ no colon here -*/}}
    {{- end -}}
    {{ $val }}
    

    (This was added in Go 1.11, 5 years ago as of this writing, and it should work in current versions of Helm.)

    For the very-deeply-nested lookup, you might find it more convenient to use the dig template function, which will also tolerate missing layers of the values file (what happens if .Values.global.pms just doesn't exist?). That could look like

    {{- define "helm-common-templates.certificate-enabled" -}}
    {{- dig "global" "pms" "logstash" "tls" "enabled" "false" .Values -}}
    {{- end }}
    

    where "false" at the end is the default value if the value isn't present or is false (also zero, empty string, empty list, empty map).