2021-12-10 02:32:38 +01:00
|
|
|
package opsgenie
|
|
|
|
|
|
|
|
import (
|
2021-12-10 03:18:25 +01:00
|
|
|
"net/http"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
2022-12-06 07:41:09 +01:00
|
|
|
"github.com/TwiN/gatus/v5/alerting/alert"
|
|
|
|
"github.com/TwiN/gatus/v5/client"
|
|
|
|
"github.com/TwiN/gatus/v5/core"
|
|
|
|
"github.com/TwiN/gatus/v5/test"
|
2021-12-10 02:32:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestAlertProvider_IsValid(t *testing.T) {
|
|
|
|
invalidProvider := AlertProvider{APIKey: ""}
|
|
|
|
if invalidProvider.IsValid() {
|
|
|
|
t.Error("provider shouldn't have been valid")
|
|
|
|
}
|
|
|
|
validProvider := AlertProvider{APIKey: "00000000-0000-0000-0000-000000000000"}
|
|
|
|
if !validProvider.IsValid() {
|
|
|
|
t.Error("provider should've been valid")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAlertProvider_Send(t *testing.T) {
|
|
|
|
defer client.InjectHTTPClient(nil)
|
|
|
|
description := "my bad alert description"
|
|
|
|
scenarios := []struct {
|
|
|
|
Name string
|
|
|
|
Provider AlertProvider
|
|
|
|
Alert alert.Alert
|
|
|
|
Resolved bool
|
|
|
|
MockRoundTripper test.MockRoundTripper
|
|
|
|
ExpectedError bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "triggered",
|
|
|
|
Provider: AlertProvider{},
|
|
|
|
Alert: alert.Alert{Description: &description, SuccessThreshold: 1, FailureThreshold: 1},
|
|
|
|
Resolved: false,
|
|
|
|
ExpectedError: false,
|
|
|
|
MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response {
|
|
|
|
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody}
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "triggered-error",
|
|
|
|
Provider: AlertProvider{},
|
|
|
|
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
|
|
|
|
Resolved: false,
|
|
|
|
ExpectedError: true,
|
|
|
|
MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response {
|
|
|
|
return &http.Response{StatusCode: http.StatusInternalServerError, Body: http.NoBody}
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "resolved",
|
|
|
|
Provider: AlertProvider{},
|
|
|
|
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
|
|
|
|
Resolved: true,
|
|
|
|
ExpectedError: false,
|
|
|
|
MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response {
|
|
|
|
return &http.Response{StatusCode: http.StatusOK, Body: http.NoBody}
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "resolved-error",
|
|
|
|
Provider: AlertProvider{},
|
|
|
|
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
|
|
|
|
Resolved: true,
|
|
|
|
ExpectedError: true,
|
|
|
|
MockRoundTripper: test.MockRoundTripper(func(r *http.Request) *http.Response {
|
|
|
|
return &http.Response{StatusCode: http.StatusInternalServerError, Body: http.NoBody}
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, scenario := range scenarios {
|
|
|
|
t.Run(scenario.Name, func(t *testing.T) {
|
|
|
|
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
|
|
|
|
err := scenario.Provider.Send(
|
|
|
|
&core.Endpoint{Name: "endpoint-name"},
|
|
|
|
&scenario.Alert,
|
|
|
|
&core.Result{
|
|
|
|
ConditionResults: []*core.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_buildCreateRequestBody(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
description := "alert description"
|
|
|
|
scenarios := []struct {
|
|
|
|
Name string
|
|
|
|
Provider *AlertProvider
|
|
|
|
Alert *alert.Alert
|
|
|
|
Endpoint *core.Endpoint
|
|
|
|
Result *core.Result
|
|
|
|
Resolved bool
|
2021-12-10 03:18:25 +01:00
|
|
|
want alertCreateRequest
|
2021-12-10 02:32:38 +01:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "missing all params (unresolved)",
|
|
|
|
Provider: &AlertProvider{},
|
|
|
|
Alert: &alert.Alert{},
|
|
|
|
Endpoint: &core.Endpoint{},
|
|
|
|
Result: &core.Result{},
|
|
|
|
Resolved: false,
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCreateRequest{
|
2021-12-10 02:32:38 +01:00
|
|
|
Message: " - ",
|
|
|
|
Priority: "P1",
|
|
|
|
Source: "gatus",
|
|
|
|
Entity: "gatus-",
|
|
|
|
Alias: "gatus-healthcheck-",
|
|
|
|
Description: "An alert for ** has been triggered due to having failed 0 time(s) in a row\n",
|
|
|
|
Tags: nil,
|
|
|
|
Details: map[string]string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "missing all params (resolved)",
|
|
|
|
Provider: &AlertProvider{},
|
|
|
|
Alert: &alert.Alert{},
|
|
|
|
Endpoint: &core.Endpoint{},
|
|
|
|
Result: &core.Result{},
|
|
|
|
Resolved: true,
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCreateRequest{
|
2021-12-10 02:32:38 +01:00
|
|
|
Message: "RESOLVED: - ",
|
|
|
|
Priority: "P1",
|
|
|
|
Source: "gatus",
|
|
|
|
Entity: "gatus-",
|
|
|
|
Alias: "gatus-healthcheck-",
|
|
|
|
Description: "An alert for ** has been resolved after passing successfully 0 time(s) in a row\n",
|
|
|
|
Tags: nil,
|
|
|
|
Details: map[string]string{},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "with default options (unresolved)",
|
|
|
|
Provider: &AlertProvider{},
|
|
|
|
Alert: &alert.Alert{
|
|
|
|
Description: &description,
|
|
|
|
FailureThreshold: 3,
|
|
|
|
},
|
|
|
|
Endpoint: &core.Endpoint{
|
2021-12-12 22:33:16 +01:00
|
|
|
Name: "my super app",
|
2021-12-10 02:32:38 +01:00
|
|
|
},
|
|
|
|
Result: &core.Result{
|
|
|
|
ConditionResults: []*core.ConditionResult{
|
|
|
|
{
|
|
|
|
Condition: "[STATUS] == 200",
|
|
|
|
Success: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Condition: "[BODY] == OK",
|
|
|
|
Success: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Resolved: false,
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCreateRequest{
|
2021-12-12 22:33:16 +01:00
|
|
|
Message: "my super app - " + description,
|
|
|
|
Priority: "P1",
|
|
|
|
Source: "gatus",
|
|
|
|
Entity: "gatus-my-super-app",
|
|
|
|
Alias: "gatus-healthcheck-my-super-app",
|
|
|
|
Description: "An alert for *my super app* has been triggered due to having failed 3 time(s) in a row\n▣ - `[STATUS] == 200`\n▢ - `[BODY] == OK`\n",
|
|
|
|
Tags: nil,
|
|
|
|
Details: map[string]string{},
|
2021-12-10 02:32:38 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "with custom options (resolved)",
|
|
|
|
Provider: &AlertProvider{
|
|
|
|
Priority: "P5",
|
|
|
|
EntityPrefix: "oompa-",
|
|
|
|
AliasPrefix: "loompa-",
|
|
|
|
Source: "gatus-hc",
|
|
|
|
Tags: []string{"do-ba-dee-doo"},
|
|
|
|
},
|
|
|
|
Alert: &alert.Alert{
|
|
|
|
Description: &description,
|
|
|
|
SuccessThreshold: 4,
|
|
|
|
},
|
|
|
|
Endpoint: &core.Endpoint{
|
|
|
|
Name: "my mega app",
|
|
|
|
},
|
|
|
|
Result: &core.Result{
|
|
|
|
ConditionResults: []*core.ConditionResult{
|
|
|
|
{
|
|
|
|
Condition: "[STATUS] == 200",
|
|
|
|
Success: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Resolved: true,
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCreateRequest{
|
2021-12-12 22:33:16 +01:00
|
|
|
Message: "RESOLVED: my mega app - " + description,
|
|
|
|
Priority: "P5",
|
|
|
|
Source: "gatus-hc",
|
|
|
|
Entity: "oompa-my-mega-app",
|
|
|
|
Alias: "loompa-my-mega-app",
|
|
|
|
Description: "An alert for *my mega app* has been resolved after passing successfully 4 time(s) in a row\n▣ - `[STATUS] == 200`\n",
|
|
|
|
Tags: []string{"do-ba-dee-doo"},
|
|
|
|
Details: map[string]string{},
|
2021-12-10 02:32:38 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "with default options and details (unresolved)",
|
|
|
|
Provider: &AlertProvider{
|
|
|
|
Tags: []string{"foo"},
|
|
|
|
},
|
|
|
|
Alert: &alert.Alert{
|
|
|
|
Description: &description,
|
|
|
|
FailureThreshold: 6,
|
|
|
|
},
|
|
|
|
Endpoint: &core.Endpoint{
|
|
|
|
Name: "my app",
|
|
|
|
Group: "end game",
|
|
|
|
URL: "https://my.go/app",
|
|
|
|
},
|
|
|
|
Result: &core.Result{
|
|
|
|
HTTPStatus: 400,
|
|
|
|
Hostname: "my.go",
|
|
|
|
Errors: []string{"error 01", "error 02"},
|
|
|
|
Success: false,
|
|
|
|
ConditionResults: []*core.ConditionResult{
|
|
|
|
{
|
|
|
|
Condition: "[STATUS] == 200",
|
|
|
|
Success: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Resolved: false,
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCreateRequest{
|
2021-12-12 22:33:16 +01:00
|
|
|
Message: "[end game] my app - " + description,
|
|
|
|
Priority: "P1",
|
|
|
|
Source: "gatus",
|
|
|
|
Entity: "gatus-end-game-my-app",
|
|
|
|
Alias: "gatus-healthcheck-end-game-my-app",
|
|
|
|
Description: "An alert for *end game/my app* has been triggered due to having failed 6 time(s) in a row\n▢ - `[STATUS] == 200`\n",
|
|
|
|
Tags: []string{"foo"},
|
2021-12-10 02:32:38 +01:00
|
|
|
Details: map[string]string{
|
|
|
|
"endpoint:url": "https://my.go/app",
|
|
|
|
"endpoint:group": "end game",
|
|
|
|
"result:hostname": "my.go",
|
|
|
|
"result:errors": "error 01,error 02",
|
|
|
|
"result:http_status": "400",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, scenario := range scenarios {
|
|
|
|
actual := scenario
|
|
|
|
t.Run(actual.Name, func(t *testing.T) {
|
|
|
|
if got := actual.Provider.buildCreateRequestBody(actual.Endpoint, actual.Alert, actual.Result, actual.Resolved); !reflect.DeepEqual(got, actual.want) {
|
|
|
|
t.Errorf("buildCreateRequestBody() = %v, want %v", got, actual.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAlertProvider_buildCloseRequestBody(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
description := "alert description"
|
|
|
|
scenarios := []struct {
|
|
|
|
Name string
|
|
|
|
Provider *AlertProvider
|
|
|
|
Alert *alert.Alert
|
|
|
|
Endpoint *core.Endpoint
|
2021-12-10 03:18:25 +01:00
|
|
|
want alertCloseRequest
|
2021-12-10 02:32:38 +01:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
Name: "Missing all values",
|
|
|
|
Provider: &AlertProvider{},
|
|
|
|
Alert: &alert.Alert{},
|
|
|
|
Endpoint: &core.Endpoint{},
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCloseRequest{
|
2021-12-10 02:32:38 +01:00
|
|
|
Source: "",
|
|
|
|
Note: "RESOLVED: - ",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Basic values",
|
|
|
|
Provider: &AlertProvider{},
|
|
|
|
Alert: &alert.Alert{
|
|
|
|
Description: &description,
|
|
|
|
},
|
|
|
|
Endpoint: &core.Endpoint{
|
|
|
|
Name: "endpoint name",
|
|
|
|
},
|
2021-12-10 03:18:25 +01:00
|
|
|
want: alertCloseRequest{
|
2021-12-10 02:32:38 +01:00
|
|
|
Source: "endpoint-name",
|
|
|
|
Note: "RESOLVED: endpoint name - alert description",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, scenario := range scenarios {
|
|
|
|
actual := scenario
|
|
|
|
t.Run(actual.Name, func(t *testing.T) {
|
|
|
|
if got := actual.Provider.buildCloseRequestBody(actual.Endpoint, actual.Alert); !reflect.DeepEqual(got, actual.want) {
|
|
|
|
t.Errorf("buildCloseRequestBody() = %v, want %v", got, actual.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|