diff --git a/.github/assets/jetbrains-space-alerts.png b/.github/assets/jetbrains-space-alerts.png deleted file mode 100644 index e339c2ed..00000000 Binary files a/.github/assets/jetbrains-space-alerts.png and /dev/null differ diff --git a/README.md b/README.md index 6ac7ba9f..ca0c84e0 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,6 @@ Have any feedback or questions? [Create a discussion](https://github.com/TwiN/ga - [Configuring IFTTT alerts](#configuring-ifttt-alerts) - [Configuring Ilert alerts](#configuring-ilert-alerts) - [Configuring Incident.io alerts](#configuring-incidentio-alerts) - - [Configuring JetBrains Space alerts](#configuring-jetbrains-space-alerts) - [Configuring Line alerts](#configuring-line-alerts) - [Configuring Matrix alerts](#configuring-matrix-alerts) - [Configuring Mattermost alerts](#configuring-mattermost-alerts) @@ -811,7 +810,6 @@ endpoints: | `alerting.ifttt` | Configuration for alerts of type `ifttt`.
See [Configuring IFTTT alerts](#configuring-ifttt-alerts). | `{}` | | `alerting.ilert` | Configuration for alerts of type `ilert`.
See [Configuring ilert alerts](#configuring-ilert-alerts). | `{}` | | `alerting.incident-io` | Configuration for alerts of type `incident-io`.
See [Configuring Incident.io alerts](#configuring-incidentio-alerts). | `{}` | -| `alerting.jetbrainsspace` | Configuration for alerts of type `jetbrainsspace`.
See [Configuring JetBrains Space alerts](#configuring-jetbrains-space-alerts). | `{}` | | `alerting.line` | Configuration for alerts of type `line`.
See [Configuring Line alerts](#configuring-line-alerts). | `{}` | | `alerting.matrix` | Configuration for alerts of type `matrix`.
See [Configuring Matrix alerts](#configuring-matrix-alerts). | `{}` | | `alerting.mattermost` | Configuration for alerts of type `mattermost`.
See [Configuring Mattermost alerts](#configuring-mattermost-alerts). | `{}` | @@ -1383,42 +1381,6 @@ In order to get the required alert source config id and authentication token, yo > **_NOTE:_** the source config id is of the form `https://api.incident.io/v2/alert_events/http/$ID` and the token is expected to be passed as a bearer token like so: `Authorization: Bearer $TOKEN` -#### Configuring JetBrains Space alerts -| Parameter | Description | Default | -|:--------------------------------------------|:-------------------------------------------------------------------------------------------|:--------------| -| `alerting.jetbrainsspace` | Configuration for alerts of type `jetbrainsspace` | `{}` | -| `alerting.jetbrainsspace.project` | JetBrains Space project name | Required `""` | -| `alerting.jetbrainsspace.channel-id` | JetBrains Space Chat Channel ID | Required `""` | -| `alerting.jetbrainsspace.token` | Token that is used for authentication. | Required `""` | -| `alerting.jetbrainsspace.default-alert` | Default alert configuration.
See [Setting a default alert](#setting-a-default-alert) | N/A | -| `alerting.jetbrainsspace.overrides` | List of overrides that may be prioritized over the default configuration | `[]` | -| `alerting.jetbrainsspace.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` | -| `alerting.jetbrainsspace.overrides[].*` | See `alerting.jetbrainsspace.*` parameters | `{}` | - -```yaml -alerting: - jetbrainsspace: - project: myproject - channel-id: ABCDE12345 - token: "**************" - -endpoints: - - name: website - url: "https://twin.sh/health" - interval: 5m - conditions: - - "[STATUS] == 200" - alerts: - - type: jetbrainsspace - description: "healthcheck failed" - send-on-resolved: true -``` - -Here's an example of what the notifications look like: - -![JetBrains Space notifications](.github/assets/jetbrains-space-alerts.png) - - #### Configuring Line alerts | Parameter | Description | Default | diff --git a/alerting/alert/type.go b/alerting/alert/type.go index 334f7d0b..43bd2487 100644 --- a/alerting/alert/type.go +++ b/alerting/alert/type.go @@ -47,9 +47,6 @@ const ( // TypeIncidentIO is the Type for the incident-io alerting provider TypeIncidentIO Type = "incident-io" - // TypeJetBrainsSpace is the Type for the jetbrains alerting provider - TypeJetBrainsSpace Type = "jetbrainsspace" - // TypeLine is the Type for the line alerting provider TypeLine Type = "line" diff --git a/alerting/config.go b/alerting/config.go index c5e39367..65150396 100644 --- a/alerting/config.go +++ b/alerting/config.go @@ -20,7 +20,6 @@ import ( "github.com/TwiN/gatus/v5/alerting/provider/ifttt" "github.com/TwiN/gatus/v5/alerting/provider/ilert" "github.com/TwiN/gatus/v5/alerting/provider/incidentio" - "github.com/TwiN/gatus/v5/alerting/provider/jetbrainsspace" "github.com/TwiN/gatus/v5/alerting/provider/line" "github.com/TwiN/gatus/v5/alerting/provider/matrix" "github.com/TwiN/gatus/v5/alerting/provider/mattermost" @@ -94,9 +93,6 @@ type Config struct { // IncidentIO is the configuration for the incident-io alerting provider IncidentIO *incidentio.AlertProvider `yaml:"incident-io,omitempty"` - // JetBrainsSpace is the configuration for the jetbrains space alerting provider - JetBrainsSpace *jetbrainsspace.AlertProvider `yaml:"jetbrainsspace,omitempty"` - // Line is the configuration for the line alerting provider Line *line.AlertProvider `yaml:"line,omitempty"` diff --git a/alerting/provider/jetbrainsspace/jetbrainsspace.go b/alerting/provider/jetbrainsspace/jetbrainsspace.go deleted file mode 100644 index 9e5fe7c5..00000000 --- a/alerting/provider/jetbrainsspace/jetbrainsspace.go +++ /dev/null @@ -1,223 +0,0 @@ -package jetbrainsspace - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - - "github.com/TwiN/gatus/v5/alerting/alert" - "github.com/TwiN/gatus/v5/client" - "github.com/TwiN/gatus/v5/config/endpoint" - "gopkg.in/yaml.v3" -) - -var ( - ErrProjectNotSet = errors.New("project not set") - ErrChannelIDNotSet = errors.New("channel-id not set") - ErrTokenNotSet = errors.New("token not set") - ErrDuplicateGroupOverride = errors.New("duplicate group override") -) - -type Config struct { - Project string `yaml:"project"` // Project name - ChannelID string `yaml:"channel-id"` // Chat Channel ID - Token string `yaml:"token"` // Bearer Token -} - -func (cfg *Config) Validate() error { - if len(cfg.Project) == 0 { - return ErrProjectNotSet - } - if len(cfg.ChannelID) == 0 { - return ErrChannelIDNotSet - } - if len(cfg.Token) == 0 { - return ErrTokenNotSet - } - return nil -} - -func (cfg *Config) Merge(override *Config) { - if len(override.Project) > 0 { - cfg.Project = override.Project - } - if len(override.ChannelID) > 0 { - cfg.ChannelID = override.ChannelID - } - if len(override.Token) > 0 { - cfg.Token = override.Token - } -} - -// AlertProvider is the configuration necessary for sending an alert using JetBrains Space -type AlertProvider struct { - DefaultConfig Config `yaml:",inline"` - - // DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type - DefaultAlert *alert.Alert `yaml:"default-alert,omitempty"` - - // Overrides is a list of Override that may be prioritized over the default configuration - Overrides []Override `yaml:"overrides,omitempty"` -} - -// Override is a case under which the default integration is overridden -type Override struct { - Group string `yaml:"group"` - Config `yaml:",inline"` -} - -// Validate the provider's configuration -func (provider *AlertProvider) Validate() error { - registeredGroups := make(map[string]bool) - if provider.Overrides != nil { - for _, override := range provider.Overrides { - if isAlreadyRegistered := registeredGroups[override.Group]; isAlreadyRegistered || override.Group == "" { - return ErrDuplicateGroupOverride - } - registeredGroups[override.Group] = true - } - } - return provider.DefaultConfig.Validate() -} - -// Send an alert using the provider -func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error { - cfg, err := provider.GetConfig(ep.Group, alert) - if err != nil { - return err - } - buffer := bytes.NewBuffer(provider.buildRequestBody(cfg, ep, alert, result, resolved)) - url := fmt.Sprintf("https://%s.jetbrains.space/api/http/chats/messages/send-message", cfg.Project) - request, err := http.NewRequest(http.MethodPost, url, buffer) - if err != nil { - return err - } - request.Header.Set("Content-Type", "application/json") - request.Header.Set("Authorization", "Bearer "+cfg.Token) - response, err := client.GetHTTPClient(nil).Do(request) - if err != nil { - return err - } - defer response.Body.Close() - if response.StatusCode > 399 { - body, _ := io.ReadAll(response.Body) - return fmt.Errorf("call to provider alert returned status code %d: %s", response.StatusCode, string(body)) - } - return err -} - -type Body struct { - Channel string `json:"channel"` - Content Content `json:"content"` -} - -type Content struct { - ClassName string `json:"className"` - Style string `json:"style"` - Sections []Section `json:"sections,omitempty"` -} - -type Section struct { - ClassName string `json:"className"` - Elements []Element `json:"elements"` - Header string `json:"header"` -} - -type Element struct { - ClassName string `json:"className"` - Accessory Accessory `json:"accessory"` - Style string `json:"style"` - Size string `json:"size"` - Content string `json:"content"` -} - -type Accessory struct { - ClassName string `json:"className"` - Icon Icon `json:"icon"` - Style string `json:"style"` -} - -type Icon struct { - Icon string `json:"icon"` -} - -// buildRequestBody builds the request body for the provider -func (provider *AlertProvider) buildRequestBody(cfg *Config, ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte { - body := Body{ - Channel: "id:" + cfg.ChannelID, - Content: Content{ - ClassName: "ChatMessage.Block", - Sections: []Section{{ - ClassName: "MessageSection", - Elements: []Element{}, - }}, - }, - } - if resolved { - body.Content.Style = "SUCCESS" - body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold) - } else { - body.Content.Style = "WARNING" - body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold) - } - for _, conditionResult := range result.ConditionResults { - icon := "warning" - style := "WARNING" - if conditionResult.Success { - icon = "success" - style = "SUCCESS" - } - body.Content.Sections[0].Elements = append(body.Content.Sections[0].Elements, Element{ - ClassName: "MessageText", - Accessory: Accessory{ - ClassName: "MessageIcon", - Icon: Icon{Icon: icon}, - Style: style, - }, - Style: style, - Size: "REGULAR", - Content: conditionResult.Condition, - }) - } - bodyAsJSON, _ := json.Marshal(body) - return bodyAsJSON -} - -// GetDefaultAlert returns the provider's default alert configuration -func (provider *AlertProvider) GetDefaultAlert() *alert.Alert { - return provider.DefaultAlert -} - -// GetConfig returns the configuration for the provider with the overrides applied -func (provider *AlertProvider) GetConfig(group string, alert *alert.Alert) (*Config, error) { - cfg := provider.DefaultConfig - // Handle group overrides - if provider.Overrides != nil { - for _, override := range provider.Overrides { - if group == override.Group { - cfg.Merge(&override.Config) - break - } - } - } - // Handle alert overrides - if len(alert.ProviderOverride) != 0 { - overrideConfig := Config{} - if err := yaml.Unmarshal(alert.ProviderOverrideAsBytes(), &overrideConfig); err != nil { - return nil, err - } - cfg.Merge(&overrideConfig) - } - // Validate the configuration - err := cfg.Validate() - return &cfg, err -} - -// ValidateOverrides validates the alert's provider override and, if present, the group override -func (provider *AlertProvider) ValidateOverrides(group string, alert *alert.Alert) error { - _, err := provider.GetConfig(group, alert) - return err -} diff --git a/alerting/provider/jetbrainsspace/jetbrainsspace_test.go b/alerting/provider/jetbrainsspace/jetbrainsspace_test.go deleted file mode 100644 index 57f834f6..00000000 --- a/alerting/provider/jetbrainsspace/jetbrainsspace_test.go +++ /dev/null @@ -1,318 +0,0 @@ -package jetbrainsspace - -import ( - "encoding/json" - "net/http" - "testing" - - "github.com/TwiN/gatus/v5/alerting/alert" - "github.com/TwiN/gatus/v5/client" - "github.com/TwiN/gatus/v5/config/endpoint" - "github.com/TwiN/gatus/v5/test" -) - -func TestAlertProvider_Validate(t *testing.T) { - invalidProvider := AlertProvider{DefaultConfig: Config{Project: ""}} - if err := invalidProvider.Validate(); err == nil { - t.Error("provider shouldn't have been valid") - } - validProvider := AlertProvider{DefaultConfig: Config{Project: "foo", ChannelID: "bar", Token: "baz"}} - if err := validProvider.Validate(); err != nil { - t.Error("provider should've been valid") - } -} - -func TestAlertProvider_ValidateWithOverride(t *testing.T) { - providerWithInvalidOverrideGroup := AlertProvider{ - DefaultConfig: Config{Project: "foobar"}, - Overrides: []Override{ - { - Config: Config{ChannelID: "http://example.com"}, - Group: "", - }, - }, - } - if err := providerWithInvalidOverrideGroup.Validate(); err == nil { - t.Error("provider Group shouldn't have been valid") - } - providerWithInvalidOverrideTo := AlertProvider{ - DefaultConfig: Config{Project: "foobar"}, - Overrides: []Override{ - { - Config: Config{ChannelID: ""}, - Group: "group", - }, - }, - } - if err := providerWithInvalidOverrideTo.Validate(); err == nil { - t.Error("provider integration key shouldn't have been valid") - } - providerWithValidOverride := AlertProvider{ - DefaultConfig: Config{ - Project: "foo", - ChannelID: "bar", - Token: "baz", - }, - Overrides: []Override{ - { - Config: Config{ChannelID: "foobar"}, - Group: "group", - }, - }, - } - if err := providerWithValidOverride.Validate(); err != nil { - t.Error("provider should've been valid") - } -} - -func TestAlertProvider_Send(t *testing.T) { - defer client.InjectHTTPClient(nil) - firstDescription := "description-1" - secondDescription := "description-2" - scenarios := []struct { - Name string - Provider AlertProvider - Alert alert.Alert - Resolved bool - MockRoundTripper test.MockRoundTripper - ExpectedError bool - }{ - { - Name: "triggered", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project", Token: "token"}}, - Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: false, - MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response { - return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody} - }), - ExpectedError: false, - }, - { - Name: "triggered-error", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project", Token: "token"}}, - Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: false, - MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response { - return &http.Response{StatusCode: http.StatusInternalServerError, Body: http.NoBody} - }), - ExpectedError: true, - }, - { - Name: "resolved", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project", Token: "token"}}, - Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: true, - MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response { - return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody} - }), - ExpectedError: false, - }, - { - Name: "resolved-error", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project", Token: "token"}}, - Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: true, - MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response { - return &http.Response{StatusCode: http.StatusInternalServerError, Body: http.NoBody} - }), - ExpectedError: true, - }, - } - for _, scenario := range scenarios { - t.Run(scenario.Name, func(t *testing.T) { - client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper}) - err := scenario.Provider.Send( - &endpoint.Endpoint{Name: "endpoint-name"}, - &scenario.Alert, - &endpoint.Result{ - ConditionResults: []*endpoint.ConditionResult{ - {Condition: "[CONNECTED] == true", Success: scenario.Resolved}, - {Condition: "[STATUS] == 200", Success: scenario.Resolved}, - }, - }, - scenario.Resolved, - ) - if scenario.ExpectedError && err == nil { - t.Error("expected error, got none") - } - if !scenario.ExpectedError && err != nil { - t.Error("expected no error, got", err.Error()) - } - }) - } -} - -func TestAlertProvider_buildRequestBody(t *testing.T) { - firstDescription := "description-1" - secondDescription := "description-2" - scenarios := []struct { - Name string - Provider AlertProvider - Endpoint endpoint.Endpoint - Alert alert.Alert - Resolved bool - ExpectedBody string - }{ - { - Name: "triggered", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project"}}, - Endpoint: endpoint.Endpoint{Name: "name"}, - Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: false, - ExpectedBody: `{"channel":"id:1","content":{"className":"ChatMessage.Block","style":"WARNING","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *name* has been triggered due to having failed 3 time(s) in a row"}]}}`, - }, - { - Name: "triggered-with-group", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project"}}, - Endpoint: endpoint.Endpoint{Name: "name", Group: "group"}, - Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: false, - ExpectedBody: `{"channel":"id:1","content":{"className":"ChatMessage.Block","style":"WARNING","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *group/name* has been triggered due to having failed 3 time(s) in a row"}]}}`, - }, - { - Name: "resolved", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project"}}, - Endpoint: endpoint.Endpoint{Name: "name"}, - Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: true, - ExpectedBody: `{"channel":"id:1","content":{"className":"ChatMessage.Block","style":"SUCCESS","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *name* has been resolved after passing successfully 5 time(s) in a row"}]}}`, - }, - { - Name: "resolved-with-group", - Provider: AlertProvider{DefaultConfig: Config{ChannelID: "1", Project: "project"}}, - Endpoint: endpoint.Endpoint{Name: "name", Group: "group"}, - Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, - Resolved: true, - ExpectedBody: `{"channel":"id:1","content":{"className":"ChatMessage.Block","style":"SUCCESS","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row"}]}}`, - }, - } - for _, scenario := range scenarios { - t.Run(scenario.Name, func(t *testing.T) { - body := scenario.Provider.buildRequestBody( - &scenario.Provider.DefaultConfig, - &scenario.Endpoint, - &scenario.Alert, - &endpoint.Result{ - ConditionResults: []*endpoint.ConditionResult{ - {Condition: "[CONNECTED] == true", Success: scenario.Resolved}, - {Condition: "[STATUS] == 200", Success: scenario.Resolved}, - }, - }, - scenario.Resolved, - ) - if string(body) != scenario.ExpectedBody { - t.Errorf("expected:\n%s\ngot:\n%s", scenario.ExpectedBody, body) - } - out := make(map[string]interface{}) - if err := json.Unmarshal(body, &out); err != nil { - t.Error("expected body to be valid JSON, got error:", err.Error()) - } - }) - } -} - -func TestAlertProvider_GetDefaultAlert(t *testing.T) { - if (&AlertProvider{DefaultAlert: &alert.Alert{}}).GetDefaultAlert() == nil { - t.Error("expected default alert to be not nil") - } - if (&AlertProvider{DefaultAlert: nil}).GetDefaultAlert() != nil { - t.Error("expected default alert to be nil") - } -} - -func TestAlertProvider_GetConfig(t *testing.T) { - scenarios := []struct { - Name string - Provider AlertProvider - InputGroup string - InputAlert alert.Alert - ExpectedOutput Config - }{ - { - Name: "provider-no-override-specify-no-group-should-default", - Provider: AlertProvider{ - DefaultConfig: Config{ChannelID: "default", Project: "project", Token: "token"}, - Overrides: nil, - }, - InputGroup: "", - InputAlert: alert.Alert{}, - ExpectedOutput: Config{ChannelID: "default", Project: "project", Token: "token"}, - }, - { - Name: "provider-no-override-specify-group-should-default", - Provider: AlertProvider{ - DefaultConfig: Config{ChannelID: "default", Project: "project", Token: "token"}, - Overrides: nil, - }, - InputGroup: "group", - InputAlert: alert.Alert{}, - ExpectedOutput: Config{ChannelID: "default", Project: "project", Token: "token"}, - }, - { - Name: "provider-with-override-specify-no-group-should-default", - Provider: AlertProvider{ - DefaultConfig: Config{ChannelID: "default", Project: "project", Token: "token"}, - Overrides: []Override{ - { - Group: "group", - Config: Config{ChannelID: "group-channel"}, - }, - }, - }, - InputGroup: "", - InputAlert: alert.Alert{}, - ExpectedOutput: Config{ChannelID: "default", Project: "project", Token: "token"}, - }, - { - Name: "provider-with-override-specify-group-should-override", - Provider: AlertProvider{ - DefaultConfig: Config{ChannelID: "default", Project: "project", Token: "token"}, - Overrides: []Override{ - { - Group: "group", - Config: Config{ChannelID: "group-channel"}, - }, - }, - }, - InputGroup: "group", - InputAlert: alert.Alert{}, - ExpectedOutput: Config{ChannelID: "group-channel", Project: "project", Token: "token"}, - }, - { - Name: "provider-with-group-override-and-alert-override--alert-override-should-take-precedence", - Provider: AlertProvider{ - DefaultConfig: Config{ChannelID: "default", Project: "project", Token: "token"}, - Overrides: []Override{ - { - Group: "group", - Config: Config{ChannelID: "group-channel"}, - }, - }, - }, - InputGroup: "group", - InputAlert: alert.Alert{ProviderOverride: map[string]any{"channel-id": "alert-channel", "project": "alert-project", "token": "alert-token"}}, - ExpectedOutput: Config{ChannelID: "alert-channel", Project: "alert-project", Token: "alert-token"}, - }, - } - for _, scenario := range scenarios { - t.Run(scenario.Name, func(t *testing.T) { - got, err := scenario.Provider.GetConfig(scenario.InputGroup, &scenario.InputAlert) - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - if got.ChannelID != scenario.ExpectedOutput.ChannelID { - t.Errorf("expected %s, got %s", scenario.ExpectedOutput.ChannelID, got.ChannelID) - } - if got.Project != scenario.ExpectedOutput.Project { - t.Errorf("expected %s, got %s", scenario.ExpectedOutput.Project, got.Project) - } - if got.Token != scenario.ExpectedOutput.Token { - t.Errorf("expected %s, got %s", scenario.ExpectedOutput.Token, got.Token) - } - // Test ValidateOverrides as well, since it really just calls GetConfig - if err = scenario.Provider.ValidateOverrides(scenario.InputGroup, &scenario.InputAlert); err != nil { - t.Errorf("unexpected error: %s", err) - } - }) - } -} diff --git a/alerting/provider/provider.go b/alerting/provider/provider.go index b3b883c4..64084e20 100644 --- a/alerting/provider/provider.go +++ b/alerting/provider/provider.go @@ -16,7 +16,6 @@ import ( "github.com/TwiN/gatus/v5/alerting/provider/ifttt" "github.com/TwiN/gatus/v5/alerting/provider/ilert" "github.com/TwiN/gatus/v5/alerting/provider/incidentio" - "github.com/TwiN/gatus/v5/alerting/provider/jetbrainsspace" "github.com/TwiN/gatus/v5/alerting/provider/line" "github.com/TwiN/gatus/v5/alerting/provider/matrix" "github.com/TwiN/gatus/v5/alerting/provider/mattermost" @@ -106,7 +105,6 @@ var ( _ AlertProvider = (*ifttt.AlertProvider)(nil) _ AlertProvider = (*ilert.AlertProvider)(nil) _ AlertProvider = (*incidentio.AlertProvider)(nil) - _ AlertProvider = (*jetbrainsspace.AlertProvider)(nil) _ AlertProvider = (*line.AlertProvider)(nil) _ AlertProvider = (*matrix.AlertProvider)(nil) _ AlertProvider = (*mattermost.AlertProvider)(nil) @@ -148,7 +146,6 @@ var ( _ Config[ifttt.Config] = (*ifttt.Config)(nil) _ Config[ilert.Config] = (*ilert.Config)(nil) _ Config[incidentio.Config] = (*incidentio.Config)(nil) - _ Config[jetbrainsspace.Config] = (*jetbrainsspace.Config)(nil) _ Config[line.Config] = (*line.Config)(nil) _ Config[matrix.Config] = (*matrix.Config)(nil) _ Config[mattermost.Config] = (*mattermost.Config)(nil) diff --git a/config/config.go b/config/config.go index 21dd91f0..4d9724b5 100644 --- a/config/config.go +++ b/config/config.go @@ -607,7 +607,6 @@ func ValidateAlertingConfig(alertingConfig *alerting.Config, endpoints []*endpoi alert.TypeIFTTT, alert.TypeIlert, alert.TypeIncidentIO, - alert.TypeJetBrainsSpace, alert.TypeLine, alert.TypeMatrix, alert.TypeMattermost, diff --git a/config/config_test.go b/config/config_test.go index f2906eac..811f0ed1 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -25,7 +25,6 @@ import ( "github.com/TwiN/gatus/v5/alerting/provider/ifttt" "github.com/TwiN/gatus/v5/alerting/provider/ilert" "github.com/TwiN/gatus/v5/alerting/provider/incidentio" - "github.com/TwiN/gatus/v5/alerting/provider/jetbrainsspace" "github.com/TwiN/gatus/v5/alerting/provider/line" "github.com/TwiN/gatus/v5/alerting/provider/matrix" "github.com/TwiN/gatus/v5/alerting/provider/mattermost" @@ -775,10 +774,6 @@ alerting: to: "+1-234-567-8901" teams: webhook-url: "http://example.com" - jetbrainsspace: - project: "foo" - channel-id: "bar" - token: "baz" endpoints: - name: website @@ -801,7 +796,6 @@ endpoints: success-threshold: 15 - type: teams - type: pushover - - type: jetbrainsspace conditions: - "[STATUS] == 200" `)) @@ -828,8 +822,8 @@ endpoints: if config.Endpoints[0].Interval != 60*time.Second { t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second) } - if len(config.Endpoints[0].Alerts) != 10 { - t.Fatal("There should've been 10 alerts configured") + if len(config.Endpoints[0].Alerts) != 9 { + t.Fatal("There should've been 9 alerts configured") } if config.Endpoints[0].Alerts[0].Type != alert.TypeSlack { @@ -936,12 +930,6 @@ endpoints: if !config.Endpoints[0].Alerts[8].IsEnabled() { t.Error("The alert should've been enabled") } - if config.Endpoints[0].Alerts[9].Type != alert.TypeJetBrainsSpace { - t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeJetBrainsSpace, config.Endpoints[0].Alerts[9].Type) - } - if !config.Endpoints[0].Alerts[9].IsEnabled() { - t.Error("The alert should've been enabled") - } } func TestParseAndValidateConfigBytesWithAlertingAndDefaultAlert(t *testing.T) { @@ -1001,14 +989,6 @@ alerting: webhook-url: "http://example.com" default-alert: enabled: true - jetbrainsspace: - project: "foo" - channel-id: "bar" - token: "baz" - default-alert: - enabled: true - failure-threshold: 5 - success-threshold: 3 email: from: "from@example.com" username: "from@example.com" @@ -1047,7 +1027,6 @@ endpoints: - type: twilio - type: teams - type: pushover - - type: jetbrainsspace - type: email - type: gotify conditions: @@ -1169,22 +1148,6 @@ endpoints: t.Fatal("Teams.GetDefaultAlert() shouldn't have returned nil") } - if config.Alerting.JetBrainsSpace == nil || config.Alerting.JetBrainsSpace.Validate() != nil { - t.Fatal("JetBrainsSpace alerting config should've been valid") - } - if config.Alerting.JetBrainsSpace.GetDefaultAlert() == nil { - t.Fatal("JetBrainsSpace.GetDefaultAlert() shouldn't have returned nil") - } - if config.Alerting.JetBrainsSpace.DefaultConfig.Project != "foo" { - t.Errorf("JetBrainsSpace webhook should've been %s, but was %s", "foo", config.Alerting.JetBrainsSpace.DefaultConfig.Project) - } - if config.Alerting.JetBrainsSpace.DefaultConfig.ChannelID != "bar" { - t.Errorf("JetBrainsSpace webhook should've been %s, but was %s", "bar", config.Alerting.JetBrainsSpace.DefaultConfig.ChannelID) - } - if config.Alerting.JetBrainsSpace.DefaultConfig.Token != "baz" { - t.Errorf("JetBrainsSpace webhook should've been %s, but was %s", "baz", config.Alerting.JetBrainsSpace.DefaultConfig.Token) - } - if config.Alerting.Email == nil || config.Alerting.Email.Validate() != nil { t.Fatal("Email alerting config should've been valid") } @@ -1256,8 +1219,8 @@ endpoints: if config.Endpoints[0].Interval != 60*time.Second { t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second) } - if len(config.Endpoints[0].Alerts) != 12 { - t.Fatalf("There should've been 12 alerts configured, got %d", len(config.Endpoints[0].Alerts)) + if len(config.Endpoints[0].Alerts) != 11 { + t.Fatalf("There should've been 11 alerts configured, got %d", len(config.Endpoints[0].Alerts)) } if config.Endpoints[0].Alerts[0].Type != alert.TypeSlack { @@ -1374,21 +1337,21 @@ endpoints: t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Endpoints[0].Alerts[8].SuccessThreshold) } - if config.Endpoints[0].Alerts[9].Type != alert.TypeJetBrainsSpace { - t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeJetBrainsSpace, config.Endpoints[0].Alerts[9].Type) + if config.Endpoints[0].Alerts[9].Type != alert.TypeEmail { + t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeEmail, config.Endpoints[0].Alerts[9].Type) } if !config.Endpoints[0].Alerts[9].IsEnabled() { t.Error("The alert should've been enabled") } - if config.Endpoints[0].Alerts[9].FailureThreshold != 5 { - t.Errorf("The default failure threshold of the alert should've been %d, but it was %d", 5, config.Endpoints[0].Alerts[9].FailureThreshold) + if config.Endpoints[0].Alerts[9].FailureThreshold != 3 { + t.Errorf("The default failure threshold of the alert should've been %d, but it was %d", 3, config.Endpoints[0].Alerts[9].FailureThreshold) } - if config.Endpoints[0].Alerts[9].SuccessThreshold != 3 { - t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 3, config.Endpoints[0].Alerts[9].SuccessThreshold) + if config.Endpoints[0].Alerts[9].SuccessThreshold != 2 { + t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Endpoints[0].Alerts[9].SuccessThreshold) } - if config.Endpoints[0].Alerts[10].Type != alert.TypeEmail { - t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeEmail, config.Endpoints[0].Alerts[10].Type) + if config.Endpoints[0].Alerts[10].Type != alert.TypeGotify { + t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeGotify, config.Endpoints[0].Alerts[10].Type) } if !config.Endpoints[0].Alerts[10].IsEnabled() { t.Error("The alert should've been enabled") @@ -1399,19 +1362,6 @@ endpoints: if config.Endpoints[0].Alerts[10].SuccessThreshold != 2 { t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Endpoints[0].Alerts[10].SuccessThreshold) } - - if config.Endpoints[0].Alerts[11].Type != alert.TypeGotify { - t.Errorf("The type of the alert should've been %s, but it was %s", alert.TypeGotify, config.Endpoints[0].Alerts[11].Type) - } - if !config.Endpoints[0].Alerts[11].IsEnabled() { - t.Error("The alert should've been enabled") - } - if config.Endpoints[0].Alerts[11].FailureThreshold != 3 { - t.Errorf("The default failure threshold of the alert should've been %d, but it was %d", 3, config.Endpoints[0].Alerts[11].FailureThreshold) - } - if config.Endpoints[0].Alerts[11].SuccessThreshold != 2 { - t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Endpoints[0].Alerts[11].SuccessThreshold) - } } func TestParseAndValidateConfigBytesWithAlertingAndDefaultAlertAndMultipleAlertsOfSameTypeWithOverriddenParameters(t *testing.T) { @@ -1917,7 +1867,6 @@ func TestGetAlertingProviderByAlertType(t *testing.T) { IFTTT: &ifttt.AlertProvider{}, Ilert: &ilert.AlertProvider{}, IncidentIO: &incidentio.AlertProvider{}, - JetBrainsSpace: &jetbrainsspace.AlertProvider{}, Line: &line.AlertProvider{}, Matrix: &matrix.AlertProvider{}, Mattermost: &mattermost.AlertProvider{}, @@ -1962,7 +1911,6 @@ func TestGetAlertingProviderByAlertType(t *testing.T) { {alertType: alert.TypeIFTTT, expected: alertingConfig.IFTTT}, {alertType: alert.TypeIlert, expected: alertingConfig.Ilert}, {alertType: alert.TypeIncidentIO, expected: alertingConfig.IncidentIO}, - {alertType: alert.TypeJetBrainsSpace, expected: alertingConfig.JetBrainsSpace}, {alertType: alert.TypeLine, expected: alertingConfig.Line}, {alertType: alert.TypeMatrix, expected: alertingConfig.Matrix}, {alertType: alert.TypeMattermost, expected: alertingConfig.Mattermost}, diff --git a/watchdog/alerting_test.go b/watchdog/alerting_test.go index 25fc7094..2c9ccd92 100644 --- a/watchdog/alerting_test.go +++ b/watchdog/alerting_test.go @@ -12,7 +12,6 @@ import ( "github.com/TwiN/gatus/v5/alerting/provider/discord" "github.com/TwiN/gatus/v5/alerting/provider/email" "github.com/TwiN/gatus/v5/alerting/provider/ifttt" - "github.com/TwiN/gatus/v5/alerting/provider/jetbrainsspace" "github.com/TwiN/gatus/v5/alerting/provider/line" "github.com/TwiN/gatus/v5/alerting/provider/matrix" "github.com/TwiN/gatus/v5/alerting/provider/mattermost" @@ -325,19 +324,6 @@ func TestHandleAlertingWithProviderThatReturnsAnError(t *testing.T) { }, }, }, - { - Name: "jetbrainsspace", - AlertType: alert.TypeJetBrainsSpace, - AlertingConfig: &alerting.Config{ - JetBrainsSpace: &jetbrainsspace.AlertProvider{ - DefaultConfig: jetbrainsspace.Config{ - Project: "foo", - ChannelID: "bar", - Token: "baz", - }, - }, - }, - }, { Name: "line", AlertType: alert.TypeLine,