Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
884f64d8e6 |
No files matched your search
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/TwiN/gatus/v5/alerting"
|
||||
"github.com/TwiN/gatus/v5/alerting/alert"
|
||||
@@ -174,3 +175,53 @@ func TestCreateExternalEndpointResult(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCreateExternalEndpointResultUnderEndpointMaintenanceWindow(t *testing.T) {
|
||||
defer store.Get().Clear()
|
||||
defer cache.Clear()
|
||||
location, err := time.LoadLocation("Europe/Berlin")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
externalEndpoint := &endpoint.ExternalEndpoint{
|
||||
Name: "n",
|
||||
Group: "g",
|
||||
Token: "token",
|
||||
Alerts: []*alert.Alert{
|
||||
{
|
||||
Type: alert.TypeDiscord,
|
||||
FailureThreshold: 2,
|
||||
SuccessThreshold: 2,
|
||||
},
|
||||
},
|
||||
MaintenanceWindows: []*maintenance.Config{{
|
||||
Start: time.Now().In(location).Add(-time.Minute).Format("15:04"),
|
||||
Duration: time.Hour,
|
||||
Timezone: "Europe/Berlin",
|
||||
}},
|
||||
}
|
||||
if err := externalEndpoint.ValidateAndSetDefaults(); err != nil {
|
||||
t.Fatal("did not expect an error, got", err)
|
||||
}
|
||||
cfg := &config.Config{
|
||||
Alerting: &alerting.Config{
|
||||
Discord: &discord.AlertProvider{},
|
||||
},
|
||||
ExternalEndpoints: []*endpoint.ExternalEndpoint{externalEndpoint},
|
||||
Maintenance: &maintenance.Config{},
|
||||
}
|
||||
router := New(cfg).Router()
|
||||
request := httptest.NewRequest("POST", "/api/v1/endpoints/g_n/external?success=false", http.NoBody)
|
||||
request.Header.Set("Authorization", "Bearer token")
|
||||
response, err := router.Test(request)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != 200 {
|
||||
t.Fatalf("expected 200, got %d", response.StatusCode)
|
||||
}
|
||||
if externalEndpoint.NumberOfFailuresInARow != 0 {
|
||||
t.Errorf("expected alerting to be skipped because the endpoint is under maintenance, but NumberOfFailuresInARow is %d", externalEndpoint.NumberOfFailuresInARow)
|
||||
}
|
||||
}
|
||||
@@ -241,6 +241,11 @@ func (e *Endpoint) ValidateAndSetDefaults() error {
|
||||
return fmt.Errorf("%v: %w", ErrInvalidConditionFormat, err)
|
||||
}
|
||||
}
|
||||
for _, maintenanceWindow := range e.MaintenanceWindows {
|
||||
if err := maintenanceWindow.ValidateAndSetDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if e.DNSConfig != nil {
|
||||
return e.DNSConfig.ValidateAndSetDefault()
|
||||
}
|
||||
@@ -250,11 +255,6 @@ func (e *Endpoint) ValidateAndSetDefaults() error {
|
||||
if e.Type() == TypeUNKNOWN {
|
||||
return ErrUnknownEndpointType
|
||||
}
|
||||
for _, maintenanceWindow := range e.MaintenanceWindows {
|
||||
if err := maintenanceWindow.ValidateAndSetDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Make sure that the request can be created
|
||||
_, err := http.NewRequest(e.Method, e.URL, bytes.NewBuffer([]byte(e.getParsedBody())))
|
||||
if err != nil {
|
||||
|
||||
@@ -616,6 +616,70 @@ func TestEndpoint_ValidateAndSetDefaultsWithSSH(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpoint_ValidateAndSetDefaultsWithMaintenanceWindowOnDNSAndSSH(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
endpoint func(windows []*maintenance.Config) *Endpoint
|
||||
}{
|
||||
{
|
||||
name: "dns",
|
||||
endpoint: func(windows []*maintenance.Config) *Endpoint {
|
||||
return &Endpoint{
|
||||
Name: "dns-test",
|
||||
URL: "8.8.8.8",
|
||||
DNSConfig: &dns.Config{QueryType: "A", QueryName: "example.com"},
|
||||
Conditions: []Condition{Condition("[DNS_RCODE] == NOERROR")},
|
||||
MaintenanceWindows: windows,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ssh",
|
||||
endpoint: func(windows []*maintenance.Config) *Endpoint {
|
||||
return &Endpoint{
|
||||
Name: "ssh-test",
|
||||
URL: "ssh://example.com:22",
|
||||
SSHConfig: &ssh.Config{Username: "username", Password: "password"},
|
||||
Conditions: []Condition{Condition("[CONNECTED] == true")},
|
||||
MaintenanceWindows: windows,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.name+"-invalid-maintenance-window", func(t *testing.T) {
|
||||
endpoint := scenario.endpoint([]*maintenance.Config{{Start: "25:00", Duration: time.Hour}})
|
||||
if err := endpoint.ValidateAndSetDefaults(); err == nil {
|
||||
t.Error("expected an error because the maintenance window has an invalid start, got none")
|
||||
}
|
||||
})
|
||||
t.Run(scenario.name+"-under-maintenance", func(t *testing.T) {
|
||||
window := newMaintenanceWindowThatStartedAMinuteAgo(t, "Europe/Berlin")
|
||||
endpoint := scenario.endpoint([]*maintenance.Config{window})
|
||||
if err := endpoint.ValidateAndSetDefaults(); err != nil {
|
||||
t.Fatal("did not expect an error, got", err)
|
||||
}
|
||||
if !endpoint.MaintenanceWindows[0].IsUnderMaintenance() {
|
||||
t.Errorf("expected endpoint to be under maintenance (window starting at %s %s)", window.Start, window.Timezone)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// newMaintenanceWindowThatStartedAMinuteAgo returns a one-hour maintenance window whose start
|
||||
// is one minute before the current time in the given timezone
|
||||
func newMaintenanceWindowThatStartedAMinuteAgo(t *testing.T, timezone string) *maintenance.Config {
|
||||
location, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return &maintenance.Config{
|
||||
Start: time.Now().In(location).Add(-time.Minute).Format("15:04"),
|
||||
Duration: time.Hour,
|
||||
Timezone: timezone,
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpoint_ValidateAndSetDefaultsWithSimpleErrors(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
endpoint *Endpoint
|
||||
|
||||
@@ -62,6 +62,11 @@ func (externalEndpoint *ExternalEndpoint) ValidateAndSetDefaults() error {
|
||||
// If the heartbeat interval is set (non-0), it must be at least 10 seconds.
|
||||
return ErrExternalEndpointHeartbeatIntervalTooLow
|
||||
}
|
||||
for _, maintenanceWindow := range externalEndpoint.MaintenanceWindows {
|
||||
if err := maintenanceWindow.ValidateAndSetDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,33 @@ func TestExternalEndpoint_ValidateAndSetDefaults(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalEndpoint_ValidateAndSetDefaultsWithMaintenanceWindow(t *testing.T) {
|
||||
t.Run("invalid-maintenance-window", func(t *testing.T) {
|
||||
externalEndpoint := &ExternalEndpoint{
|
||||
Name: "test-endpoint",
|
||||
Token: "valid-token",
|
||||
MaintenanceWindows: []*maintenance.Config{{Start: "25:00", Duration: time.Hour}},
|
||||
}
|
||||
if err := externalEndpoint.ValidateAndSetDefaults(); err == nil {
|
||||
t.Error("expected an error because the maintenance window has an invalid start, got none")
|
||||
}
|
||||
})
|
||||
t.Run("under-maintenance", func(t *testing.T) {
|
||||
window := newMaintenanceWindowThatStartedAMinuteAgo(t, "Europe/Berlin")
|
||||
externalEndpoint := &ExternalEndpoint{
|
||||
Name: "test-endpoint",
|
||||
Token: "valid-token",
|
||||
MaintenanceWindows: []*maintenance.Config{window},
|
||||
}
|
||||
if err := externalEndpoint.ValidateAndSetDefaults(); err != nil {
|
||||
t.Fatal("did not expect an error, got", err)
|
||||
}
|
||||
if !externalEndpoint.MaintenanceWindows[0].IsUnderMaintenance() {
|
||||
t.Errorf("expected external endpoint to be under maintenance (window starting at %s %s)", window.Start, window.Timezone)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestExternalEndpoint_IsEnabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Reference in new issue
Block a user