diff --git a/alerting/alert/alert.go b/alerting/alert/alert.go
index c1fbdcf8..4d90ced2 100644
--- a/alerting/alert/alert.go
+++ b/alerting/alert/alert.go
@@ -10,7 +10,7 @@ var (
ErrAlertWithInvalidDescription = errors.New("alert description must not have \" or \\")
)
-// Alert is a core.Endpoint's alert configuration
+// Alert is a endpoint.Endpoint's alert configuration
type Alert struct {
// Type of alert (required)
Type Type `yaml:"type"`
diff --git a/alerting/provider/awsses/awsses.go b/alerting/provider/awsses/awsses.go
index 17ba05cc..955531a1 100644
--- a/alerting/provider/awsses/awsses.go
+++ b/alerting/provider/awsses/awsses.go
@@ -5,7 +5,7 @@ import (
"strings"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
@@ -57,14 +57,14 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
sess, err := provider.createSession()
if err != nil {
return err
}
svc := ses.New(sess)
- subject, body := provider.buildMessageSubjectAndBody(endpoint, alert, result, resolved)
- emails := strings.Split(provider.getToForGroup(endpoint.Group), ",")
+ subject, body := provider.buildMessageSubjectAndBody(ep, alert, result, resolved)
+ emails := strings.Split(provider.getToForGroup(ep.Group), ",")
input := &ses.SendEmailInput{
Destination: &ses.Destination{
@@ -110,14 +110,14 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert,
}
// buildMessageSubjectAndBody builds the message subject and body
-func (provider *AlertProvider) buildMessageSubjectAndBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) (string, string) {
+func (provider *AlertProvider) buildMessageSubjectAndBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) (string, string) {
var subject, message string
if resolved {
- subject = fmt.Sprintf("[%s] Alert resolved", endpoint.DisplayName())
- message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ subject = fmt.Sprintf("[%s] Alert resolved", ep.DisplayName())
+ message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- subject = fmt.Sprintf("[%s] Alert triggered", endpoint.DisplayName())
- message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ subject = fmt.Sprintf("[%s] Alert triggered", ep.DisplayName())
+ message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
if len(result.ConditionResults) > 0 {
diff --git a/alerting/provider/awsses/awsses_test.go b/alerting/provider/awsses/awsses_test.go
index d13022b1..35b5eaf3 100644
--- a/alerting/provider/awsses/awsses_test.go
+++ b/alerting/provider/awsses/awsses_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestAlertDefaultProvider_IsValid(t *testing.T) {
@@ -95,10 +95,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
subject, body := scenario.Provider.buildMessageSubjectAndBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/custom/custom.go b/alerting/provider/custom/custom.go
index 052af1ab..fc661edf 100644
--- a/alerting/provider/custom/custom.go
+++ b/alerting/provider/custom/custom.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using a custom HTTP request
@@ -50,16 +50,16 @@ func (provider *AlertProvider) GetAlertStatePlaceholderValue(resolved bool) stri
return status
}
-func (provider *AlertProvider) buildHTTPRequest(endpoint *core.Endpoint, alert *alert.Alert, resolved bool) *http.Request {
+func (provider *AlertProvider) buildHTTPRequest(ep *endpoint.Endpoint, alert *alert.Alert, resolved bool) *http.Request {
body, url, method := provider.Body, provider.URL, provider.Method
body = strings.ReplaceAll(body, "[ALERT_DESCRIPTION]", alert.GetDescription())
url = strings.ReplaceAll(url, "[ALERT_DESCRIPTION]", alert.GetDescription())
- body = strings.ReplaceAll(body, "[ENDPOINT_NAME]", endpoint.Name)
- url = strings.ReplaceAll(url, "[ENDPOINT_NAME]", endpoint.Name)
- body = strings.ReplaceAll(body, "[ENDPOINT_GROUP]", endpoint.Group)
- url = strings.ReplaceAll(url, "[ENDPOINT_GROUP]", endpoint.Group)
- body = strings.ReplaceAll(body, "[ENDPOINT_URL]", endpoint.URL)
- url = strings.ReplaceAll(url, "[ENDPOINT_URL]", endpoint.URL)
+ body = strings.ReplaceAll(body, "[ENDPOINT_NAME]", ep.Name)
+ url = strings.ReplaceAll(url, "[ENDPOINT_NAME]", ep.Name)
+ body = strings.ReplaceAll(body, "[ENDPOINT_GROUP]", ep.Group)
+ url = strings.ReplaceAll(url, "[ENDPOINT_GROUP]", ep.Group)
+ body = strings.ReplaceAll(body, "[ENDPOINT_URL]", ep.URL)
+ url = strings.ReplaceAll(url, "[ENDPOINT_URL]", ep.URL)
if resolved {
body = strings.ReplaceAll(body, "[ALERT_TRIGGERED_OR_RESOLVED]", provider.GetAlertStatePlaceholderValue(true))
url = strings.ReplaceAll(url, "[ALERT_TRIGGERED_OR_RESOLVED]", provider.GetAlertStatePlaceholderValue(true))
@@ -78,8 +78,8 @@ func (provider *AlertProvider) buildHTTPRequest(endpoint *core.Endpoint, alert *
return request
}
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- request := provider.buildHTTPRequest(endpoint, alert, resolved)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ request := provider.buildHTTPRequest(ep, alert, resolved)
response, err := client.GetHTTPClient(provider.ClientConfig).Do(request)
if err != nil {
return err
diff --git a/alerting/provider/custom/custom_test.go b/alerting/provider/custom/custom_test.go
index 3927bb6c..1678a7fe 100644
--- a/alerting/provider/custom/custom_test.go
+++ b/alerting/provider/custom/custom_test.go
@@ -8,7 +8,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -90,10 +90,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -138,7 +138,7 @@ func TestAlertProvider_buildHTTPRequest(t *testing.T) {
for _, scenario := range scenarios {
t.Run(fmt.Sprintf("resolved-%v-with-default-placeholders", scenario.Resolved), func(t *testing.T) {
request := customAlertProvider.buildHTTPRequest(
- &core.Endpoint{Name: "endpoint-name", Group: "endpoint-group", URL: "https://example.com"},
+ &endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group", URL: "https://example.com"},
&alert.Alert{Description: &alertDescription},
scenario.Resolved,
)
@@ -188,7 +188,7 @@ func TestAlertProvider_buildHTTPRequestWithCustomPlaceholder(t *testing.T) {
for _, scenario := range scenarios {
t.Run(fmt.Sprintf("resolved-%v-with-custom-placeholders", scenario.Resolved), func(t *testing.T) {
request := customAlertProvider.buildHTTPRequest(
- &core.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
+ &endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
&alert.Alert{Description: &alertDescription},
scenario.Resolved,
)
diff --git a/alerting/provider/discord/discord.go b/alerting/provider/discord/discord.go
index d4ac2c96..fe302934 100644
--- a/alerting/provider/discord/discord.go
+++ b/alerting/provider/discord/discord.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Discord
@@ -47,9 +47,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
- request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(ep.Group), buffer)
if err != nil {
return err
}
@@ -85,14 +85,14 @@ type Field struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message 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", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for **%s** has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), 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", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
colorCode = 15158332
}
var formattedConditionResults string
diff --git a/alerting/provider/discord/discord_test.go b/alerting/provider/discord/discord_test.go
index 2c8f1230..14d2d9bf 100644
--- a/alerting/provider/discord/discord_test.go
+++ b/alerting/provider/discord/discord_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -127,10 +127,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -191,18 +191,18 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- var conditionResults []*core.ConditionResult
+ var conditionResults []*endpoint.ConditionResult
if !scenario.NoConditions {
- conditionResults = []*core.ConditionResult{
+ conditionResults = []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
{Condition: "[BODY] != \"\"", Success: scenario.Resolved},
}
}
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
+ &endpoint.Result{
ConditionResults: conditionResults,
},
scenario.Resolved,
diff --git a/alerting/provider/email/email.go b/alerting/provider/email/email.go
index e2fe542b..391d607d 100644
--- a/alerting/provider/email/email.go
+++ b/alerting/provider/email/email.go
@@ -8,7 +8,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
gomail "gopkg.in/mail.v2"
)
@@ -53,17 +53,17 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
var username string
if len(provider.Username) > 0 {
username = provider.Username
} else {
username = provider.From
}
- subject, body := provider.buildMessageSubjectAndBody(endpoint, alert, result, resolved)
+ subject, body := provider.buildMessageSubjectAndBody(ep, alert, result, resolved)
m := gomail.NewMessage()
m.SetHeader("From", provider.From)
- m.SetHeader("To", strings.Split(provider.getToForGroup(endpoint.Group), ",")...)
+ m.SetHeader("To", strings.Split(provider.getToForGroup(ep.Group), ",")...)
m.SetHeader("Subject", subject)
m.SetBody("text/plain", body)
var d *gomail.Dialer
@@ -87,14 +87,14 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert,
}
// buildMessageSubjectAndBody builds the message subject and body
-func (provider *AlertProvider) buildMessageSubjectAndBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) (string, string) {
+func (provider *AlertProvider) buildMessageSubjectAndBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) (string, string) {
var subject, message string
if resolved {
- subject = fmt.Sprintf("[%s] Alert resolved", endpoint.DisplayName())
- message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ subject = fmt.Sprintf("[%s] Alert resolved", ep.DisplayName())
+ message = fmt.Sprintf("An alert for %s has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- subject = fmt.Sprintf("[%s] Alert triggered", endpoint.DisplayName())
- message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ subject = fmt.Sprintf("[%s] Alert triggered", ep.DisplayName())
+ message = fmt.Sprintf("An alert for %s has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
if len(result.ConditionResults) > 0 {
diff --git a/alerting/provider/email/email_test.go b/alerting/provider/email/email_test.go
index 4cab7134..a1134f27 100644
--- a/alerting/provider/email/email_test.go
+++ b/alerting/provider/email/email_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestAlertDefaultProvider_IsValid(t *testing.T) {
@@ -97,10 +97,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
subject, body := scenario.Provider.buildMessageSubjectAndBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/github/github.go b/alerting/provider/github/github.go
index f86b9053..c425d669 100644
--- a/alerting/provider/github/github.go
+++ b/alerting/provider/github/github.go
@@ -8,7 +8,7 @@ import (
"time"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/google/go-github/v48/github"
"golang.org/x/oauth2"
)
@@ -70,12 +70,12 @@ func (provider *AlertProvider) IsValid() bool {
// Send creates an issue in the designed RepositoryURL if the resolved parameter passed is false,
// or closes the relevant issue(s) if the resolved parameter passed is true.
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- title := "alert(gatus): " + endpoint.DisplayName()
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ title := "alert(gatus): " + ep.DisplayName()
if !resolved {
_, _, err := provider.githubClient.Issues.Create(context.Background(), provider.repositoryOwner, provider.repositoryName, &github.IssueRequest{
Title: github.String(title),
- Body: github.String(provider.buildIssueBody(endpoint, alert, result)),
+ Body: github.String(provider.buildIssueBody(ep, alert, result)),
})
if err != nil {
return fmt.Errorf("failed to create issue: %w", err)
@@ -104,7 +104,7 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert,
}
// buildIssueBody builds the body of the issue
-func (provider *AlertProvider) buildIssueBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result) string {
+func (provider *AlertProvider) buildIssueBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result) string {
var formattedConditionResults string
if len(result.ConditionResults) > 0 {
formattedConditionResults = "\n\n## Condition results\n"
@@ -122,7 +122,7 @@ func (provider *AlertProvider) buildIssueBody(endpoint *core.Endpoint, alert *al
if alertDescription := alert.GetDescription(); len(alertDescription) > 0 {
description = ":\n> " + alertDescription
}
- message := fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message := fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
return message + description + formattedConditionResults
}
diff --git a/alerting/provider/github/github_test.go b/alerting/provider/github/github_test.go
index d1f45e48..e69a3197 100644
--- a/alerting/provider/github/github_test.go
+++ b/alerting/provider/github/github_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
"github.com/google/go-github/v48/github"
)
@@ -85,10 +85,10 @@ func TestAlertProvider_Send(t *testing.T) {
scenario.Provider.githubClient = github.NewClient(nil)
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
+ &endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -109,7 +109,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
firstDescription := "description-1"
scenarios := []struct {
Name string
- Endpoint core.Endpoint
+ Endpoint endpoint.Endpoint
Provider AlertProvider
Alert alert.Alert
NoConditions bool
@@ -117,14 +117,14 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}{
{
Name: "triggered",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, FailureThreshold: 3},
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 3 time(s) in a row:\n> description-1\n\n## Condition results\n- :white_check_mark: - `[CONNECTED] == true`\n- :x: - `[STATUS] == 200`",
},
{
Name: "triggered-with-no-description",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{FailureThreshold: 10},
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 10 time(s) in a row\n\n## Condition results\n- :white_check_mark: - `[CONNECTED] == true`\n- :x: - `[STATUS] == 200`",
@@ -132,7 +132,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered-with-no-conditions",
NoConditions: true,
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, FailureThreshold: 10},
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 10 time(s) in a row:\n> description-1",
@@ -140,9 +140,9 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- var conditionResults []*core.ConditionResult
+ var conditionResults []*endpoint.ConditionResult
if !scenario.NoConditions {
- conditionResults = []*core.ConditionResult{
+ conditionResults = []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: true},
{Condition: "[STATUS] == 200", Success: false},
}
@@ -150,7 +150,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
body := scenario.Provider.buildIssueBody(
&scenario.Endpoint,
&scenario.Alert,
- &core.Result{ConditionResults: conditionResults},
+ &endpoint.Result{ConditionResults: conditionResults},
)
if strings.TrimSpace(body) != strings.TrimSpace(scenario.ExpectedBody) {
t.Errorf("expected:\n%s\ngot:\n%s", scenario.ExpectedBody, body)
diff --git a/alerting/provider/gitlab/gitlab.go b/alerting/provider/gitlab/gitlab.go
index f87b4c4e..d9d5676a 100644
--- a/alerting/provider/gitlab/gitlab.go
+++ b/alerting/provider/gitlab/gitlab.go
@@ -11,7 +11,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/google/uuid"
)
@@ -51,11 +51,11 @@ func (provider *AlertProvider) IsValid() bool {
// Send creates an issue in the designed RepositoryURL if the resolved parameter passed is false,
// or closes the relevant issue(s) if the resolved parameter passed is true.
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
if len(alert.ResolveKey) == 0 {
alert.ResolveKey = uuid.NewString()
}
- buffer := bytes.NewBuffer(provider.buildAlertBody(endpoint, alert, result, resolved))
+ buffer := bytes.NewBuffer(provider.buildAlertBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, provider.WebhookURL, buffer)
if err != nil {
return err
@@ -94,21 +94,21 @@ func (provider *AlertProvider) monitoringTool() string {
return "gatus"
}
-func (provider *AlertProvider) service(endpoint *core.Endpoint) string {
+func (provider *AlertProvider) service(ep *endpoint.Endpoint) string {
if len(provider.Service) > 0 {
return provider.Service
}
- return endpoint.DisplayName()
+ return ep.DisplayName()
}
// buildAlertBody builds the body of the alert
-func (provider *AlertProvider) buildAlertBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildAlertBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
body := AlertBody{
- Title: fmt.Sprintf("alert(%s): %s", provider.monitoringTool(), provider.service(endpoint)),
+ Title: fmt.Sprintf("alert(%s): %s", provider.monitoringTool(), provider.service(ep)),
StartTime: result.Timestamp.Format(time.RFC3339),
- Service: provider.service(endpoint),
+ Service: provider.service(ep),
MonitoringTool: provider.monitoringTool(),
- Hosts: endpoint.URL,
+ Hosts: ep.URL,
GitlabEnvironmentName: provider.EnvironmentName,
Severity: provider.Severity,
Fingerprint: alert.ResolveKey,
@@ -135,9 +135,9 @@ func (provider *AlertProvider) buildAlertBody(endpoint *core.Endpoint, alert *al
}
var message string
if resolved {
- message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
body.Description = message + description + formattedConditionResults
bodyAsJSON, _ := json.Marshal(body)
diff --git a/alerting/provider/gitlab/gitlab_test.go b/alerting/provider/gitlab/gitlab_test.go
index 8ea389fd..290b2e6e 100644
--- a/alerting/provider/gitlab/gitlab_test.go
+++ b/alerting/provider/gitlab/gitlab_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -84,10 +84,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
+ &endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -108,21 +108,21 @@ func TestAlertProvider_buildAlertBody(t *testing.T) {
firstDescription := "description-1"
scenarios := []struct {
Name string
- Endpoint core.Endpoint
+ Endpoint endpoint.Endpoint
Provider AlertProvider
Alert alert.Alert
ExpectedBody string
}{
{
Name: "triggered",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, FailureThreshold: 3},
ExpectedBody: "{\"title\":\"alert(gatus): endpoint-name\",\"description\":\"An alert for *endpoint-name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\\n\\n## Condition results\\n- :white_check_mark: - `[CONNECTED] == true`\\n- :x: - `[STATUS] == 200`\\n\",\"start_time\":\"0001-01-01T00:00:00Z\",\"service\":\"endpoint-name\",\"monitoring_tool\":\"gatus\",\"hosts\":\"https://example.org\"}",
},
{
Name: "no-description",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{FailureThreshold: 10},
ExpectedBody: "{\"title\":\"alert(gatus): endpoint-name\",\"description\":\"An alert for *endpoint-name* has been triggered due to having failed 10 time(s) in a row\\n\\n## Condition results\\n- :white_check_mark: - `[CONNECTED] == true`\\n- :x: - `[STATUS] == 200`\\n\",\"start_time\":\"0001-01-01T00:00:00Z\",\"service\":\"endpoint-name\",\"monitoring_tool\":\"gatus\",\"hosts\":\"https://example.org\"}",
@@ -133,8 +133,8 @@ func TestAlertProvider_buildAlertBody(t *testing.T) {
body := scenario.Provider.buildAlertBody(
&scenario.Endpoint,
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: true},
{Condition: "[STATUS] == 200", Success: false},
},
diff --git a/alerting/provider/googlechat/googlechat.go b/alerting/provider/googlechat/googlechat.go
index 19330c92..fb2f8f97 100644
--- a/alerting/provider/googlechat/googlechat.go
+++ b/alerting/provider/googlechat/googlechat.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Google chat
@@ -50,9 +50,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
- request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(ep.Group), buffer)
if err != nil {
return err
}
@@ -112,7 +112,7 @@ type OpenLink struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, color string
if resolved {
color = "#36A64F"
@@ -143,7 +143,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
Widgets: []Widgets{
{
KeyValue: &KeyValue{
- TopLabel: endpoint.DisplayName(),
+ TopLabel: ep.DisplayName(),
Content: message,
ContentMultiline: "true",
BottomLabel: description,
@@ -166,7 +166,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
},
})
}
- if endpoint.Type() == core.EndpointTypeHTTP {
+ if ep.Type() == endpoint.TypeHTTP {
// We only include a button targeting the URL if the endpoint is an HTTP endpoint
// If the URL isn't prefixed with https://, Google Chat will just display a blank message aynways.
// See https://github.com/TwiN/gatus/issues/362
@@ -175,7 +175,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
{
TextButton: TextButton{
Text: "URL",
- OnClick: OnClick{OpenLink: OpenLink{URL: endpoint.URL}},
+ OnClick: OnClick{OpenLink: OpenLink{URL: ep.URL}},
},
},
},
diff --git a/alerting/provider/googlechat/googlechat_test.go b/alerting/provider/googlechat/googlechat_test.go
index 7cd2c0a9..78e5e6ea 100644
--- a/alerting/provider/googlechat/googlechat_test.go
+++ b/alerting/provider/googlechat/googlechat_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -116,10 +116,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
+ &endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -141,7 +141,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
secondDescription := "description-2"
scenarios := []struct {
Name string
- Endpoint core.Endpoint
+ Endpoint endpoint.Endpoint
Provider AlertProvider
Alert alert.Alert
Resolved bool
@@ -149,7 +149,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}{
{
Name: "triggered",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -157,7 +157,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "resolved",
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
@@ -165,7 +165,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "icmp-should-not-include-url", // See https://github.com/TwiN/gatus/issues/362
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "icmp://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "icmp://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -173,7 +173,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
},
{
Name: "tcp-should-not-include-url", // See https://github.com/TwiN/gatus/issues/362
- Endpoint: core.Endpoint{Name: "endpoint-name", URL: "tcp://example.org"},
+ Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "tcp://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
@@ -185,8 +185,8 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
body := scenario.Provider.buildRequestBody(
&scenario.Endpoint,
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/gotify/gotify.go b/alerting/provider/gotify/gotify.go
index 7f4bfcf6..7b1f7a61 100644
--- a/alerting/provider/gotify/gotify.go
+++ b/alerting/provider/gotify/gotify.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const DefaultPriority = 5
@@ -41,8 +41,8 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, provider.ServerURL+"/message?token="+provider.Token, buffer)
if err != nil {
return err
@@ -67,12 +67,12 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message string
if resolved {
- message = fmt.Sprintf("An alert for `%s` has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for `%s` has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("An alert for `%s` has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for `%s` has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
for _, conditionResult := range result.ConditionResults {
@@ -88,7 +88,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
message += " with the following description: " + alert.GetDescription()
}
message += formattedConditionResults
- title := "Gatus: " + endpoint.DisplayName()
+ title := "Gatus: " + ep.DisplayName()
if provider.Title != "" {
title = provider.Title
}
diff --git a/alerting/provider/gotify/gotify_test.go b/alerting/provider/gotify/gotify_test.go
index 19a68b97..af644f48 100644
--- a/alerting/provider/gotify/gotify_test.go
+++ b/alerting/provider/gotify/gotify_test.go
@@ -6,7 +6,7 @@ import (
"testing"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestAlertProvider_IsValid(t *testing.T) {
@@ -49,7 +49,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
var (
description = "custom-description"
//title = "custom-title"
- endpoint = "custom-endpoint"
+ endpointName = "custom-endpoint"
)
scenarios := []struct {
Name string
@@ -63,30 +63,30 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
Provider: AlertProvider{ServerURL: "https://gotify.example.com", Token: "faketoken"},
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
- ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been triggered due to having failed 3 time(s) in a row with the following description: %s\\n✕ - [CONNECTED] == true\\n✕ - [STATUS] == 200\",\"title\":\"Gatus: custom-endpoint\",\"priority\":0}", endpoint, description),
+ ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been triggered due to having failed 3 time(s) in a row with the following description: %s\\n✕ - [CONNECTED] == true\\n✕ - [STATUS] == 200\",\"title\":\"Gatus: custom-endpoint\",\"priority\":0}", endpointName, description),
},
{
Name: "resolved",
Provider: AlertProvider{ServerURL: "https://gotify.example.com", Token: "faketoken"},
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
- ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been resolved after passing successfully 5 time(s) in a row with the following description: %s\\n✓ - [CONNECTED] == true\\n✓ - [STATUS] == 200\",\"title\":\"Gatus: custom-endpoint\",\"priority\":0}", endpoint, description),
+ ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been resolved after passing successfully 5 time(s) in a row with the following description: %s\\n✓ - [CONNECTED] == true\\n✓ - [STATUS] == 200\",\"title\":\"Gatus: custom-endpoint\",\"priority\":0}", endpointName, description),
},
{
Name: "custom-title",
Provider: AlertProvider{ServerURL: "https://gotify.example.com", Token: "faketoken", Title: "custom-title"},
Alert: alert.Alert{Description: &description, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
- ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been triggered due to having failed 3 time(s) in a row with the following description: %s\\n✕ - [CONNECTED] == true\\n✕ - [STATUS] == 200\",\"title\":\"custom-title\",\"priority\":0}", endpoint, description),
+ ExpectedBody: fmt.Sprintf("{\"message\":\"An alert for `%s` has been triggered due to having failed 3 time(s) in a row with the following description: %s\\n✕ - [CONNECTED] == true\\n✕ - [STATUS] == 200\",\"title\":\"custom-title\",\"priority\":0}", endpointName, description),
},
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: endpoint},
+ &endpoint.Endpoint{Name: endpointName},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/jetbrainsspace/jetbrainsspace.go b/alerting/provider/jetbrainsspace/jetbrainsspace.go
index bf031663..aa9d928f 100644
--- a/alerting/provider/jetbrainsspace/jetbrainsspace.go
+++ b/alerting/provider/jetbrainsspace/jetbrainsspace.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using JetBrains Space
@@ -46,8 +46,8 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
url := fmt.Sprintf("https://%s.jetbrains.space/api/http/chats/messages/send-message", provider.Project)
request, err := http.NewRequest(http.MethodPost, url, buffer)
if err != nil {
@@ -103,9 +103,9 @@ type Icon struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
body := Body{
- Channel: "id:" + provider.getChannelIDForGroup(endpoint.Group),
+ Channel: "id:" + provider.getChannelIDForGroup(ep.Group),
Content: Content{
ClassName: "ChatMessage.Block",
Sections: []Section{{
@@ -116,10 +116,10 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
}
if resolved {
body.Content.Style = "SUCCESS"
- body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
body.Content.Style = "WARNING"
- body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ body.Content.Sections[0].Header = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
for _, conditionResult := range result.ConditionResults {
icon := "warning"
diff --git a/alerting/provider/jetbrainsspace/jetbrainsspace_test.go b/alerting/provider/jetbrainsspace/jetbrainsspace_test.go
index 8eae2590..c9fbcd9c 100644
--- a/alerting/provider/jetbrainsspace/jetbrainsspace_test.go
+++ b/alerting/provider/jetbrainsspace/jetbrainsspace_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -120,10 +120,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -146,7 +146,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
scenarios := []struct {
Name string
Provider AlertProvider
- Endpoint core.Endpoint
+ Endpoint endpoint.Endpoint
Alert alert.Alert
Resolved bool
ExpectedBody string
@@ -154,7 +154,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name"},
+ Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: `{"channel":"id:","content":{"className":"ChatMessage.Block","style":"WARNING","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *name* has been triggered due to having failed 3 time(s) in a row"}]}}`,
@@ -162,7 +162,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered-with-group",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name", Group: "group"},
+ Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: `{"channel":"id:","content":{"className":"ChatMessage.Block","style":"WARNING","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"warning"},"style":"WARNING"},"style":"WARNING","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *group/name* has been triggered due to having failed 3 time(s) in a row"}]}}`,
@@ -170,7 +170,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "resolved",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name"},
+ Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
ExpectedBody: `{"channel":"id:","content":{"className":"ChatMessage.Block","style":"SUCCESS","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *name* has been resolved after passing successfully 5 time(s) in a row"}]}}`,
@@ -178,7 +178,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "resolved-with-group",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name", Group: "group"},
+ Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
ExpectedBody: `{"channel":"id:","content":{"className":"ChatMessage.Block","style":"SUCCESS","sections":[{"className":"MessageSection","elements":[{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[CONNECTED] == true"},{"className":"MessageText","accessory":{"className":"MessageIcon","icon":{"icon":"success"},"style":"SUCCESS"},"style":"SUCCESS","size":"REGULAR","content":"[STATUS] == 200"}],"header":"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row"}]}}`,
@@ -189,8 +189,8 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
body := scenario.Provider.buildRequestBody(
&scenario.Endpoint,
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/matrix/matrix.go b/alerting/provider/matrix/matrix.go
index 92907889..4bc8754d 100644
--- a/alerting/provider/matrix/matrix.go
+++ b/alerting/provider/matrix/matrix.go
@@ -12,7 +12,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Matrix
@@ -61,9 +61,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
- config := provider.getConfigForGroup(endpoint.Group)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
+ config := provider.getConfigForGroup(ep.Group)
if config.ServerURL == "" {
config.ServerURL = defaultServerURL
}
@@ -103,23 +103,23 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
body, _ := json.Marshal(Body{
MsgType: "m.text",
Format: "org.matrix.custom.html",
- Body: buildPlaintextMessageBody(endpoint, alert, result, resolved),
- FormattedBody: buildHTMLMessageBody(endpoint, alert, result, resolved),
+ Body: buildPlaintextMessageBody(ep, alert, result, resolved),
+ FormattedBody: buildHTMLMessageBody(ep, alert, result, resolved),
})
return body
}
// buildPlaintextMessageBody builds the message body in plaintext to include in request
-func buildPlaintextMessageBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) string {
+func buildPlaintextMessageBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) string {
var message string
if resolved {
- message = fmt.Sprintf("An alert for `%s` has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for `%s` has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("An alert for `%s` has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for `%s` has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
for _, conditionResult := range result.ConditionResults {
@@ -139,12 +139,12 @@ func buildPlaintextMessageBody(endpoint *core.Endpoint, alert *alert.Alert, resu
}
// buildHTMLMessageBody builds the message body in HTML to include in request
-func buildHTMLMessageBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) string {
+func buildHTMLMessageBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) string {
var message string
if resolved {
- message = fmt.Sprintf("An alert for %s
has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for %s
has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("An alert for %s
has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for %s
has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
if len(result.ConditionResults) > 0 {
diff --git a/alerting/provider/matrix/matrix_test.go b/alerting/provider/matrix/matrix_test.go
index 2d9ae57a..923cae55 100644
--- a/alerting/provider/matrix/matrix_test.go
+++ b/alerting/provider/matrix/matrix_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -149,10 +149,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -197,10 +197,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/mattermost/mattermost.go b/alerting/provider/mattermost/mattermost.go
index 41b34542..830dd044 100644
--- a/alerting/provider/mattermost/mattermost.go
+++ b/alerting/provider/mattermost/mattermost.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Mattermost
@@ -50,9 +50,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(endpoint, alert, result, resolved)))
- request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(ep, alert, result, resolved)))
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(ep.Group), buffer)
if err != nil {
return err
}
@@ -92,13 +92,13 @@ type Field struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, color string
if resolved {
- message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
color = "#36A64F"
} else {
- message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
color = "#DD0000"
}
var formattedConditionResults string
diff --git a/alerting/provider/mattermost/mattermost_test.go b/alerting/provider/mattermost/mattermost_test.go
index 016ac406..b476bfc8 100644
--- a/alerting/provider/mattermost/mattermost_test.go
+++ b/alerting/provider/mattermost/mattermost_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -120,10 +120,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -168,10 +168,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/messagebird/messagebird.go b/alerting/provider/messagebird/messagebird.go
index eaf93937..235a0a60 100644
--- a/alerting/provider/messagebird/messagebird.go
+++ b/alerting/provider/messagebird/messagebird.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -33,8 +33,8 @@ func (provider *AlertProvider) IsValid() bool {
// Send an alert using the provider
// Reference doc for messagebird: https://developers.messagebird.com/api/sms-messaging/#send-outbound-sms
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, restAPIURL, buffer)
if err != nil {
return err
@@ -60,12 +60,12 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message string
if resolved {
- message = fmt.Sprintf("RESOLVED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("RESOLVED: %s - %s", ep.DisplayName(), alert.GetDescription())
} else {
- message = fmt.Sprintf("TRIGGERED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("TRIGGERED: %s - %s", ep.DisplayName(), alert.GetDescription())
}
body, _ := json.Marshal(Body{
Originator: provider.Originator,
diff --git a/alerting/provider/messagebird/messagebird_test.go b/alerting/provider/messagebird/messagebird_test.go
index a5a7b3b2..22c9a4d6 100644
--- a/alerting/provider/messagebird/messagebird_test.go
+++ b/alerting/provider/messagebird/messagebird_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -83,10 +83,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -131,10 +131,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/ntfy/ntfy.go b/alerting/provider/ntfy/ntfy.go
index bd10ef83..1530c10f 100644
--- a/alerting/provider/ntfy/ntfy.go
+++ b/alerting/provider/ntfy/ntfy.go
@@ -11,7 +11,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -46,8 +46,8 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, provider.URL, buffer)
if err != nil {
return err
@@ -77,7 +77,7 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, formattedConditionResults, tag string
if resolved {
tag = "white_check_mark"
@@ -101,7 +101,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
message += formattedConditionResults
body, _ := json.Marshal(Body{
Topic: provider.Topic,
- Title: "Gatus: " + endpoint.DisplayName(),
+ Title: "Gatus: " + ep.DisplayName(),
Message: message,
Tags: []string{tag},
Priority: provider.Priority,
diff --git a/alerting/provider/ntfy/ntfy_test.go b/alerting/provider/ntfy/ntfy_test.go
index 6786f3b3..3ca3e59d 100644
--- a/alerting/provider/ntfy/ntfy_test.go
+++ b/alerting/provider/ntfy/ntfy_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestAlertDefaultProvider_IsValid(t *testing.T) {
@@ -92,10 +92,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/opsgenie/opsgenie.go b/alerting/provider/opsgenie/opsgenie.go
index 5d105661..a0b4167f 100644
--- a/alerting/provider/opsgenie/opsgenie.go
+++ b/alerting/provider/opsgenie/opsgenie.go
@@ -11,7 +11,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -59,13 +59,13 @@ func (provider *AlertProvider) IsValid() bool {
// Send an alert using the provider
//
// Relevant: https://docs.opsgenie.com/docs/alert-api
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- err := provider.createAlert(endpoint, alert, result, resolved)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ err := provider.createAlert(ep, alert, result, resolved)
if err != nil {
return err
}
if resolved {
- err = provider.closeAlert(endpoint, alert)
+ err = provider.closeAlert(ep, alert)
if err != nil {
return err
}
@@ -75,20 +75,20 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert,
// The alert has been resolved and there's no error, so we can clear the alert's ResolveKey
alert.ResolveKey = ""
} else {
- alert.ResolveKey = provider.alias(buildKey(endpoint))
+ alert.ResolveKey = provider.alias(buildKey(ep))
}
}
return nil
}
-func (provider *AlertProvider) createAlert(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- payload := provider.buildCreateRequestBody(endpoint, alert, result, resolved)
+func (provider *AlertProvider) createAlert(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ payload := provider.buildCreateRequestBody(ep, alert, result, resolved)
return provider.sendRequest(restAPI, http.MethodPost, payload)
}
-func (provider *AlertProvider) closeAlert(endpoint *core.Endpoint, alert *alert.Alert) error {
- payload := provider.buildCloseRequestBody(endpoint, alert)
- url := restAPI + "/" + provider.alias(buildKey(endpoint)) + "/close?identifierType=alias"
+func (provider *AlertProvider) closeAlert(ep *endpoint.Endpoint, alert *alert.Alert) error {
+ payload := provider.buildCloseRequestBody(ep, alert)
+ url := restAPI + "/" + provider.alias(buildKey(ep)) + "/close?identifierType=alias"
return provider.sendRequest(url, http.MethodPost, payload)
}
@@ -115,17 +115,17 @@ func (provider *AlertProvider) sendRequest(url, method string, payload interface
return nil
}
-func (provider *AlertProvider) buildCreateRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) alertCreateRequest {
+func (provider *AlertProvider) buildCreateRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) alertCreateRequest {
var message, description string
if resolved {
- message = fmt.Sprintf("RESOLVED: %s - %s", endpoint.Name, alert.GetDescription())
- description = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("RESOLVED: %s - %s", ep.Name, alert.GetDescription())
+ description = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("%s - %s", endpoint.Name, alert.GetDescription())
- description = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("%s - %s", ep.Name, alert.GetDescription())
+ description = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
}
- if endpoint.Group != "" {
- message = fmt.Sprintf("[%s] %s", endpoint.Group, message)
+ if ep.Group != "" {
+ message = fmt.Sprintf("[%s] %s", ep.Group, message)
}
var formattedConditionResults string
for _, conditionResult := range result.ConditionResults {
@@ -138,10 +138,10 @@ func (provider *AlertProvider) buildCreateRequestBody(endpoint *core.Endpoint, a
formattedConditionResults += fmt.Sprintf("%s - `%s`\n", prefix, conditionResult.Condition)
}
description = description + "\n" + formattedConditionResults
- key := buildKey(endpoint)
+ key := buildKey(ep)
details := map[string]string{
- "endpoint:url": endpoint.URL,
- "endpoint:group": endpoint.Group,
+ "endpoint:url": ep.URL,
+ "endpoint:group": ep.Group,
"result:hostname": result.Hostname,
"result:ip": result.IP,
"result:dns_code": result.DNSRCode,
@@ -167,10 +167,10 @@ func (provider *AlertProvider) buildCreateRequestBody(endpoint *core.Endpoint, a
}
}
-func (provider *AlertProvider) buildCloseRequestBody(endpoint *core.Endpoint, alert *alert.Alert) alertCloseRequest {
+func (provider *AlertProvider) buildCloseRequestBody(ep *endpoint.Endpoint, alert *alert.Alert) alertCloseRequest {
return alertCloseRequest{
- Source: buildKey(endpoint),
- Note: fmt.Sprintf("RESOLVED: %s - %s", endpoint.Name, alert.GetDescription()),
+ Source: buildKey(ep),
+ Note: fmt.Sprintf("RESOLVED: %s - %s", ep.Name, alert.GetDescription()),
}
}
@@ -211,12 +211,12 @@ func (provider *AlertProvider) GetDefaultAlert() *alert.Alert {
return provider.DefaultAlert
}
-func buildKey(endpoint *core.Endpoint) string {
- name := toKebabCase(endpoint.Name)
- if endpoint.Group == "" {
+func buildKey(ep *endpoint.Endpoint) string {
+ name := toKebabCase(ep.Name)
+ if ep.Group == "" {
return name
}
- return toKebabCase(endpoint.Group) + "-" + name
+ return toKebabCase(ep.Group) + "-" + name
}
func toKebabCase(val string) string {
diff --git a/alerting/provider/opsgenie/opsgenie_test.go b/alerting/provider/opsgenie/opsgenie_test.go
index ab054b86..746eb387 100644
--- a/alerting/provider/opsgenie/opsgenie_test.go
+++ b/alerting/provider/opsgenie/opsgenie_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -79,10 +79,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -106,8 +106,8 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Name string
Provider *AlertProvider
Alert *alert.Alert
- Endpoint *core.Endpoint
- Result *core.Result
+ Endpoint *endpoint.Endpoint
+ Result *endpoint.Result
Resolved bool
want alertCreateRequest
}{
@@ -115,8 +115,8 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Name: "missing all params (unresolved)",
Provider: &AlertProvider{},
Alert: &alert.Alert{},
- Endpoint: &core.Endpoint{},
- Result: &core.Result{},
+ Endpoint: &endpoint.Endpoint{},
+ Result: &endpoint.Result{},
Resolved: false,
want: alertCreateRequest{
Message: " - ",
@@ -133,8 +133,8 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Name: "missing all params (resolved)",
Provider: &AlertProvider{},
Alert: &alert.Alert{},
- Endpoint: &core.Endpoint{},
- Result: &core.Result{},
+ Endpoint: &endpoint.Endpoint{},
+ Result: &endpoint.Result{},
Resolved: true,
want: alertCreateRequest{
Message: "RESOLVED: - ",
@@ -154,11 +154,11 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Description: &description,
FailureThreshold: 3,
},
- Endpoint: &core.Endpoint{
+ Endpoint: &endpoint.Endpoint{
Name: "my super app",
},
- Result: &core.Result{
- ConditionResults: []*core.ConditionResult{
+ Result: &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -194,11 +194,11 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Description: &description,
SuccessThreshold: 4,
},
- Endpoint: &core.Endpoint{
+ Endpoint: &endpoint.Endpoint{
Name: "my mega app",
},
- Result: &core.Result{
- ConditionResults: []*core.ConditionResult{
+ Result: &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -226,17 +226,17 @@ func TestAlertProvider_buildCreateRequestBody(t *testing.T) {
Description: &description,
FailureThreshold: 6,
},
- Endpoint: &core.Endpoint{
+ Endpoint: &endpoint.Endpoint{
Name: "my app",
Group: "end game",
URL: "https://my.go/app",
},
- Result: &core.Result{
+ Result: &endpoint.Result{
HTTPStatus: 400,
Hostname: "my.go",
Errors: []string{"error 01", "error 02"},
Success: false,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: false,
@@ -279,14 +279,14 @@ func TestAlertProvider_buildCloseRequestBody(t *testing.T) {
Name string
Provider *AlertProvider
Alert *alert.Alert
- Endpoint *core.Endpoint
+ Endpoint *endpoint.Endpoint
want alertCloseRequest
}{
{
Name: "Missing all values",
Provider: &AlertProvider{},
Alert: &alert.Alert{},
- Endpoint: &core.Endpoint{},
+ Endpoint: &endpoint.Endpoint{},
want: alertCloseRequest{
Source: "",
Note: "RESOLVED: - ",
@@ -298,7 +298,7 @@ func TestAlertProvider_buildCloseRequestBody(t *testing.T) {
Alert: &alert.Alert{
Description: &description,
},
- Endpoint: &core.Endpoint{
+ Endpoint: &endpoint.Endpoint{
Name: "endpoint name",
},
want: alertCloseRequest{
diff --git a/alerting/provider/pagerduty/pagerduty.go b/alerting/provider/pagerduty/pagerduty.go
index b3ab6e01..cc76751f 100644
--- a/alerting/provider/pagerduty/pagerduty.go
+++ b/alerting/provider/pagerduty/pagerduty.go
@@ -10,7 +10,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -52,8 +52,8 @@ func (provider *AlertProvider) IsValid() bool {
// Send an alert using the provider
//
// Relevant: https://developer.pagerduty.com/docs/events-api-v2/trigger-events/
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, restAPIURL, buffer)
if err != nil {
return err
@@ -101,19 +101,19 @@ type Payload struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, eventAction, resolveKey string
if resolved {
- message = fmt.Sprintf("RESOLVED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("RESOLVED: %s - %s", ep.DisplayName(), alert.GetDescription())
eventAction = "resolve"
resolveKey = alert.ResolveKey
} else {
- message = fmt.Sprintf("TRIGGERED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("TRIGGERED: %s - %s", ep.DisplayName(), alert.GetDescription())
eventAction = "trigger"
resolveKey = ""
}
body, _ := json.Marshal(Body{
- RoutingKey: provider.getIntegrationKeyForGroup(endpoint.Group),
+ RoutingKey: provider.getIntegrationKeyForGroup(ep.Group),
DedupKey: resolveKey,
EventAction: eventAction,
Payload: Payload{
diff --git a/alerting/provider/pagerduty/pagerduty_test.go b/alerting/provider/pagerduty/pagerduty_test.go
index 4523f280..23d0b410 100644
--- a/alerting/provider/pagerduty/pagerduty_test.go
+++ b/alerting/provider/pagerduty/pagerduty_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -115,10 +115,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -161,7 +161,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- body := scenario.Provider.buildRequestBody(&core.Endpoint{Name: "endpoint-name"}, &scenario.Alert, &core.Result{}, scenario.Resolved)
+ body := scenario.Provider.buildRequestBody(&endpoint.Endpoint{Name: "endpoint-name"}, &scenario.Alert, &endpoint.Result{}, scenario.Resolved)
if string(body) != scenario.ExpectedBody {
t.Errorf("expected:\n%s\ngot:\n%s", scenario.ExpectedBody, body)
}
diff --git a/alerting/provider/provider.go b/alerting/provider/provider.go
index f8c5257b..a294ad9b 100644
--- a/alerting/provider/provider.go
+++ b/alerting/provider/provider.go
@@ -21,7 +21,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/provider/teams"
"github.com/TwiN/gatus/v5/alerting/provider/telegram"
"github.com/TwiN/gatus/v5/alerting/provider/twilio"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the interface that each provider should implement
@@ -33,7 +33,7 @@ type AlertProvider interface {
GetDefaultAlert() *alert.Alert
// Send an alert using the provider
- Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error
+ Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error
}
// ParseWithDefaultAlert parses an Endpoint alert by using the provider's default alert as a baseline
diff --git a/alerting/provider/pushover/pushover.go b/alerting/provider/pushover/pushover.go
index 6b5343fd..b90b17a5 100644
--- a/alerting/provider/pushover/pushover.go
+++ b/alerting/provider/pushover/pushover.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -52,8 +52,8 @@ func (provider *AlertProvider) IsValid() bool {
// Send an alert using the provider
// Reference doc for pushover: https://pushover.net/api
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
request, err := http.NewRequest(http.MethodPost, restAPIURL, buffer)
if err != nil {
return err
@@ -81,12 +81,12 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message string
if resolved {
- message = fmt.Sprintf("RESOLVED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("RESOLVED: %s - %s", ep.DisplayName(), alert.GetDescription())
} else {
- message = fmt.Sprintf("TRIGGERED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("TRIGGERED: %s - %s", ep.DisplayName(), alert.GetDescription())
}
body, _ := json.Marshal(Body{
Token: provider.ApplicationToken,
diff --git a/alerting/provider/pushover/pushover_test.go b/alerting/provider/pushover/pushover_test.go
index 57f03fb5..942a82bf 100644
--- a/alerting/provider/pushover/pushover_test.go
+++ b/alerting/provider/pushover/pushover_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -95,10 +95,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -150,10 +150,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/alerting/provider/slack/slack.go b/alerting/provider/slack/slack.go
index e498cee1..46d327b2 100644
--- a/alerting/provider/slack/slack.go
+++ b/alerting/provider/slack/slack.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Slack
@@ -42,9 +42,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
- request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(ep.Group), buffer)
if err != nil {
return err
}
@@ -81,13 +81,13 @@ type Field struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, color string
if resolved {
- message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
color = "#36A64F"
} else {
- message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
color = "#DD0000"
}
var formattedConditionResults string
diff --git a/alerting/provider/slack/slack_test.go b/alerting/provider/slack/slack_test.go
index 4bd10e15..f3e95fcd 100644
--- a/alerting/provider/slack/slack_test.go
+++ b/alerting/provider/slack/slack_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -116,10 +116,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -142,7 +142,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
scenarios := []struct {
Name string
Provider AlertProvider
- Endpoint core.Endpoint
+ Endpoint endpoint.Endpoint
Alert alert.Alert
NoConditions bool
Resolved bool
@@ -151,7 +151,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name"},
+ Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":x: - `[CONNECTED] == true`\\n:x: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
@@ -159,7 +159,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "triggered-with-group",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name", Group: "group"},
+ Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *group/name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":x: - `[CONNECTED] == true`\\n:x: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
@@ -168,7 +168,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
Name: "triggered-with-no-conditions",
NoConditions: true,
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name"},
+ Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been triggered due to having failed 3 time(s) in a row:\\n\\u003e description-1\",\"short\":false,\"color\":\"#DD0000\"}]}",
@@ -176,7 +176,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "resolved",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name"},
+ Endpoint: endpoint.Endpoint{Name: "name"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
@@ -184,7 +184,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
{
Name: "resolved-with-group",
Provider: AlertProvider{},
- Endpoint: core.Endpoint{Name: "name", Group: "group"},
+ Endpoint: endpoint.Endpoint{Name: "name", Group: "group"},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true,
ExpectedBody: "{\"text\":\"\",\"attachments\":[{\"title\":\":helmet_with_white_cross: Gatus\",\"text\":\"An alert for *group/name* has been resolved after passing successfully 5 time(s) in a row:\\n\\u003e description-2\",\"short\":false,\"color\":\"#36A64F\",\"fields\":[{\"title\":\"Condition results\",\"value\":\":white_check_mark: - `[CONNECTED] == true`\\n:white_check_mark: - `[STATUS] == 200`\\n\",\"short\":false}]}]}",
@@ -192,9 +192,9 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- var conditionResults []*core.ConditionResult
+ var conditionResults []*endpoint.ConditionResult
if !scenario.NoConditions {
- conditionResults = []*core.ConditionResult{
+ conditionResults = []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
}
@@ -202,7 +202,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
body := scenario.Provider.buildRequestBody(
&scenario.Endpoint,
&scenario.Alert,
- &core.Result{
+ &endpoint.Result{
ConditionResults: conditionResults,
},
scenario.Resolved,
diff --git a/alerting/provider/teams/teams.go b/alerting/provider/teams/teams.go
index 3dcd1812..671649be 100644
--- a/alerting/provider/teams/teams.go
+++ b/alerting/provider/teams/teams.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Teams
@@ -21,7 +21,7 @@ type AlertProvider struct {
// Overrides is a list of Override that may be prioritized over the default configuration
Overrides []Override `yaml:"overrides,omitempty"`
-
+
// Title is the title of the message that will be sent
Title string `yaml:"title,omitempty"`
}
@@ -47,9 +47,9 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
- request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(ep.Group), buffer)
if err != nil {
return err
}
@@ -81,13 +81,13 @@ type Section struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message, color string
if resolved {
- message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been resolved after passing successfully %d time(s) in a row", ep.DisplayName(), alert.SuccessThreshold)
color = "#36A64F"
} else {
- message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
color = "#DD0000"
}
var formattedConditionResults string
diff --git a/alerting/provider/teams/teams_test.go b/alerting/provider/teams/teams_test.go
index 7f7cdb21..802a070e 100644
--- a/alerting/provider/teams/teams_test.go
+++ b/alerting/provider/teams/teams_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -116,10 +116,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -172,17 +172,17 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- var conditionResults []*core.ConditionResult
+ var conditionResults []*endpoint.ConditionResult
if !scenario.NoConditions {
- conditionResults = []*core.ConditionResult{
+ conditionResults = []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
}
}
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{ConditionResults: conditionResults},
+ &endpoint.Result{ConditionResults: conditionResults},
scenario.Resolved,
)
if string(body) != scenario.ExpectedBody {
diff --git a/alerting/provider/telegram/telegram.go b/alerting/provider/telegram/telegram.go
index db9ea0a0..f5950a17 100644
--- a/alerting/provider/telegram/telegram.go
+++ b/alerting/provider/telegram/telegram.go
@@ -9,7 +9,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const defaultAPIURL = "https://api.telegram.org"
@@ -36,8 +36,8 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer(provider.buildRequestBody(endpoint, alert, result, resolved))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer(provider.buildRequestBody(ep, alert, result, resolved))
apiURL := provider.APIURL
if apiURL == "" {
apiURL = defaultAPIURL
@@ -66,12 +66,12 @@ type Body struct {
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) []byte {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) []byte {
var message string
if resolved {
- message = fmt.Sprintf("An alert for *%s* has been resolved:\n—\n _healthcheck passing successfully %d time(s) in a row_\n— ", endpoint.DisplayName(), alert.SuccessThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been resolved:\n—\n _healthcheck passing successfully %d time(s) in a row_\n— ", ep.DisplayName(), alert.SuccessThreshold)
} else {
- message = fmt.Sprintf("An alert for *%s* has been triggered:\n—\n _healthcheck failed %d time(s) in a row_\n— ", endpoint.DisplayName(), alert.FailureThreshold)
+ message = fmt.Sprintf("An alert for *%s* has been triggered:\n—\n _healthcheck failed %d time(s) in a row_\n— ", ep.DisplayName(), alert.FailureThreshold)
}
var formattedConditionResults string
if len(result.ConditionResults) > 0 {
diff --git a/alerting/provider/telegram/telegram_test.go b/alerting/provider/telegram/telegram_test.go
index 3dcebb07..6c9b9109 100644
--- a/alerting/provider/telegram/telegram_test.go
+++ b/alerting/provider/telegram/telegram_test.go
@@ -7,7 +7,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/test"
)
@@ -89,10 +89,10 @@ func TestAlertProvider_Send(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
err := scenario.Provider.Send(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
@@ -145,17 +145,17 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- var conditionResults []*core.ConditionResult
+ var conditionResults []*endpoint.ConditionResult
if !scenario.NoConditions {
- conditionResults = []*core.ConditionResult{
+ conditionResults = []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
}
}
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{ConditionResults: conditionResults},
+ &endpoint.Result{ConditionResults: conditionResults},
scenario.Resolved,
)
if string(body) != scenario.ExpectedBody {
diff --git a/alerting/provider/twilio/twilio.go b/alerting/provider/twilio/twilio.go
index 8370a298..b2879444 100644
--- a/alerting/provider/twilio/twilio.go
+++ b/alerting/provider/twilio/twilio.go
@@ -10,7 +10,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// AlertProvider is the configuration necessary for sending an alert using Twilio
@@ -30,8 +30,8 @@ func (provider *AlertProvider) IsValid() bool {
}
// Send an alert using the provider
-func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) error {
- buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(endpoint, alert, result, resolved)))
+func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
+ buffer := bytes.NewBuffer([]byte(provider.buildRequestBody(ep, alert, result, resolved)))
request, err := http.NewRequest(http.MethodPost, fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json", provider.SID), buffer)
if err != nil {
return err
@@ -51,12 +51,12 @@ func (provider *AlertProvider) Send(endpoint *core.Endpoint, alert *alert.Alert,
}
// buildRequestBody builds the request body for the provider
-func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *alert.Alert, result *core.Result, resolved bool) string {
+func (provider *AlertProvider) buildRequestBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) string {
var message string
if resolved {
- message = fmt.Sprintf("RESOLVED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("RESOLVED: %s - %s", ep.DisplayName(), alert.GetDescription())
} else {
- message = fmt.Sprintf("TRIGGERED: %s - %s", endpoint.DisplayName(), alert.GetDescription())
+ message = fmt.Sprintf("TRIGGERED: %s - %s", ep.DisplayName(), alert.GetDescription())
}
return url.Values{
"To": {provider.To},
diff --git a/alerting/provider/twilio/twilio_test.go b/alerting/provider/twilio/twilio_test.go
index 31328a2f..66e1737f 100644
--- a/alerting/provider/twilio/twilio_test.go
+++ b/alerting/provider/twilio/twilio_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestTwilioAlertProvider_IsValid(t *testing.T) {
@@ -51,10 +51,10 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody(
- &core.Endpoint{Name: "endpoint-name"},
+ &endpoint.Endpoint{Name: "endpoint-name"},
&scenario.Alert,
- &core.Result{
- ConditionResults: []*core.ConditionResult{
+ &endpoint.Result{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
},
diff --git a/api/badge.go b/api/badge.go
index fb04fce3..66a8a36b 100644
--- a/api/badge.go
+++ b/api/badge.go
@@ -9,7 +9,7 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core/ui"
+ "github.com/TwiN/gatus/v5/config/endpoint/ui"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
diff --git a/api/badge_test.go b/api/badge_test.go
index d3da9da6..a5be60d2 100644
--- a/api/badge_test.go
+++ b/api/badge_test.go
@@ -8,8 +8,8 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core"
- "github.com/TwiN/gatus/v5/core/ui"
+ "github.com/TwiN/gatus/v5/config/endpoint"
+ "github.com/TwiN/gatus/v5/config/endpoint/ui"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/watchdog"
)
@@ -19,7 +19,7 @@ func TestBadge(t *testing.T) {
defer cache.Clear()
cfg := &config.Config{
Metrics: true,
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "frontend",
Group: "core",
@@ -34,8 +34,8 @@ func TestBadge(t *testing.T) {
cfg.Endpoints[0].UIConfig = ui.GetDefaultConfig()
cfg.Endpoints[1].UIConfig = ui.GetDefaultConfig()
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Connected: true, Duration: time.Millisecond, Timestamp: time.Now()})
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Connected: false, Duration: time.Second, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &endpoint.Result{Success: true, Connected: true, Duration: time.Millisecond, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &endpoint.Result{Success: false, Connected: false, Duration: time.Second, Timestamp: time.Now()})
api := New(cfg)
router := api.Router()
type Scenario struct {
@@ -218,30 +218,30 @@ func TestGetBadgeColorFromResponseTime(t *testing.T) {
defer cache.Clear()
var (
- firstCondition = core.Condition("[STATUS] == 200")
- secondCondition = core.Condition("[RESPONSE_TIME] < 500")
- thirdCondition = core.Condition("[CERTIFICATE_EXPIRATION] < 72h")
+ firstCondition = endpoint.Condition("[STATUS] == 200")
+ secondCondition = endpoint.Condition("[RESPONSE_TIME] < 500")
+ thirdCondition = endpoint.Condition("[CERTIFICATE_EXPIRATION] < 72h")
)
- firstTestEndpoint := core.Endpoint{
+ firstTestEndpoint := endpoint.Endpoint{
Name: "a",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{firstCondition, secondCondition, thirdCondition},
+ Conditions: []endpoint.Condition{firstCondition, secondCondition, thirdCondition},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
UIConfig: ui.GetDefaultConfig(),
}
- secondTestEndpoint := core.Endpoint{
+ secondTestEndpoint := endpoint.Endpoint{
Name: "b",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{firstCondition, secondCondition, thirdCondition},
+ Conditions: []endpoint.Condition{firstCondition, secondCondition, thirdCondition},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
@@ -255,10 +255,10 @@ func TestGetBadgeColorFromResponseTime(t *testing.T) {
}
cfg := &config.Config{
Metrics: true,
- Endpoints: []*core.Endpoint{&firstTestEndpoint, &secondTestEndpoint},
+ Endpoints: []*endpoint.Endpoint{&firstTestEndpoint, &secondTestEndpoint},
}
- testSuccessfulResult := core.Result{
+ testSuccessfulResult := endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -268,7 +268,7 @@ func TestGetBadgeColorFromResponseTime(t *testing.T) {
Timestamp: time.Now(),
Duration: 150 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
diff --git a/api/chart_test.go b/api/chart_test.go
index 341c6725..0c3c769e 100644
--- a/api/chart_test.go
+++ b/api/chart_test.go
@@ -7,7 +7,7 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/watchdog"
)
@@ -17,7 +17,7 @@ func TestResponseTimeChart(t *testing.T) {
defer cache.Clear()
cfg := &config.Config{
Metrics: true,
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "frontend",
Group: "core",
@@ -28,8 +28,8 @@ func TestResponseTimeChart(t *testing.T) {
},
},
}
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &endpoint.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &endpoint.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
api := New(cfg)
router := api.Router()
type Scenario struct {
diff --git a/api/endpoint_status.go b/api/endpoint_status.go
index ac9e37b5..41627de2 100644
--- a/api/endpoint_status.go
+++ b/api/endpoint_status.go
@@ -9,8 +9,8 @@ import (
"github.com/TwiN/gatus/v5/client"
"github.com/TwiN/gatus/v5/config"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/remote"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
@@ -51,11 +51,11 @@ func EndpointStatuses(cfg *config.Config) fiber.Handler {
}
}
-func getEndpointStatusesFromRemoteInstances(remoteConfig *remote.Config) ([]*core.EndpointStatus, error) {
+func getEndpointStatusesFromRemoteInstances(remoteConfig *remote.Config) ([]*endpoint.Status, error) {
if remoteConfig == nil || len(remoteConfig.Instances) == 0 {
return nil, nil
}
- var endpointStatusesFromAllRemotes []*core.EndpointStatus
+ var endpointStatusesFromAllRemotes []*endpoint.Status
httpClient := client.GetHTTPClient(remoteConfig.ClientConfig)
for _, instance := range remoteConfig.Instances {
response, err := httpClient.Get(instance.URL)
@@ -68,7 +68,7 @@ func getEndpointStatusesFromRemoteInstances(remoteConfig *remote.Config) ([]*cor
log.Printf("[api.getEndpointStatusesFromRemoteInstances] Silently failed to retrieve endpoint statuses from %s: %s", instance.URL, err.Error())
continue
}
- var endpointStatuses []*core.EndpointStatus
+ var endpointStatuses []*endpoint.Status
if err = json.Unmarshal(body, &endpointStatuses); err != nil {
_ = response.Body.Close()
log.Printf("[api.getEndpointStatusesFromRemoteInstances] Silently failed to retrieve endpoint statuses from %s: %s", instance.URL, err.Error())
@@ -83,7 +83,7 @@ func getEndpointStatusesFromRemoteInstances(remoteConfig *remote.Config) ([]*cor
return endpointStatusesFromAllRemotes, nil
}
-// EndpointStatus retrieves a single core.EndpointStatus by group and endpoint name
+// EndpointStatus retrieves a single endpoint.Status by group and endpoint name
func EndpointStatus(c *fiber.Ctx) error {
page, pageSize := extractPageAndPageSizeFromRequest(c)
endpointStatus, err := store.Get().GetEndpointStatusByKey(c.Params("key"), paging.NewEndpointStatusParams().WithResults(page, pageSize).WithEvents(1, common.MaximumNumberOfEvents))
diff --git a/api/endpoint_status_test.go b/api/endpoint_status_test.go
index b88a915f..08725393 100644
--- a/api/endpoint_status_test.go
+++ b/api/endpoint_status_test.go
@@ -8,7 +8,7 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/watchdog"
)
@@ -16,19 +16,19 @@ import (
var (
timestamp = time.Now()
- testEndpoint = core.Endpoint{
+ testEndpoint = endpoint.Endpoint{
Name: "name",
Group: "group",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{core.Condition("[STATUS] == 200"), core.Condition("[RESPONSE_TIME] < 500"), core.Condition("[CERTIFICATE_EXPIRATION] < 72h")},
+ Conditions: []endpoint.Condition{endpoint.Condition("[STATUS] == 200"), endpoint.Condition("[RESPONSE_TIME] < 500"), endpoint.Condition("[CERTIFICATE_EXPIRATION] < 72h")},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
- testSuccessfulResult = core.Result{
+ testSuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -38,7 +38,7 @@ var (
Timestamp: timestamp,
Duration: 150 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -53,7 +53,7 @@ var (
},
},
}
- testUnsuccessfulResult = core.Result{
+ testUnsuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -63,7 +63,7 @@ var (
Timestamp: timestamp,
Duration: 750 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -85,7 +85,7 @@ func TestEndpointStatus(t *testing.T) {
defer cache.Clear()
cfg := &config.Config{
Metrics: true,
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "frontend",
Group: "core",
@@ -96,8 +96,8 @@ func TestEndpointStatus(t *testing.T) {
},
},
}
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &endpoint.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &endpoint.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
api := New(cfg)
router := api.Router()
type Scenario struct {
diff --git a/api/external_endpoint.go b/api/external_endpoint.go
index 93ec5809..4874d805 100644
--- a/api/external_endpoint.go
+++ b/api/external_endpoint.go
@@ -7,7 +7,7 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/watchdog"
@@ -41,7 +41,7 @@ func CreateExternalEndpointResult(cfg *config.Config) fiber.Handler {
return c.Status(401).SendString("invalid token")
}
// Persist the result in the storage
- result := &core.Result{
+ result := &endpoint.Result{
Timestamp: time.Now(),
Success: c.QueryBool("success"),
Errors: []string{},
diff --git a/api/external_endpoint_test.go b/api/external_endpoint_test.go
index 72078cb7..60ebcd7b 100644
--- a/api/external_endpoint_test.go
+++ b/api/external_endpoint_test.go
@@ -9,8 +9,8 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/alerting/provider/discord"
"github.com/TwiN/gatus/v5/config"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/maintenance"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
@@ -22,7 +22,7 @@ func TestCreateExternalEndpointResult(t *testing.T) {
Alerting: &alerting.Config{
Discord: &discord.AlertProvider{},
},
- ExternalEndpoints: []*core.ExternalEndpoint{
+ ExternalEndpoints: []*endpoint.ExternalEndpoint{
{
Name: "n",
Group: "g",
diff --git a/api/spa_test.go b/api/spa_test.go
index 250ecdde..11da2adf 100644
--- a/api/spa_test.go
+++ b/api/spa_test.go
@@ -9,8 +9,8 @@ import (
"time"
"github.com/TwiN/gatus/v5/config"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/ui"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/storage/store"
"github.com/TwiN/gatus/v5/watchdog"
)
@@ -20,7 +20,7 @@ func TestSinglePageApplication(t *testing.T) {
defer cache.Clear()
cfg := &config.Config{
Metrics: true,
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "frontend",
Group: "core",
@@ -34,8 +34,8 @@ func TestSinglePageApplication(t *testing.T) {
Title: "example-title",
},
}
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
- watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &endpoint.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
+ watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &endpoint.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
api := New(cfg)
router := api.Router()
type Scenario struct {
diff --git a/client/client.go b/client/client.go
index 7a00a767..b63fb93b 100644
--- a/client/client.go
+++ b/client/client.go
@@ -16,11 +16,16 @@ import (
"github.com/TwiN/gocache/v2"
"github.com/TwiN/whois"
"github.com/ishidawataru/sctp"
+ "github.com/miekg/dns"
ping "github.com/prometheus-community/pro-bing"
"golang.org/x/crypto/ssh"
"golang.org/x/net/websocket"
)
+const (
+ dnsPort = 53
+)
+
var (
// injectedHTTPClient is used for testing purposes
injectedHTTPClient *http.Client
@@ -291,6 +296,49 @@ func QueryWebSocket(address, body string, config *Config) (bool, []byte, error)
return true, msg[:n], nil
}
+func QueryDNS(queryType, queryName, url string) (connected bool, dnsRcode string, body []byte, err error) {
+ if !strings.Contains(url, ":") {
+ url = fmt.Sprintf("%s:%d", url, dnsPort)
+ }
+ queryTypeAsUint16 := dns.StringToType[queryType]
+ c := new(dns.Client)
+ m := new(dns.Msg)
+ m.SetQuestion(queryName, queryTypeAsUint16)
+ r, _, err := c.Exchange(m, url)
+ if err != nil {
+ return false, "", nil, err
+ }
+ connected = true
+ dnsRcode = dns.RcodeToString[r.Rcode]
+ for _, rr := range r.Answer {
+ switch rr.Header().Rrtype {
+ case dns.TypeA:
+ if a, ok := rr.(*dns.A); ok {
+ body = []byte(a.A.String())
+ }
+ case dns.TypeAAAA:
+ if aaaa, ok := rr.(*dns.AAAA); ok {
+ body = []byte(aaaa.AAAA.String())
+ }
+ case dns.TypeCNAME:
+ if cname, ok := rr.(*dns.CNAME); ok {
+ body = []byte(cname.Target)
+ }
+ case dns.TypeMX:
+ if mx, ok := rr.(*dns.MX); ok {
+ body = []byte(mx.Mx)
+ }
+ case dns.TypeNS:
+ if ns, ok := rr.(*dns.NS); ok {
+ body = []byte(ns.Ns)
+ }
+ default:
+ body = []byte("query type is not supported yet")
+ }
+ }
+ return connected, dnsRcode, body, nil
+}
+
// InjectHTTPClient is used to inject a custom HTTP client for testing purposes
func InjectHTTPClient(httpClient *http.Client) {
injectedHTTPClient = httpClient
diff --git a/client/client_test.go b/client/client_test.go
index 10cc9ca4..10392e78 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -8,6 +8,8 @@ import (
"testing"
"time"
+ "github.com/TwiN/gatus/v5/config/endpoint/dns"
+ "github.com/TwiN/gatus/v5/pattern"
"github.com/TwiN/gatus/v5/test"
)
@@ -334,3 +336,97 @@ func TestTlsRenegotiation(t *testing.T) {
})
}
}
+
+func TestQueryDNS(t *testing.T) {
+ tests := []struct {
+ name string
+ inputDNS dns.Config
+ inputURL string
+ expectedDNSCode string
+ expectedBody string
+ isErrExpected bool
+ }{
+ {
+ name: "test Config with type A",
+ inputDNS: dns.Config{
+ QueryType: "A",
+ QueryName: "example.com.",
+ },
+ inputURL: "8.8.8.8",
+ expectedDNSCode: "NOERROR",
+ expectedBody: "93.184.215.14",
+ },
+ {
+ name: "test Config with type AAAA",
+ inputDNS: dns.Config{
+ QueryType: "AAAA",
+ QueryName: "example.com.",
+ },
+ inputURL: "8.8.8.8",
+ expectedDNSCode: "NOERROR",
+ expectedBody: "2606:2800:21f:cb07:6820:80da:af6b:8b2c",
+ },
+ {
+ name: "test Config with type CNAME",
+ inputDNS: dns.Config{
+ QueryType: "CNAME",
+ QueryName: "en.wikipedia.org.",
+ },
+ inputURL: "8.8.8.8",
+ expectedDNSCode: "NOERROR",
+ expectedBody: "dyna.wikimedia.org.",
+ },
+ {
+ name: "test Config with type MX",
+ inputDNS: dns.Config{
+ QueryType: "MX",
+ QueryName: "example.com.",
+ },
+ inputURL: "8.8.8.8",
+ expectedDNSCode: "NOERROR",
+ expectedBody: ".",
+ },
+ {
+ name: "test Config with type NS",
+ inputDNS: dns.Config{
+ QueryType: "NS",
+ QueryName: "example.com.",
+ },
+ inputURL: "8.8.8.8",
+ expectedDNSCode: "NOERROR",
+ expectedBody: "*.iana-servers.net.",
+ },
+ {
+ name: "test Config with fake type and retrieve error",
+ inputDNS: dns.Config{
+ QueryType: "B",
+ QueryName: "example",
+ },
+ inputURL: "8.8.8.8",
+ isErrExpected: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ _, dnsRCode, body, err := QueryDNS(test.inputDNS.QueryType, test.inputDNS.QueryName, test.inputURL)
+ if test.isErrExpected && err == nil {
+ t.Errorf("there should be an error")
+ }
+ if dnsRCode != test.expectedDNSCode {
+ t.Errorf("expected DNSRCode to be %s, got %s", test.expectedDNSCode, dnsRCode)
+ }
+ if test.inputDNS.QueryType == "NS" {
+ // Because there are often multiple nameservers backing a single domain, we'll only look at the suffix
+ if !pattern.Match(test.expectedBody, string(body)) {
+ t.Errorf("got %s, expected result %s,", string(body), test.expectedBody)
+ }
+ } else {
+ if string(body) != test.expectedBody {
+ t.Errorf("got %s, expected result %s,", string(body), test.expectedBody)
+ }
+ }
+ })
+ time.Sleep(5 * time.Millisecond)
+ }
+}
diff --git a/config/config.go b/config/config.go
index 667be593..14fde4b0 100644
--- a/config/config.go
+++ b/config/config.go
@@ -15,14 +15,13 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/alerting/provider"
"github.com/TwiN/gatus/v5/config/connectivity"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/maintenance"
"github.com/TwiN/gatus/v5/config/remote"
"github.com/TwiN/gatus/v5/config/ui"
"github.com/TwiN/gatus/v5/config/web"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/security"
"github.com/TwiN/gatus/v5/storage"
- "github.com/TwiN/gatus/v5/util"
"gopkg.in/yaml.v3"
)
@@ -74,10 +73,10 @@ type Config struct {
Alerting *alerting.Config `yaml:"alerting,omitempty"`
// Endpoints is the list of endpoints to monitor
- Endpoints []*core.Endpoint `yaml:"endpoints,omitempty"`
+ Endpoints []*endpoint.Endpoint `yaml:"endpoints,omitempty"`
// ExternalEndpoints is the list of all external endpoints
- ExternalEndpoints []*core.ExternalEndpoint `yaml:"external-endpoints,omitempty"`
+ ExternalEndpoints []*endpoint.ExternalEndpoint `yaml:"external-endpoints,omitempty"`
// Storage is the configuration for how the data is stored
Storage *storage.Config `yaml:"storage,omitempty"`
@@ -102,20 +101,20 @@ type Config struct {
lastFileModTime time.Time // last modification time
}
-func (config *Config) GetEndpointByKey(key string) *core.Endpoint {
+func (config *Config) GetEndpointByKey(key string) *endpoint.Endpoint {
for i := 0; i < len(config.Endpoints); i++ {
ep := config.Endpoints[i]
- if util.ConvertGroupAndEndpointNameToKey(ep.Group, ep.Name) == key {
+ if ep.Key() == key {
return ep
}
}
return nil
}
-func (config *Config) GetExternalEndpointByKey(key string) *core.ExternalEndpoint {
+func (config *Config) GetExternalEndpointByKey(key string) *endpoint.ExternalEndpoint {
for i := 0; i < len(config.ExternalEndpoints); i++ {
ee := config.ExternalEndpoints[i]
- if util.ConvertGroupAndEndpointNameToKey(ee.Group, ee.Name) == key {
+ if ee.Key() == key {
return ee
}
}
@@ -339,12 +338,12 @@ func validateWebConfig(config *Config) error {
}
func validateEndpointsConfig(config *Config) error {
- for _, endpoint := range config.Endpoints {
+ for _, ep := range config.Endpoints {
if config.Debug {
- log.Printf("[config.validateEndpointsConfig] Validating endpoint '%s'", endpoint.Name)
+ log.Printf("[config.validateEndpointsConfig] Validating endpoint '%s'", ep.Name)
}
- if err := endpoint.ValidateAndSetDefaults(); err != nil {
- return fmt.Errorf("invalid endpoint %s: %w", endpoint.DisplayName(), err)
+ if err := ep.ValidateAndSetDefaults(); err != nil {
+ return fmt.Errorf("invalid endpoint %s: %w", ep.DisplayName(), err)
}
}
log.Printf("[config.validateEndpointsConfig] Validated %d endpoints", len(config.Endpoints))
@@ -352,12 +351,12 @@ func validateEndpointsConfig(config *Config) error {
}
func validateExternalEndpointsConfig(config *Config) error {
- for _, externalEndpoint := range config.ExternalEndpoints {
+ for _, ee := range config.ExternalEndpoints {
if config.Debug {
- log.Printf("[config.validateExternalEndpointsConfig] Validating external endpoint '%s'", externalEndpoint.Name)
+ log.Printf("[config.validateExternalEndpointsConfig] Validating external endpoint '%s'", ee.Name)
}
- if err := externalEndpoint.ValidateAndSetDefaults(); err != nil {
- return fmt.Errorf("invalid external endpoint %s: %w", externalEndpoint.DisplayName(), err)
+ if err := ee.ValidateAndSetDefaults(); err != nil {
+ return fmt.Errorf("invalid external endpoint %s: %w", ee.DisplayName(), err)
}
}
log.Printf("[config.validateExternalEndpointsConfig] Validated %d external endpoints", len(config.ExternalEndpoints))
@@ -381,9 +380,9 @@ func validateSecurityConfig(config *Config) error {
// validateAlertingConfig validates the alerting configuration
// Note that the alerting configuration has to be validated before the endpoint configuration, because the default alert
-// returned by provider.AlertProvider.GetDefaultAlert() must be parsed before core.Endpoint.ValidateAndSetDefaults()
+// returned by provider.AlertProvider.GetDefaultAlert() must be parsed before endpoint.Endpoint.ValidateAndSetDefaults()
// sets the default alert values when none are set.
-func validateAlertingConfig(alertingConfig *alerting.Config, endpoints []*core.Endpoint, debug bool) {
+func validateAlertingConfig(alertingConfig *alerting.Config, endpoints []*endpoint.Endpoint, debug bool) {
if alertingConfig == nil {
log.Printf("[config.validateAlertingConfig] Alerting is not configured")
return
@@ -417,11 +416,11 @@ func validateAlertingConfig(alertingConfig *alerting.Config, endpoints []*core.E
if alertProvider.IsValid() {
// Parse alerts with the provider's default alert
if alertProvider.GetDefaultAlert() != nil {
- for _, endpoint := range endpoints {
- for alertIndex, endpointAlert := range endpoint.Alerts {
+ for _, ep := range endpoints {
+ for alertIndex, endpointAlert := range ep.Alerts {
if alertType == endpointAlert.Type {
if debug {
- log.Printf("[config.validateAlertingConfig] Parsing alert %d with provider's default alert for provider=%s in endpoint=%s", alertIndex, alertType, endpoint.Name)
+ log.Printf("[config.validateAlertingConfig] Parsing alert %d with provider's default alert for provider=%s in endpoint=%s", alertIndex, alertType, ep.Name)
}
provider.ParseWithDefaultAlert(alertProvider.GetDefaultAlert(), endpointAlert)
}
diff --git a/config/config_test.go b/config/config_test.go
index 2f076936..f94b170e 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -29,8 +29,8 @@ import (
"github.com/TwiN/gatus/v5/alerting/provider/telegram"
"github.com/TwiN/gatus/v5/alerting/provider/twilio"
"github.com/TwiN/gatus/v5/client"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/web"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/storage"
"gopkg.in/yaml.v3"
)
@@ -65,7 +65,7 @@ func TestLoadConfiguration(t *testing.T) {
endpoints:
- name: website`,
},
- expectedError: core.ErrEndpointWithNoURL,
+ expectedError: endpoint.ErrEndpointWithNoURL,
},
{
name: "config-file-with-endpoint-that-has-no-conditions",
@@ -76,7 +76,7 @@ endpoints:
- name: website
url: https://twin.sh/health`,
},
- expectedError: core.ErrEndpointWithNoCondition,
+ expectedError: endpoint.ErrEndpointWithNoCondition,
},
{
name: "config-file",
@@ -90,11 +90,11 @@ endpoints:
- "[STATUS] == 200"`,
},
expectedConfig: &Config{
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "website",
URL: "https://twin.sh/health",
- Conditions: []core.Condition{"[STATUS] == 200"},
+ Conditions: []endpoint.Condition{"[STATUS] == 200"},
},
},
},
@@ -136,21 +136,21 @@ endpoints:
- "[BODY].status == UP"`,
},
expectedConfig: &Config{
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "one",
URL: "https://example.com",
- Conditions: []core.Condition{"[CONNECTED] == true", "[STATUS] == 200"},
+ Conditions: []endpoint.Condition{"[CONNECTED] == true", "[STATUS] == 200"},
},
{
Name: "two",
URL: "https://example.org",
- Conditions: []core.Condition{"len([BODY]) > 0"},
+ Conditions: []endpoint.Condition{"len([BODY]) > 0"},
},
{
Name: "three",
URL: "https://twin.sh/health",
- Conditions: []core.Condition{"[STATUS] == 200", "[BODY].status == UP"},
+ Conditions: []endpoint.Condition{"[STATUS] == 200", "[BODY].status == UP"},
},
},
},
@@ -192,17 +192,17 @@ endpoints:
Discord: &discord.AlertProvider{WebhookURL: "https://discord.com/api/webhooks/xxx/yyy"},
Slack: &slack.AlertProvider{WebhookURL: "https://hooks.slack.com/services/xxx/yyy/zzz"},
},
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "example",
URL: "https://example.org",
Interval: 5 * time.Second,
- Conditions: []core.Condition{"[STATUS] == 200"},
+ Conditions: []endpoint.Condition{"[STATUS] == 200"},
},
{
Name: "frontend",
URL: "https://example.com",
- Conditions: []core.Condition{"[STATUS] == 200"},
+ Conditions: []endpoint.Condition{"[STATUS] == 200"},
},
},
},
@@ -689,8 +689,8 @@ endpoints:
if config.Endpoints[0].Interval != 60*time.Second {
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
}
- if userAgent := config.Endpoints[0].Headers["User-Agent"]; userAgent != core.GatusUserAgent {
- t.Errorf("User-Agent should've been %s because it's the default value, got %s", core.GatusUserAgent, userAgent)
+ if userAgent := config.Endpoints[0].Headers["User-Agent"]; userAgent != endpoint.GatusUserAgent {
+ t.Errorf("User-Agent should've been %s because it's the default value, got %s", endpoint.GatusUserAgent, userAgent)
}
}
diff --git a/core/endpoint_common.go b/config/endpoint/common.go
similarity index 98%
rename from core/endpoint_common.go
rename to config/endpoint/common.go
index f99e5501..f3da8bf8 100644
--- a/core/endpoint_common.go
+++ b/config/endpoint/common.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"errors"
diff --git a/core/endpoint_common_test.go b/config/endpoint/common_test.go
similarity index 98%
rename from core/endpoint_common_test.go
rename to config/endpoint/common_test.go
index e1c63178..ab4fc9ef 100644
--- a/core/endpoint_common_test.go
+++ b/config/endpoint/common_test.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"errors"
diff --git a/core/condition.go b/config/endpoint/condition.go
similarity index 99%
rename from core/condition.go
rename to config/endpoint/condition.go
index 42f70d92..6d36babd 100644
--- a/core/condition.go
+++ b/config/endpoint/condition.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"errors"
diff --git a/core/condition_bench_test.go b/config/endpoint/condition_bench_test.go
similarity index 98%
rename from core/condition_bench_test.go
rename to config/endpoint/condition_bench_test.go
index 0126871f..82061f69 100644
--- a/core/condition_bench_test.go
+++ b/config/endpoint/condition_bench_test.go
@@ -1,6 +1,8 @@
-package core
+package endpoint
-import "testing"
+import (
+ "testing"
+)
func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
diff --git a/core/condition_result.go b/config/endpoint/condition_result.go
similarity index 93%
rename from core/condition_result.go
rename to config/endpoint/condition_result.go
index d8bdc1e9..00af8620 100644
--- a/core/condition_result.go
+++ b/config/endpoint/condition_result.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
// ConditionResult result of a Condition
type ConditionResult struct {
diff --git a/core/condition_test.go b/config/endpoint/condition_test.go
similarity index 99%
rename from core/condition_test.go
rename to config/endpoint/condition_test.go
index ef2e79ed..3e98912f 100644
--- a/core/condition_test.go
+++ b/config/endpoint/condition_test.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"errors"
diff --git a/config/endpoint/dns/dns.go b/config/endpoint/dns/dns.go
new file mode 100644
index 00000000..47a29bdc
--- /dev/null
+++ b/config/endpoint/dns/dns.go
@@ -0,0 +1,38 @@
+package dns
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/miekg/dns"
+)
+
+var (
+ // ErrDNSWithNoQueryName is the error with which gatus will panic if a dns is configured without query name
+ ErrDNSWithNoQueryName = errors.New("you must specify a query name in the DNS configuration")
+
+ // ErrDNSWithInvalidQueryType is the error with which gatus will panic if a dns is configured with invalid query type
+ ErrDNSWithInvalidQueryType = errors.New("invalid query type in the DNS configuration")
+)
+
+// Config for an Endpoint of type DNS
+type Config struct {
+ // QueryType is the type for the DNS records like A, AAAA, CNAME...
+ QueryType string `yaml:"query-type"`
+
+ // QueryName is the query for DNS
+ QueryName string `yaml:"query-name"`
+}
+
+func (d *Config) ValidateAndSetDefault() error {
+ if len(d.QueryName) == 0 {
+ return ErrDNSWithNoQueryName
+ }
+ if !strings.HasSuffix(d.QueryName, ".") {
+ d.QueryName += "."
+ }
+ if _, ok := dns.StringToType[d.QueryType]; !ok {
+ return ErrDNSWithInvalidQueryType
+ }
+ return nil
+}
diff --git a/config/endpoint/dns/dns_test.go b/config/endpoint/dns/dns_test.go
new file mode 100644
index 00000000..57e96296
--- /dev/null
+++ b/config/endpoint/dns/dns_test.go
@@ -0,0 +1,27 @@
+package dns
+
+import (
+ "testing"
+)
+
+func TestConfig_ValidateAndSetDefault(t *testing.T) {
+ dns := &Config{
+ QueryType: "A",
+ QueryName: "",
+ }
+ err := dns.ValidateAndSetDefault()
+ if err == nil {
+ t.Error("Should've returned an error because endpoint's dns didn't have a query name, which is a mandatory field for dns")
+ }
+}
+
+func TestConfig_ValidateAndSetDefaultsWithInvalidDNSQueryType(t *testing.T) {
+ dns := &Config{
+ QueryType: "B",
+ QueryName: "example.com",
+ }
+ err := dns.ValidateAndSetDefault()
+ if err == nil {
+ t.Error("Should've returned an error because endpoint's dns query type is invalid, it needs to be a valid query name like A, AAAA, CNAME...")
+ }
+}
diff --git a/core/endpoint.go b/config/endpoint/endpoint.go
similarity index 58%
rename from core/endpoint.go
rename to config/endpoint/endpoint.go
index 749b1d3d..ac765c1a 100644
--- a/core/endpoint.go
+++ b/config/endpoint/endpoint.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"bytes"
@@ -15,12 +15,13 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core/ui"
- "github.com/TwiN/gatus/v5/util"
+ "github.com/TwiN/gatus/v5/config/endpoint/dns"
+ sshconfig "github.com/TwiN/gatus/v5/config/endpoint/ssh"
+ "github.com/TwiN/gatus/v5/config/endpoint/ui"
"golang.org/x/crypto/ssh"
)
-type EndpointType string
+type Type string
const (
// HostHeader is the name of the header used to specify the host
@@ -35,17 +36,17 @@ const (
// GatusUserAgent is the default user agent that Gatus uses to send requests.
GatusUserAgent = "Gatus/1.0"
- EndpointTypeDNS EndpointType = "DNS"
- EndpointTypeTCP EndpointType = "TCP"
- EndpointTypeSCTP EndpointType = "SCTP"
- EndpointTypeUDP EndpointType = "UDP"
- EndpointTypeICMP EndpointType = "ICMP"
- EndpointTypeSTARTTLS EndpointType = "STARTTLS"
- EndpointTypeTLS EndpointType = "TLS"
- EndpointTypeHTTP EndpointType = "HTTP"
- EndpointTypeWS EndpointType = "WEBSOCKET"
- EndpointTypeSSH EndpointType = "SSH"
- EndpointTypeUNKNOWN EndpointType = "UNKNOWN"
+ TypeDNS Type = "DNS"
+ TypeTCP Type = "TCP"
+ TypeSCTP Type = "SCTP"
+ TypeUDP Type = "UDP"
+ TypeICMP Type = "ICMP"
+ TypeSTARTTLS Type = "STARTTLS"
+ TypeTLS Type = "TLS"
+ TypeHTTP Type = "HTTP"
+ TypeWS Type = "WEBSOCKET"
+ TypeSSH Type = "SSH"
+ TypeUNKNOWN Type = "UNKNOWN"
)
var (
@@ -82,12 +83,6 @@ type Endpoint struct {
// URL to send the request to
URL string `yaml:"url"`
- // DNS is the configuration of DNS monitoring
- DNS *DNS `yaml:"dns,omitempty"`
-
- // SSH is the configuration of SSH monitoring.
- SSH *SSH `yaml:"ssh,omitempty"`
-
// Method of the request made to the url of the endpoint
Method string `yaml:"method,omitempty"`
@@ -109,6 +104,12 @@ type Endpoint struct {
// Alerts is the alerting configuration for the endpoint in case of failure
Alerts []*alert.Alert `yaml:"alerts,omitempty"`
+ // DNSConfig is the configuration for DNS monitoring
+ DNSConfig *dns.Config `yaml:"dns,omitempty"`
+
+ // SSH is the configuration for SSH monitoring
+ SSHConfig *sshconfig.Config `yaml:"ssh,omitempty"`
+
// ClientConfig is the configuration of the client used to communicate with the endpoint's target
ClientConfig *client.Config `yaml:"client,omitempty"`
@@ -123,103 +124,103 @@ type Endpoint struct {
}
// IsEnabled returns whether the endpoint is enabled or not
-func (endpoint *Endpoint) IsEnabled() bool {
- if endpoint.Enabled == nil {
+func (e *Endpoint) IsEnabled() bool {
+ if e.Enabled == nil {
return true
}
- return *endpoint.Enabled
+ return *e.Enabled
}
// Type returns the endpoint type
-func (endpoint *Endpoint) Type() EndpointType {
+func (e *Endpoint) Type() Type {
switch {
- case endpoint.DNS != nil:
- return EndpointTypeDNS
- case strings.HasPrefix(endpoint.URL, "tcp://"):
- return EndpointTypeTCP
- case strings.HasPrefix(endpoint.URL, "sctp://"):
- return EndpointTypeSCTP
- case strings.HasPrefix(endpoint.URL, "udp://"):
- return EndpointTypeUDP
- case strings.HasPrefix(endpoint.URL, "icmp://"):
- return EndpointTypeICMP
- case strings.HasPrefix(endpoint.URL, "starttls://"):
- return EndpointTypeSTARTTLS
- case strings.HasPrefix(endpoint.URL, "tls://"):
- return EndpointTypeTLS
- case strings.HasPrefix(endpoint.URL, "http://") || strings.HasPrefix(endpoint.URL, "https://"):
- return EndpointTypeHTTP
- case strings.HasPrefix(endpoint.URL, "ws://") || strings.HasPrefix(endpoint.URL, "wss://"):
- return EndpointTypeWS
- case strings.HasPrefix(endpoint.URL, "ssh://"):
- return EndpointTypeSSH
+ case e.DNSConfig != nil:
+ return TypeDNS
+ case strings.HasPrefix(e.URL, "tcp://"):
+ return TypeTCP
+ case strings.HasPrefix(e.URL, "sctp://"):
+ return TypeSCTP
+ case strings.HasPrefix(e.URL, "udp://"):
+ return TypeUDP
+ case strings.HasPrefix(e.URL, "icmp://"):
+ return TypeICMP
+ case strings.HasPrefix(e.URL, "starttls://"):
+ return TypeSTARTTLS
+ case strings.HasPrefix(e.URL, "tls://"):
+ return TypeTLS
+ case strings.HasPrefix(e.URL, "http://") || strings.HasPrefix(e.URL, "https://"):
+ return TypeHTTP
+ case strings.HasPrefix(e.URL, "ws://") || strings.HasPrefix(e.URL, "wss://"):
+ return TypeWS
+ case strings.HasPrefix(e.URL, "ssh://"):
+ return TypeSSH
default:
- return EndpointTypeUNKNOWN
+ return TypeUNKNOWN
}
}
// ValidateAndSetDefaults validates the endpoint's configuration and sets the default value of args that have one
-func (endpoint *Endpoint) ValidateAndSetDefaults() error {
- if err := validateEndpointNameGroupAndAlerts(endpoint.Name, endpoint.Group, endpoint.Alerts); err != nil {
+func (e *Endpoint) ValidateAndSetDefaults() error {
+ if err := validateEndpointNameGroupAndAlerts(e.Name, e.Group, e.Alerts); err != nil {
return err
}
- if len(endpoint.URL) == 0 {
+ if len(e.URL) == 0 {
return ErrEndpointWithNoURL
}
- if endpoint.ClientConfig == nil {
- endpoint.ClientConfig = client.GetDefaultConfig()
+ if e.ClientConfig == nil {
+ e.ClientConfig = client.GetDefaultConfig()
} else {
- if err := endpoint.ClientConfig.ValidateAndSetDefaults(); err != nil {
+ if err := e.ClientConfig.ValidateAndSetDefaults(); err != nil {
return err
}
}
- if endpoint.UIConfig == nil {
- endpoint.UIConfig = ui.GetDefaultConfig()
+ if e.UIConfig == nil {
+ e.UIConfig = ui.GetDefaultConfig()
} else {
- if err := endpoint.UIConfig.ValidateAndSetDefaults(); err != nil {
+ if err := e.UIConfig.ValidateAndSetDefaults(); err != nil {
return err
}
}
- if endpoint.Interval == 0 {
- endpoint.Interval = 1 * time.Minute
+ if e.Interval == 0 {
+ e.Interval = 1 * time.Minute
}
- if len(endpoint.Method) == 0 {
- endpoint.Method = http.MethodGet
+ if len(e.Method) == 0 {
+ e.Method = http.MethodGet
}
- if len(endpoint.Headers) == 0 {
- endpoint.Headers = make(map[string]string)
+ if len(e.Headers) == 0 {
+ e.Headers = make(map[string]string)
}
// Automatically add user agent header if there isn't one specified in the endpoint configuration
- if _, userAgentHeaderExists := endpoint.Headers[UserAgentHeader]; !userAgentHeaderExists {
- endpoint.Headers[UserAgentHeader] = GatusUserAgent
+ if _, userAgentHeaderExists := e.Headers[UserAgentHeader]; !userAgentHeaderExists {
+ e.Headers[UserAgentHeader] = GatusUserAgent
}
// Automatically add "Content-Type: application/json" header if there's no Content-Type set
// and endpoint.GraphQL is set to true
- if _, contentTypeHeaderExists := endpoint.Headers[ContentTypeHeader]; !contentTypeHeaderExists && endpoint.GraphQL {
- endpoint.Headers[ContentTypeHeader] = "application/json"
+ if _, contentTypeHeaderExists := e.Headers[ContentTypeHeader]; !contentTypeHeaderExists && e.GraphQL {
+ e.Headers[ContentTypeHeader] = "application/json"
}
- if len(endpoint.Conditions) == 0 {
+ if len(e.Conditions) == 0 {
return ErrEndpointWithNoCondition
}
- for _, c := range endpoint.Conditions {
- if endpoint.Interval < 5*time.Minute && c.hasDomainExpirationPlaceholder() {
+ for _, c := range e.Conditions {
+ if e.Interval < 5*time.Minute && c.hasDomainExpirationPlaceholder() {
return ErrInvalidEndpointIntervalForDomainExpirationPlaceholder
}
if err := c.Validate(); err != nil {
return fmt.Errorf("%v: %w", ErrInvalidConditionFormat, err)
}
}
- if endpoint.DNS != nil {
- return endpoint.DNS.validateAndSetDefault()
+ if e.DNSConfig != nil {
+ return e.DNSConfig.ValidateAndSetDefault()
}
- if endpoint.SSH != nil {
- return endpoint.SSH.validate()
+ if e.SSHConfig != nil {
+ return e.SSHConfig.Validate()
}
- if endpoint.Type() == EndpointTypeUNKNOWN {
+ if e.Type() == TypeUNKNOWN {
return ErrUnknownEndpointType
}
// Make sure that the request can be created
- _, err := http.NewRequest(endpoint.Method, endpoint.URL, bytes.NewBuffer([]byte(endpoint.Body)))
+ _, err := http.NewRequest(e.Method, e.URL, bytes.NewBuffer([]byte(e.Body)))
if err != nil {
return err
}
@@ -227,35 +228,35 @@ func (endpoint *Endpoint) ValidateAndSetDefaults() error {
}
// DisplayName returns an identifier made up of the Name and, if not empty, the Group.
-func (endpoint *Endpoint) DisplayName() string {
- if len(endpoint.Group) > 0 {
- return endpoint.Group + "/" + endpoint.Name
+func (e *Endpoint) DisplayName() string {
+ if len(e.Group) > 0 {
+ return e.Group + "/" + e.Name
}
- return endpoint.Name
+ return e.Name
}
// Key returns the unique key for the Endpoint
-func (endpoint *Endpoint) Key() string {
- return util.ConvertGroupAndEndpointNameToKey(endpoint.Group, endpoint.Name)
+func (e *Endpoint) Key() string {
+ return ConvertGroupAndEndpointNameToKey(e.Group, e.Name)
}
// Close HTTP connections between watchdog and endpoints to avoid dangling socket file descriptors
// on configuration reload.
// More context on https://github.com/TwiN/gatus/issues/536
-func (endpoint *Endpoint) Close() {
- if endpoint.Type() == EndpointTypeHTTP {
- client.GetHTTPClient(endpoint.ClientConfig).CloseIdleConnections()
+func (e *Endpoint) Close() {
+ if e.Type() == TypeHTTP {
+ client.GetHTTPClient(e.ClientConfig).CloseIdleConnections()
}
}
// EvaluateHealth sends a request to the endpoint's URL and evaluates the conditions of the endpoint.
-func (endpoint *Endpoint) EvaluateHealth() *Result {
+func (e *Endpoint) EvaluateHealth() *Result {
result := &Result{Success: true, Errors: []string{}}
// Parse or extract hostname from URL
- if endpoint.DNS != nil {
- result.Hostname = strings.TrimSuffix(endpoint.URL, ":53")
+ if e.DNSConfig != nil {
+ result.Hostname = strings.TrimSuffix(e.URL, ":53")
} else {
- urlObject, err := url.Parse(endpoint.URL)
+ urlObject, err := url.Parse(e.URL)
if err != nil {
result.AddError(err.Error())
} else {
@@ -263,11 +264,11 @@ func (endpoint *Endpoint) EvaluateHealth() *Result {
}
}
// Retrieve IP if necessary
- if endpoint.needsToRetrieveIP() {
- endpoint.getIP(result)
+ if e.needsToRetrieveIP() {
+ e.getIP(result)
}
// Retrieve domain expiration if necessary
- if endpoint.needsToRetrieveDomainExpiration() && len(result.Hostname) > 0 {
+ if e.needsToRetrieveDomainExpiration() && len(result.Hostname) > 0 {
var err error
if result.DomainExpiration, err = client.GetDomainExpiration(result.Hostname); err != nil {
result.AddError(err.Error())
@@ -275,37 +276,37 @@ func (endpoint *Endpoint) EvaluateHealth() *Result {
}
// Call the endpoint (if there's no errors)
if len(result.Errors) == 0 {
- endpoint.call(result)
+ e.call(result)
} else {
result.Success = false
}
// Evaluate the conditions
- for _, condition := range endpoint.Conditions {
- success := condition.evaluate(result, endpoint.UIConfig.DontResolveFailedConditions)
+ for _, condition := range e.Conditions {
+ success := condition.evaluate(result, e.UIConfig.DontResolveFailedConditions)
if !success {
result.Success = false
}
}
result.Timestamp = time.Now()
// Clean up parameters that we don't need to keep in the results
- if endpoint.UIConfig.HideURL {
+ if e.UIConfig.HideURL {
for errIdx, errorString := range result.Errors {
- result.Errors[errIdx] = strings.ReplaceAll(errorString, endpoint.URL, "")
+ result.Errors[errIdx] = strings.ReplaceAll(errorString, e.URL, "")
}
}
- if endpoint.UIConfig.HideHostname {
+ if e.UIConfig.HideHostname {
for errIdx, errorString := range result.Errors {
result.Errors[errIdx] = strings.ReplaceAll(errorString, result.Hostname, "")
}
result.Hostname = ""
}
- if endpoint.UIConfig.HideConditions {
+ if e.UIConfig.HideConditions {
result.ConditionResults = nil
}
return result
}
-func (endpoint *Endpoint) getIP(result *Result) {
+func (e *Endpoint) getIP(result *Result) {
if ips, err := net.LookupIP(result.Hostname); err != nil {
result.AddError(err.Error())
return
@@ -314,24 +315,28 @@ func (endpoint *Endpoint) getIP(result *Result) {
}
}
-func (endpoint *Endpoint) call(result *Result) {
+func (e *Endpoint) call(result *Result) {
var request *http.Request
var response *http.Response
var err error
var certificate *x509.Certificate
- endpointType := endpoint.Type()
- if endpointType == EndpointTypeHTTP {
- request = endpoint.buildHTTPRequest()
+ endpointType := e.Type()
+ if endpointType == TypeHTTP {
+ request = e.buildHTTPRequest()
}
startTime := time.Now()
- if endpointType == EndpointTypeDNS {
- endpoint.DNS.query(endpoint.URL, result)
+ if endpointType == TypeDNS {
+ result.Connected, result.DNSRCode, result.Body, err = client.QueryDNS(e.DNSConfig.QueryType, e.DNSConfig.QueryName, e.URL)
+ if err != nil {
+ result.AddError(err.Error())
+ return
+ }
result.Duration = time.Since(startTime)
- } else if endpointType == EndpointTypeSTARTTLS || endpointType == EndpointTypeTLS {
- if endpointType == EndpointTypeSTARTTLS {
- result.Connected, certificate, err = client.CanPerformStartTLS(strings.TrimPrefix(endpoint.URL, "starttls://"), endpoint.ClientConfig)
+ } else if endpointType == TypeSTARTTLS || endpointType == TypeTLS {
+ if endpointType == TypeSTARTTLS {
+ result.Connected, certificate, err = client.CanPerformStartTLS(strings.TrimPrefix(e.URL, "starttls://"), e.ClientConfig)
} else {
- result.Connected, certificate, err = client.CanPerformTLS(strings.TrimPrefix(endpoint.URL, "tls://"), endpoint.ClientConfig)
+ result.Connected, certificate, err = client.CanPerformTLS(strings.TrimPrefix(e.URL, "tls://"), e.ClientConfig)
}
if err != nil {
result.AddError(err.Error())
@@ -339,39 +344,39 @@ func (endpoint *Endpoint) call(result *Result) {
}
result.Duration = time.Since(startTime)
result.CertificateExpiration = time.Until(certificate.NotAfter)
- } else if endpointType == EndpointTypeTCP {
- result.Connected = client.CanCreateTCPConnection(strings.TrimPrefix(endpoint.URL, "tcp://"), endpoint.ClientConfig)
+ } else if endpointType == TypeTCP {
+ result.Connected = client.CanCreateTCPConnection(strings.TrimPrefix(e.URL, "tcp://"), e.ClientConfig)
result.Duration = time.Since(startTime)
- } else if endpointType == EndpointTypeUDP {
- result.Connected = client.CanCreateUDPConnection(strings.TrimPrefix(endpoint.URL, "udp://"), endpoint.ClientConfig)
+ } else if endpointType == TypeUDP {
+ result.Connected = client.CanCreateUDPConnection(strings.TrimPrefix(e.URL, "udp://"), e.ClientConfig)
result.Duration = time.Since(startTime)
- } else if endpointType == EndpointTypeSCTP {
- result.Connected = client.CanCreateSCTPConnection(strings.TrimPrefix(endpoint.URL, "sctp://"), endpoint.ClientConfig)
+ } else if endpointType == TypeSCTP {
+ result.Connected = client.CanCreateSCTPConnection(strings.TrimPrefix(e.URL, "sctp://"), e.ClientConfig)
result.Duration = time.Since(startTime)
- } else if endpointType == EndpointTypeICMP {
- result.Connected, result.Duration = client.Ping(strings.TrimPrefix(endpoint.URL, "icmp://"), endpoint.ClientConfig)
- } else if endpointType == EndpointTypeWS {
- result.Connected, result.Body, err = client.QueryWebSocket(endpoint.URL, endpoint.Body, endpoint.ClientConfig)
+ } else if endpointType == TypeICMP {
+ result.Connected, result.Duration = client.Ping(strings.TrimPrefix(e.URL, "icmp://"), e.ClientConfig)
+ } else if endpointType == TypeWS {
+ result.Connected, result.Body, err = client.QueryWebSocket(e.URL, e.Body, e.ClientConfig)
if err != nil {
result.AddError(err.Error())
return
}
result.Duration = time.Since(startTime)
- } else if endpointType == EndpointTypeSSH {
+ } else if endpointType == TypeSSH {
var cli *ssh.Client
- result.Connected, cli, err = client.CanCreateSSHConnection(strings.TrimPrefix(endpoint.URL, "ssh://"), endpoint.SSH.Username, endpoint.SSH.Password, endpoint.ClientConfig)
+ result.Connected, cli, err = client.CanCreateSSHConnection(strings.TrimPrefix(e.URL, "ssh://"), e.SSHConfig.Username, e.SSHConfig.Password, e.ClientConfig)
if err != nil {
result.AddError(err.Error())
return
}
- result.Success, result.HTTPStatus, err = client.ExecuteSSHCommand(cli, endpoint.Body, endpoint.ClientConfig)
+ result.Success, result.HTTPStatus, err = client.ExecuteSSHCommand(cli, e.Body, e.ClientConfig)
if err != nil {
result.AddError(err.Error())
return
}
result.Duration = time.Since(startTime)
} else {
- response, err = client.GetHTTPClient(endpoint.ClientConfig).Do(request)
+ response, err = client.GetHTTPClient(e.ClientConfig).Do(request)
result.Duration = time.Since(startTime)
if err != nil {
result.AddError(err.Error())
@@ -385,7 +390,7 @@ func (endpoint *Endpoint) call(result *Result) {
result.HTTPStatus = response.StatusCode
result.Connected = response.StatusCode > 0
// Only read the Body if there's a condition that uses the BodyPlaceholder
- if endpoint.needsToReadBody() {
+ if e.needsToReadBody() {
result.Body, err = io.ReadAll(response.Body)
if err != nil {
result.AddError("error reading response body:" + err.Error())
@@ -394,19 +399,19 @@ func (endpoint *Endpoint) call(result *Result) {
}
}
-func (endpoint *Endpoint) buildHTTPRequest() *http.Request {
+func (e *Endpoint) buildHTTPRequest() *http.Request {
var bodyBuffer *bytes.Buffer
- if endpoint.GraphQL {
+ if e.GraphQL {
graphQlBody := map[string]string{
- "query": endpoint.Body,
+ "query": e.Body,
}
body, _ := json.Marshal(graphQlBody)
bodyBuffer = bytes.NewBuffer(body)
} else {
- bodyBuffer = bytes.NewBuffer([]byte(endpoint.Body))
+ bodyBuffer = bytes.NewBuffer([]byte(e.Body))
}
- request, _ := http.NewRequest(endpoint.Method, endpoint.URL, bodyBuffer)
- for k, v := range endpoint.Headers {
+ request, _ := http.NewRequest(e.Method, e.URL, bodyBuffer)
+ for k, v := range e.Headers {
request.Header.Set(k, v)
if k == HostHeader {
request.Host = v
@@ -416,8 +421,8 @@ func (endpoint *Endpoint) buildHTTPRequest() *http.Request {
}
// needsToReadBody checks if there's any condition that requires the response Body to be read
-func (endpoint *Endpoint) needsToReadBody() bool {
- for _, condition := range endpoint.Conditions {
+func (e *Endpoint) needsToReadBody() bool {
+ for _, condition := range e.Conditions {
if condition.hasBodyPlaceholder() {
return true
}
@@ -426,8 +431,8 @@ func (endpoint *Endpoint) needsToReadBody() bool {
}
// needsToRetrieveDomainExpiration checks if there's any condition that requires a whois query to be performed
-func (endpoint *Endpoint) needsToRetrieveDomainExpiration() bool {
- for _, condition := range endpoint.Conditions {
+func (e *Endpoint) needsToRetrieveDomainExpiration() bool {
+ for _, condition := range e.Conditions {
if condition.hasDomainExpirationPlaceholder() {
return true
}
@@ -436,8 +441,8 @@ func (endpoint *Endpoint) needsToRetrieveDomainExpiration() bool {
}
// needsToRetrieveIP checks if there's any condition that requires an IP lookup
-func (endpoint *Endpoint) needsToRetrieveIP() bool {
- for _, condition := range endpoint.Conditions {
+func (e *Endpoint) needsToRetrieveIP() bool {
+ for _, condition := range e.Conditions {
if condition.hasIPPlaceholder() {
return true
}
diff --git a/core/endpoint_test.go b/config/endpoint/endpoint_test.go
similarity index 95%
rename from core/endpoint_test.go
rename to config/endpoint/endpoint_test.go
index 18f5be69..c2d434b0 100644
--- a/core/endpoint_test.go
+++ b/config/endpoint/endpoint_test.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"bytes"
@@ -13,7 +13,9 @@ import (
"github.com/TwiN/gatus/v5/alerting/alert"
"github.com/TwiN/gatus/v5/client"
- "github.com/TwiN/gatus/v5/core/ui"
+ "github.com/TwiN/gatus/v5/config/endpoint/dns"
+ "github.com/TwiN/gatus/v5/config/endpoint/ssh"
+ "github.com/TwiN/gatus/v5/config/endpoint/ui"
"github.com/TwiN/gatus/v5/test"
)
@@ -279,105 +281,105 @@ func TestEndpoint_IsEnabled(t *testing.T) {
func TestEndpoint_Type(t *testing.T) {
type args struct {
URL string
- DNS *DNS
- SSH *SSH
+ DNS *dns.Config
+ SSH *ssh.Config
}
tests := []struct {
args args
- want EndpointType
+ want Type
}{
{
args: args{
URL: "8.8.8.8",
- DNS: &DNS{
+ DNS: &dns.Config{
QueryType: "A",
QueryName: "example.com",
},
},
- want: EndpointTypeDNS,
+ want: TypeDNS,
},
{
args: args{
URL: "tcp://127.0.0.1:6379",
},
- want: EndpointTypeTCP,
+ want: TypeTCP,
},
{
args: args{
URL: "icmp://example.com",
},
- want: EndpointTypeICMP,
+ want: TypeICMP,
},
{
args: args{
URL: "sctp://example.com",
},
- want: EndpointTypeSCTP,
+ want: TypeSCTP,
},
{
args: args{
URL: "udp://example.com",
},
- want: EndpointTypeUDP,
+ want: TypeUDP,
},
{
args: args{
URL: "starttls://smtp.gmail.com:587",
},
- want: EndpointTypeSTARTTLS,
+ want: TypeSTARTTLS,
},
{
args: args{
URL: "tls://example.com:443",
},
- want: EndpointTypeTLS,
+ want: TypeTLS,
},
{
args: args{
URL: "https://twin.sh/health",
},
- want: EndpointTypeHTTP,
+ want: TypeHTTP,
},
{
args: args{
URL: "wss://example.com/",
},
- want: EndpointTypeWS,
+ want: TypeWS,
},
{
args: args{
URL: "ws://example.com/",
},
- want: EndpointTypeWS,
+ want: TypeWS,
},
{
args: args{
URL: "ssh://example.com:22",
- SSH: &SSH{
+ SSH: &ssh.Config{
Username: "root",
Password: "password",
},
},
- want: EndpointTypeSSH,
+ want: TypeSSH,
},
{
args: args{
URL: "invalid://example.org",
},
- want: EndpointTypeUNKNOWN,
+ want: TypeUNKNOWN,
},
{
args: args{
URL: "no-scheme",
},
- want: EndpointTypeUNKNOWN,
+ want: TypeUNKNOWN,
},
}
for _, tt := range tests {
t.Run(string(tt.want), func(t *testing.T) {
endpoint := Endpoint{
- URL: tt.args.URL,
- DNS: tt.args.DNS,
+ URL: tt.args.URL,
+ DNSConfig: tt.args.DNS,
}
if got := endpoint.Type(); got != tt.want {
t.Errorf("Endpoint.Type() = %v, want %v", got, tt.want)
@@ -477,7 +479,7 @@ func TestEndpoint_ValidateAndSetDefaultsWithDNS(t *testing.T) {
endpoint := &Endpoint{
Name: "dns-test",
URL: "https://example.com",
- DNS: &DNS{
+ DNSConfig: &dns.Config{
QueryType: "A",
QueryName: "example.com",
},
@@ -487,7 +489,7 @@ func TestEndpoint_ValidateAndSetDefaultsWithDNS(t *testing.T) {
if err != nil {
t.Error("did not expect an error, got", err)
}
- if endpoint.DNS.QueryName != "example.com." {
+ if endpoint.DNSConfig.QueryName != "example.com." {
t.Error("Endpoint.dns.query-name should be formatted with . suffix")
}
}
@@ -503,13 +505,13 @@ func TestEndpoint_ValidateAndSetDefaultsWithSSH(t *testing.T) {
name: "fail when has no user",
username: "",
password: "password",
- expectedErr: ErrEndpointWithoutSSHUsername,
+ expectedErr: ssh.ErrEndpointWithoutSSHUsername,
},
{
name: "fail when has no password",
username: "username",
password: "",
- expectedErr: ErrEndpointWithoutSSHPassword,
+ expectedErr: ssh.ErrEndpointWithoutSSHPassword,
},
{
name: "success when all fields are set",
@@ -524,7 +526,7 @@ func TestEndpoint_ValidateAndSetDefaultsWithSSH(t *testing.T) {
endpoint := &Endpoint{
Name: "ssh-test",
URL: "https://example.com",
- SSH: &SSH{
+ SSHConfig: &ssh.Config{
Username: scenario.username,
Password: scenario.password,
},
@@ -763,7 +765,7 @@ func TestIntegrationEvaluateHealthForDNS(t *testing.T) {
endpoint := Endpoint{
Name: "example",
URL: "8.8.8.8",
- DNS: &DNS{
+ DNSConfig: &dns.Config{
QueryType: "A",
QueryName: "example.com.",
},
@@ -786,7 +788,7 @@ func TestIntegrationEvaluateHealthForDNS(t *testing.T) {
}
func TestIntegrationEvaluateHealthForSSH(t *testing.T) {
- tests := []struct {
+ scenarios := []struct {
name string
endpoint Endpoint
conditions []Condition
@@ -797,9 +799,9 @@ func TestIntegrationEvaluateHealthForSSH(t *testing.T) {
endpoint: Endpoint{
Name: "ssh-success",
URL: "ssh://localhost",
- SSH: &SSH{
- Username: "test",
- Password: "test",
+ SSHConfig: &ssh.Config{
+ Username: "scenario",
+ Password: "scenario",
},
Body: "{ \"command\": \"uptime\" }",
},
@@ -811,9 +813,9 @@ func TestIntegrationEvaluateHealthForSSH(t *testing.T) {
endpoint: Endpoint{
Name: "ssh-failure",
URL: "ssh://localhost",
- SSH: &SSH{
- Username: "test",
- Password: "test",
+ SSHConfig: &ssh.Config{
+ Username: "scenario",
+ Password: "scenario",
},
Body: "{ \"command\": \"uptime\" }",
},
@@ -822,13 +824,13 @@ func TestIntegrationEvaluateHealthForSSH(t *testing.T) {
},
}
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- test.endpoint.ValidateAndSetDefaults()
- test.endpoint.Conditions = test.conditions
- result := test.endpoint.EvaluateHealth()
- if result.Success != test.success {
- t.Errorf("Expected success to be %v, but was %v", test.success, result.Success)
+ for _, scenario := range scenarios {
+ t.Run(scenario.name, func(t *testing.T) {
+ scenario.endpoint.ValidateAndSetDefaults()
+ scenario.endpoint.Conditions = scenario.conditions
+ result := scenario.endpoint.EvaluateHealth()
+ if result.Success != scenario.success {
+ t.Errorf("Expected success to be %v, but was %v", scenario.success, result.Success)
}
})
}
diff --git a/core/event.go b/config/endpoint/event.go
similarity index 96%
rename from core/event.go
rename to config/endpoint/event.go
index 43f9cf76..da8d2275 100644
--- a/core/event.go
+++ b/config/endpoint/event.go
@@ -1,6 +1,8 @@
-package core
+package endpoint
-import "time"
+import (
+ "time"
+)
// Event is something that happens at a specific time
type Event struct {
diff --git a/core/event_test.go b/config/endpoint/event_test.go
similarity index 89%
rename from core/event_test.go
rename to config/endpoint/event_test.go
index 2269178a..bdfe07a2 100644
--- a/core/event_test.go
+++ b/config/endpoint/event_test.go
@@ -1,6 +1,8 @@
-package core
+package endpoint
-import "testing"
+import (
+ "testing"
+)
func TestNewEventFromResult(t *testing.T) {
if event := NewEventFromResult(&Result{Success: true}); event.Type != EventHealthy {
diff --git a/core/external_endpoint.go b/config/endpoint/external_endpoint.go
similarity index 95%
rename from core/external_endpoint.go
rename to config/endpoint/external_endpoint.go
index 709deea5..b096d395 100644
--- a/core/external_endpoint.go
+++ b/config/endpoint/external_endpoint.go
@@ -1,10 +1,9 @@
-package core
+package endpoint
import (
"errors"
"github.com/TwiN/gatus/v5/alerting/alert"
- "github.com/TwiN/gatus/v5/util"
)
var (
@@ -72,7 +71,7 @@ func (externalEndpoint *ExternalEndpoint) DisplayName() string {
// Key returns the unique key for the Endpoint
func (externalEndpoint *ExternalEndpoint) Key() string {
- return util.ConvertGroupAndEndpointNameToKey(externalEndpoint.Group, externalEndpoint.Name)
+ return ConvertGroupAndEndpointNameToKey(externalEndpoint.Group, externalEndpoint.Name)
}
// ToEndpoint converts the ExternalEndpoint to an Endpoint
diff --git a/core/external_endpoint_test.go b/config/endpoint/external_endpoint_test.go
similarity index 97%
rename from core/external_endpoint_test.go
rename to config/endpoint/external_endpoint_test.go
index a79456c3..4ead308b 100644
--- a/core/external_endpoint_test.go
+++ b/config/endpoint/external_endpoint_test.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"testing"
diff --git a/util/key.go b/config/endpoint/key.go
similarity index 96%
rename from util/key.go
rename to config/endpoint/key.go
index a56a21ec..89c35488 100644
--- a/util/key.go
+++ b/config/endpoint/key.go
@@ -1,4 +1,4 @@
-package util
+package endpoint
import "strings"
diff --git a/util/key_bench_test.go b/config/endpoint/key_bench_test.go
similarity index 91%
rename from util/key_bench_test.go
rename to config/endpoint/key_bench_test.go
index 7f974f41..cfec8c8b 100644
--- a/util/key_bench_test.go
+++ b/config/endpoint/key_bench_test.go
@@ -1,4 +1,4 @@
-package util
+package endpoint
import (
"testing"
diff --git a/util/key_test.go b/config/endpoint/key_test.go
similarity index 98%
rename from util/key_test.go
rename to config/endpoint/key_test.go
index 03341770..c693ba5d 100644
--- a/util/key_test.go
+++ b/config/endpoint/key_test.go
@@ -1,4 +1,4 @@
-package util
+package endpoint
import "testing"
diff --git a/core/result.go b/config/endpoint/result.go
similarity index 99%
rename from core/result.go
rename to config/endpoint/result.go
index 8380d1f4..1d20a5c6 100644
--- a/core/result.go
+++ b/config/endpoint/result.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"time"
diff --git a/core/result_test.go b/config/endpoint/result_test.go
similarity index 96%
rename from core/result_test.go
rename to config/endpoint/result_test.go
index 899ec7f9..1e521c8f 100644
--- a/core/result_test.go
+++ b/config/endpoint/result_test.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
import (
"testing"
diff --git a/core/ssh.go b/config/endpoint/ssh/ssh.go
similarity index 81%
rename from core/ssh.go
rename to config/endpoint/ssh/ssh.go
index b0349bac..88636473 100644
--- a/core/ssh.go
+++ b/config/endpoint/ssh/ssh.go
@@ -1,4 +1,4 @@
-package core
+package ssh
import (
"errors"
@@ -12,17 +12,17 @@ var (
ErrEndpointWithoutSSHPassword = errors.New("you must specify a password for each SSH endpoint")
)
-type SSH struct {
+type Config struct {
Username string `yaml:"username,omitempty"`
Password string `yaml:"password,omitempty"`
}
-// validate validates the endpoint
-func (s *SSH) validate() error {
- if len(s.Username) == 0 {
+// Validate the SSH configuration
+func (cfg *Config) Validate() error {
+ if len(cfg.Username) == 0 {
return ErrEndpointWithoutSSHUsername
}
- if len(s.Password) == 0 {
+ if len(cfg.Password) == 0 {
return ErrEndpointWithoutSSHPassword
}
return nil
diff --git a/core/ssh_test.go b/config/endpoint/ssh/ssh_test.go
similarity index 70%
rename from core/ssh_test.go
rename to config/endpoint/ssh/ssh_test.go
index 15e70433..ed563028 100644
--- a/core/ssh_test.go
+++ b/config/endpoint/ssh/ssh_test.go
@@ -1,4 +1,4 @@
-package core
+package ssh
import (
"errors"
@@ -6,20 +6,20 @@ import (
)
func TestSSH_validate(t *testing.T) {
- ssh := &SSH{}
- if err := ssh.validate(); err == nil {
+ cfg := &Config{}
+ if err := cfg.Validate(); err == nil {
t.Error("expected an error")
} else if !errors.Is(err, ErrEndpointWithoutSSHUsername) {
t.Errorf("expected error to be '%v', got '%v'", ErrEndpointWithoutSSHUsername, err)
}
- ssh.Username = "username"
- if err := ssh.validate(); err == nil {
+ cfg.Username = "username"
+ if err := cfg.Validate(); err == nil {
t.Error("expected an error")
} else if !errors.Is(err, ErrEndpointWithoutSSHPassword) {
t.Errorf("expected error to be '%v', got '%v'", ErrEndpointWithoutSSHPassword, err)
}
- ssh.Password = "password"
- if err := ssh.validate(); err != nil {
+ cfg.Password = "password"
+ if err := cfg.Validate(); err != nil {
t.Errorf("expected no error, got '%v'", err)
}
}
diff --git a/core/endpoint_status.go b/config/endpoint/status.go
similarity index 64%
rename from core/endpoint_status.go
rename to config/endpoint/status.go
index db1ccd78..f1a725ba 100644
--- a/core/endpoint_status.go
+++ b/config/endpoint/status.go
@@ -1,16 +1,14 @@
-package core
+package endpoint
-import "github.com/TwiN/gatus/v5/util"
-
-// EndpointStatus contains the evaluation Results of an Endpoint
-type EndpointStatus struct {
+// Status contains the evaluation Results of an Endpoint
+type Status struct {
// Name of the endpoint
Name string `json:"name,omitempty"`
// Group the endpoint is a part of. Used for grouping multiple endpoints together on the front end.
Group string `json:"group,omitempty"`
- // Key is the key representing the EndpointStatus
+ // Key of the Endpoint
Key string `json:"key"`
// Results is the list of endpoint evaluation results
@@ -27,12 +25,12 @@ type EndpointStatus struct {
Uptime *Uptime `json:"-"`
}
-// NewEndpointStatus creates a new EndpointStatus
-func NewEndpointStatus(group, name string) *EndpointStatus {
- return &EndpointStatus{
+// NewStatus creates a new Status
+func NewStatus(group, name string) *Status {
+ return &Status{
Name: name,
Group: group,
- Key: util.ConvertGroupAndEndpointNameToKey(group, name),
+ Key: ConvertGroupAndEndpointNameToKey(group, name),
Results: make([]*Result, 0),
Events: make([]*Event, 0),
Uptime: NewUptime(),
diff --git a/config/endpoint/status_test.go b/config/endpoint/status_test.go
new file mode 100644
index 00000000..510f9b51
--- /dev/null
+++ b/config/endpoint/status_test.go
@@ -0,0 +1,19 @@
+package endpoint
+
+import (
+ "testing"
+)
+
+func TestNewEndpointStatus(t *testing.T) {
+ ep := &Endpoint{Name: "name", Group: "group"}
+ status := NewStatus(ep.Group, ep.Name)
+ if status.Name != ep.Name {
+ t.Errorf("expected %s, got %s", ep.Name, status.Name)
+ }
+ if status.Group != ep.Group {
+ t.Errorf("expected %s, got %s", ep.Group, status.Group)
+ }
+ if status.Key != "group_name" {
+ t.Errorf("expected %s, got %s", "group_name", status.Key)
+ }
+}
diff --git a/core/ui/ui.go b/config/endpoint/ui/ui.go
similarity index 97%
rename from core/ui/ui.go
rename to config/endpoint/ui/ui.go
index 7ea6eeec..5a13ccdc 100644
--- a/core/ui/ui.go
+++ b/config/endpoint/ui/ui.go
@@ -2,7 +2,7 @@ package ui
import "errors"
-// Config is the UI configuration for core.Endpoint
+// Config is the UI configuration for endpoint.Endpoint
type Config struct {
// HideConditions whether to hide the condition results on the UI
HideConditions bool `yaml:"hide-conditions"`
diff --git a/core/ui/ui_test.go b/config/endpoint/ui/ui_test.go
similarity index 100%
rename from core/ui/ui_test.go
rename to config/endpoint/ui/ui_test.go
diff --git a/core/uptime.go b/config/endpoint/uptime.go
similarity index 98%
rename from core/uptime.go
rename to config/endpoint/uptime.go
index 514b4a77..da4d2139 100644
--- a/core/uptime.go
+++ b/config/endpoint/uptime.go
@@ -1,4 +1,4 @@
-package core
+package endpoint
// Uptime is the struct that contains the relevant data for calculating the uptime as well as the uptime itself
// and some other statistics
diff --git a/config/endpoints/README.md b/config/endpoints/README.md
deleted file mode 100644
index 9416ef98..00000000
--- a/config/endpoints/README.md
+++ /dev/null
@@ -1 +0,0 @@
-TODO: move files from core to here.
\ No newline at end of file
diff --git a/controller/controller_test.go b/controller/controller_test.go
index 62a28297..aaefcbdc 100644
--- a/controller/controller_test.go
+++ b/controller/controller_test.go
@@ -8,8 +8,8 @@ import (
"testing"
"github.com/TwiN/gatus/v5/config"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/web"
- "github.com/TwiN/gatus/v5/core"
"github.com/gofiber/fiber/v2"
)
@@ -19,7 +19,7 @@ func TestHandle(t *testing.T) {
Address: "0.0.0.0",
Port: rand.Intn(65534),
},
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{
Name: "frontend",
Group: "core",
@@ -64,7 +64,7 @@ func TestHandleTLS(t *testing.T) {
t.Run(scenario.name, func(t *testing.T) {
cfg := &config.Config{
Web: &web.Config{Address: "0.0.0.0", Port: rand.Intn(65534), TLS: scenario.tls},
- Endpoints: []*core.Endpoint{
+ Endpoints: []*endpoint.Endpoint{
{Name: "frontend", Group: "core"},
{Name: "backend", Group: "core"},
},
diff --git a/core/dns.go b/core/dns.go
deleted file mode 100644
index 3cae0eb9..00000000
--- a/core/dns.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package core
-
-import (
- "errors"
- "fmt"
- "strings"
-
- "github.com/miekg/dns"
-)
-
-var (
- // ErrDNSWithNoQueryName is the error with which gatus will panic if a dns is configured without query name
- ErrDNSWithNoQueryName = errors.New("you must specify a query name for DNS")
-
- // ErrDNSWithInvalidQueryType is the error with which gatus will panic if a dns is configured with invalid query type
- ErrDNSWithInvalidQueryType = errors.New("invalid query type")
-)
-
-const (
- dnsPort = 53
-)
-
-// DNS is the configuration for a Endpoint of type DNS
-type DNS struct {
- // QueryType is the type for the DNS records like A, AAAA, CNAME...
- QueryType string `yaml:"query-type"`
-
- // QueryName is the query for DNS
- QueryName string `yaml:"query-name"`
-}
-
-func (d *DNS) validateAndSetDefault() error {
- if len(d.QueryName) == 0 {
- return ErrDNSWithNoQueryName
- }
- if !strings.HasSuffix(d.QueryName, ".") {
- d.QueryName += "."
- }
- if _, ok := dns.StringToType[d.QueryType]; !ok {
- return ErrDNSWithInvalidQueryType
- }
- return nil
-}
-
-func (d *DNS) query(url string, result *Result) {
- if !strings.Contains(url, ":") {
- url = fmt.Sprintf("%s:%d", url, dnsPort)
- }
- queryType := dns.StringToType[d.QueryType]
- c := new(dns.Client)
- m := new(dns.Msg)
- m.SetQuestion(d.QueryName, queryType)
- r, _, err := c.Exchange(m, url)
- if err != nil {
- result.AddError(err.Error())
- return
- }
- result.Connected = true
- result.DNSRCode = dns.RcodeToString[r.Rcode]
- for _, rr := range r.Answer {
- switch rr.Header().Rrtype {
- case dns.TypeA:
- if a, ok := rr.(*dns.A); ok {
- result.Body = []byte(a.A.String())
- }
- case dns.TypeAAAA:
- if aaaa, ok := rr.(*dns.AAAA); ok {
- result.Body = []byte(aaaa.AAAA.String())
- }
- case dns.TypeCNAME:
- if cname, ok := rr.(*dns.CNAME); ok {
- result.Body = []byte(cname.Target)
- }
- case dns.TypeMX:
- if mx, ok := rr.(*dns.MX); ok {
- result.Body = []byte(mx.Mx)
- }
- case dns.TypeNS:
- if ns, ok := rr.(*dns.NS); ok {
- result.Body = []byte(ns.Ns)
- }
- default:
- result.Body = []byte("query type is not supported yet")
- }
- }
-}
diff --git a/core/dns_test.go b/core/dns_test.go
deleted file mode 100644
index 29e57da1..00000000
--- a/core/dns_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package core
-
-import (
- "testing"
- "time"
-
- "github.com/TwiN/gatus/v5/pattern"
-)
-
-func TestIntegrationQuery(t *testing.T) {
- tests := []struct {
- name string
- inputDNS DNS
- inputURL string
- expectedDNSCode string
- expectedBody string
- isErrExpected bool
- }{
- {
- name: "test DNS with type A",
- inputDNS: DNS{
- QueryType: "A",
- QueryName: "example.com.",
- },
- inputURL: "8.8.8.8",
- expectedDNSCode: "NOERROR",
- expectedBody: "93.184.215.14",
- },
- {
- name: "test DNS with type AAAA",
- inputDNS: DNS{
- QueryType: "AAAA",
- QueryName: "example.com.",
- },
- inputURL: "8.8.8.8",
- expectedDNSCode: "NOERROR",
- expectedBody: "2606:2800:21f:cb07:6820:80da:af6b:8b2c",
- },
- {
- name: "test DNS with type CNAME",
- inputDNS: DNS{
- QueryType: "CNAME",
- QueryName: "en.wikipedia.org.",
- },
- inputURL: "8.8.8.8",
- expectedDNSCode: "NOERROR",
- expectedBody: "dyna.wikimedia.org.",
- },
- {
- name: "test DNS with type MX",
- inputDNS: DNS{
- QueryType: "MX",
- QueryName: "example.com.",
- },
- inputURL: "8.8.8.8",
- expectedDNSCode: "NOERROR",
- expectedBody: ".",
- },
- {
- name: "test DNS with type NS",
- inputDNS: DNS{
- QueryType: "NS",
- QueryName: "example.com.",
- },
- inputURL: "8.8.8.8",
- expectedDNSCode: "NOERROR",
- expectedBody: "*.iana-servers.net.",
- },
- {
- name: "test DNS with fake type and retrieve error",
- inputDNS: DNS{
- QueryType: "B",
- QueryName: "example",
- },
- inputURL: "8.8.8.8",
- isErrExpected: true,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- dns := test.inputDNS
- result := &Result{}
- dns.query(test.inputURL, result)
- if test.isErrExpected && len(result.Errors) == 0 {
- t.Errorf("there should be errors")
- }
- if result.DNSRCode != test.expectedDNSCode {
- t.Errorf("expected DNSRCode to be %s, got %s", test.expectedDNSCode, result.DNSRCode)
- }
- if test.inputDNS.QueryType == "NS" {
- // Because there are often multiple nameservers backing a single domain, we'll only look at the suffix
- if !pattern.Match(test.expectedBody, string(result.Body)) {
- t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
- }
- } else {
- if string(result.Body) != test.expectedBody {
- t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
- }
- }
- })
- time.Sleep(5 * time.Millisecond)
- }
-}
-
-func TestDNS_validateAndSetDefault(t *testing.T) {
- dns := &DNS{
- QueryType: "A",
- QueryName: "",
- }
- err := dns.validateAndSetDefault()
- if err == nil {
- t.Error("Should've returned an error because endpoint's dns didn't have a query name, which is a mandatory field for dns")
- }
-}
-
-func TestEndpoint_ValidateAndSetDefaultsWithInvalidDNSQueryType(t *testing.T) {
- dns := &DNS{
- QueryType: "B",
- QueryName: "example.com",
- }
- err := dns.validateAndSetDefault()
- if err == nil {
- t.Error("Should've returned an error because endpoint's dns query type is invalid, it needs to be a valid query name like A, AAAA, CNAME...")
- }
-}
diff --git a/core/endpoint_status_test.go b/core/endpoint_status_test.go
deleted file mode 100644
index 0eed7d29..00000000
--- a/core/endpoint_status_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package core
-
-import (
- "testing"
-)
-
-func TestNewEndpointStatus(t *testing.T) {
- endpoint := &Endpoint{Name: "name", Group: "group"}
- status := NewEndpointStatus(endpoint.Group, endpoint.Name)
- if status.Name != endpoint.Name {
- t.Errorf("expected %s, got %s", endpoint.Name, status.Name)
- }
- if status.Group != endpoint.Group {
- t.Errorf("expected %s, got %s", endpoint.Group, status.Group)
- }
- if status.Key != "group_name" {
- t.Errorf("expected %s, got %s", "group_name", status.Key)
- }
-}
diff --git a/main.go b/main.go
index c5994ac6..c1890451 100644
--- a/main.go
+++ b/main.go
@@ -80,8 +80,8 @@ func initializeStorage(cfg *config.Config) {
}
// Remove all EndpointStatus that represent endpoints which no longer exist in the configuration
var keys []string
- for _, endpoint := range cfg.Endpoints {
- keys = append(keys, endpoint.Key())
+ for _, ep := range cfg.Endpoints {
+ keys = append(keys, ep.Key())
}
for _, externalEndpoint := range cfg.ExternalEndpoints {
keys = append(keys, externalEndpoint.Key())
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 37027f24..42600c4b 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -3,7 +3,7 @@ package metrics
import (
"strconv"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
@@ -50,24 +50,24 @@ func initializePrometheusMetrics() {
// PublishMetricsForEndpoint publishes metrics for the given endpoint and its result.
// These metrics will be exposed at /metrics if the metrics are enabled
-func PublishMetricsForEndpoint(endpoint *core.Endpoint, result *core.Result) {
+func PublishMetricsForEndpoint(ep *endpoint.Endpoint, result *endpoint.Result) {
if !initializedMetrics {
initializePrometheusMetrics()
initializedMetrics = true
}
- endpointType := endpoint.Type()
- resultTotal.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType), strconv.FormatBool(result.Success)).Inc()
- resultDurationSeconds.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType)).Set(result.Duration.Seconds())
+ endpointType := ep.Type()
+ resultTotal.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType), strconv.FormatBool(result.Success)).Inc()
+ resultDurationSeconds.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType)).Set(result.Duration.Seconds())
if result.Connected {
- resultConnectedTotal.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType)).Inc()
+ resultConnectedTotal.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType)).Inc()
}
if result.DNSRCode != "" {
- resultCodeTotal.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType), result.DNSRCode).Inc()
+ resultCodeTotal.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType), result.DNSRCode).Inc()
}
if result.HTTPStatus != 0 {
- resultCodeTotal.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType), strconv.Itoa(result.HTTPStatus)).Inc()
+ resultCodeTotal.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType), strconv.Itoa(result.HTTPStatus)).Inc()
}
if result.CertificateExpiration != 0 {
- resultCertificateExpirationSeconds.WithLabelValues(endpoint.Key(), endpoint.Group, endpoint.Name, string(endpointType)).Set(result.CertificateExpiration.Seconds())
+ resultCertificateExpirationSeconds.WithLabelValues(ep.Key(), ep.Group, ep.Name, string(endpointType)).Set(result.CertificateExpiration.Seconds())
}
}
diff --git a/metrics/metrics_test.go b/metrics/metrics_test.go
index 4a1bb35e..ecc1602a 100644
--- a/metrics/metrics_test.go
+++ b/metrics/metrics_test.go
@@ -5,18 +5,19 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
+ "github.com/TwiN/gatus/v5/config/endpoint/dns"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/testutil"
)
func TestPublishMetricsForEndpoint(t *testing.T) {
- httpEndpoint := &core.Endpoint{Name: "http-ep-name", Group: "http-ep-group", URL: "https://example.org"}
- PublishMetricsForEndpoint(httpEndpoint, &core.Result{
+ httpEndpoint := &endpoint.Endpoint{Name: "http-ep-name", Group: "http-ep-group", URL: "https://example.org"}
+ PublishMetricsForEndpoint(httpEndpoint, &endpoint.Result{
HTTPStatus: 200,
Connected: true,
Duration: 123 * time.Millisecond,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[STATUS] == 200", Success: true},
{Condition: "[CERTIFICATE_EXPIRATION] > 48h", Success: true},
},
@@ -43,11 +44,11 @@ gatus_results_total{group="http-ep-group",key="http-ep-group_http-ep-name",name=
if err != nil {
t.Errorf("Expected no errors but got: %v", err)
}
- PublishMetricsForEndpoint(httpEndpoint, &core.Result{
+ PublishMetricsForEndpoint(httpEndpoint, &endpoint.Result{
HTTPStatus: 200,
Connected: true,
Duration: 125 * time.Millisecond,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[STATUS] == 200", Success: true},
{Condition: "[CERTIFICATE_EXPIRATION] > 47h", Success: false},
},
@@ -75,15 +76,15 @@ gatus_results_total{group="http-ep-group",key="http-ep-group_http-ep-name",name=
if err != nil {
t.Errorf("Expected no errors but got: %v", err)
}
- dnsEndpoint := &core.Endpoint{Name: "dns-ep-name", Group: "dns-ep-group", URL: "8.8.8.8", DNS: &core.DNS{
+ dnsEndpoint := &endpoint.Endpoint{Name: "dns-ep-name", Group: "dns-ep-group", URL: "8.8.8.8", DNSConfig: &dns.Config{
QueryType: "A",
QueryName: "example.com.",
}}
- PublishMetricsForEndpoint(dnsEndpoint, &core.Result{
+ PublishMetricsForEndpoint(dnsEndpoint, &endpoint.Result{
DNSRCode: "NOERROR",
Connected: true,
Duration: 50 * time.Millisecond,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{Condition: "[DNS_RCODE] == NOERROR", Success: true},
},
Success: true,
diff --git a/storage/store/memory/memory.go b/storage/store/memory/memory.go
index 281e4a59..fac3fd3d 100644
--- a/storage/store/memory/memory.go
+++ b/storage/store/memory/memory.go
@@ -5,10 +5,9 @@ import (
"sync"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
- "github.com/TwiN/gatus/v5/util"
"github.com/TwiN/gocache/v2"
)
@@ -30,13 +29,13 @@ func NewStore() (*Store, error) {
return store, nil
}
-// GetAllEndpointStatuses returns all monitored core.EndpointStatus
-// with a subset of core.Result defined by the page and pageSize parameters
-func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*core.EndpointStatus, error) {
+// GetAllEndpointStatuses returns all monitored endpoint.Status
+// with a subset of endpoint.Result defined by the page and pageSize parameters
+func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*endpoint.Status, error) {
endpointStatuses := s.cache.GetAll()
- pagedEndpointStatuses := make([]*core.EndpointStatus, 0, len(endpointStatuses))
+ pagedEndpointStatuses := make([]*endpoint.Status, 0, len(endpointStatuses))
for _, v := range endpointStatuses {
- pagedEndpointStatuses = append(pagedEndpointStatuses, ShallowCopyEndpointStatus(v.(*core.EndpointStatus), params))
+ pagedEndpointStatuses = append(pagedEndpointStatuses, ShallowCopyEndpointStatus(v.(*endpoint.Status), params))
}
sort.Slice(pagedEndpointStatuses, func(i, j int) bool {
return pagedEndpointStatuses[i].Key < pagedEndpointStatuses[j].Key
@@ -45,17 +44,17 @@ func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*
}
// GetEndpointStatus returns the endpoint status for a given endpoint name in the given group
-func (s *Store) GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error) {
- return s.GetEndpointStatusByKey(util.ConvertGroupAndEndpointNameToKey(groupName, endpointName), params)
+func (s *Store) GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*endpoint.Status, error) {
+ return s.GetEndpointStatusByKey(endpoint.ConvertGroupAndEndpointNameToKey(groupName, endpointName), params)
}
// GetEndpointStatusByKey returns the endpoint status for a given key
-func (s *Store) GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error) {
+func (s *Store) GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*endpoint.Status, error) {
endpointStatus := s.cache.GetValue(key)
if endpointStatus == nil {
return nil, common.ErrEndpointNotFound
}
- return ShallowCopyEndpointStatus(endpointStatus.(*core.EndpointStatus), params), nil
+ return ShallowCopyEndpointStatus(endpointStatus.(*endpoint.Status), params), nil
}
// GetUptimeByKey returns the uptime percentage during a time range
@@ -64,7 +63,7 @@ func (s *Store) GetUptimeByKey(key string, from, to time.Time) (float64, error)
return 0, common.ErrInvalidTimeRange
}
endpointStatus := s.cache.GetValue(key)
- if endpointStatus == nil || endpointStatus.(*core.EndpointStatus).Uptime == nil {
+ if endpointStatus == nil || endpointStatus.(*endpoint.Status).Uptime == nil {
return 0, common.ErrEndpointNotFound
}
successfulExecutions := uint64(0)
@@ -72,7 +71,7 @@ func (s *Store) GetUptimeByKey(key string, from, to time.Time) (float64, error)
current := from
for to.Sub(current) >= 0 {
hourlyUnixTimestamp := current.Truncate(time.Hour).Unix()
- hourlyStats := endpointStatus.(*core.EndpointStatus).Uptime.HourlyStatistics[hourlyUnixTimestamp]
+ hourlyStats := endpointStatus.(*endpoint.Status).Uptime.HourlyStatistics[hourlyUnixTimestamp]
if hourlyStats == nil || hourlyStats.TotalExecutions == 0 {
current = current.Add(time.Hour)
continue
@@ -93,14 +92,14 @@ func (s *Store) GetAverageResponseTimeByKey(key string, from, to time.Time) (int
return 0, common.ErrInvalidTimeRange
}
endpointStatus := s.cache.GetValue(key)
- if endpointStatus == nil || endpointStatus.(*core.EndpointStatus).Uptime == nil {
+ if endpointStatus == nil || endpointStatus.(*endpoint.Status).Uptime == nil {
return 0, common.ErrEndpointNotFound
}
current := from
var totalExecutions, totalResponseTime uint64
for to.Sub(current) >= 0 {
hourlyUnixTimestamp := current.Truncate(time.Hour).Unix()
- hourlyStats := endpointStatus.(*core.EndpointStatus).Uptime.HourlyStatistics[hourlyUnixTimestamp]
+ hourlyStats := endpointStatus.(*endpoint.Status).Uptime.HourlyStatistics[hourlyUnixTimestamp]
if hourlyStats == nil || hourlyStats.TotalExecutions == 0 {
current = current.Add(time.Hour)
continue
@@ -121,14 +120,14 @@ func (s *Store) GetHourlyAverageResponseTimeByKey(key string, from, to time.Time
return nil, common.ErrInvalidTimeRange
}
endpointStatus := s.cache.GetValue(key)
- if endpointStatus == nil || endpointStatus.(*core.EndpointStatus).Uptime == nil {
+ if endpointStatus == nil || endpointStatus.(*endpoint.Status).Uptime == nil {
return nil, common.ErrEndpointNotFound
}
hourlyAverageResponseTimes := make(map[int64]int)
current := from
for to.Sub(current) >= 0 {
hourlyUnixTimestamp := current.Truncate(time.Hour).Unix()
- hourlyStats := endpointStatus.(*core.EndpointStatus).Uptime.HourlyStatistics[hourlyUnixTimestamp]
+ hourlyStats := endpointStatus.(*endpoint.Status).Uptime.HourlyStatistics[hourlyUnixTimestamp]
if hourlyStats == nil || hourlyStats.TotalExecutions == 0 {
current = current.Add(time.Hour)
continue
@@ -140,24 +139,24 @@ func (s *Store) GetHourlyAverageResponseTimeByKey(key string, from, to time.Time
}
// Insert adds the observed result for the specified endpoint into the store
-func (s *Store) Insert(endpoint *core.Endpoint, result *core.Result) error {
- key := endpoint.Key()
+func (s *Store) Insert(ep *endpoint.Endpoint, result *endpoint.Result) error {
+ key := ep.Key()
s.Lock()
status, exists := s.cache.Get(key)
if !exists {
- status = core.NewEndpointStatus(endpoint.Group, endpoint.Name)
- status.(*core.EndpointStatus).Events = append(status.(*core.EndpointStatus).Events, &core.Event{
- Type: core.EventStart,
+ status = endpoint.NewStatus(ep.Group, ep.Name)
+ status.(*endpoint.Status).Events = append(status.(*endpoint.Status).Events, &endpoint.Event{
+ Type: endpoint.EventStart,
Timestamp: time.Now(),
})
}
- AddResult(status.(*core.EndpointStatus), result)
+ AddResult(status.(*endpoint.Status), result)
s.cache.Set(key, status)
s.Unlock()
return nil
}
-// DeleteAllEndpointStatusesNotInKeys removes all EndpointStatus that are not within the keys provided
+// DeleteAllEndpointStatusesNotInKeys removes all Status that are not within the keys provided
func (s *Store) DeleteAllEndpointStatusesNotInKeys(keys []string) int {
var keysToDelete []string
for _, existingKey := range s.cache.GetKeysByPattern("*", 0) {
diff --git a/storage/store/memory/memory_test.go b/storage/store/memory/memory_test.go
index ea0bd1cd..5d489677 100644
--- a/storage/store/memory/memory_test.go
+++ b/storage/store/memory/memory_test.go
@@ -4,30 +4,30 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
var (
- firstCondition = core.Condition("[STATUS] == 200")
- secondCondition = core.Condition("[RESPONSE_TIME] < 500")
- thirdCondition = core.Condition("[CERTIFICATE_EXPIRATION] < 72h")
+ firstCondition = endpoint.Condition("[STATUS] == 200")
+ secondCondition = endpoint.Condition("[RESPONSE_TIME] < 500")
+ thirdCondition = endpoint.Condition("[CERTIFICATE_EXPIRATION] < 72h")
now = time.Now()
- testEndpoint = core.Endpoint{
+ testEndpoint = endpoint.Endpoint{
Name: "name",
Group: "group",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{firstCondition, secondCondition, thirdCondition},
+ Conditions: []endpoint.Condition{firstCondition, secondCondition, thirdCondition},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
- testSuccessfulResult = core.Result{
+ testSuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -37,7 +37,7 @@ var (
Timestamp: now,
Duration: 150 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -52,7 +52,7 @@ var (
},
},
}
- testUnsuccessfulResult = core.Result{
+ testUnsuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -62,7 +62,7 @@ var (
Timestamp: now,
Duration: 750 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
diff --git a/storage/store/memory/uptime.go b/storage/store/memory/uptime.go
index ffb4863b..29259f6d 100644
--- a/storage/store/memory/uptime.go
+++ b/storage/store/memory/uptime.go
@@ -3,7 +3,7 @@ package memory
import (
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
const (
@@ -13,14 +13,14 @@ const (
// processUptimeAfterResult processes the result by extracting the relevant from the result and recalculating the uptime
// if necessary
-func processUptimeAfterResult(uptime *core.Uptime, result *core.Result) {
+func processUptimeAfterResult(uptime *endpoint.Uptime, result *endpoint.Result) {
if uptime.HourlyStatistics == nil {
- uptime.HourlyStatistics = make(map[int64]*core.HourlyUptimeStatistics)
+ uptime.HourlyStatistics = make(map[int64]*endpoint.HourlyUptimeStatistics)
}
unixTimestampFlooredAtHour := result.Timestamp.Truncate(time.Hour).Unix()
hourlyStats, _ := uptime.HourlyStatistics[unixTimestampFlooredAtHour]
if hourlyStats == nil {
- hourlyStats = &core.HourlyUptimeStatistics{}
+ hourlyStats = &endpoint.HourlyUptimeStatistics{}
uptime.HourlyStatistics[unixTimestampFlooredAtHour] = hourlyStats
}
if result.Success {
diff --git a/storage/store/memory/uptime_bench_test.go b/storage/store/memory/uptime_bench_test.go
index 886ba4df..f055339a 100644
--- a/storage/store/memory/uptime_bench_test.go
+++ b/storage/store/memory/uptime_bench_test.go
@@ -4,17 +4,17 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func BenchmarkProcessUptimeAfterResult(b *testing.B) {
- uptime := core.NewUptime()
+ uptime := endpoint.NewUptime()
now := time.Now()
now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
// Start 12000 days ago
timestamp := now.Add(-12000 * 24 * time.Hour)
for n := 0; n < b.N; n++ {
- processUptimeAfterResult(uptime, &core.Result{
+ processUptimeAfterResult(uptime, &endpoint.Result{
Duration: 18 * time.Millisecond,
Success: n%15 == 0,
Timestamp: timestamp,
diff --git a/storage/store/memory/uptime_test.go b/storage/store/memory/uptime_test.go
index 071bb4ce..01670ad3 100644
--- a/storage/store/memory/uptime_test.go
+++ b/storage/store/memory/uptime_test.go
@@ -4,53 +4,53 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestProcessUptimeAfterResult(t *testing.T) {
- endpoint := &core.Endpoint{Name: "name", Group: "group"}
- status := core.NewEndpointStatus(endpoint.Group, endpoint.Name)
+ ep := &endpoint.Endpoint{Name: "name", Group: "group"}
+ status := endpoint.NewStatus(ep.Group, ep.Name)
uptime := status.Uptime
now := time.Now()
now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-7 * 24 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-7 * 24 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-6 * 24 * time.Hour), Success: false})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-6 * 24 * time.Hour), Success: false})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * 24 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-8 * 24 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-24 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-12 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-24 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-12 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-1 * time.Hour), Success: true, Duration: 10 * time.Millisecond})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-1 * time.Hour), Success: true, Duration: 10 * time.Millisecond})
checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 10, 1, 1)
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-30 * time.Minute), Success: false, Duration: 500 * time.Millisecond})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-30 * time.Minute), Success: false, Duration: 500 * time.Millisecond})
checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 510, 2, 1)
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-15 * time.Minute), Success: false, Duration: 25 * time.Millisecond})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-15 * time.Minute), Success: false, Duration: 25 * time.Millisecond})
checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 535, 3, 1)
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-10 * time.Minute), Success: false})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-10 * time.Minute), Success: false})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-120 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-119 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-118 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-117 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-10 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * time.Hour), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-30 * time.Minute), Success: true})
- processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-25 * time.Minute), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-120 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-119 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-118 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-117 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-10 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-8 * time.Hour), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-30 * time.Minute), Success: true})
+ processUptimeAfterResult(uptime, &endpoint.Result{Timestamp: now.Add(-25 * time.Minute), Success: true})
}
func TestAddResultUptimeIsCleaningUpAfterItself(t *testing.T) {
- endpoint := &core.Endpoint{Name: "name", Group: "group"}
- status := core.NewEndpointStatus(endpoint.Group, endpoint.Name)
+ ep := &endpoint.Endpoint{Name: "name", Group: "group"}
+ status := endpoint.NewStatus(ep.Group, ep.Name)
now := time.Now()
now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
// Start 12 days ago
timestamp := now.Add(-12 * 24 * time.Hour)
for timestamp.Unix() <= now.Unix() {
- AddResult(status, &core.Result{Timestamp: timestamp, Success: true})
+ AddResult(status, &endpoint.Result{Timestamp: timestamp, Success: true})
if len(status.Uptime.HourlyStatistics) > numberOfHoursInTenDays {
t.Errorf("At no point in time should there be more than %d entries in status.SuccessfulExecutionsPerHour, but there are %d", numberOfHoursInTenDays, len(status.Uptime.HourlyStatistics))
}
@@ -59,7 +59,7 @@ func TestAddResultUptimeIsCleaningUpAfterItself(t *testing.T) {
}
}
-func checkHourlyStatistics(t *testing.T, hourlyUptimeStatistics *core.HourlyUptimeStatistics, expectedTotalExecutionsResponseTime uint64, expectedTotalExecutions uint64, expectedSuccessfulExecutions uint64) {
+func checkHourlyStatistics(t *testing.T, hourlyUptimeStatistics *endpoint.HourlyUptimeStatistics, expectedTotalExecutionsResponseTime uint64, expectedTotalExecutions uint64, expectedSuccessfulExecutions uint64) {
if hourlyUptimeStatistics.TotalExecutionsResponseTime != expectedTotalExecutionsResponseTime {
t.Error("TotalExecutionsResponseTime should've been", expectedTotalExecutionsResponseTime, "got", hourlyUptimeStatistics.TotalExecutionsResponseTime)
}
diff --git a/storage/store/memory/util.go b/storage/store/memory/util.go
index 7ba757e1..961f740a 100644
--- a/storage/store/memory/util.go
+++ b/storage/store/memory/util.go
@@ -1,31 +1,31 @@
package memory
import (
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
-// ShallowCopyEndpointStatus returns a shallow copy of a EndpointStatus with only the results
+// ShallowCopyEndpointStatus returns a shallow copy of a Status with only the results
// within the range defined by the page and pageSize parameters
-func ShallowCopyEndpointStatus(ss *core.EndpointStatus, params *paging.EndpointStatusParams) *core.EndpointStatus {
- shallowCopy := &core.EndpointStatus{
+func ShallowCopyEndpointStatus(ss *endpoint.Status, params *paging.EndpointStatusParams) *endpoint.Status {
+ shallowCopy := &endpoint.Status{
Name: ss.Name,
Group: ss.Group,
Key: ss.Key,
- Uptime: core.NewUptime(),
+ Uptime: endpoint.NewUptime(),
}
numberOfResults := len(ss.Results)
resultsStart, resultsEnd := getStartAndEndIndex(numberOfResults, params.ResultsPage, params.ResultsPageSize)
if resultsStart < 0 || resultsEnd < 0 {
- shallowCopy.Results = []*core.Result{}
+ shallowCopy.Results = []*endpoint.Result{}
} else {
shallowCopy.Results = ss.Results[resultsStart:resultsEnd]
}
numberOfEvents := len(ss.Events)
eventsStart, eventsEnd := getStartAndEndIndex(numberOfEvents, params.EventsPage, params.EventsPageSize)
if eventsStart < 0 || eventsEnd < 0 {
- shallowCopy.Events = []*core.Event{}
+ shallowCopy.Events = []*endpoint.Event{}
} else {
shallowCopy.Events = ss.Events[eventsStart:eventsEnd]
}
@@ -49,16 +49,16 @@ func getStartAndEndIndex(numberOfResults int, page, pageSize int) (int, int) {
return start, end
}
-// AddResult adds a Result to EndpointStatus.Results and makes sure that there are
+// AddResult adds a Result to Status.Results and makes sure that there are
// no more than MaximumNumberOfResults results in the Results slice
-func AddResult(ss *core.EndpointStatus, result *core.Result) {
+func AddResult(ss *endpoint.Status, result *endpoint.Result) {
if ss == nil {
return
}
if len(ss.Results) > 0 {
// Check if there's any change since the last result
if ss.Results[len(ss.Results)-1].Success != result.Success {
- ss.Events = append(ss.Events, core.NewEventFromResult(result))
+ ss.Events = append(ss.Events, endpoint.NewEventFromResult(result))
if len(ss.Events) > common.MaximumNumberOfEvents {
// Doing ss.Events[1:] would usually be sufficient, but in the case where for some reason, the slice has
// more than one extra element, we can get rid of all of them at once and thus returning the slice to a
@@ -68,7 +68,7 @@ func AddResult(ss *core.EndpointStatus, result *core.Result) {
}
} else {
// This is the first result, so we need to add the first healthy/unhealthy event
- ss.Events = append(ss.Events, core.NewEventFromResult(result))
+ ss.Events = append(ss.Events, endpoint.NewEventFromResult(result))
}
ss.Results = append(ss.Results, result)
if len(ss.Results) > common.MaximumNumberOfResults {
diff --git a/storage/store/memory/util_bench_test.go b/storage/store/memory/util_bench_test.go
index e832f149..36252829 100644
--- a/storage/store/memory/util_bench_test.go
+++ b/storage/store/memory/util_bench_test.go
@@ -3,14 +3,14 @@ package memory
import (
"testing"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
func BenchmarkShallowCopyEndpointStatus(b *testing.B) {
- endpoint := &testEndpoint
- status := core.NewEndpointStatus(endpoint.Group, endpoint.Name)
+ ep := &testEndpoint
+ status := endpoint.NewStatus(ep.Group, ep.Name)
for i := 0; i < common.MaximumNumberOfResults; i++ {
AddResult(status, &testSuccessfulResult)
}
diff --git a/storage/store/memory/util_test.go b/storage/store/memory/util_test.go
index 8f88299e..1de445e7 100644
--- a/storage/store/memory/util_test.go
+++ b/storage/store/memory/util_test.go
@@ -4,16 +4,16 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
func TestAddResult(t *testing.T) {
- endpoint := &core.Endpoint{Name: "name", Group: "group"}
- endpointStatus := core.NewEndpointStatus(endpoint.Group, endpoint.Name)
+ ep := &endpoint.Endpoint{Name: "name", Group: "group"}
+ endpointStatus := endpoint.NewStatus(ep.Group, ep.Name)
for i := 0; i < (common.MaximumNumberOfResults+common.MaximumNumberOfEvents)*2; i++ {
- AddResult(endpointStatus, &core.Result{Success: i%2 == 0, Timestamp: time.Now()})
+ AddResult(endpointStatus, &endpoint.Result{Success: i%2 == 0, Timestamp: time.Now()})
}
if len(endpointStatus.Results) != common.MaximumNumberOfResults {
t.Errorf("expected endpointStatus.Results to not exceed a length of %d", common.MaximumNumberOfResults)
@@ -22,15 +22,15 @@ func TestAddResult(t *testing.T) {
t.Errorf("expected endpointStatus.Events to not exceed a length of %d", common.MaximumNumberOfEvents)
}
// Try to add nil endpointStatus
- AddResult(nil, &core.Result{Timestamp: time.Now()})
+ AddResult(nil, &endpoint.Result{Timestamp: time.Now()})
}
func TestShallowCopyEndpointStatus(t *testing.T) {
- endpoint := &core.Endpoint{Name: "name", Group: "group"}
- endpointStatus := core.NewEndpointStatus(endpoint.Group, endpoint.Name)
+ ep := &endpoint.Endpoint{Name: "name", Group: "group"}
+ endpointStatus := endpoint.NewStatus(ep.Group, ep.Name)
ts := time.Now().Add(-25 * time.Hour)
for i := 0; i < 25; i++ {
- AddResult(endpointStatus, &core.Result{Success: i%2 == 0, Timestamp: ts})
+ AddResult(endpointStatus, &endpoint.Result{Success: i%2 == 0, Timestamp: ts})
ts = ts.Add(time.Hour)
}
if len(ShallowCopyEndpointStatus(endpointStatus, paging.NewEndpointStatusParams().WithResults(-1, -1)).Results) != 0 {
diff --git a/storage/store/sql/sql.go b/storage/store/sql/sql.go
index cd94c824..ec25b564 100644
--- a/storage/store/sql/sql.go
+++ b/storage/store/sql/sql.go
@@ -9,10 +9,9 @@ import (
"strings"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
- "github.com/TwiN/gatus/v5/util"
"github.com/TwiN/gocache/v2"
_ "github.com/lib/pq"
_ "modernc.org/sqlite"
@@ -100,9 +99,9 @@ func (s *Store) createSchema() error {
return s.createPostgresSchema()
}
-// GetAllEndpointStatuses returns all monitored core.EndpointStatus
-// with a subset of core.Result defined by the page and pageSize parameters
-func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*core.EndpointStatus, error) {
+// GetAllEndpointStatuses returns all monitored endpoint.Status
+// with a subset of endpoint.Result defined by the page and pageSize parameters
+func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*endpoint.Status, error) {
tx, err := s.db.Begin()
if err != nil {
return nil, err
@@ -112,7 +111,7 @@ func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*
_ = tx.Rollback()
return nil, err
}
- endpointStatuses := make([]*core.EndpointStatus, 0, len(keys))
+ endpointStatuses := make([]*endpoint.Status, 0, len(keys))
for _, key := range keys {
endpointStatus, err := s.getEndpointStatusByKey(tx, key, params)
if err != nil {
@@ -127,12 +126,12 @@ func (s *Store) GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*
}
// GetEndpointStatus returns the endpoint status for a given endpoint name in the given group
-func (s *Store) GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error) {
- return s.GetEndpointStatusByKey(util.ConvertGroupAndEndpointNameToKey(groupName, endpointName), params)
+func (s *Store) GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*endpoint.Status, error) {
+ return s.GetEndpointStatusByKey(endpoint.ConvertGroupAndEndpointNameToKey(groupName, endpointName), params)
}
// GetEndpointStatusByKey returns the endpoint status for a given key
-func (s *Store) GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error) {
+func (s *Store) GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*endpoint.Status, error) {
tx, err := s.db.Begin()
if err != nil {
return nil, err
@@ -224,30 +223,30 @@ func (s *Store) GetHourlyAverageResponseTimeByKey(key string, from, to time.Time
}
// Insert adds the observed result for the specified endpoint into the store
-func (s *Store) Insert(endpoint *core.Endpoint, result *core.Result) error {
+func (s *Store) Insert(ep *endpoint.Endpoint, result *endpoint.Result) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
- endpointID, err := s.getEndpointID(tx, endpoint)
+ endpointID, err := s.getEndpointID(tx, ep)
if err != nil {
if errors.Is(err, common.ErrEndpointNotFound) {
// Endpoint doesn't exist in the database, insert it
- if endpointID, err = s.insertEndpoint(tx, endpoint); err != nil {
+ if endpointID, err = s.insertEndpoint(tx, ep); err != nil {
_ = tx.Rollback()
- log.Printf("[sql.Insert] Failed to create endpoint with group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to create endpoint with group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
return err
}
} else {
_ = tx.Rollback()
- log.Printf("[sql.Insert] Failed to retrieve id of endpoint with group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to retrieve id of endpoint with group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
return err
}
}
// First, we need to check if we need to insert a new event.
//
// A new event must be added if either of the following cases happen:
- // 1. There is only 1 event. The total number of events for a endpoint can only be 1 if the only existing event is
+ // 1. There is only 1 event. The total number of events for an endpoint can only be 1 if the only existing event is
// of type EventStart, in which case we will have to create a new event of type EventHealthy or EventUnhealthy
// based on result.Success.
// 2. The lastResult.Success != result.Success. This implies that the endpoint went from healthy to unhealthy or
@@ -256,38 +255,38 @@ func (s *Store) Insert(endpoint *core.Endpoint, result *core.Result) error {
numberOfEvents, err := s.getNumberOfEventsByEndpointID(tx, endpointID)
if err != nil {
// Silently fail
- log.Printf("[sql.Insert] Failed to retrieve total number of events for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to retrieve total number of events for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
}
if numberOfEvents == 0 {
// There's no events yet, which means we need to add the EventStart and the first healthy/unhealthy event
- err = s.insertEndpointEvent(tx, endpointID, &core.Event{
- Type: core.EventStart,
+ err = s.insertEndpointEvent(tx, endpointID, &endpoint.Event{
+ Type: endpoint.EventStart,
Timestamp: result.Timestamp.Add(-50 * time.Millisecond),
})
if err != nil {
// Silently fail
- log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", core.EventStart, endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", endpoint.EventStart, ep.Group, ep.Name, err.Error())
}
- event := core.NewEventFromResult(result)
+ event := endpoint.NewEventFromResult(result)
if err = s.insertEndpointEvent(tx, endpointID, event); err != nil {
// Silently fail
- log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", event.Type, endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", event.Type, ep.Group, ep.Name, err.Error())
}
} else {
// Get the success value of the previous result
var lastResultSuccess bool
if lastResultSuccess, err = s.getLastEndpointResultSuccessValue(tx, endpointID); err != nil {
- log.Printf("[sql.Insert] Failed to retrieve outcome of previous result for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to retrieve outcome of previous result for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
} else {
// If we managed to retrieve the outcome of the previous result, we'll compare it with the new result.
// If the final outcome (success or failure) of the previous and the new result aren't the same, it means
// that the endpoint either went from Healthy to Unhealthy or Unhealthy -> Healthy, therefore, we'll add
// an event to mark the change in state
if lastResultSuccess != result.Success {
- event := core.NewEventFromResult(result)
+ event := endpoint.NewEventFromResult(result)
if err = s.insertEndpointEvent(tx, endpointID, event); err != nil {
// Silently fail
- log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", event.Type, endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to insert event=%s for group=%s; endpoint=%s: %s", event.Type, ep.Group, ep.Name, err.Error())
}
}
}
@@ -296,45 +295,45 @@ func (s *Store) Insert(endpoint *core.Endpoint, result *core.Result) error {
// (since we're only deleting MaximumNumberOfEvents at a time instead of 1)
if numberOfEvents > eventsCleanUpThreshold {
if err = s.deleteOldEndpointEvents(tx, endpointID); err != nil {
- log.Printf("[sql.Insert] Failed to delete old events for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to delete old events for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
}
}
}
// Second, we need to insert the result.
if err = s.insertEndpointResult(tx, endpointID, result); err != nil {
- log.Printf("[sql.Insert] Failed to insert result for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to insert result for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
_ = tx.Rollback() // If we can't insert the result, we'll rollback now since there's no point continuing
return err
}
// Clean up old results
numberOfResults, err := s.getNumberOfResultsByEndpointID(tx, endpointID)
if err != nil {
- log.Printf("[sql.Insert] Failed to retrieve total number of results for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to retrieve total number of results for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
} else {
if numberOfResults > resultsCleanUpThreshold {
if err = s.deleteOldEndpointResults(tx, endpointID); err != nil {
- log.Printf("[sql.Insert] Failed to delete old results for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to delete old results for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
}
}
}
// Finally, we need to insert the uptime data.
// Because the uptime data significantly outlives the results, we can't rely on the results for determining the uptime
if err = s.updateEndpointUptime(tx, endpointID, result); err != nil {
- log.Printf("[sql.Insert] Failed to update uptime for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to update uptime for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
}
// Clean up old uptime entries
ageOfOldestUptimeEntry, err := s.getAgeOfOldestEndpointUptimeEntry(tx, endpointID)
if err != nil {
- log.Printf("[sql.Insert] Failed to retrieve oldest endpoint uptime entry for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to retrieve oldest endpoint uptime entry for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
} else {
if ageOfOldestUptimeEntry > uptimeCleanUpThreshold {
if err = s.deleteOldUptimeEntries(tx, endpointID, time.Now().Add(-(uptimeRetention + time.Hour))); err != nil {
- log.Printf("[sql.Insert] Failed to delete old uptime entries for group=%s; endpoint=%s: %s", endpoint.Group, endpoint.Name, err.Error())
+ log.Printf("[sql.Insert] Failed to delete old uptime entries for group=%s; endpoint=%s: %s", ep.Group, ep.Name, err.Error())
}
}
}
if s.writeThroughCache != nil {
- cacheKeysToRefresh := s.writeThroughCache.GetKeysByPattern(endpoint.Key()+"*", 0)
+ cacheKeysToRefresh := s.writeThroughCache.GetKeysByPattern(ep.Key()+"*", 0)
for _, cacheKey := range cacheKeysToRefresh {
s.writeThroughCache.Delete(cacheKey)
endpointKey, params, err := extractKeyAndParamsFromCacheKey(cacheKey)
@@ -405,14 +404,14 @@ func (s *Store) Close() {
}
// insertEndpoint inserts an endpoint in the store and returns the generated id of said endpoint
-func (s *Store) insertEndpoint(tx *sql.Tx, endpoint *core.Endpoint) (int64, error) {
- //log.Printf("[sql.insertEndpoint] Inserting endpoint with group=%s and name=%s", endpoint.Group, endpoint.Name)
+func (s *Store) insertEndpoint(tx *sql.Tx, ep *endpoint.Endpoint) (int64, error) {
+ //log.Printf("[sql.insertEndpoint] Inserting endpoint with group=%s and name=%s", ep.Group, ep.Name)
var id int64
err := tx.QueryRow(
"INSERT INTO endpoints (endpoint_key, endpoint_name, endpoint_group) VALUES ($1, $2, $3) RETURNING endpoint_id",
- endpoint.Key(),
- endpoint.Name,
- endpoint.Group,
+ ep.Key(),
+ ep.Name,
+ ep.Group,
).Scan(&id)
if err != nil {
return 0, err
@@ -421,7 +420,7 @@ func (s *Store) insertEndpoint(tx *sql.Tx, endpoint *core.Endpoint) (int64, erro
}
// insertEndpointEvent inserts en event in the store
-func (s *Store) insertEndpointEvent(tx *sql.Tx, endpointID int64, event *core.Event) error {
+func (s *Store) insertEndpointEvent(tx *sql.Tx, endpointID int64, event *endpoint.Event) error {
_, err := tx.Exec(
"INSERT INTO endpoint_events (endpoint_id, event_type, event_timestamp) VALUES ($1, $2, $3)",
endpointID,
@@ -435,7 +434,7 @@ func (s *Store) insertEndpointEvent(tx *sql.Tx, endpointID int64, event *core.Ev
}
// insertEndpointResult inserts a result in the store
-func (s *Store) insertEndpointResult(tx *sql.Tx, endpointID int64, result *core.Result) error {
+func (s *Store) insertEndpointResult(tx *sql.Tx, endpointID int64, result *endpoint.Result) error {
var endpointResultID int64
err := tx.QueryRow(
`
@@ -462,7 +461,7 @@ func (s *Store) insertEndpointResult(tx *sql.Tx, endpointID int64, result *core.
return s.insertConditionResults(tx, endpointResultID, result.ConditionResults)
}
-func (s *Store) insertConditionResults(tx *sql.Tx, endpointResultID int64, conditionResults []*core.ConditionResult) error {
+func (s *Store) insertConditionResults(tx *sql.Tx, endpointResultID int64, conditionResults []*endpoint.ConditionResult) error {
var err error
for _, cr := range conditionResults {
_, err = tx.Exec("INSERT INTO endpoint_result_conditions (endpoint_result_id, condition, success) VALUES ($1, $2, $3)",
@@ -477,7 +476,7 @@ func (s *Store) insertConditionResults(tx *sql.Tx, endpointResultID int64, condi
return nil
}
-func (s *Store) updateEndpointUptime(tx *sql.Tx, endpointID int64, result *core.Result) error {
+func (s *Store) updateEndpointUptime(tx *sql.Tx, endpointID int64, result *endpoint.Result) error {
unixTimestampFlooredAtHour := result.Timestamp.Truncate(time.Hour).Unix()
var successfulExecutions int
if result.Success {
@@ -514,12 +513,12 @@ func (s *Store) getAllEndpointKeys(tx *sql.Tx) (keys []string, err error) {
return
}
-func (s *Store) getEndpointStatusByKey(tx *sql.Tx, key string, parameters *paging.EndpointStatusParams) (*core.EndpointStatus, error) {
+func (s *Store) getEndpointStatusByKey(tx *sql.Tx, key string, parameters *paging.EndpointStatusParams) (*endpoint.Status, error) {
var cacheKey string
if s.writeThroughCache != nil {
cacheKey = generateCacheKey(key, parameters)
if cachedEndpointStatus, exists := s.writeThroughCache.Get(cacheKey); exists {
- if castedCachedEndpointStatus, ok := cachedEndpointStatus.(*core.EndpointStatus); ok {
+ if castedCachedEndpointStatus, ok := cachedEndpointStatus.(*endpoint.Status); ok {
return castedCachedEndpointStatus, nil
}
}
@@ -528,7 +527,7 @@ func (s *Store) getEndpointStatusByKey(tx *sql.Tx, key string, parameters *pagin
if err != nil {
return nil, err
}
- endpointStatus := core.NewEndpointStatus(group, endpointName)
+ endpointStatus := endpoint.NewStatus(group, endpointName)
if parameters.EventsPageSize > 0 {
if endpointStatus.Events, err = s.getEndpointEventsByEndpointID(tx, endpointID, parameters.EventsPage, parameters.EventsPageSize); err != nil {
log.Printf("[sql.getEndpointStatusByKey] Failed to retrieve events for key=%s: %s", key, err.Error())
@@ -564,7 +563,7 @@ func (s *Store) getEndpointIDGroupAndNameByKey(tx *sql.Tx, key string) (id int64
return
}
-func (s *Store) getEndpointEventsByEndpointID(tx *sql.Tx, endpointID int64, page, pageSize int) (events []*core.Event, err error) {
+func (s *Store) getEndpointEventsByEndpointID(tx *sql.Tx, endpointID int64, page, pageSize int) (events []*endpoint.Event, err error) {
rows, err := tx.Query(
`
SELECT event_type, event_timestamp
@@ -581,14 +580,14 @@ func (s *Store) getEndpointEventsByEndpointID(tx *sql.Tx, endpointID int64, page
return nil, err
}
for rows.Next() {
- event := &core.Event{}
+ event := &endpoint.Event{}
_ = rows.Scan(&event.Type, &event.Timestamp)
events = append(events, event)
}
return
}
-func (s *Store) getEndpointResultsByEndpointID(tx *sql.Tx, endpointID int64, page, pageSize int) (results []*core.Result, err error) {
+func (s *Store) getEndpointResultsByEndpointID(tx *sql.Tx, endpointID int64, page, pageSize int) (results []*endpoint.Result, err error) {
rows, err := tx.Query(
`
SELECT endpoint_result_id, success, errors, connected, status, dns_rcode, certificate_expiration, domain_expiration, hostname, ip, duration, timestamp
@@ -604,9 +603,9 @@ func (s *Store) getEndpointResultsByEndpointID(tx *sql.Tx, endpointID int64, pag
if err != nil {
return nil, err
}
- idResultMap := make(map[int64]*core.Result)
+ idResultMap := make(map[int64]*endpoint.Result)
for rows.Next() {
- result := &core.Result{}
+ result := &endpoint.Result{}
var id int64
var joinedErrors string
err = rows.Scan(&id, &result.Success, &joinedErrors, &result.Connected, &result.HTTPStatus, &result.DNSRCode, &result.CertificateExpiration, &result.DomainExpiration, &result.Hostname, &result.IP, &result.Duration, &result.Timestamp)
@@ -618,7 +617,7 @@ func (s *Store) getEndpointResultsByEndpointID(tx *sql.Tx, endpointID int64, pag
result.Errors = strings.Split(joinedErrors, arraySeparator)
}
// This is faster than using a subselect
- results = append([]*core.Result{result}, results...)
+ results = append([]*endpoint.Result{result}, results...)
idResultMap[id] = result
}
if len(idResultMap) == 0 {
@@ -643,7 +642,7 @@ func (s *Store) getEndpointResultsByEndpointID(tx *sql.Tx, endpointID int64, pag
}
defer rows.Close() // explicitly defer the close in case an error happens during the scan
for rows.Next() {
- conditionResult := &core.ConditionResult{}
+ conditionResult := &endpoint.ConditionResult{}
var endpointResultID int64
if err = rows.Scan(&endpointResultID, &conditionResult.Condition, &conditionResult.Success); err != nil {
return
@@ -734,9 +733,9 @@ func (s *Store) getEndpointHourlyAverageResponseTimes(tx *sql.Tx, endpointID int
return hourlyAverageResponseTimes, nil
}
-func (s *Store) getEndpointID(tx *sql.Tx, endpoint *core.Endpoint) (int64, error) {
+func (s *Store) getEndpointID(tx *sql.Tx, ep *endpoint.Endpoint) (int64, error) {
var id int64
- err := tx.QueryRow("SELECT endpoint_id FROM endpoints WHERE endpoint_key = $1", endpoint.Key()).Scan(&id)
+ err := tx.QueryRow("SELECT endpoint_id FROM endpoints WHERE endpoint_key = $1", ep.Key()).Scan(&id)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return 0, common.ErrEndpointNotFound
diff --git a/storage/store/sql/sql_test.go b/storage/store/sql/sql_test.go
index cfd3c8bd..da611a4a 100644
--- a/storage/store/sql/sql_test.go
+++ b/storage/store/sql/sql_test.go
@@ -4,31 +4,31 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
)
var (
- firstCondition = core.Condition("[STATUS] == 200")
- secondCondition = core.Condition("[RESPONSE_TIME] < 500")
- thirdCondition = core.Condition("[CERTIFICATE_EXPIRATION] < 72h")
+ firstCondition = endpoint.Condition("[STATUS] == 200")
+ secondCondition = endpoint.Condition("[RESPONSE_TIME] < 500")
+ thirdCondition = endpoint.Condition("[CERTIFICATE_EXPIRATION] < 72h")
now = time.Now()
- testEndpoint = core.Endpoint{
+ testEndpoint = endpoint.Endpoint{
Name: "name",
Group: "group",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{firstCondition, secondCondition, thirdCondition},
+ Conditions: []endpoint.Condition{firstCondition, secondCondition, thirdCondition},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
- testSuccessfulResult = core.Result{
+ testSuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -38,7 +38,7 @@ var (
Timestamp: now,
Duration: 150 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -53,7 +53,7 @@ var (
},
},
}
- testUnsuccessfulResult = core.Result{
+ testUnsuccessfulResult = endpoint.Result{
Hostname: "example.org",
IP: "127.0.0.1",
HTTPStatus: 200,
@@ -63,7 +63,7 @@ var (
Timestamp: now,
Duration: 750 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -100,7 +100,7 @@ func TestStore_InsertCleansUpOldUptimeEntriesProperly(t *testing.T) {
now := time.Now().Truncate(time.Hour)
now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
- store.Insert(&testEndpoint, &core.Result{Timestamp: now.Add(-5 * time.Hour), Success: true})
+ store.Insert(&testEndpoint, &endpoint.Result{Timestamp: now.Add(-5 * time.Hour), Success: true})
tx, _ := store.db.Begin()
oldest, _ := store.getAgeOfOldestEndpointUptimeEntry(tx, 1)
@@ -110,7 +110,7 @@ func TestStore_InsertCleansUpOldUptimeEntriesProperly(t *testing.T) {
}
// The oldest cache entry should remain at ~5 hours old, because this entry is more recent
- store.Insert(&testEndpoint, &core.Result{Timestamp: now.Add(-3 * time.Hour), Success: true})
+ store.Insert(&testEndpoint, &endpoint.Result{Timestamp: now.Add(-3 * time.Hour), Success: true})
tx, _ = store.db.Begin()
oldest, _ = store.getAgeOfOldestEndpointUptimeEntry(tx, 1)
@@ -120,7 +120,7 @@ func TestStore_InsertCleansUpOldUptimeEntriesProperly(t *testing.T) {
}
// The oldest cache entry should now become at ~8 hours old, because this entry is older
- store.Insert(&testEndpoint, &core.Result{Timestamp: now.Add(-8 * time.Hour), Success: true})
+ store.Insert(&testEndpoint, &endpoint.Result{Timestamp: now.Add(-8 * time.Hour), Success: true})
tx, _ = store.db.Begin()
oldest, _ = store.getAgeOfOldestEndpointUptimeEntry(tx, 1)
@@ -130,7 +130,7 @@ func TestStore_InsertCleansUpOldUptimeEntriesProperly(t *testing.T) {
}
// Since this is one hour before reaching the clean up threshold, the oldest entry should now be this one
- store.Insert(&testEndpoint, &core.Result{Timestamp: now.Add(-(uptimeCleanUpThreshold - time.Hour)), Success: true})
+ store.Insert(&testEndpoint, &endpoint.Result{Timestamp: now.Add(-(uptimeCleanUpThreshold - time.Hour)), Success: true})
tx, _ = store.db.Begin()
oldest, _ = store.getAgeOfOldestEndpointUptimeEntry(tx, 1)
@@ -141,7 +141,7 @@ func TestStore_InsertCleansUpOldUptimeEntriesProperly(t *testing.T) {
// Since this entry is after the uptimeCleanUpThreshold, both this entry as well as the previous
// one should be deleted since they both surpass uptimeRetention
- store.Insert(&testEndpoint, &core.Result{Timestamp: now.Add(-(uptimeCleanUpThreshold + time.Hour)), Success: true})
+ store.Insert(&testEndpoint, &endpoint.Result{Timestamp: now.Add(-(uptimeCleanUpThreshold + time.Hour)), Success: true})
tx, _ = store.db.Begin()
oldest, _ = store.getAgeOfOldestEndpointUptimeEntry(tx, 1)
@@ -313,7 +313,7 @@ func TestStore_InvalidTransaction(t *testing.T) {
if _, err := store.insertEndpoint(tx, &testEndpoint); err == nil {
t.Error("should've returned an error, because the transaction was already committed")
}
- if err := store.insertEndpointEvent(tx, 1, core.NewEventFromResult(&testSuccessfulResult)); err == nil {
+ if err := store.insertEndpointEvent(tx, 1, endpoint.NewEventFromResult(&testSuccessfulResult)); err == nil {
t.Error("should've returned an error, because the transaction was already committed")
}
if err := store.insertEndpointResult(tx, 1, &testSuccessfulResult); err == nil {
diff --git a/storage/store/store.go b/storage/store/store.go
index f4d1d986..4dea6dcf 100644
--- a/storage/store/store.go
+++ b/storage/store/store.go
@@ -5,7 +5,7 @@ import (
"log"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
"github.com/TwiN/gatus/v5/storage/store/memory"
@@ -14,15 +14,15 @@ import (
// Store is the interface that each store should implement
type Store interface {
- // GetAllEndpointStatuses returns the JSON encoding of all monitored core.EndpointStatus
- // with a subset of core.Result defined by the page and pageSize parameters
- GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*core.EndpointStatus, error)
+ // GetAllEndpointStatuses returns the JSON encoding of all monitored endpoint.Status
+ // with a subset of endpoint.Result defined by the page and pageSize parameters
+ GetAllEndpointStatuses(params *paging.EndpointStatusParams) ([]*endpoint.Status, error)
// GetEndpointStatus returns the endpoint status for a given endpoint name in the given group
- GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error)
+ GetEndpointStatus(groupName, endpointName string, params *paging.EndpointStatusParams) (*endpoint.Status, error)
// GetEndpointStatusByKey returns the endpoint status for a given key
- GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*core.EndpointStatus, error)
+ GetEndpointStatusByKey(key string, params *paging.EndpointStatusParams) (*endpoint.Status, error)
// GetUptimeByKey returns the uptime percentage during a time range
GetUptimeByKey(key string, from, to time.Time) (float64, error)
@@ -34,9 +34,9 @@ type Store interface {
GetHourlyAverageResponseTimeByKey(key string, from, to time.Time) (map[int64]int, error)
// Insert adds the observed result for the specified endpoint into the store
- Insert(endpoint *core.Endpoint, result *core.Result) error
+ Insert(ep *endpoint.Endpoint, result *endpoint.Result) error
- // DeleteAllEndpointStatusesNotInKeys removes all EndpointStatus that are not within the keys provided
+ // DeleteAllEndpointStatusesNotInKeys removes all Status that are not within the keys provided
//
// Used to delete endpoints that have been persisted but are no longer part of the configured endpoints
DeleteAllEndpointStatusesNotInKeys(keys []string) int
diff --git a/storage/store/store_bench_test.go b/storage/store/store_bench_test.go
index 67a8e06c..0ed4c2db 100644
--- a/storage/store/store_bench_test.go
+++ b/storage/store/store_bench_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
"github.com/TwiN/gatus/v5/storage/store/memory"
"github.com/TwiN/gatus/v5/storage/store/sql"
@@ -53,11 +53,11 @@ func BenchmarkStore_GetAllEndpointStatuses(b *testing.B) {
for _, numberOfEndpointsToCreate := range numberOfEndpoints {
// Create endpoints and insert results
for i := 0; i < numberOfEndpointsToCreate; i++ {
- endpoint := testEndpoint
- endpoint.Name = "endpoint" + strconv.Itoa(i)
+ ep := testEndpoint
+ ep.Name = "endpoint" + strconv.Itoa(i)
// Insert 20 results for each endpoint
for j := 0; j < 20; j++ {
- scenario.Store.Insert(&endpoint, &testSuccessfulResult)
+ scenario.Store.Insert(&ep, &testSuccessfulResult)
}
}
// Run the scenarios
@@ -123,7 +123,7 @@ func BenchmarkStore_Insert(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
n := 0
for pb.Next() {
- var result core.Result
+ var result endpoint.Result
if n%10 == 0 {
result = testUnsuccessfulResult
} else {
@@ -136,7 +136,7 @@ func BenchmarkStore_Insert(b *testing.B) {
})
} else {
for n := 0; n < b.N; n++ {
- var result core.Result
+ var result endpoint.Result
if n%10 == 0 {
result = testUnsuccessfulResult
} else {
diff --git a/storage/store/store_test.go b/storage/store/store_test.go
index 8aec8182..6f18f446 100644
--- a/storage/store/store_test.go
+++ b/storage/store/store_test.go
@@ -1,11 +1,12 @@
package store
import (
+ "errors"
"path/filepath"
"testing"
"time"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/storage"
"github.com/TwiN/gatus/v5/storage/store/common"
"github.com/TwiN/gatus/v5/storage/store/common/paging"
@@ -14,25 +15,25 @@ import (
)
var (
- firstCondition = core.Condition("[STATUS] == 200")
- secondCondition = core.Condition("[RESPONSE_TIME] < 500")
- thirdCondition = core.Condition("[CERTIFICATE_EXPIRATION] < 72h")
+ firstCondition = endpoint.Condition("[STATUS] == 200")
+ secondCondition = endpoint.Condition("[RESPONSE_TIME] < 500")
+ thirdCondition = endpoint.Condition("[CERTIFICATE_EXPIRATION] < 72h")
now = time.Now().Truncate(time.Hour)
- testEndpoint = core.Endpoint{
+ testEndpoint = endpoint.Endpoint{
Name: "name",
Group: "group",
URL: "https://example.org/what/ever",
Method: "GET",
Body: "body",
Interval: 30 * time.Second,
- Conditions: []core.Condition{firstCondition, secondCondition, thirdCondition},
+ Conditions: []endpoint.Condition{firstCondition, secondCondition, thirdCondition},
Alerts: nil,
NumberOfFailuresInARow: 0,
NumberOfSuccessesInARow: 0,
}
- testSuccessfulResult = core.Result{
+ testSuccessfulResult = endpoint.Result{
Timestamp: now,
Success: true,
Hostname: "example.org",
@@ -42,7 +43,7 @@ var (
Connected: true,
Duration: 150 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -57,7 +58,7 @@ var (
},
},
}
- testUnsuccessfulResult = core.Result{
+ testUnsuccessfulResult = endpoint.Result{
Timestamp: now,
Success: false,
Hostname: "example.org",
@@ -67,7 +68,7 @@ var (
Connected: true,
Duration: 750 * time.Millisecond,
CertificateExpiration: 10 * time.Hour,
- ConditionResults: []*core.ConditionResult{
+ ConditionResults: []*endpoint.ConditionResult{
{
Condition: "[STATUS] == 200",
Success: true,
@@ -176,21 +177,21 @@ func TestStore_GetEndpointStatusForMissingStatusReturnsNil(t *testing.T) {
t.Run(scenario.Name, func(t *testing.T) {
scenario.Store.Insert(&testEndpoint, &testSuccessfulResult)
endpointStatus, err := scenario.Store.GetEndpointStatus("nonexistantgroup", "nonexistantname", paging.NewEndpointStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
- if err != common.ErrEndpointNotFound {
+ if !errors.Is(err, common.ErrEndpointNotFound) {
t.Error("should've returned ErrEndpointNotFound, got", err)
}
if endpointStatus != nil {
t.Errorf("Returned endpoint status for group '%s' and name '%s' not nil after inserting the endpoint into the store", testEndpoint.Group, testEndpoint.Name)
}
endpointStatus, err = scenario.Store.GetEndpointStatus(testEndpoint.Group, "nonexistantname", paging.NewEndpointStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
- if err != common.ErrEndpointNotFound {
+ if !errors.Is(err, common.ErrEndpointNotFound) {
t.Error("should've returned ErrEndpointNotFound, got", err)
}
if endpointStatus != nil {
t.Errorf("Returned endpoint status for group '%s' and name '%s' not nil after inserting the endpoint into the store", testEndpoint.Group, "nonexistantname")
}
endpointStatus, err = scenario.Store.GetEndpointStatus("nonexistantgroup", testEndpoint.Name, paging.NewEndpointStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
- if err != common.ErrEndpointNotFound {
+ if !errors.Is(err, common.ErrEndpointNotFound) {
t.Error("should've returned ErrEndpointNotFound, got", err)
}
if endpointStatus != nil {
@@ -482,7 +483,7 @@ func TestStore_Insert(t *testing.T) {
if len(ss.Results) != 2 {
t.Fatalf("Endpoint '%s' should've had 2 results, got %d", ss.Name, len(ss.Results))
}
- for i, expectedResult := range []core.Result{firstResult, secondResult} {
+ for i, expectedResult := range []endpoint.Result{firstResult, secondResult} {
if expectedResult.HTTPStatus != ss.Results[i].HTTPStatus {
t.Errorf("Result at index %d should've had a HTTPStatus of %d, got %d", i, ss.Results[i].HTTPStatus, expectedResult.HTTPStatus)
}
@@ -539,13 +540,13 @@ func TestStore_Insert(t *testing.T) {
func TestStore_DeleteAllEndpointStatusesNotInKeys(t *testing.T) {
scenarios := initStoresAndBaseScenarios(t, "TestStore_DeleteAllEndpointStatusesNotInKeys")
defer cleanUp(scenarios)
- firstEndpoint := core.Endpoint{Name: "endpoint-1", Group: "group"}
- secondEndpoint := core.Endpoint{Name: "endpoint-2", Group: "group"}
- result := &testSuccessfulResult
+ firstEndpoint := endpoint.Endpoint{Name: "endpoint-1", Group: "group"}
+ secondEndpoint := endpoint.Endpoint{Name: "endpoint-2", Group: "group"}
+ r := &testSuccessfulResult
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- scenario.Store.Insert(&firstEndpoint, result)
- scenario.Store.Insert(&secondEndpoint, result)
+ scenario.Store.Insert(&firstEndpoint, r)
+ scenario.Store.Insert(&secondEndpoint, r)
if ss, _ := scenario.Store.GetEndpointStatusByKey(firstEndpoint.Key(), paging.NewEndpointStatusParams()); ss == nil {
t.Fatal("firstEndpoint should exist, got", ss)
}
@@ -631,7 +632,7 @@ func TestInitialize(t *testing.T) {
store.Close()
// Try to initialize it again
err = Initialize(scenario.Cfg)
- if err != scenario.ExpectedErr {
+ if !errors.Is(err, scenario.ExpectedErr) {
t.Errorf("expected %v, got %v", scenario.ExpectedErr, err)
return
}
diff --git a/watchdog/alerting.go b/watchdog/alerting.go
index 29898016..09e73a40 100644
--- a/watchdog/alerting.go
+++ b/watchdog/alerting.go
@@ -6,48 +6,48 @@ import (
"os"
"github.com/TwiN/gatus/v5/alerting"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
// HandleAlerting takes care of alerts to resolve and alerts to trigger based on result success or failure
-func HandleAlerting(endpoint *core.Endpoint, result *core.Result, alertingConfig *alerting.Config, debug bool) {
+func HandleAlerting(ep *endpoint.Endpoint, result *endpoint.Result, alertingConfig *alerting.Config, debug bool) {
if alertingConfig == nil {
return
}
if result.Success {
- handleAlertsToResolve(endpoint, result, alertingConfig, debug)
+ handleAlertsToResolve(ep, result, alertingConfig, debug)
} else {
- handleAlertsToTrigger(endpoint, result, alertingConfig, debug)
+ handleAlertsToTrigger(ep, result, alertingConfig, debug)
}
}
-func handleAlertsToTrigger(endpoint *core.Endpoint, result *core.Result, alertingConfig *alerting.Config, debug bool) {
- endpoint.NumberOfSuccessesInARow = 0
- endpoint.NumberOfFailuresInARow++
- for _, endpointAlert := range endpoint.Alerts {
+func handleAlertsToTrigger(ep *endpoint.Endpoint, result *endpoint.Result, alertingConfig *alerting.Config, debug bool) {
+ ep.NumberOfSuccessesInARow = 0
+ ep.NumberOfFailuresInARow++
+ for _, endpointAlert := range ep.Alerts {
// If the alert hasn't been triggered, move to the next one
- if !endpointAlert.IsEnabled() || endpointAlert.FailureThreshold > endpoint.NumberOfFailuresInARow {
+ if !endpointAlert.IsEnabled() || endpointAlert.FailureThreshold > ep.NumberOfFailuresInARow {
continue
}
if endpointAlert.Triggered {
if debug {
- log.Printf("[watchdog.handleAlertsToTrigger] Alert for endpoint=%s with description='%s' has already been TRIGGERED, skipping", endpoint.Name, endpointAlert.GetDescription())
+ log.Printf("[watchdog.handleAlertsToTrigger] Alert for endpoint=%s with description='%s' has already been TRIGGERED, skipping", ep.Name, endpointAlert.GetDescription())
}
continue
}
alertProvider := alertingConfig.GetAlertingProviderByAlertType(endpointAlert.Type)
if alertProvider != nil {
- log.Printf("[watchdog.handleAlertsToTrigger] Sending %s alert because alert for endpoint=%s with description='%s' has been TRIGGERED", endpointAlert.Type, endpoint.Name, endpointAlert.GetDescription())
+ log.Printf("[watchdog.handleAlertsToTrigger] Sending %s alert because alert for endpoint=%s with description='%s' has been TRIGGERED", endpointAlert.Type, ep.Name, endpointAlert.GetDescription())
var err error
if os.Getenv("MOCK_ALERT_PROVIDER") == "true" {
if os.Getenv("MOCK_ALERT_PROVIDER_ERROR") == "true" {
err = errors.New("error")
}
} else {
- err = alertProvider.Send(endpoint, endpointAlert, result, false)
+ err = alertProvider.Send(ep, endpointAlert, result, false)
}
if err != nil {
- log.Printf("[watchdog.handleAlertsToTrigger] Failed to send an alert for endpoint=%s: %s", endpoint.Name, err.Error())
+ log.Printf("[watchdog.handleAlertsToTrigger] Failed to send an alert for endpoint=%s: %s", ep.Name, err.Error())
} else {
endpointAlert.Triggered = true
}
@@ -57,10 +57,10 @@ func handleAlertsToTrigger(endpoint *core.Endpoint, result *core.Result, alertin
}
}
-func handleAlertsToResolve(endpoint *core.Endpoint, result *core.Result, alertingConfig *alerting.Config, debug bool) {
- endpoint.NumberOfSuccessesInARow++
- for _, endpointAlert := range endpoint.Alerts {
- if !endpointAlert.IsEnabled() || !endpointAlert.Triggered || endpointAlert.SuccessThreshold > endpoint.NumberOfSuccessesInARow {
+func handleAlertsToResolve(ep *endpoint.Endpoint, result *endpoint.Result, alertingConfig *alerting.Config, debug bool) {
+ ep.NumberOfSuccessesInARow++
+ for _, endpointAlert := range ep.Alerts {
+ if !endpointAlert.IsEnabled() || !endpointAlert.Triggered || endpointAlert.SuccessThreshold > ep.NumberOfSuccessesInARow {
continue
}
// Even if the alert provider returns an error, we still set the alert's Triggered variable to false.
@@ -71,14 +71,14 @@ func handleAlertsToResolve(endpoint *core.Endpoint, result *core.Result, alertin
}
alertProvider := alertingConfig.GetAlertingProviderByAlertType(endpointAlert.Type)
if alertProvider != nil {
- log.Printf("[watchdog.handleAlertsToResolve] Sending %s alert because alert for endpoint=%s with description='%s' has been RESOLVED", endpointAlert.Type, endpoint.Name, endpointAlert.GetDescription())
- err := alertProvider.Send(endpoint, endpointAlert, result, true)
+ log.Printf("[watchdog.handleAlertsToResolve] Sending %s alert because alert for endpoint=%s with description='%s' has been RESOLVED", endpointAlert.Type, ep.Name, endpointAlert.GetDescription())
+ err := alertProvider.Send(ep, endpointAlert, result, true)
if err != nil {
- log.Printf("[watchdog.handleAlertsToResolve] Failed to send an alert for endpoint=%s: %s", endpoint.Name, err.Error())
+ log.Printf("[watchdog.handleAlertsToResolve] Failed to send an alert for endpoint=%s: %s", ep.Name, err.Error())
}
} else {
log.Printf("[watchdog.handleAlertsToResolve] Not sending alert of type=%s despite being RESOLVED, because the provider wasn't configured properly", endpointAlert.Type)
}
}
- endpoint.NumberOfFailuresInARow = 0
+ ep.NumberOfFailuresInARow = 0
}
diff --git a/watchdog/alerting_test.go b/watchdog/alerting_test.go
index 358412d8..914355e4 100644
--- a/watchdog/alerting_test.go
+++ b/watchdog/alerting_test.go
@@ -20,7 +20,7 @@ import (
"github.com/TwiN/gatus/v5/alerting/provider/telegram"
"github.com/TwiN/gatus/v5/alerting/provider/twilio"
"github.com/TwiN/gatus/v5/config"
- "github.com/TwiN/gatus/v5/core"
+ "github.com/TwiN/gatus/v5/config/endpoint"
)
func TestHandleAlerting(t *testing.T) {
@@ -37,7 +37,7 @@ func TestHandleAlerting(t *testing.T) {
},
}
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -51,23 +51,23 @@ func TestHandleAlerting(t *testing.T) {
},
}
- 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")
+ verify(t, ep, 0, 0, false, "The alert shouldn't start triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, false, "The alert shouldn't have triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 2, 0, true, "The alert should've triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 3, 0, true, "The alert should still be triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 4, 0, true, "The alert should still be triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, true, "The alert should still be triggered (because endpoint.Alerts[0].SuccessThreshold is 3)")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 2, true, "The alert should still be triggered (because endpoint.Alerts[0].SuccessThreshold is 3)")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 3, false, "The alert should've been resolved")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 4, false, "The alert should no longer be triggered")
}
func TestHandleAlertingWhenAlertingConfigIsNil(t *testing.T) {
@@ -81,7 +81,7 @@ func TestHandleAlertingWithBadAlertProvider(t *testing.T) {
defer os.Clearenv()
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "http://example.com",
Alerts: []*alert.Alert{
{
@@ -95,11 +95,11 @@ func TestHandleAlertingWithBadAlertProvider(t *testing.T) {
},
}
- 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")
+ verify(t, ep, 0, 0, false, "The alert shouldn't start triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, &alerting.Config{}, false)
+ verify(t, ep, 1, 0, false, "The alert shouldn't have triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, &alerting.Config{}, false)
+ verify(t, ep, 2, 0, false, "The alert shouldn't have triggered, because the provider wasn't configured properly")
}
func TestHandleAlertingWhenTriggeredAlertIsAlmostResolvedButendpointStartFailingAgain(t *testing.T) {
@@ -116,7 +116,7 @@ func TestHandleAlertingWhenTriggeredAlertIsAlmostResolvedButendpointStartFailing
},
}
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -132,8 +132,8 @@ func TestHandleAlertingWhenTriggeredAlertIsAlmostResolvedButendpointStartFailing
}
// This test simulate an alert that was already triggered
- 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")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 2, 0, true, "The alert was already triggered at the beginning of this test")
}
func TestHandleAlertingWhenTriggeredAlertIsResolvedButSendOnResolvedIsFalse(t *testing.T) {
@@ -151,7 +151,7 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedButSendOnResolvedIsFalse(t *t
}
enabled := true
disabled := false
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -166,8 +166,8 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedButSendOnResolvedIsFalse(t *t
NumberOfFailuresInARow: 1,
}
- HandleAlerting(endpoint, &core.Result{Success: true}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 0, 1, false, "The alert should've been resolved")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "The alert should've been resolved")
}
func TestHandleAlertingWhenTriggeredAlertIsResolvedPagerDuty(t *testing.T) {
@@ -183,7 +183,7 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedPagerDuty(t *testing.T) {
},
}
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -198,11 +198,11 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedPagerDuty(t *testing.T) {
NumberOfFailuresInARow: 0,
}
- HandleAlerting(endpoint, &core.Result{Success: false}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 1, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, true, "")
- HandleAlerting(endpoint, &core.Result{Success: true}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 0, 1, false, "The alert should've been resolved")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "The alert should've been resolved")
}
func TestHandleAlertingWhenTriggeredAlertIsResolvedPushover(t *testing.T) {
@@ -219,7 +219,7 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedPushover(t *testing.T) {
},
}
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -234,11 +234,11 @@ func TestHandleAlertingWhenTriggeredAlertIsResolvedPushover(t *testing.T) {
NumberOfFailuresInARow: 0,
}
- HandleAlerting(endpoint, &core.Result{Success: false}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 1, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, true, "")
- HandleAlerting(endpoint, &core.Result{Success: true}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 0, 1, false, "The alert should've been resolved")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "The alert should've been resolved")
}
func TestHandleAlertingWithProviderThatReturnsAnError(t *testing.T) {
@@ -389,7 +389,7 @@ func TestHandleAlertingWithProviderThatReturnsAnError(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -403,33 +403,33 @@ func TestHandleAlertingWithProviderThatReturnsAnError(t *testing.T) {
},
}
_ = 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")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 1, 0, false, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 2, 0, false, "The alert should have failed to trigger, because the alert provider is returning an error")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 3, 0, false, "The alert should still not be triggered, because the alert provider is still returning an error")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 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")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 5, 0, true, "The alert should've been triggered because the alert provider is no longer returning an error")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, scenario.AlertingConfig, true)
+ verify(t, ep, 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.")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, scenario.AlertingConfig, true)
+ verify(t, ep, 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")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 1, 0, false, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, scenario.AlertingConfig, true)
+ verify(t, ep, 2, 0, true, "The alert should have triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, scenario.AlertingConfig, true)
+ verify(t, ep, 0, 1, true, "The alert should still be triggered")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, scenario.AlertingConfig, true)
+ verify(t, ep, 0, 2, false, "The alert should have been resolved")
})
}
@@ -449,7 +449,7 @@ func TestHandleAlertingWithProviderThatOnlyReturnsErrorOnResolve(t *testing.T) {
},
}
enabled := true
- endpoint := &core.Endpoint{
+ ep := &endpoint.Endpoint{
URL: "https://example.com",
Alerts: []*alert.Alert{
{
@@ -463,38 +463,38 @@ func TestHandleAlertingWithProviderThatOnlyReturnsErrorOnResolve(t *testing.T) {
},
}
- HandleAlerting(endpoint, &core.Result{Success: false}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 1, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, true, "")
_ = os.Setenv("MOCK_ALERT_PROVIDER_ERROR", "true")
- HandleAlerting(endpoint, &core.Result{Success: true}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 0, 1, false, "")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "")
_ = os.Setenv("MOCK_ALERT_PROVIDER_ERROR", "false")
- HandleAlerting(endpoint, &core.Result{Success: false}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 1, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, true, "")
_ = os.Setenv("MOCK_ALERT_PROVIDER_ERROR", "true")
- HandleAlerting(endpoint, &core.Result{Success: true}, cfg.Alerting, cfg.Debug)
- verify(t, endpoint, 0, 1, false, "")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "")
_ = 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}, 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, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 1, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: false}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 2, 0, true, "")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 1, false, "")
+ HandleAlerting(ep, &endpoint.Result{Success: true}, cfg.Alerting, cfg.Debug)
+ verify(t, ep, 0, 2, false, "")
}
-func verify(t *testing.T, endpoint *core.Endpoint, expectedNumberOfFailuresInARow, expectedNumberOfSuccessInARow int, expectedTriggered bool, expectedTriggeredReason string) {
- if endpoint.NumberOfFailuresInARow != expectedNumberOfFailuresInARow {
- t.Errorf("endpoint.NumberOfFailuresInARow should've been %d, got %d", expectedNumberOfFailuresInARow, endpoint.NumberOfFailuresInARow)
+func verify(t *testing.T, ep *endpoint.Endpoint, expectedNumberOfFailuresInARow, expectedNumberOfSuccessInARow int, expectedTriggered bool, expectedTriggeredReason string) {
+ if ep.NumberOfFailuresInARow != expectedNumberOfFailuresInARow {
+ t.Errorf("endpoint.NumberOfFailuresInARow should've been %d, got %d", expectedNumberOfFailuresInARow, ep.NumberOfFailuresInARow)
}
- if endpoint.NumberOfSuccessesInARow != expectedNumberOfSuccessInARow {
- t.Errorf("endpoint.NumberOfSuccessesInARow should've been %d, got %d", expectedNumberOfSuccessInARow, endpoint.NumberOfSuccessesInARow)
+ if ep.NumberOfSuccessesInARow != expectedNumberOfSuccessInARow {
+ t.Errorf("endpoint.NumberOfSuccessesInARow should've been %d, got %d", expectedNumberOfSuccessInARow, ep.NumberOfSuccessesInARow)
}
- if endpoint.Alerts[0].Triggered != expectedTriggered {
+ if ep.Alerts[0].Triggered != expectedTriggered {
if len(expectedTriggeredReason) != 0 {
t.Error(expectedTriggeredReason)
} else {
diff --git a/watchdog/watchdog.go b/watchdog/watchdog.go
index 2557b413..3fcb977a 100644
--- a/watchdog/watchdog.go
+++ b/watchdog/watchdog.go
@@ -9,8 +9,8 @@ import (
"github.com/TwiN/gatus/v5/alerting"
"github.com/TwiN/gatus/v5/config"
"github.com/TwiN/gatus/v5/config/connectivity"
+ "github.com/TwiN/gatus/v5/config/endpoint"
"github.com/TwiN/gatus/v5/config/maintenance"
- "github.com/TwiN/gatus/v5/core"
"github.com/TwiN/gatus/v5/metrics"
"github.com/TwiN/gatus/v5/storage/store"
)
@@ -37,17 +37,17 @@ func Monitor(cfg *config.Config) {
}
// monitor a single endpoint in a loop
-func monitor(endpoint *core.Endpoint, alertingConfig *alerting.Config, maintenanceConfig *maintenance.Config, connectivityConfig *connectivity.Config, disableMonitoringLock, enabledMetrics, debug bool, ctx context.Context) {
+func monitor(ep *endpoint.Endpoint, alertingConfig *alerting.Config, maintenanceConfig *maintenance.Config, connectivityConfig *connectivity.Config, disableMonitoringLock, enabledMetrics, debug bool, ctx context.Context) {
// Run it immediately on start
- execute(endpoint, alertingConfig, maintenanceConfig, connectivityConfig, disableMonitoringLock, enabledMetrics, debug)
+ execute(ep, alertingConfig, maintenanceConfig, connectivityConfig, disableMonitoringLock, enabledMetrics, debug)
// Loop for the next executions
for {
select {
case <-ctx.Done():
- log.Printf("[watchdog.monitor] Canceling current execution of group=%s; endpoint=%s", endpoint.Group, endpoint.Name)
+ log.Printf("[watchdog.monitor] Canceling current execution of group=%s; endpoint=%s", ep.Group, ep.Name)
return
- case <-time.After(endpoint.Interval):
- execute(endpoint, alertingConfig, maintenanceConfig, connectivityConfig, disableMonitoringLock, enabledMetrics, debug)
+ case <-time.After(ep.Interval):
+ execute(ep, alertingConfig, maintenanceConfig, connectivityConfig, disableMonitoringLock, enabledMetrics, debug)
}
}
// Just in case somebody wandered all the way to here and wonders, "what about ExternalEndpoints?"
@@ -55,7 +55,7 @@ func monitor(endpoint *core.Endpoint, alertingConfig *alerting.Config, maintenan
// periodically like they are for normal endpoints.
}
-func execute(endpoint *core.Endpoint, alertingConfig *alerting.Config, maintenanceConfig *maintenance.Config, connectivityConfig *connectivity.Config, disableMonitoringLock, enabledMetrics, debug bool) {
+func execute(ep *endpoint.Endpoint, alertingConfig *alerting.Config, maintenanceConfig *maintenance.Config, connectivityConfig *connectivity.Config, disableMonitoringLock, enabledMetrics, debug bool) {
if !disableMonitoringLock {
// By placing the lock here, we prevent multiple endpoints from being monitored at the exact same time, which
// could cause performance issues and return inaccurate results
@@ -68,32 +68,32 @@ func execute(endpoint *core.Endpoint, alertingConfig *alerting.Config, maintenan
return
}
if debug {
- log.Printf("[watchdog.execute] Monitoring group=%s; endpoint=%s", endpoint.Group, endpoint.Name)
+ log.Printf("[watchdog.execute] Monitoring group=%s; endpoint=%s", ep.Group, ep.Name)
}
- result := endpoint.EvaluateHealth()
+ result := ep.EvaluateHealth()
if enabledMetrics {
- metrics.PublishMetricsForEndpoint(endpoint, result)
+ metrics.PublishMetricsForEndpoint(ep, result)
}
- UpdateEndpointStatuses(endpoint, result)
+ UpdateEndpointStatuses(ep, result)
if debug && !result.Success {
- log.Printf("[watchdog.execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s; body=%s", endpoint.Group, endpoint.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond), result.Body)
+ log.Printf("[watchdog.execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s; body=%s", ep.Group, ep.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond), result.Body)
} else {
- log.Printf("[watchdog.execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s", endpoint.Group, endpoint.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond))
+ log.Printf("[watchdog.execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s", ep.Group, ep.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond))
}
if !maintenanceConfig.IsUnderMaintenance() {
// TODO: Consider moving this after the monitoring lock is unlocked? I mean, how much noise can a single alerting provider cause...
- HandleAlerting(endpoint, result, alertingConfig, debug)
+ HandleAlerting(ep, result, alertingConfig, debug)
} else if debug {
log.Println("[watchdog.execute] Not handling alerting because currently in the maintenance window")
}
if debug {
- log.Printf("[watchdog.execute] Waiting for interval=%s before monitoring group=%s endpoint=%s again", endpoint.Interval, endpoint.Group, endpoint.Name)
+ log.Printf("[watchdog.execute] Waiting for interval=%s before monitoring group=%s endpoint=%s again", ep.Interval, ep.Group, ep.Name)
}
}
// UpdateEndpointStatuses updates the slice of endpoint statuses
-func UpdateEndpointStatuses(endpoint *core.Endpoint, result *core.Result) {
- if err := store.Get().Insert(endpoint, result); err != nil {
+func UpdateEndpointStatuses(ep *endpoint.Endpoint, result *endpoint.Result) {
+ if err := store.Get().Insert(ep, result); err != nil {
log.Println("[watchdog.UpdateEndpointStatuses] Failed to insert result in storage:", err.Error())
}
}
@@ -101,8 +101,8 @@ func UpdateEndpointStatuses(endpoint *core.Endpoint, result *core.Result) {
// Shutdown stops monitoring all endpoints
func Shutdown(cfg *config.Config) {
// Disable all the old HTTP connections
- for _, endpoint := range cfg.Endpoints {
- endpoint.Close()
+ for _, ep := range cfg.Endpoints {
+ ep.Close()
}
cancelFunc()
}