2021-01-10 04:55:36 +01:00
package watchdog
import (
2021-01-10 07:22:27 +01:00
"os"
2021-01-10 04:55:36 +01:00
"testing"
2021-10-08 03:28:04 +02:00
"github.com/TwiN/gatus/v3/alerting"
"github.com/TwiN/gatus/v3/alerting/alert"
"github.com/TwiN/gatus/v3/alerting/provider/custom"
2021-12-03 04:15:51 +01:00
"github.com/TwiN/gatus/v3/alerting/provider/discord"
"github.com/TwiN/gatus/v3/alerting/provider/email"
"github.com/TwiN/gatus/v3/alerting/provider/mattermost"
"github.com/TwiN/gatus/v3/alerting/provider/messagebird"
2021-10-08 03:28:04 +02:00
"github.com/TwiN/gatus/v3/alerting/provider/pagerduty"
2021-12-03 04:15:51 +01:00
"github.com/TwiN/gatus/v3/alerting/provider/slack"
"github.com/TwiN/gatus/v3/alerting/provider/teams"
"github.com/TwiN/gatus/v3/alerting/provider/telegram"
"github.com/TwiN/gatus/v3/alerting/provider/twilio"
2021-10-08 03:28:04 +02:00
"github.com/TwiN/gatus/v3/config"
"github.com/TwiN/gatus/v3/core"
2021-01-10 04:55:36 +01:00
)
func TestHandleAlerting ( t * testing . T ) {
2021-01-10 07:22:27 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
2021-01-10 04:55:36 +01:00
cfg := & config . Config {
2021-01-10 05:52:11 +01:00
Debug : true ,
2021-01-10 04:55:36 +01:00
Alerting : & alerting . Config {
Custom : & custom . AlertProvider {
2021-09-18 18:42:11 +02:00
URL : "https://twin.sh/health" ,
2021-01-10 04:55:36 +01:00
Method : "GET" ,
} ,
} ,
}
2021-05-16 03:54:23 +02:00
enabled := true
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
URL : "https://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-10 04:55:36 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypeCustom ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-10 04:55:36 +01:00
FailureThreshold : 2 ,
SuccessThreshold : 3 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & enabled ,
2021-01-10 04:55:36 +01:00
Triggered : false ,
} ,
} ,
}
2021-10-23 22:47:12 +02:00
verify ( t , endpoint , 0 , 0 , false , "The alert shouldn't start triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 1 , 0 , false , "The alert shouldn't have triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 2 , 0 , true , "The alert should've triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 3 , 0 , true , "The alert should still be triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 4 , 0 , true , "The alert should still be triggered" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , true , "The alert should still be triggered (because endpoint.Alerts[0].SuccessThreshold is 3)" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 2 , true , "The alert should still be triggered (because endpoint.Alerts[0].SuccessThreshold is 3)" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 3 , false , "The alert should've been resolved" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 4 , false , "The alert should no longer be triggered" )
2021-01-10 04:55:36 +01:00
}
2021-01-10 05:52:11 +01:00
func TestHandleAlertingWhenAlertingConfigIsNil ( t * testing . T ) {
2021-01-10 07:22:27 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
2021-05-19 04:29:15 +02:00
HandleAlerting ( nil , nil , nil , true )
2021-01-10 05:52:11 +01:00
}
func TestHandleAlertingWithBadAlertProvider ( t * testing . T ) {
2021-01-10 07:22:27 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
2021-05-16 03:54:23 +02:00
enabled := true
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
2021-01-10 05:52:11 +01:00
URL : "http://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-10 05:52:11 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypeCustom ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-10 05:52:11 +01:00
FailureThreshold : 1 ,
SuccessThreshold : 1 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & enabled ,
2021-01-10 05:52:11 +01:00
Triggered : false ,
} ,
} ,
}
2021-10-23 22:47:12 +02:00
verify ( t , endpoint , 0 , 0 , false , "The alert shouldn't start triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , & alerting . Config { } , false )
verify ( t , endpoint , 1 , 0 , false , "The alert shouldn't have triggered" )
HandleAlerting ( endpoint , & core . Result { Success : false } , & alerting . Config { } , false )
verify ( t , endpoint , 2 , 0 , false , "The alert shouldn't have triggered, because the provider wasn't configured properly" )
2021-01-10 05:52:11 +01:00
}
2021-01-10 06:24:31 +01:00
2021-10-23 22:47:12 +02:00
func TestHandleAlertingWhenTriggeredAlertIsAlmostResolvedButendpointStartFailingAgain ( t * testing . T ) {
2021-01-10 07:22:27 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
2021-01-10 06:24:31 +01:00
cfg := & config . Config {
Debug : true ,
Alerting : & alerting . Config {
Custom : & custom . AlertProvider {
2021-09-18 18:42:11 +02:00
URL : "https://twin.sh/health" ,
2021-01-10 06:24:31 +01:00
Method : "GET" ,
} ,
} ,
}
2021-05-16 03:54:23 +02:00
enabled := true
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
2021-12-03 04:15:51 +01:00
URL : "https://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-10 06:24:31 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypeCustom ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-10 06:24:31 +01:00
FailureThreshold : 2 ,
SuccessThreshold : 3 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & enabled ,
2021-01-10 06:24:31 +01:00
Triggered : true ,
} ,
} ,
NumberOfFailuresInARow : 1 ,
}
// This test simulate an alert that was already triggered
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 2 , 0 , true , "The alert was already triggered at the beginning of this test" )
2021-01-10 06:24:31 +01:00
}
2021-01-10 07:22:27 +01:00
2021-01-10 07:32:50 +01:00
func TestHandleAlertingWhenTriggeredAlertIsResolvedButSendOnResolvedIsFalse ( t * testing . T ) {
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
cfg := & config . Config {
Debug : true ,
Alerting : & alerting . Config {
Custom : & custom . AlertProvider {
2021-09-18 18:42:11 +02:00
URL : "https://twin.sh/health" ,
2021-01-10 07:32:50 +01:00
Method : "GET" ,
} ,
} ,
}
2021-05-16 03:54:23 +02:00
enabled := true
disabled := false
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
2021-12-03 04:15:51 +01:00
URL : "https://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-10 07:32:50 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypeCustom ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-10 07:32:50 +01:00
FailureThreshold : 1 ,
SuccessThreshold : 1 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & disabled ,
2021-01-10 07:32:50 +01:00
Triggered : true ,
} ,
} ,
NumberOfFailuresInARow : 1 ,
}
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , false , "The alert should've been resolved" )
2021-01-10 07:32:50 +01:00
}
2021-01-10 07:22:27 +01:00
func TestHandleAlertingWhenTriggeredAlertIsResolvedPagerDuty ( t * testing . T ) {
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
cfg := & config . Config {
Debug : true ,
Alerting : & alerting . Config {
PagerDuty : & pagerduty . AlertProvider {
IntegrationKey : "00000000000000000000000000000000" ,
} ,
} ,
}
2021-05-16 03:54:23 +02:00
enabled := true
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
2021-12-03 04:15:51 +01:00
URL : "https://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-10 07:22:27 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypePagerDuty ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-10 07:22:27 +01:00
FailureThreshold : 1 ,
SuccessThreshold : 1 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & enabled ,
2021-01-10 07:22:27 +01:00
Triggered : false ,
} ,
} ,
NumberOfFailuresInARow : 0 ,
}
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 1 , 0 , true , "" )
2021-01-21 22:14:32 +01:00
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , false , "The alert should've been resolved" )
2021-01-21 22:14:32 +01:00
}
func TestHandleAlertingWithProviderThatReturnsAnError ( t * testing . T ) {
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
2021-12-03 04:15:51 +01:00
enabled := true
scenarios := [ ] struct {
Name string
AlertingConfig * alerting . Config
AlertType alert . Type
} {
{
Name : "custom" ,
AlertType : alert . TypeCustom ,
AlertingConfig : & alerting . Config {
Custom : & custom . AlertProvider {
URL : "https://twin.sh/health" ,
Method : "GET" ,
} ,
2021-01-21 22:14:32 +01:00
} ,
} ,
2021-12-03 04:15:51 +01:00
{
Name : "discord" ,
AlertType : alert . TypeDiscord ,
AlertingConfig : & alerting . Config {
Discord : & discord . AlertProvider {
WebhookURL : "https://example.com" ,
} ,
} ,
} ,
{
Name : "email" ,
AlertType : alert . TypeEmail ,
AlertingConfig : & alerting . Config {
Email : & email . AlertProvider {
From : "from@example.com" ,
Password : "hunter2" ,
Host : "mail.example.com" ,
Port : 587 ,
To : "to@example.com" ,
} ,
} ,
} ,
{
Name : "mattermost" ,
AlertType : alert . TypeMattermost ,
AlertingConfig : & alerting . Config {
Mattermost : & mattermost . AlertProvider {
WebhookURL : "https://example.com" ,
} ,
} ,
} ,
{
Name : "messagebird" ,
AlertType : alert . TypeMessagebird ,
AlertingConfig : & alerting . Config {
Messagebird : & messagebird . AlertProvider {
AccessKey : "1" ,
Originator : "2" ,
Recipients : "3" ,
} ,
} ,
} ,
{
Name : "pagerduty" ,
AlertType : alert . TypePagerDuty ,
AlertingConfig : & alerting . Config {
PagerDuty : & pagerduty . AlertProvider {
IntegrationKey : "00000000000000000000000000000000" ,
} ,
} ,
} ,
{
Name : "slack" ,
AlertType : alert . TypeSlack ,
AlertingConfig : & alerting . Config {
Slack : & slack . AlertProvider {
WebhookURL : "https://example.com" ,
} ,
} ,
} ,
{
Name : "teams" ,
AlertType : alert . TypeTeams ,
AlertingConfig : & alerting . Config {
Teams : & teams . AlertProvider {
WebhookURL : "https://example.com" ,
} ,
} ,
} ,
{
Name : "telegram" ,
AlertType : alert . TypeTelegram ,
AlertingConfig : & alerting . Config {
Telegram : & telegram . AlertProvider {
Token : "1" ,
ID : "2" ,
} ,
} ,
} ,
{
Name : "twilio" ,
AlertType : alert . TypeTwilio ,
AlertingConfig : & alerting . Config {
Twilio : & twilio . AlertProvider {
SID : "1" ,
Token : "2" ,
From : "3" ,
To : "4" ,
} ,
2021-01-21 22:14:32 +01:00
} ,
} ,
2021-01-10 07:22:27 +01:00
}
2021-12-03 04:15:51 +01:00
for _ , scenario := range scenarios {
t . Run ( scenario . Name , func ( t * testing . T ) {
endpoint := & core . Endpoint {
URL : "https://example.com" ,
Alerts : [ ] * alert . Alert {
{
Type : scenario . AlertType ,
Enabled : & enabled ,
FailureThreshold : 2 ,
SuccessThreshold : 2 ,
SendOnResolved : & enabled ,
Triggered : false ,
} ,
} ,
}
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "true" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 1 , 0 , false , "" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 2 , 0 , false , "The alert should have failed to trigger, because the alert provider is returning an error" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 3 , 0 , false , "The alert should still not be triggered, because the alert provider is still returning an error" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 4 , 0 , false , "The alert should still not be triggered, because the alert provider is still returning an error" )
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "false" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 5 , 0 , true , "The alert should've been triggered because the alert provider is no longer returning an error" )
HandleAlerting ( endpoint , & core . Result { Success : true } , scenario . AlertingConfig , true )
verify ( t , endpoint , 0 , 1 , true , "The alert should've still been triggered" )
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "true" )
HandleAlerting ( endpoint , & core . Result { Success : true } , scenario . AlertingConfig , true )
verify ( t , endpoint , 0 , 2 , false , "The alert should've been resolved DESPITE THE ALERT PROVIDER RETURNING AN ERROR. See Alert.Triggered for further explanation." )
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "false" )
// Make sure that everything's working as expected after a rough patch
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 1 , 0 , false , "" )
HandleAlerting ( endpoint , & core . Result { Success : false } , scenario . AlertingConfig , true )
verify ( t , endpoint , 2 , 0 , true , "The alert should have triggered" )
HandleAlerting ( endpoint , & core . Result { Success : true } , scenario . AlertingConfig , true )
verify ( t , endpoint , 0 , 1 , true , "The alert should still be triggered" )
HandleAlerting ( endpoint , & core . Result { Success : true } , scenario . AlertingConfig , true )
verify ( t , endpoint , 0 , 2 , false , "The alert should have been resolved" )
} )
}
2021-01-21 22:14:32 +01:00
}
func TestHandleAlertingWithProviderThatOnlyReturnsErrorOnResolve ( t * testing . T ) {
_ = os . Setenv ( "MOCK_ALERT_PROVIDER" , "true" )
defer os . Clearenv ( )
cfg := & config . Config {
Debug : true ,
Alerting : & alerting . Config {
Custom : & custom . AlertProvider {
2021-09-18 18:42:11 +02:00
URL : "https://twin.sh/health" ,
2021-01-21 22:14:32 +01:00
Method : "GET" ,
} ,
} ,
2021-01-10 07:22:27 +01:00
}
2021-05-16 03:54:23 +02:00
enabled := true
2021-10-23 22:47:12 +02:00
endpoint := & core . Endpoint {
2021-12-03 04:15:51 +01:00
URL : "https://example.com" ,
2021-05-19 04:29:15 +02:00
Alerts : [ ] * alert . Alert {
2021-01-21 22:14:32 +01:00
{
2021-05-19 04:29:15 +02:00
Type : alert . TypeCustom ,
2021-05-16 03:54:23 +02:00
Enabled : & enabled ,
2021-01-21 22:14:32 +01:00
FailureThreshold : 1 ,
SuccessThreshold : 1 ,
2021-05-16 03:54:23 +02:00
SendOnResolved : & enabled ,
2021-01-21 22:14:32 +01:00
Triggered : false ,
} ,
} ,
2021-01-10 07:22:27 +01:00
}
2021-01-21 22:14:32 +01:00
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 1 , 0 , true , "" )
2021-01-21 22:14:32 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "true" )
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , false , "" )
2021-01-21 22:14:32 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "false" )
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 1 , 0 , true , "" )
2021-01-21 22:14:32 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "true" )
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , false , "" )
2021-01-21 22:14:32 +01:00
_ = os . Setenv ( "MOCK_ALERT_PROVIDER_ERROR" , "false" )
// Make sure that everything's working as expected after a rough patch
2021-10-23 22:47:12 +02:00
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 1 , 0 , true , "" )
HandleAlerting ( endpoint , & core . Result { Success : false } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 2 , 0 , true , "" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 1 , false , "" )
HandleAlerting ( endpoint , & core . Result { Success : true } , cfg . Alerting , cfg . Debug )
verify ( t , endpoint , 0 , 2 , false , "" )
2021-01-21 22:14:32 +01:00
}
2021-10-23 22:47:12 +02:00
func verify ( t * testing . T , endpoint * core . Endpoint , expectedNumberOfFailuresInARow , expectedNumberOfSuccessInARow int , expectedTriggered bool , expectedTriggeredReason string ) {
if endpoint . NumberOfFailuresInARow != expectedNumberOfFailuresInARow {
2021-12-03 04:15:51 +01:00
t . Errorf ( "endpoint.NumberOfFailuresInARow should've been %d, got %d" , expectedNumberOfFailuresInARow , endpoint . NumberOfFailuresInARow )
2021-01-21 22:14:32 +01:00
}
2021-10-23 22:47:12 +02:00
if endpoint . NumberOfSuccessesInARow != expectedNumberOfSuccessInARow {
2021-12-03 04:15:51 +01:00
t . Errorf ( "endpoint.NumberOfSuccessesInARow should've been %d, got %d" , expectedNumberOfSuccessInARow , endpoint . NumberOfSuccessesInARow )
2021-01-21 22:14:32 +01:00
}
2021-10-23 22:47:12 +02:00
if endpoint . Alerts [ 0 ] . Triggered != expectedTriggered {
2021-01-21 22:14:32 +01:00
if len ( expectedTriggeredReason ) != 0 {
2021-12-03 04:15:51 +01:00
t . Error ( expectedTriggeredReason )
2021-01-21 22:14:32 +01:00
} else {
if expectedTriggered {
2021-12-03 04:15:51 +01:00
t . Error ( "The alert should've been triggered" )
2021-01-21 22:14:32 +01:00
} else {
2021-12-03 04:15:51 +01:00
t . Error ( "The alert shouldn't have been triggered" )
2021-01-21 22:14:32 +01:00
}
}
2021-01-10 07:22:27 +01:00
}
}