From 48b55f39bf4a477f47e0da5dab808f048155f451 Mon Sep 17 00:00:00 2001 From: Yuri Tseretyan Date: Fri, 27 Oct 2023 13:06:46 -0400 Subject: [PATCH] Alerting: Add support for responders to Opsgenie integration (#77159) * add support for responders in opsgenie UI config * update export model Co-authored-by: Santiago --- go.mod | 2 +- go.sum | 2 ++ .../api/tooling/definitions/contact_points.go | 20 +++++++---- .../channels_config/available_channels.go | 35 +++++++++++++++++++ .../notifier/channels_config/plugin.go | 29 ++++++++------- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 4e74b99195f..3f070d31c07 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/google/uuid v1.3.1 // @grafana/backend-platform github.com/google/wire v0.5.0 // @grafana/backend-platform github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad - github.com/grafana/alerting v0.0.0-20231017091417-a53b5db2235d // @grafana/alerting-squad-backend + github.com/grafana/alerting v0.0.0-20231026192550-079966731bbe // @grafana/alerting-squad-backend github.com/grafana/cuetsy v0.1.10 // @grafana/grafana-as-code github.com/grafana/grafana-aws-sdk v0.19.1 // @grafana/aws-datasources github.com/grafana/grafana-azure-sdk-go v1.9.0 // @grafana/backend-platform diff --git a/go.sum b/go.sum index 6e9513c5677..bb09dc0c15c 100644 --- a/go.sum +++ b/go.sum @@ -1798,6 +1798,8 @@ github.com/gotestyourself/gotestyourself v1.3.0/go.mod h1:zZKM6oeNM8k+FRljX1mnzV github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/grafana/alerting v0.0.0-20231017091417-a53b5db2235d h1:fxHDUyKFc1mfyJAtW+Qxi66dMahYu+o5/lH+f8SoMHg= github.com/grafana/alerting v0.0.0-20231017091417-a53b5db2235d/go.mod h1:6BES5CyEqz7fDAG3MYvJLe0hqGwvIoGDN8A1aNrLGus= +github.com/grafana/alerting v0.0.0-20231026192550-079966731bbe h1:6jY5mWR//GbYOjvqpnoncgkdxbeYImkTsy9rPvVFOlk= +github.com/grafana/alerting v0.0.0-20231026192550-079966731bbe/go.mod h1:6BES5CyEqz7fDAG3MYvJLe0hqGwvIoGDN8A1aNrLGus= github.com/grafana/codejen v0.0.3 h1:tAWxoTUuhgmEqxJPOLtJoxlPBbMULFwKFOcRsPRPXDw= github.com/grafana/codejen v0.0.3/go.mod h1:zmwwM/DRyQB7pfuBjTWII3CWtxcXh8LTwAYGfDfpR6s= github.com/grafana/cue v0.0.0-20230926092038-971951014e3f h1:TmYAMnqg3d5KYEAaT6PtTguL2GjLfvr6wnAX8Azw6tQ= diff --git a/pkg/services/ngalert/api/tooling/definitions/contact_points.go b/pkg/services/ngalert/api/tooling/definitions/contact_points.go index 3f484be097f..5797c0314b3 100644 --- a/pkg/services/ngalert/api/tooling/definitions/contact_points.go +++ b/pkg/services/ngalert/api/tooling/definitions/contact_points.go @@ -100,17 +100,25 @@ type OnCallIntegration struct { Message *string `json:"message,omitempty" yaml:"message,omitempty" hcl:"message"` } +type OpsgenieIntegrationResponder struct { + ID *string `json:"id,omitempty" yaml:"id,omitempty" hcl:"id"` + Name *string `json:"name,omitempty" yaml:"name,omitempty" hcl:"name"` + Username *string `json:"username,omitempty" yaml:"username,omitempty" hcl:"username"` + Type string `json:"type" yaml:"type" hcl:"type"` +} + type OpsgenieIntegration struct { DisableResolveMessage *bool `json:"-" yaml:"-" hcl:"disable_resolve_message"` APIKey Secret `json:"apiKey" yaml:"apiKey" hcl:"api_key"` - APIUrl *string `json:"apiUrl,omitempty" yaml:"apiUrl,omitempty" hcl:"url"` - Message *string `json:"message,omitempty" yaml:"message,omitempty" hcl:"message"` - Description *string `json:"description,omitempty" yaml:"description,omitempty" hcl:"description"` - AutoClose *bool `json:"autoClose,omitempty" yaml:"autoClose,omitempty" hcl:"auto_close"` - OverridePriority *bool `json:"overridePriority,omitempty" yaml:"overridePriority,omitempty" hcl:"override_priority"` - SendTagsAs *string `json:"sendTagsAs,omitempty" yaml:"sendTagsAs,omitempty" hcl:"send_tags_as"` + APIUrl *string `json:"apiUrl,omitempty" yaml:"apiUrl,omitempty" hcl:"url"` + Message *string `json:"message,omitempty" yaml:"message,omitempty" hcl:"message"` + Description *string `json:"description,omitempty" yaml:"description,omitempty" hcl:"description"` + AutoClose *bool `json:"autoClose,omitempty" yaml:"autoClose,omitempty" hcl:"auto_close"` + OverridePriority *bool `json:"overridePriority,omitempty" yaml:"overridePriority,omitempty" hcl:"override_priority"` + SendTagsAs *string `json:"sendTagsAs,omitempty" yaml:"sendTagsAs,omitempty" hcl:"send_tags_as"` + Responders []OpsgenieIntegrationResponder `json:"responders,omitempty" yaml:"responders,omitempty" hcl:"responders,block"` } type PagerdutyIntegration struct { diff --git a/pkg/services/ngalert/notifier/channels_config/available_channels.go b/pkg/services/ngalert/notifier/channels_config/available_channels.go index 45072be5009..5fac854bc10 100644 --- a/pkg/services/ngalert/notifier/channels_config/available_channels.go +++ b/pkg/services/ngalert/notifier/channels_config/available_channels.go @@ -3,6 +3,7 @@ package channels_config import ( "fmt" "os" + "strings" alertingOpsgenie "github.com/grafana/alerting/receivers/opsgenie" alertingTemplates "github.com/grafana/alerting/templates" @@ -1293,6 +1294,40 @@ func GetAvailableNotifiers() []*NotifierPlugin { Description: "Send the common annotations to Opsgenie as either Extra Properties, Tags or both", PropertyName: "sendTagsAs", }, + // New in 10.3 + { + Label: "Responders", + PropertyName: "responders", + Description: "If the API key belongs to a team, this field is ignored.", + Element: ElementSubformArray, + SubformOptions: []NotifierOption{ + { + Label: "Type", + Description: fmt.Sprintf("%s or a template", strings.Join(alertingOpsgenie.SupportedResponderTypes, ", ")), + Element: ElementTypeInput, + Required: true, + PropertyName: "type", + }, + { + Label: "Name", + Element: ElementTypeInput, + Description: "Name of the responder. Must be specified if ID and Username are empty or if the type is 'teams'.", + PropertyName: "name", + }, + { + Label: "ID", + Element: ElementTypeInput, + Description: "ID of the responder. Must be specified if name and Username are empty.", + PropertyName: "id", + }, + { + Label: "Username", + Element: ElementTypeInput, + Description: "User name of the responder. Must be specified if ID and Name are empty.", + PropertyName: "username", + }, + }, + }, }, }, { diff --git a/pkg/services/ngalert/notifier/channels_config/plugin.go b/pkg/services/ngalert/notifier/channels_config/plugin.go index 8417d304e99..f390ee1d9fc 100644 --- a/pkg/services/ngalert/notifier/channels_config/plugin.go +++ b/pkg/services/ngalert/notifier/channels_config/plugin.go @@ -12,18 +12,19 @@ type NotifierPlugin struct { // NotifierOption holds information about options specific for the NotifierPlugin. type NotifierOption struct { - Element ElementType `json:"element"` - InputType InputType `json:"inputType"` - Label string `json:"label"` - Description string `json:"description"` - Placeholder string `json:"placeholder"` - PropertyName string `json:"propertyName"` - SelectOptions []SelectOption `json:"selectOptions"` - ShowWhen ShowWhen `json:"showWhen"` - Required bool `json:"required"` - ValidationRule string `json:"validationRule"` - Secure bool `json:"secure"` - DependsOn string `json:"dependsOn"` + Element ElementType `json:"element"` + InputType InputType `json:"inputType"` + Label string `json:"label"` + Description string `json:"description"` + Placeholder string `json:"placeholder"` + PropertyName string `json:"propertyName"` + SelectOptions []SelectOption `json:"selectOptions"` + ShowWhen ShowWhen `json:"showWhen"` + Required bool `json:"required"` + ValidationRule string `json:"validationRule"` + Secure bool `json:"secure"` + DependsOn string `json:"dependsOn"` + SubformOptions []NotifierOption `json:"subformOptions"` } // ElementType is the type of element that can be rendered in the frontend. @@ -40,6 +41,10 @@ const ( ElementTypeTextArea = "textarea" // ElementTypeKeyValueMap will render inputs to add arbitrary key-value pairs ElementTypeKeyValueMap = "key_value_map" + // ElementSubformArray will render a sub-form with schema defined in SubformOptions + ElementTypeSubform = "subform" + // ElementSubformArray will render a multiple sub-forms with schema defined in SubformOptions + ElementSubformArray = "subform_array" ) // InputType is the type of input that can be rendered in the frontend.