Search code examples
godevopsgo-templatesprometheus-alertmanager

Go Template if condition


how can i combine and and eq/ne functions together?

I wrote this snippet

{{ define "opsgenie.default.tmpl" }}
  <font size="+0"><b>{{.CommonLabels.alertname }}</b></font>
  {{- range $i, $alert := .Alerts }}
  <font size="+0">{{ .Annotations.description }}</font>
  {{- end -}}
  {{- "\n" -}}
  {{- "\n" -}}
  {{- if and eq .CommonLabels.infoalert "true" eq .CommonLabels.topic "database" -}}
  Grafana: https://{{ .CommonLabels.url }}
  {{- "\n" -}}{{- end -}}
  {{- if and ne .CommonLabels.infoalert "true" eq .CommonLabels.topic "database" -}}
  Database:
    • https://{{ .CommonLabels.url }}/
    • https://{{ .CommonLabels.url }}/
  {{- "\n" -}}{{- end -}}
  {{- end -}}
  {{- end -}}
{{- end -}}

The goal is:

  • if my alert contains both labels infoalert: true and topic: database then show only Grafana link
  • if my alert contains only label topic: database but not infoalert: true then show only Databsse link

It looks like the syntax for condition {{- if and eq .CommonLabels.infoalert "true" eq .CommonLabels.topic "database" -}} is not correct because i get this error in alertmanager.log when alert is fired:

notify retry canceled due to unrecoverable error after 1 attempts: templating error: template: email.tmpl:24:17: executing \"opsgenie.default.tmpl\" at <eq>: wrong number of args for eq: want at least 1 got 0

Solution

  • Simply use parenthesis to group the expressions:

    {{- if and (eq .CommonLabels.infoalert "true") (eq .CommonLabels.topic "database") -}}
    
    {{- if and (ne .CommonLabels.infoalert "true") (eq .CommonLabels.topic "database") -}}
    

    See this testable example:

    func main() {
        t := template.Must(template.New("").Parse(src))
    
        m := map[string]any{
            "infoalert": "true",
            "topic":     "database",
        }
        if err := t.Execute(os.Stdout, m); err != nil {
            panic(err)
        }
    
        fmt.Println("Second round")
        m["infoalert"] = "false"
        if err := t.Execute(os.Stdout, m); err != nil {
            panic(err)
        }
    }
    
    const src = `
    {{- if and (eq .infoalert "true") (eq .topic "database") -}}
        infoalert is true and topic is database
    {{- end -}}
    {{- if and (ne .infoalert "true") (eq .topic "database") -}}
        infoalert is NOT true and topic is database
    {{ end }}
    `
    

    This will output (try it on the Go Playground):

    infoalert is true and topic is database
    Second round
    infoalert is NOT true and topic is database