Capt
Capt

Reputation: 39

Helm Templating in Configmap for values.yaml

I"m looking for help to create a generic configmap.yaml that can support several services.

values.yaml (THIS WORKS)

value1:  val1

genericConfigMapProperties:
  application.properties: |-
    prop1=prop1value
    prop2=prop2value

configmap.yaml

apiVersion: 1
kind: ConfigMap
...
...
data:
{{ (toYaml .Values.genericConfigMapProperties)  . | ident 4 }}

The template {{ (toYaml .Values.genericConfigMapProperties) . | ident 4 }} is almost perfect. It renders application.properties correctly:

data:
  application.properties: |-
    prop1=prop1value
    prop2=prop2value

values.yaml (THIS DOES NOT WORK)

value1:  val1

genericConfigMapProperties:
  cmValue1: {{ .Values.value1 | default "default val1" | quote }}

  application.properties: |-
    prop1=prop1value
    prop2=prop2value

It is getting errors rendering cmValue1. I am expecting this answer:

data:
  cmValue1: val1

  application.properties: |-
    prop1=prop1value
    prop2=prop2value

Errors:

Error: failed to parse values.yaml: error converting YAML to JSON: yaml: invalid map key: map[interface {}]interface {}{".Values.value1 | default \"default val1\" | quote":interface {}(nill)}
helm.go:88: [debug]  error converting YAML to JSON: yaml: invalid map key: map[interface {}]interface {}{".Values.value1 | default \"default val1\" | quote":interface {}(nill)}
failed to parse values.yaml

What additional helm template code do I need to support cmValue1 rendering?

Thank you.

Upvotes: 1

Views: 9958

Answers (2)

Capt
Capt

Reputation: 39

Thank you for responding.

I've found this awesome solution from bitnami common templates. It works just about anywhere.

https://github.com/bitnami/charts/blob/master/bitnami/common/templates/_tplvalues.tpl

Copy this template file:

{{/* vim: set filetype=mustache: */}}
{{/*
Renders a value that contains template.
Usage:
{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }}
*/}}
{{- define "common.tplvalues.render" -}}
    {{- if typeIs "string" .value }}
        {{- tpl .value .context }}
    {{- else }}
        {{- tpl (.value | toYaml) .context }}
    {{- end }}
{{- end -}}

Use it to template any values in configmap.yaml or deployment.yaml or anywhere else...

values.yaml:

configMapProperties:
  cmValue1: "val1"
  application.properties: |-
    prop1=prop1value
    prop2=prop2value

configmap.yaml

data:
    {{- if .Values.configMapProperties }}
    {{- include "common.tplvalues.render" ( dict "value" .Values.configMapProperties "context" $ ) | nindent 2 }}
    {{- end }}

Upvotes: 1

z.x
z.x

Reputation: 2507

Helm does not support secondary rendering, but you can use yaml anchor to achieve this function, or indirectly by using named templates.

Plan A : anchor

values.yaml

value1: &value1 val1

genericConfigMapProperties:
  cmValue1: *value1

  application.properties: |-
    prop1=prop1value
    prop2=prop2value

templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  config.yaml: |
    {{- toYaml $.Values.genericConfigMapProperties | nindent 4 }}

output

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  config.yaml: |
    application.properties: |-
      prop1=prop1value
      prop2=prop2value
    cmValue1: val1

Plan B: Named Template

values.yaml

value1: val1

templates/_helpers.tpl

{{/*
cmValue template
*/}}
{{- define "genericConfigMapProperties" -}}
cmValue1: {{ .Values.value1 | default "default val1" | quote }}
application.properties: |-
  prop1=prop1value
  prop2=prop2value
{{- end -}}

templates/configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  config.yaml: |
     {{- include "genericConfigMapProperties" . | nindent 4 }}

output

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data: 
  config.yaml: |
    cmValue1: "val1"
    application.properties: |-
      prop1=prop1value
      prop2=prop2value

Upvotes: 1

Related Questions