diff --git a/go.mod b/go.mod index e664a31975a..1ddd0152b12 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.1 // @grafana/grafana-backend-group github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 // @grafana/alerting-backend + github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 // @grafana/alerting-backend github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // @grafana/identity-access-team github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics diff --git a/go.sum b/go.sum index 29c820b8964..21c166a08d9 100644 --- a/go.sum +++ b/go.sum @@ -1525,8 +1525,8 @@ github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7Fsg github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 h1:iQ0h/h+QoguSZDF+ZpPxcM/C+m1kjh+aXjMpxywowPA= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 h1:kESrzm0FcRVLmGIQCgl1MCwDGLH4sLzWphr7mcFdbfI= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8= diff --git a/pkg/services/ngalert/api/api_alertmanager.go b/pkg/services/ngalert/api/api_alertmanager.go index 1d174a149c7..90c3843b65e 100644 --- a/pkg/services/ngalert/api/api_alertmanager.go +++ b/pkg/services/ngalert/api/api_alertmanager.go @@ -353,8 +353,9 @@ func newTestTemplateResult(res *notifier.TestTemplatesResults) apimodels.TestTem apiRes := apimodels.TestTemplatesResults{} for _, r := range res.Results { apiRes.Results = append(apiRes.Results, apimodels.TestTemplatesResult{ - Name: r.Name, - Text: r.Text, + Name: r.Name, + Text: r.Text, + Scope: apimodels.TemplateScope(r.Scope), }) } for _, e := range res.Errors { diff --git a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go index 84d29dcb249..5a9c6a5b868 100644 --- a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go +++ b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go @@ -369,6 +369,10 @@ type TestTemplatesResult struct { // Interpolated value of the template. Text string `json:"text"` + + // Scope that was successfully used to interpolate the template. If the root scope "." fails, more specific + // scopes will be tried, such as ".Alerts', or ".Alert". + Scope TemplateScope `json:"scope"` } type TestTemplatesErrorResult struct { @@ -390,6 +394,15 @@ const ( ExecutionError TemplateErrorKind = "execution_error" ) +// swagger:enum TemplateScope +type TemplateScope string + +const ( + RootScope TemplateScope = "." + AlertsScope TemplateScope = ".Alerts" + AlertScope TemplateScope = ".Alert" +) + // swagger:parameters RouteCreateSilence RouteCreateGrafanaSilence type CreateSilenceParams struct { // in:body diff --git a/pkg/services/ngalert/notifier/templates_test.go b/pkg/services/ngalert/notifier/templates_test.go index a5806405642..fb266ac15f9 100644 --- a/pkg/services/ngalert/notifier/templates_test.go +++ b/pkg/services/ngalert/notifier/templates_test.go @@ -53,8 +53,9 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: "\nReceiver: TestReceiver\nStatus: firing\nExternalURL: http://localhost:9093\nAlerts: 1\nFiring Alerts: 1\nResolved Alerts: 0\nGroupLabels: group_label=group_label_value \nCommonLabels: alertname=alert1 grafana_folder=folder title lbl1=val1 \nCommonAnnotations: ann1=annv1 \n", + Name: "slack.title", + Text: "\nReceiver: TestReceiver\nStatus: firing\nExternalURL: http://localhost:9093\nAlerts: 1\nFiring Alerts: 1\nResolved Alerts: 0\nGroupLabels: group_label=group_label_value \nCommonLabels: alertname=alert1 grafana_folder=folder title lbl1=val1 \nCommonAnnotations: ann1=annv1 \n", + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -67,8 +68,9 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: DefaultLabels[prometheusModel.AlertNameLabel], + Name: "slack.title", + Text: DefaultLabels[prometheusModel.AlertNameLabel], + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -81,8 +83,9 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: DefaultLabels[alertingModels.FolderTitleLabel], + Name: "slack.title", + Text: DefaultLabels[alertingModels.FolderTitleLabel], + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -95,8 +98,9 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: "B=22 C=1 ", + Name: "slack.title", + Text: "B=22 C=1 ", + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -109,8 +113,9 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: DefaultAnnotations[alertingModels.ValueStringAnnotation], + Name: "slack.title", + Text: DefaultAnnotations[alertingModels.ValueStringAnnotation], + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -127,6 +132,7 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val Text: fmt.Sprintf("http://localhost:9093/d/%s?orgId=%s", DefaultAnnotations[alertingModels.DashboardUIDAnnotation], DefaultAnnotations[alertingModels.OrgIDAnnotation]), + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -144,6 +150,7 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val DefaultAnnotations[alertingModels.DashboardUIDAnnotation], DefaultAnnotations[alertingModels.OrgIDAnnotation], DefaultAnnotations[alertingModels.PanelIDAnnotation]), + Scope: alertingNotify.TemplateScope(apimodels.RootScope), }}, Errors: nil, }, @@ -156,8 +163,47 @@ CommonAnnotations: {{ range .CommonAnnotations.SortedPairs }}{{ .Name }}={{ .Val }, expected: TestTemplatesResults{ Results: []alertingNotify.TestTemplatesResult{{ - Name: "slack.title", - Text: fmt.Sprintf("http://localhost:3000?orgId=%s", DefaultAnnotations[alertingModels.OrgIDAnnotation]), + Name: "slack.title", + Text: fmt.Sprintf("http://localhost:3000?orgId=%s", DefaultAnnotations[alertingModels.OrgIDAnnotation]), + Scope: alertingNotify.TemplateScope(apimodels.RootScope), + }}, + Errors: nil, + }, + }, { + name: "Alerts scoped templated ", + input: apimodels.TestTemplatesConfigBodyParams{ + Alerts: []*amv2.PostableAlert{{Alert: amv2.Alert{GeneratorURL: "http://localhost:3000"}}}, + Name: "slack.title", + Template: `{{ define "slack.title" }} + {{ range . }} + Status: {{ .Status }} + Starts at: {{ .StartsAt }} + {{ end }} +{{ end }}`, + }, + expected: TestTemplatesResults{ + Results: []alertingNotify.TestTemplatesResult{{ + Name: "slack.title", + Text: "\n\t\n\t\tStatus: firing\n\t\tStarts at: 0001-01-01 00:00:00 +0000 UTC\n\t\n", + Scope: alertingNotify.TemplateScope(apimodels.AlertsScope), + }}, + Errors: nil, + }, + }, { + name: "Alert scoped templated ", + input: apimodels.TestTemplatesConfigBodyParams{ + Alerts: []*amv2.PostableAlert{{Alert: amv2.Alert{GeneratorURL: "http://localhost:3000"}}}, + Name: "slack.title", + Template: `{{ define "slack.title" }} + Status: {{ .Status }} + Starts at: {{ .StartsAt }} +{{ end }}`, + }, + expected: TestTemplatesResults{ + Results: []alertingNotify.TestTemplatesResult{{ + Name: "slack.title", + Text: "\n\tStatus: firing\n\tStarts at: 0001-01-01 00:00:00 +0000 UTC\n", + Scope: alertingNotify.TemplateScope(apimodels.AlertScope), }}, Errors: nil, }, diff --git a/pkg/storage/unified/apistore/go.mod b/pkg/storage/unified/apistore/go.mod index c515663008a..bc3820efab7 100644 --- a/pkg/storage/unified/apistore/go.mod +++ b/pkg/storage/unified/apistore/go.mod @@ -192,7 +192,7 @@ require ( github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 // indirect + github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 // indirect github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // indirect diff --git a/pkg/storage/unified/apistore/go.sum b/pkg/storage/unified/apistore/go.sum index 11a44305649..a3a38f639b9 100644 --- a/pkg/storage/unified/apistore/go.sum +++ b/pkg/storage/unified/apistore/go.sum @@ -567,8 +567,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 h1:iQ0h/h+QoguSZDF+ZpPxcM/C+m1kjh+aXjMpxywowPA= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 h1:kESrzm0FcRVLmGIQCgl1MCwDGLH4sLzWphr7mcFdbfI= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8= diff --git a/pkg/storage/unified/resource/go.mod b/pkg/storage/unified/resource/go.mod index 75b69ced369..a6802a0d5b2 100644 --- a/pkg/storage/unified/resource/go.mod +++ b/pkg/storage/unified/resource/go.mod @@ -117,7 +117,7 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 // indirect + github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 // indirect github.com/grafana/dataplane/sdata v0.0.9 // indirect github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect github.com/grafana/grafana-aws-sdk v0.31.5 // indirect diff --git a/pkg/storage/unified/resource/go.sum b/pkg/storage/unified/resource/go.sum index 83d766f41aa..49c224e0ad3 100644 --- a/pkg/storage/unified/resource/go.sum +++ b/pkg/storage/unified/resource/go.sum @@ -398,8 +398,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642 h1:iQ0h/h+QoguSZDF+ZpPxcM/C+m1kjh+aXjMpxywowPA= -github.com/grafana/alerting v0.0.0-20250224133628-2acbeef29642/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2 h1:kESrzm0FcRVLmGIQCgl1MCwDGLH4sLzWphr7mcFdbfI= +github.com/grafana/alerting v0.0.0-20250225150117-15e285d78df2/go.mod h1:hdGB3dSl8Ma9Rjo2YiAEAjMkZ5HiNJbNDqRKDefRZrM= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501 h1:FTuDRy/Shw8yOdG+v1DnkeuaCAl8fvwgcfaG9Wccuhg= github.com/grafana/authlib v0.0.0-20250225105729-99e678595501/go.mod h1:XVpdLhaeYqz414FmGnW00/0vTe1x8c0GRH3KaeRtyg0= github.com/grafana/authlib/types v0.0.0-20250224151205-5ef97131cc82 h1:DnRUYiAotHXnrfYJCvhH1NkiyWVcPm5Pd+P7Ugqt/d8=