mirror of
https://github.com/TwiN/gatus.git
synced 2025-01-20 12:58:36 +01:00
Close #48: Implement Discord alerting providers
This commit is contained in:
parent
c094c06e56
commit
8fe9d013b5
42
README.md
42
README.md
@ -26,6 +26,7 @@ core applications: https://status.twinnation.org/
|
|||||||
- [Functions](#functions)
|
- [Functions](#functions)
|
||||||
- [Alerting](#alerting)
|
- [Alerting](#alerting)
|
||||||
- [Configuring Slack alerts](#configuring-slack-alerts)
|
- [Configuring Slack alerts](#configuring-slack-alerts)
|
||||||
|
- [Configuring Discord alerts](#configuring-discord-alerts)
|
||||||
- [Configuring PagerDuty alerts](#configuring-pagerduty-alerts)
|
- [Configuring PagerDuty alerts](#configuring-pagerduty-alerts)
|
||||||
- [Configuring Twilio alerts](#configuring-twilio-alerts)
|
- [Configuring Twilio alerts](#configuring-twilio-alerts)
|
||||||
- [Configuring Mattermost alerts](#configuring-mattermost-alerts)
|
- [Configuring Mattermost alerts](#configuring-mattermost-alerts)
|
||||||
@ -118,7 +119,7 @@ Note that you can also add environment variables in the configuration file (i.e.
|
|||||||
| `services[].dns` | Configuration for a service of type DNS. See [Monitoring using DNS queries](#monitoring-using-dns-queries) | `""` |
|
| `services[].dns` | Configuration for a service of type DNS. See [Monitoring using DNS queries](#monitoring-using-dns-queries) | `""` |
|
||||||
| `services[].dns.query-type` | Query type for DNS service | `""` |
|
| `services[].dns.query-type` | Query type for DNS service | `""` |
|
||||||
| `services[].dns.query-name` | Query name for DNS service | `""` |
|
| `services[].dns.query-name` | Query name for DNS service | `""` |
|
||||||
| `services[].alerts[].type` | Type of alert. Valid types: `slack`, `pagerduty`, `twilio`, `mattermost`, `messagebird`, `custom` | Required `""` |
|
| `services[].alerts[].type` | Type of alert. Valid types: `slack`, `discord`m `pagerduty`, `twilio`, `mattermost`, `messagebird`, `custom` | Required `""` |
|
||||||
| `services[].alerts[].enabled` | Whether to enable the alert | `false` |
|
| `services[].alerts[].enabled` | Whether to enable the alert | `false` |
|
||||||
| `services[].alerts[].failure-threshold` | Number of failures in a row needed before triggering the alert | `3` |
|
| `services[].alerts[].failure-threshold` | Number of failures in a row needed before triggering the alert | `3` |
|
||||||
| `services[].alerts[].success-threshold` | Number of successes in a row before an ongoing incident is marked as resolved | `2` |
|
| `services[].alerts[].success-threshold` | Number of successes in a row before an ongoing incident is marked as resolved | `2` |
|
||||||
@ -127,6 +128,8 @@ Note that you can also add environment variables in the configuration file (i.e.
|
|||||||
| `alerting` | Configuration for alerting | `{}` |
|
| `alerting` | Configuration for alerting | `{}` |
|
||||||
| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
|
| `alerting.slack` | Configuration for alerts of type `slack` | `{}` |
|
||||||
| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
|
| `alerting.slack.webhook-url` | Slack Webhook URL | Required `""` |
|
||||||
|
| `alerting.discord` | Configuration for alerts of type `discord` | `{}` |
|
||||||
|
| `alerting.discord.webhook-url` | Discord Webhook URL | Required `""` |
|
||||||
| `alerting.pagerduty` | Configuration for alerts of type `pagerduty` | `{}` |
|
| `alerting.pagerduty` | Configuration for alerts of type `pagerduty` | `{}` |
|
||||||
| `alerting.pagerduty.integration-key` | PagerDuty Events API v2 integration key. | Required `""` |
|
| `alerting.pagerduty.integration-key` | PagerDuty Events API v2 integration key. | Required `""` |
|
||||||
| `alerting.twilio` | Settings for alerts of type `twilio` | `{}` |
|
| `alerting.twilio` | Settings for alerts of type `twilio` | `{}` |
|
||||||
@ -223,6 +226,7 @@ ignored.
|
|||||||
alerting:
|
alerting:
|
||||||
slack:
|
slack:
|
||||||
webhook-url: "https://hooks.slack.com/services/**********/**********/**********"
|
webhook-url: "https://hooks.slack.com/services/**********/**********/**********"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
url: "https://twinnation.org/health"
|
url: "https://twinnation.org/health"
|
||||||
@ -248,6 +252,29 @@ Here's an example of what the notifications look like:
|
|||||||
![Slack notifications](.github/assets/slack-alerts.png)
|
![Slack notifications](.github/assets/slack-alerts.png)
|
||||||
|
|
||||||
|
|
||||||
|
#### Configuring Discord alerts
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
alerting:
|
||||||
|
discord:
|
||||||
|
webhook-url: "https://discord.com/api/webhooks/**********/**********"
|
||||||
|
|
||||||
|
services:
|
||||||
|
- name: twinnation
|
||||||
|
url: "https://twinnation.org/health"
|
||||||
|
interval: 30s
|
||||||
|
alerts:
|
||||||
|
- type: discord
|
||||||
|
enabled: true
|
||||||
|
description: "healthcheck failed"
|
||||||
|
send-on-resolved: true
|
||||||
|
conditions:
|
||||||
|
- "[STATUS] == 200"
|
||||||
|
- "[BODY].status == UP"
|
||||||
|
- "[RESPONSE_TIME] < 300"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
#### Configuring PagerDuty alerts
|
#### Configuring PagerDuty alerts
|
||||||
|
|
||||||
It is highly recommended to set `services[].alerts[].send-on-resolved` to `true` for alerts
|
It is highly recommended to set `services[].alerts[].send-on-resolved` to `true` for alerts
|
||||||
@ -259,6 +286,7 @@ PagerDuty instead.
|
|||||||
alerting:
|
alerting:
|
||||||
pagerduty:
|
pagerduty:
|
||||||
integration-key: "********************************"
|
integration-key: "********************************"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
url: "https://twinnation.org/health"
|
url: "https://twinnation.org/health"
|
||||||
@ -269,7 +297,7 @@ services:
|
|||||||
failure-threshold: 3
|
failure-threshold: 3
|
||||||
success-threshold: 5
|
success-threshold: 5
|
||||||
send-on-resolved: true
|
send-on-resolved: true
|
||||||
description: "healthcheck failed 3 times in a row"
|
description: "healthcheck failed"
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
- "[BODY].status == UP"
|
- "[BODY].status == UP"
|
||||||
@ -286,6 +314,7 @@ alerting:
|
|||||||
token: "..."
|
token: "..."
|
||||||
from: "+1-234-567-8901"
|
from: "+1-234-567-8901"
|
||||||
to: "+1-234-567-8901"
|
to: "+1-234-567-8901"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@ -295,7 +324,7 @@ services:
|
|||||||
enabled: true
|
enabled: true
|
||||||
failure-threshold: 5
|
failure-threshold: 5
|
||||||
send-on-resolved: true
|
send-on-resolved: true
|
||||||
description: "healthcheck failed 5 times in a row"
|
description: "healthcheck failed"
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
- "[BODY].status == UP"
|
- "[BODY].status == UP"
|
||||||
@ -310,6 +339,7 @@ alerting:
|
|||||||
mattermost:
|
mattermost:
|
||||||
webhook-url: "http://**********/hooks/**********"
|
webhook-url: "http://**********/hooks/**********"
|
||||||
insecure: true
|
insecure: true
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
url: "https://twinnation.org/health"
|
url: "https://twinnation.org/health"
|
||||||
@ -317,7 +347,7 @@ services:
|
|||||||
alerts:
|
alerts:
|
||||||
- type: mattermost
|
- type: mattermost
|
||||||
enabled: true
|
enabled: true
|
||||||
description: "healthcheck failed 3 times in a row"
|
description: "healthcheck failed"
|
||||||
send-on-resolved: true
|
send-on-resolved: true
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
@ -349,7 +379,7 @@ services:
|
|||||||
enabled: true
|
enabled: true
|
||||||
failure-threshold: 3
|
failure-threshold: 3
|
||||||
send-on-resolved: true
|
send-on-resolved: true
|
||||||
description: "healthcheck failed 3 times in a row"
|
description: "healthcheck failed"
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
- "[BODY].status == UP"
|
- "[BODY].status == UP"
|
||||||
@ -395,7 +425,7 @@ services:
|
|||||||
failure-threshold: 10
|
failure-threshold: 10
|
||||||
success-threshold: 3
|
success-threshold: 3
|
||||||
send-on-resolved: true
|
send-on-resolved: true
|
||||||
description: "healthcheck failed 10 times in a row"
|
description: "healthcheck failed"
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
- "[BODY].status == UP"
|
- "[BODY].status == UP"
|
||||||
|
@ -2,6 +2,7 @@ package alerting
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/discord"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/mattermost"
|
"github.com/TwinProduction/gatus/alerting/provider/mattermost"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/messagebird"
|
"github.com/TwinProduction/gatus/alerting/provider/messagebird"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/pagerduty"
|
"github.com/TwinProduction/gatus/alerting/provider/pagerduty"
|
||||||
@ -11,8 +12,11 @@ import (
|
|||||||
|
|
||||||
// Config is the configuration for alerting providers
|
// Config is the configuration for alerting providers
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Slack is the configuration for the slack alerting provider
|
// Custom is the configuration for the custom alerting provider
|
||||||
Slack *slack.AlertProvider `yaml:"slack"`
|
Custom *custom.AlertProvider `yaml:"custom"`
|
||||||
|
|
||||||
|
// Discord is the configuration for the discord alerting provider
|
||||||
|
Discord *discord.AlertProvider `yaml:"discord"`
|
||||||
|
|
||||||
// Mattermost is the configuration for the mattermost alerting provider
|
// Mattermost is the configuration for the mattermost alerting provider
|
||||||
Mattermost *mattermost.AlertProvider `yaml:"mattermost"`
|
Mattermost *mattermost.AlertProvider `yaml:"mattermost"`
|
||||||
@ -20,12 +24,12 @@ type Config struct {
|
|||||||
// Messagebird is the configuration for the messagebird alerting provider
|
// Messagebird is the configuration for the messagebird alerting provider
|
||||||
Messagebird *messagebird.AlertProvider `yaml:"messagebird"`
|
Messagebird *messagebird.AlertProvider `yaml:"messagebird"`
|
||||||
|
|
||||||
// Pagerduty is the configuration for the pagerduty alerting provider
|
// PagerDuty is the configuration for the pagerduty alerting provider
|
||||||
PagerDuty *pagerduty.AlertProvider `yaml:"pagerduty"`
|
PagerDuty *pagerduty.AlertProvider `yaml:"pagerduty"`
|
||||||
|
|
||||||
|
// Slack is the configuration for the slack alerting provider
|
||||||
|
Slack *slack.AlertProvider `yaml:"slack"`
|
||||||
|
|
||||||
// Twilio is the configuration for the twilio alerting provider
|
// Twilio is the configuration for the twilio alerting provider
|
||||||
Twilio *twilio.AlertProvider `yaml:"twilio"`
|
Twilio *twilio.AlertProvider `yaml:"twilio"`
|
||||||
|
|
||||||
// Custom is the configuration for the custom alerting provider
|
|
||||||
Custom *custom.AlertProvider `yaml:"custom"`
|
|
||||||
}
|
}
|
||||||
|
63
alerting/provider/discord/discord.go
Normal file
63
alerting/provider/discord/discord.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
||||||
|
"github.com/TwinProduction/gatus/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AlertProvider is the configuration necessary for sending an alert using Discord
|
||||||
|
type AlertProvider struct {
|
||||||
|
WebhookURL string `yaml:"webhook-url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid returns whether the provider's configuration is valid
|
||||||
|
func (provider *AlertProvider) IsValid() bool {
|
||||||
|
return len(provider.WebhookURL) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCustomAlertProvider converts the provider into a custom.AlertProvider
|
||||||
|
func (provider *AlertProvider) ToCustomAlertProvider(service *core.Service, alert *core.Alert, result *core.Result, resolved bool) *custom.AlertProvider {
|
||||||
|
var message, results string
|
||||||
|
var colorCode int
|
||||||
|
if resolved {
|
||||||
|
message = fmt.Sprintf("An alert for **%s** has been resolved after passing successfully %d time(s) in a row", service.Name, alert.SuccessThreshold)
|
||||||
|
colorCode = 3066993
|
||||||
|
} else {
|
||||||
|
message = fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", service.Name, alert.FailureThreshold)
|
||||||
|
colorCode = 15158332
|
||||||
|
}
|
||||||
|
for _, conditionResult := range result.ConditionResults {
|
||||||
|
var prefix string
|
||||||
|
if conditionResult.Success {
|
||||||
|
prefix = ":white_check_mark:"
|
||||||
|
} else {
|
||||||
|
prefix = ":x:"
|
||||||
|
}
|
||||||
|
results += fmt.Sprintf("%s - `%s`\\n", prefix, conditionResult.Condition)
|
||||||
|
}
|
||||||
|
return &custom.AlertProvider{
|
||||||
|
URL: provider.WebhookURL,
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Body: fmt.Sprintf(`{
|
||||||
|
"content": "",
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
"title": ":helmet_with_white_cross: Gatus",
|
||||||
|
"description": "%s:\n> %s",
|
||||||
|
"color": %d,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Condition results",
|
||||||
|
"value": "%s",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`, message, alert.Description, colorCode, results),
|
||||||
|
Headers: map[string]string{"Content-Type": "application/json"},
|
||||||
|
}
|
||||||
|
}
|
65
alerting/provider/discord/discord_test.go
Normal file
65
alerting/provider/discord/discord_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TwinProduction/gatus/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAlertProvider_IsValid(t *testing.T) {
|
||||||
|
invalidProvider := AlertProvider{WebhookURL: ""}
|
||||||
|
if invalidProvider.IsValid() {
|
||||||
|
t.Error("provider shouldn't have been valid")
|
||||||
|
}
|
||||||
|
validProvider := AlertProvider{WebhookURL: "http://example.com"}
|
||||||
|
if !validProvider.IsValid() {
|
||||||
|
t.Error("provider should've been valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlertProvider_ToCustomAlertProviderWithResolvedAlert(t *testing.T) {
|
||||||
|
provider := AlertProvider{WebhookURL: "http://example.com"}
|
||||||
|
customAlertProvider := provider.ToCustomAlertProvider(&core.Service{}, &core.Alert{}, &core.Result{ConditionResults: []*core.ConditionResult{{Condition: "SUCCESSFUL_CONDITION", Success: true}}}, true)
|
||||||
|
if customAlertProvider == nil {
|
||||||
|
t.Fatal("customAlertProvider shouldn't have been nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(customAlertProvider.Body, "resolved") {
|
||||||
|
t.Error("customAlertProvider.Body should've contained the substring resolved")
|
||||||
|
}
|
||||||
|
if customAlertProvider.URL != "http://example.com" {
|
||||||
|
t.Errorf("expected URL to be %s, got %s", "http://example.com", customAlertProvider.URL)
|
||||||
|
}
|
||||||
|
if customAlertProvider.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected method to be %s, got %s", http.MethodPost, customAlertProvider.Method)
|
||||||
|
}
|
||||||
|
body := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal([]byte(customAlertProvider.Body), &body)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("expected body to be valid JSON, got error:", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAlertProvider_ToCustomAlertProviderWithTriggeredAlert(t *testing.T) {
|
||||||
|
provider := AlertProvider{WebhookURL: "http://example.com"}
|
||||||
|
customAlertProvider := provider.ToCustomAlertProvider(&core.Service{}, &core.Alert{}, &core.Result{ConditionResults: []*core.ConditionResult{{Condition: "UNSUCCESSFUL_CONDITION", Success: false}}}, false)
|
||||||
|
if customAlertProvider == nil {
|
||||||
|
t.Fatal("customAlertProvider shouldn't have been nil")
|
||||||
|
}
|
||||||
|
if !strings.Contains(customAlertProvider.Body, "triggered") {
|
||||||
|
t.Error("customAlertProvider.Body should've contained the substring triggered")
|
||||||
|
}
|
||||||
|
if customAlertProvider.URL != "http://example.com" {
|
||||||
|
t.Errorf("expected URL to be %s, got %s", "http://example.com", customAlertProvider.URL)
|
||||||
|
}
|
||||||
|
if customAlertProvider.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected method to be %s, got %s", http.MethodPost, customAlertProvider.Method)
|
||||||
|
}
|
||||||
|
body := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal([]byte(customAlertProvider.Body), &body)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("expected body to be valid JSON, got error:", err.Error())
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package provider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/discord"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/mattermost"
|
"github.com/TwinProduction/gatus/alerting/provider/mattermost"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/messagebird"
|
"github.com/TwinProduction/gatus/alerting/provider/messagebird"
|
||||||
"github.com/TwinProduction/gatus/alerting/provider/pagerduty"
|
"github.com/TwinProduction/gatus/alerting/provider/pagerduty"
|
||||||
@ -22,9 +23,10 @@ type AlertProvider interface {
|
|||||||
var (
|
var (
|
||||||
// Validate interface implementation on compile
|
// Validate interface implementation on compile
|
||||||
_ AlertProvider = (*custom.AlertProvider)(nil)
|
_ AlertProvider = (*custom.AlertProvider)(nil)
|
||||||
_ AlertProvider = (*twilio.AlertProvider)(nil)
|
_ AlertProvider = (*discord.AlertProvider)(nil)
|
||||||
_ AlertProvider = (*slack.AlertProvider)(nil)
|
|
||||||
_ AlertProvider = (*mattermost.AlertProvider)(nil)
|
_ AlertProvider = (*mattermost.AlertProvider)(nil)
|
||||||
_ AlertProvider = (*messagebird.AlertProvider)(nil)
|
_ AlertProvider = (*messagebird.AlertProvider)(nil)
|
||||||
_ AlertProvider = (*pagerduty.AlertProvider)(nil)
|
_ AlertProvider = (*pagerduty.AlertProvider)(nil)
|
||||||
|
_ AlertProvider = (*slack.AlertProvider)(nil)
|
||||||
|
_ AlertProvider = (*twilio.AlertProvider)(nil)
|
||||||
)
|
)
|
||||||
|
@ -228,12 +228,13 @@ func validateAlertingConfig(config *Config) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
alertTypes := []core.AlertType{
|
alertTypes := []core.AlertType{
|
||||||
core.SlackAlert,
|
core.CustomAlert,
|
||||||
|
core.DiscordAlert,
|
||||||
core.MattermostAlert,
|
core.MattermostAlert,
|
||||||
core.MessagebirdAlert,
|
core.MessagebirdAlert,
|
||||||
core.TwilioAlert,
|
|
||||||
core.PagerDutyAlert,
|
core.PagerDutyAlert,
|
||||||
core.CustomAlert,
|
core.SlackAlert,
|
||||||
|
core.TwilioAlert,
|
||||||
}
|
}
|
||||||
var validProviders, invalidProviders []core.AlertType
|
var validProviders, invalidProviders []core.AlertType
|
||||||
for _, alertType := range alertTypes {
|
for _, alertType := range alertTypes {
|
||||||
@ -255,12 +256,18 @@ func validateAlertingConfig(config *Config) {
|
|||||||
// GetAlertingProviderByAlertType returns an provider.AlertProvider by its corresponding core.AlertType
|
// GetAlertingProviderByAlertType returns an provider.AlertProvider by its corresponding core.AlertType
|
||||||
func GetAlertingProviderByAlertType(config *Config, alertType core.AlertType) provider.AlertProvider {
|
func GetAlertingProviderByAlertType(config *Config, alertType core.AlertType) provider.AlertProvider {
|
||||||
switch alertType {
|
switch alertType {
|
||||||
case core.SlackAlert:
|
case core.CustomAlert:
|
||||||
if config.Alerting.Slack == nil {
|
if config.Alerting.Custom == nil {
|
||||||
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return config.Alerting.Slack
|
return config.Alerting.Custom
|
||||||
|
case core.DiscordAlert:
|
||||||
|
if config.Alerting.Discord == nil {
|
||||||
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return config.Alerting.Discord
|
||||||
case core.MattermostAlert:
|
case core.MattermostAlert:
|
||||||
if config.Alerting.Mattermost == nil {
|
if config.Alerting.Mattermost == nil {
|
||||||
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
@ -273,24 +280,24 @@ func GetAlertingProviderByAlertType(config *Config, alertType core.AlertType) pr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return config.Alerting.Messagebird
|
return config.Alerting.Messagebird
|
||||||
case core.TwilioAlert:
|
|
||||||
if config.Alerting.Twilio == nil {
|
|
||||||
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return config.Alerting.Twilio
|
|
||||||
case core.PagerDutyAlert:
|
case core.PagerDutyAlert:
|
||||||
if config.Alerting.PagerDuty == nil {
|
if config.Alerting.PagerDuty == nil {
|
||||||
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return config.Alerting.PagerDuty
|
return config.Alerting.PagerDuty
|
||||||
case core.CustomAlert:
|
case core.SlackAlert:
|
||||||
if config.Alerting.Custom == nil {
|
if config.Alerting.Slack == nil {
|
||||||
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return config.Alerting.Custom
|
return config.Alerting.Slack
|
||||||
|
case core.TwilioAlert:
|
||||||
|
if config.Alerting.Twilio == nil {
|
||||||
|
// Since we're returning an interface, we need to explicitly return nil, even if the provider itself is nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return config.Alerting.Twilio
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/TwinProduction/gatus/alerting"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/custom"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/discord"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/mattermost"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/messagebird"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/pagerduty"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/slack"
|
||||||
|
"github.com/TwinProduction/gatus/alerting/provider/twilio"
|
||||||
"github.com/TwinProduction/gatus/core"
|
"github.com/TwinProduction/gatus/core"
|
||||||
"github.com/TwinProduction/gatus/k8stest"
|
"github.com/TwinProduction/gatus/k8stest"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
@ -338,6 +346,8 @@ debug: true
|
|||||||
alerting:
|
alerting:
|
||||||
slack:
|
slack:
|
||||||
webhook-url: "http://example.com"
|
webhook-url: "http://example.com"
|
||||||
|
discord:
|
||||||
|
webhook-url: "http://example.org"
|
||||||
pagerduty:
|
pagerduty:
|
||||||
integration-key: "00000000000000000000000000000000"
|
integration-key: "00000000000000000000000000000000"
|
||||||
messagebird:
|
messagebird:
|
||||||
@ -356,7 +366,9 @@ services:
|
|||||||
success-threshold: 5
|
success-threshold: 5
|
||||||
description: "Healthcheck failed 7 times in a row"
|
description: "Healthcheck failed 7 times in a row"
|
||||||
- type: messagebird
|
- type: messagebird
|
||||||
|
- type: discord
|
||||||
enabled: true
|
enabled: true
|
||||||
|
failure-threshold: 10
|
||||||
conditions:
|
conditions:
|
||||||
- "[STATUS] == 200"
|
- "[STATUS] == 200"
|
||||||
`))
|
`))
|
||||||
@ -369,6 +381,7 @@ services:
|
|||||||
if config.Metrics {
|
if config.Metrics {
|
||||||
t.Error("Metrics should've been false by default")
|
t.Error("Metrics should've been false by default")
|
||||||
}
|
}
|
||||||
|
// Alerting providers
|
||||||
if config.Alerting == nil {
|
if config.Alerting == nil {
|
||||||
t.Fatal("config.Alerting shouldn't have been nil")
|
t.Fatal("config.Alerting shouldn't have been nil")
|
||||||
}
|
}
|
||||||
@ -396,6 +409,16 @@ services:
|
|||||||
if config.Alerting.Messagebird.Recipients != "31619191919" {
|
if config.Alerting.Messagebird.Recipients != "31619191919" {
|
||||||
t.Errorf("Messagebird to recipients should've been %s, but was %s", "31619191919", config.Alerting.Messagebird.Recipients)
|
t.Errorf("Messagebird to recipients should've been %s, but was %s", "31619191919", config.Alerting.Messagebird.Recipients)
|
||||||
}
|
}
|
||||||
|
if config.Alerting.Discord == nil || !config.Alerting.Discord.IsValid() {
|
||||||
|
t.Fatal("Discord alerting config should've been valid")
|
||||||
|
}
|
||||||
|
if config.Alerting.Discord.WebhookURL != "http://example.org" {
|
||||||
|
t.Errorf("Discord webhook should've been %s, but was %s", "http://example.org", config.Alerting.Discord.WebhookURL)
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(config, core.DiscordAlert) != config.Alerting.Discord {
|
||||||
|
t.Error("expected discord configuration")
|
||||||
|
}
|
||||||
|
// Services
|
||||||
if len(config.Services) != 1 {
|
if len(config.Services) != 1 {
|
||||||
t.Error("There should've been 1 service")
|
t.Error("There should've been 1 service")
|
||||||
}
|
}
|
||||||
@ -405,11 +428,12 @@ services:
|
|||||||
if config.Services[0].Interval != 60*time.Second {
|
if config.Services[0].Interval != 60*time.Second {
|
||||||
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
||||||
}
|
}
|
||||||
if config.Services[0].Alerts == nil {
|
if len(config.Services[0].Alerts) != 4 {
|
||||||
t.Fatal("The service alerts shouldn't have been nil")
|
t.Fatal("There should've been 4 alerts configured")
|
||||||
}
|
}
|
||||||
if len(config.Services[0].Alerts) != 3 {
|
|
||||||
t.Fatal("There should've been 3 alert configured")
|
if config.Services[0].Alerts[0].Type != core.SlackAlert {
|
||||||
|
t.Errorf("The type of the alert should've been %s, but it was %s", core.SlackAlert, config.Services[0].Alerts[0].Type)
|
||||||
}
|
}
|
||||||
if !config.Services[0].Alerts[0].Enabled {
|
if !config.Services[0].Alerts[0].Enabled {
|
||||||
t.Error("The alert should've been enabled")
|
t.Error("The alert should've been enabled")
|
||||||
@ -420,23 +444,35 @@ services:
|
|||||||
if config.Services[0].Alerts[0].SuccessThreshold != 2 {
|
if config.Services[0].Alerts[0].SuccessThreshold != 2 {
|
||||||
t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Services[0].Alerts[0].SuccessThreshold)
|
t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Services[0].Alerts[0].SuccessThreshold)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Services[0].Alerts[1].Type != core.PagerDutyAlert {
|
||||||
|
t.Errorf("The type of the alert should've been %s, but it was %s", core.PagerDutyAlert, config.Services[0].Alerts[1].Type)
|
||||||
|
}
|
||||||
|
if config.Services[0].Alerts[1].Description != "Healthcheck failed 7 times in a row" {
|
||||||
|
t.Errorf("The description of the alert should've been %s, but it was %s", "Healthcheck failed 7 times in a row", config.Services[0].Alerts[1].Description)
|
||||||
|
}
|
||||||
if config.Services[0].Alerts[1].FailureThreshold != 7 {
|
if config.Services[0].Alerts[1].FailureThreshold != 7 {
|
||||||
t.Errorf("The failure threshold of the alert should've been %d, but it was %d", 7, config.Services[0].Alerts[1].FailureThreshold)
|
t.Errorf("The failure threshold of the alert should've been %d, but it was %d", 7, config.Services[0].Alerts[1].FailureThreshold)
|
||||||
}
|
}
|
||||||
if config.Services[0].Alerts[1].SuccessThreshold != 5 {
|
if config.Services[0].Alerts[1].SuccessThreshold != 5 {
|
||||||
t.Errorf("The success threshold of the alert should've been %d, but it was %d", 5, config.Services[0].Alerts[1].SuccessThreshold)
|
t.Errorf("The success threshold of the alert should've been %d, but it was %d", 5, config.Services[0].Alerts[1].SuccessThreshold)
|
||||||
}
|
}
|
||||||
if config.Services[0].Alerts[0].Type != core.SlackAlert {
|
|
||||||
t.Errorf("The type of the alert should've been %s, but it was %s", core.SlackAlert, config.Services[0].Alerts[0].Type)
|
|
||||||
}
|
|
||||||
if config.Services[0].Alerts[1].Type != core.PagerDutyAlert {
|
|
||||||
t.Errorf("The type of the alert should've been %s, but it was %s", core.PagerDutyAlert, config.Services[0].Alerts[1].Type)
|
|
||||||
}
|
|
||||||
if config.Services[0].Alerts[1].Description != "Healthcheck failed 7 times in a row" {
|
|
||||||
t.Errorf("The description of the alert should've been %s, but it was %s", "Healthcheck failed 7 times in a row", config.Services[0].Alerts[0].Description)
|
|
||||||
}
|
|
||||||
if config.Services[0].Alerts[2].Type != core.MessagebirdAlert {
|
if config.Services[0].Alerts[2].Type != core.MessagebirdAlert {
|
||||||
t.Errorf("The type of the alert should've been %s, but it was %s", core.MessagebirdAlert, config.Services[0].Alerts[1].Type)
|
t.Errorf("The type of the alert should've been %s, but it was %s", core.MessagebirdAlert, config.Services[0].Alerts[2].Type)
|
||||||
|
}
|
||||||
|
if config.Services[0].Alerts[2].Enabled {
|
||||||
|
t.Error("The alert should've been disabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.Services[0].Alerts[3].Type != core.DiscordAlert {
|
||||||
|
t.Errorf("The type of the alert should've been %s, but it was %s", core.DiscordAlert, config.Services[0].Alerts[3].Type)
|
||||||
|
}
|
||||||
|
if config.Services[0].Alerts[3].FailureThreshold != 10 {
|
||||||
|
t.Errorf("The failure threshold of the alert should've been %d, but it was %d", 10, config.Services[0].Alerts[3].FailureThreshold)
|
||||||
|
}
|
||||||
|
if config.Services[0].Alerts[3].SuccessThreshold != 2 {
|
||||||
|
t.Errorf("The default success threshold of the alert should've been %d, but it was %d", 2, config.Services[0].Alerts[3].SuccessThreshold)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,3 +845,38 @@ kubernetes:
|
|||||||
// TODO: find a way to test this?
|
// TODO: find a way to test this?
|
||||||
t.Error("Function should've panicked because testing with ClusterModeIn isn't supported")
|
t.Error("Function should've panicked because testing with ClusterModeIn isn't supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAlertingProviderByAlertType(t *testing.T) {
|
||||||
|
cfg := &Config{
|
||||||
|
Alerting: &alerting.Config{
|
||||||
|
Custom: &custom.AlertProvider{},
|
||||||
|
Discord: &discord.AlertProvider{},
|
||||||
|
Mattermost: &mattermost.AlertProvider{},
|
||||||
|
Messagebird: &messagebird.AlertProvider{},
|
||||||
|
PagerDuty: &pagerduty.AlertProvider{},
|
||||||
|
Slack: &slack.AlertProvider{},
|
||||||
|
Twilio: &twilio.AlertProvider{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.CustomAlert) != cfg.Alerting.Custom {
|
||||||
|
t.Error("expected Custom configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.DiscordAlert) != cfg.Alerting.Discord {
|
||||||
|
t.Error("expected Discord configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.MattermostAlert) != cfg.Alerting.Mattermost {
|
||||||
|
t.Error("expected Mattermost configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.MessagebirdAlert) != cfg.Alerting.Messagebird {
|
||||||
|
t.Error("expected Messagebird configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.PagerDutyAlert) != cfg.Alerting.PagerDuty {
|
||||||
|
t.Error("expected PagerDuty configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.SlackAlert) != cfg.Alerting.Slack {
|
||||||
|
t.Error("expected Slack configuration")
|
||||||
|
}
|
||||||
|
if GetAlertingProviderByAlertType(cfg, core.TwilioAlert) != cfg.Alerting.Twilio {
|
||||||
|
t.Error("expected Twilio configuration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,8 +40,11 @@ type Alert struct {
|
|||||||
type AlertType string
|
type AlertType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// SlackAlert is the AlertType for the slack alerting provider
|
// CustomAlert is the AlertType for the custom alerting provider
|
||||||
SlackAlert AlertType = "slack"
|
CustomAlert AlertType = "custom"
|
||||||
|
|
||||||
|
// DiscordAlert is the AlertType for the discord alerting provider
|
||||||
|
DiscordAlert AlertType = "discord"
|
||||||
|
|
||||||
// MattermostAlert is the AlertType for the mattermost alerting provider
|
// MattermostAlert is the AlertType for the mattermost alerting provider
|
||||||
MattermostAlert AlertType = "mattermost"
|
MattermostAlert AlertType = "mattermost"
|
||||||
@ -52,9 +55,9 @@ const (
|
|||||||
// PagerDutyAlert is the AlertType for the pagerduty alerting provider
|
// PagerDutyAlert is the AlertType for the pagerduty alerting provider
|
||||||
PagerDutyAlert AlertType = "pagerduty"
|
PagerDutyAlert AlertType = "pagerduty"
|
||||||
|
|
||||||
|
// SlackAlert is the AlertType for the slack alerting provider
|
||||||
|
SlackAlert AlertType = "slack"
|
||||||
|
|
||||||
// TwilioAlert is the AlertType for the twilio alerting provider
|
// TwilioAlert is the AlertType for the twilio alerting provider
|
||||||
TwilioAlert AlertType = "twilio"
|
TwilioAlert AlertType = "twilio"
|
||||||
|
|
||||||
// CustomAlert is the AlertType for the custom alerting provider
|
|
||||||
CustomAlert AlertType = "custom"
|
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user