Search code examples
templateskubernetes-helmgo-templates

How to template Helm to insert templating language from other application?


I have a configMap that has a piece of alerting that looks like this:

alert_output:
  outputs:
    - type: webhook
      enabled: true
      template: |
          {{- if ne (print .PolicyType) "Heartbeat" -}}
          {"text": "New Alert\n Type: {{.PolicyType}}\n Details: {{.Description}}"
          {{- end -}}

How can I template this in Helm so that the text inside the outputs.template can be customizable via values file like this?

alert_output:
  outputs:
    - type: webhook
      enabled: true
      template: |
          {{- if ne (print .PolicyType) "Heartbeat" -}}
          {"text": {{ .Values.custom_alert_text }}
          {{- end -}}
  • valus.yaml
custom_alert_test: "New Alert\n Type: {{.PolicyType}}\n Details: {{.Description}}"

Of course the original {{}} are interpreted as being the Helm templates instead of the application templating language.


Solution

  • You need to do two things to make this work.

    In the template itself, you need to cause Helm (or more properly the Go text/template engine) to output a {{ rather than interpret it as template markup. I've found the easiest way to do this is to write a template block that emits the curly braces:

    {{/* A template that evaluates to the literal string "{{" */}}
    {{"{{"}}- if ne ... -}}
    

    The curly braces are not interpreted in the values.yaml file so you do not need to make a change there. However, parsing the YAML file will convert the \n escape sequence into a newline character and consume any quoting that might have been there. Helm includes a toJson function that will render anything to valid JSON, and should do the required quoting and escaping for you.

    In your example there also needs to be one more } at the end of the line matching the { JSON object syntax.

    Putting these things together, you should get something like:

    alert_output:
      outputs:
        - type: webhook
          enabled: true
          template: |
              {{"{{"}}- if ne (print .PolicyType) "Heartbeat" -}}
              {"text": {{ toJson .Values.custom_alert_text }}}
              {{"{{"}}- end -}}
    

    You could also assemble the entire object in template language and then serialize that; which would look something like

    template: |
      {{"{{"}}- if ne (print .PolicyType) "Heartbeat" -}}
      {{ dict "text" .Values.custom_alert_text | toJson }}
      {{"{{"}}- end -}}