mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-23 00:13:30 +01:00
332 lines
9.1 KiB
Go
332 lines
9.1 KiB
Go
|
package opsgenie
|
||
|
|
||
|
import (
|
||
|
"github.com/TwiN/gatus/v3/alerting/alert"
|
||
|
"github.com/TwiN/gatus/v3/client"
|
||
|
"github.com/TwiN/gatus/v3/core"
|
||
|
"github.com/TwiN/gatus/v3/test"
|
||
|
"net/http"
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
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
|
||
|
want opsgenieAlertCreateRequest
|
||
|
}{
|
||
|
{
|
||
|
Name: "missing all params (unresolved)",
|
||
|
Provider: &AlertProvider{},
|
||
|
Alert: &alert.Alert{},
|
||
|
Endpoint: &core.Endpoint{},
|
||
|
Result: &core.Result{},
|
||
|
Resolved: false,
|
||
|
want: opsgenieAlertCreateRequest{
|
||
|
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,
|
||
|
want: opsgenieAlertCreateRequest{
|
||
|
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{
|
||
|
Name: "my supper app",
|
||
|
},
|
||
|
Result: &core.Result{
|
||
|
ConditionResults: []*core.ConditionResult{
|
||
|
{
|
||
|
Condition: "[STATUS] == 200",
|
||
|
Success: true,
|
||
|
},
|
||
|
{
|
||
|
Condition: "[BODY] == OK",
|
||
|
Success: false,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
Resolved: false,
|
||
|
want: opsgenieAlertCreateRequest{
|
||
|
Message: "my supper app - " + description,
|
||
|
Priority: "P1",
|
||
|
Source: "gatus",
|
||
|
Entity: "gatus-my-supper-app",
|
||
|
Alias: "gatus-healthcheck-my-supper-app",
|
||
|
Description: "An alert for *my supper 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{},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
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,
|
||
|
want: opsgenieAlertCreateRequest{
|
||
|
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{},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
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,
|
||
|
want: opsgenieAlertCreateRequest{
|
||
|
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 *my app* has been triggered due to having failed 6 time(s) in a row\n" +
|
||
|
"▢ - `[STATUS] == 200`\n",
|
||
|
Tags: []string{"foo"},
|
||
|
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
|
||
|
want opsgenieAlertCloseRequest
|
||
|
}{
|
||
|
{
|
||
|
Name: "Missing all values",
|
||
|
Provider: &AlertProvider{},
|
||
|
Alert: &alert.Alert{},
|
||
|
Endpoint: &core.Endpoint{},
|
||
|
want: opsgenieAlertCloseRequest{
|
||
|
Source: "",
|
||
|
Note: "RESOLVED: - ",
|
||
|
},
|
||
|
},
|
||
|
|
||
|
{
|
||
|
Name: "Basic values",
|
||
|
Provider: &AlertProvider{},
|
||
|
Alert: &alert.Alert{
|
||
|
Description: &description,
|
||
|
},
|
||
|
Endpoint: &core.Endpoint{
|
||
|
Name: "endpoint name",
|
||
|
},
|
||
|
want: opsgenieAlertCloseRequest{
|
||
|
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)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|