Search code examples
templatesyamlkubernetes-helmargocd

Helm tpl template yaml object without using a string


Heaving some trouble getting something to work in the argo-helm helm chart.

I am trying to make use of the very conveinet extraObjects value in their argo-cd chart.

Setup

values.yaml

extraObjects:
  - apiVersion: v1
    kind: ConfigMap
    metadata:
      labels: "{{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | nindent 4 | trim }}"
      name: some-config-map
    data:
      something: something

template/extra-manifests.yaml

{{ range .Values.extraObjects }}
---
{{ tpl (toYaml .) $ }}
{{ end }}

Result

sadly it will produce

# Source: argo-cd/templates/extra-manifests.yaml
apiVersion: v1
data:
  something: something
kind: ConfigMap
metadata:
  labels: '
    helm.sh/chart: argo-cd-5.19.12
    app.kubernetes.io/name: some-config-map
    app.kubernetes.io/instance: argocd
    app.kubernetes.io/component: configmap
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/part-of: argocd'
  name: some-config-map
---

The problem

This is unsurprising really. We put the template into a string so it makes sense that we see a string with the templated content.

I want the template to "float" on the labels field. But I can't do that because {{ blablaba }} isnt a vaild yaml object. (Or it is but {} is object notation)

Because they are using the toYaml function to turn a valid YAML object into a string for use in the tpl function, I can't represent the template any other way other than using the string.

What I've tried

Comment Trick?

labels: # {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | nindent 4 | trim }}

Thought becuse of the nindent it could insert the labels under the comment but it must be striped by toYaml or helm when the values used

Yaml !!map

labels: !!map |
  {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | nindent 4 | trim }}

and

labels: !!map |
  {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | fromYaml }}

I don't think yaml has built in conversion but it was worth a shot.

Yaml !!yaml

Tried to play around with !!yaml but I don't understand what it's supposed to do.

Tried this:

labels:
  !!yaml: '!' : '!map'
  !!value = : {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | nindent 4 | trim }}

and

labels:
  !!yaml: '!' : '!map'
  !!value = : {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | fromYaml }}

Question

Is there any valid YAML notation or object I can use to pass the template through toYaml without using a string?

Is there anyway to represent {{ blabla }} in YAML without using a string?

The Correct Way

Obviously doing away with toYaml and using strings will result in the expected behavior

extraObjects:
  - |
      apiVersion: v1
      kind: ConfigMap
      metadata:
        labels: 
          {{ include `argo-cd.labels` (dict `context` . `component` `configmap`  `name`  `some-config-map`) | nindent 4 | trim }}
        name: some-config-map
      data:
        something: something
{{ range .Values.extraObjects }}
---
{{ tpl . $ }}
{{ end }}

Before I open an issue with the Argo-CD Helm team I just want to know if there is any workaround?


Solution

  • I only know this dirty trick:

    customServiceTemplate: |
        {{- define "extraService" -}}
        Service'
        apiVersion: v1
        metadata:
          name: {{ .fullName }}-{{ .serviceName }}
        spec:
          type: LoadBalancer
        # '¯\_(ツ)_/¯
        {{- end }}
        {{- $serviceConfig := dict -}}
        {{- $serviceConfig := merge $serviceConfig .Values.service-}}
        {{- $_ := set $serviceConfig "serviceName" "extra-service" -}}
        {{- $_ := set $serviceConfig "fullName" (include "x.fullname" .) -}}
        {{- $_ := set $serviceConfig "namespace" (include "x.namespace" .) -}}
        {{- include "extraService" $serviceConfig -}}
    
    extraObjects:
      - kind: "{{ tpl .Values.customServiceTemplate . }}"
    

    It's rendered as

    ---
    # Source: xchart/templates/extraManifests.yaml
    kind: 'Service'
    apiVersion: v1
    metadata:
      name: kong-edge-dp-kong-v1-stream-proxy
    spec:
      type: LoadBalancer
    # '¯\_(ツ)_/¯'