helmfile icon indicating copy to clipboard operation
helmfile copied to clipboard

Templating complex values.yaml files

Open ChrisCooney opened this issue 5 years ago • 10 comments

Consider the following values.yaml file. This is an excerpt from the default values file for the prometheus helm chart:

## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.server.configMapOverrideName}}
## Defining configMapOverrideName will cause templates/server-configmap.yaml
## to NOT generate a ConfigMap resource
##
configMapOverrideName: ""

When we're attempting to use helmfile to template into this values.yaml.gotpl file, we are seeing errors. Obviously it is picking up on {{ and seeing it as a template. We can accept this for comments since they can simply be deleted, however the same thing is happening for nested values that are not in comments.

## alertmanager ConfigMap entries
##
alertmanagerFiles:
  alertmanager.yml:
    global:
      slack_api_url: 'https://slack.com'

    receivers:
    - name: default-receiver
      pagerduty_configs:
        - service_key: key
      slack_configs:
      - channel: '{{ .CommonAnnotations.channel }}'
        send_resolved: true
        title: '{{ template "slack.default.title" . }}'
        title_link: '{{ template "slack.default.titlelink" . }}'
        pretext: '{{ .CommonAnnotations.summary }}'
        text: |-
          {{ range .Alerts }}
             *Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}`
            *Description:* {{ .Annotations.description }}
            *Details:*
            {{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
            {{ end }}
          {{ end }}

To be completely honest, I don't really know what the answer to this question is. It is understandable that helmfile is detecting these interpolation tokens - however it introduces a lot of escaping and complexity. Given that prometheus is such a widely used chart, I felt it was worth raising to start a discussion.

ChrisCooney avatar Jun 17 '19 16:06 ChrisCooney

@ChrisCooney Thanks for trying helmfile and bringing this up! I feel frustrated to this problem as well. Perhaps you may be interested in #658 for a possible longer-term solution.

Have you tried making your all or part(s) of your values.yaml non-template file(Omit .tpl), so that it isn't rendered as a go template? Or escaping expressions?

{{` {{ .Whatever }} `}}

If you've already tried that, and you still wanted to have a single file that has nice comments containing example template expressions and alertmanager configs - yeah we don't currently have an elegant way .

Since #658 I've considered another delimiters for helmfile templates, like (( )), [[ ]], {{{ }}} but each of them seems to have its own pros and cos.

That's why I started to think that we eventually need a completely different "language" that doesn't conflict with go templates. There's a bunch of "embedded" languages used for generating dynamic configs - Skylark(See kubetest), Rego(See conftest), Lua(Helm v3, gofish), ECMAScript(jkcfg/jk), and so on.

One of helmfile ways is that being consistent with helm. Fortunately helm v3 is introducing Lua support for chart libraries and hooks. So add Lua as an another language to describe dynamic helmfile values.yaml files?

I'm okay with Lua but not sure if everyone is. WDYT?

mumoshu avatar Jun 18 '19 01:06 mumoshu

Can I drop the name of k14s/ytt as an alternative templating option? It's been getting a lot of popularity lately. Just putting it out there for consideration 👍

aegershman avatar Jun 18 '19 05:06 aegershman

@aegershman Yeah I'm eager to add various templating options. The only consideration needed here is how to implement it without bloating the helmfile codebase 😄

Perhaps someone could propose a pluggable template engine system for helmfile so that helmfile is able to use any template engine without bloating code and sacrificing binary size.

mumoshu avatar Jun 18 '19 08:06 mumoshu

I'd say only go template and Lua can be the first-class citizens to make helmfile friendly for helm users.

mumoshu avatar Jun 18 '19 08:06 mumoshu

tried to configure prometheus alertmanager templates and faced with this issue. any news regarding this issue ? seems like the problem is still actual...

StepanKuksenko avatar Jun 02 '21 10:06 StepanKuksenko

@StepanKuksenko Hey! Sorry but could you share what you've tried? This is already "solved" with the below syntax:

{{` {{ .Whatever }} `}}

That's go text/template's native comment sytnax, so that you can literally render {{ .Whatever }} without evaluating it as a template expression.

mumoshu avatar Jun 02 '21 23:06 mumoshu

Faced same issue with vector helm chart. Mainly this part:

      labels:
        forwarder: "vector"
        file:  '{{ file }}'
        stream:  "{{ stream }}"
        source_type:  "{{ source_type }}"
        k8s_pod_namespace:  "{{ kubernetes.pod_namespace }}"
        k8s_pod_name:  "{{ kubernetes.pod_name }}"
        k8s_pod_uid:  "{{ kubernetes.pod_uid }}"
        k8s_pod_ip:  "{{ kubernetes.pod_ip }}"
        k8s_pod_ips:  "{{ kubernetes.pod_ips }}"
        k8s_pod_node_name:  "{{ kubernetes.pod_node_name }}"
        k8s_app:  "{{ kubernetes.pod_labels.app }}"
        k8s_kubernetes_io_instance:  '{{ kubernetes.pod_labels.app\.kubernetes\.io/instance}}'
        k8s_kubernetes_io_component:  '{{ kubernetes.pod_labels.app\.kubernetes\.io/component }}'
        k8s_kubernetes_io_name:  '{{ kubernetes.pod_labels.app\.kubernetes\.io/name }}'
        k8s_container_name:  "{{ kubernetes.container_name }}"
        k8s_container_image:  "{{ kubernetes.container_image }}"

Even if i wrap

file:  '{{ file }}'

to

file: {{` '{{ file }}' `}}

It still fails trying to treat file as a function:

parse error at (vector-agent/templates/configmap.yaml:13): function "file" not defined

It uses toYaml to generate resulting configmap

rlex avatar Oct 07 '21 15:10 rlex

Hi! I have the same problem, I'm trying to set a value to an annotations:

    annotations:
      alb.ingress.kubernetes.io/conditions.any: "{{ .Values.otherServiceName    }}"
      alb.ingress.kubernetes.io/conditions.any2: "{{` '{{ .Values.otherServiceName }}' `}}"

And it always renders the instruction to me but does not resolve it. Could someone solve?

Thanks

jefrnc avatar Sep 13 '22 22:09 jefrnc

parse error at (vector-agent/templates/configmap.yaml:13): function "file" not defined

@rlex This seems to be coming from your chart, not helmfile, right? Then almost certainly you're misusing the chart. Mind sharing the chart and the offending chart template, so that we can hopefully see what's going on?

mumoshu avatar Sep 14 '22 00:09 mumoshu

Everyone, please share the exact chart, helmfile.yaml, and all the values.yaml files if you need user support!

mumoshu avatar Sep 14 '22 00:09 mumoshu