2019-09-06 04:02:00 +00:00
|
|
|
package config
|
|
|
|
|
2019-09-09 01:07:08 +00:00
|
|
|
import (
|
2020-10-14 23:22:58 +00:00
|
|
|
"fmt"
|
2020-08-22 18:15:21 +00:00
|
|
|
"github.com/TwinProduction/gatus/core"
|
2019-09-09 01:07:08 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
2019-09-06 04:02:00 +00:00
|
|
|
|
2019-10-20 02:03:55 +00:00
|
|
|
func TestParseAndValidateConfigBytes(t *testing.T) {
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(`
|
2019-09-06 04:02:00 +00:00
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
2019-09-09 01:07:08 +00:00
|
|
|
interval: 15s
|
2019-09-06 04:02:00 +00:00
|
|
|
conditions:
|
2019-12-04 22:27:27 +00:00
|
|
|
- "[STATUS] == 200"
|
2019-09-06 04:02:00 +00:00
|
|
|
- name: github
|
2019-09-09 01:07:08 +00:00
|
|
|
url: https://api.github.com/healthz
|
2019-09-06 04:02:00 +00:00
|
|
|
conditions:
|
2019-12-04 22:27:27 +00:00
|
|
|
- "[STATUS] != 400"
|
|
|
|
- "[STATUS] != 500"
|
2019-09-06 04:02:00 +00:00
|
|
|
`))
|
2019-10-20 02:03:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
2020-08-22 18:15:21 +00:00
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
2019-09-06 04:02:00 +00:00
|
|
|
if len(config.Services) != 2 {
|
|
|
|
t.Error("Should have returned two services")
|
|
|
|
}
|
|
|
|
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
|
|
|
t.Errorf("URL should have been %s", "https://twinnation.org/actuator/health")
|
|
|
|
}
|
2019-09-09 01:07:08 +00:00
|
|
|
if config.Services[1].Url != "https://api.github.com/healthz" {
|
|
|
|
t.Errorf("URL should have been %s", "https://api.github.com/healthz")
|
2019-09-06 04:02:00 +00:00
|
|
|
}
|
2019-09-09 01:07:08 +00:00
|
|
|
if config.Services[0].Interval != 15*time.Second {
|
|
|
|
t.Errorf("Interval should have been %s", 15*time.Second)
|
2019-09-06 04:02:00 +00:00
|
|
|
}
|
2020-09-01 16:46:23 +00:00
|
|
|
if config.Services[1].Interval != 60*time.Second {
|
|
|
|
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
2019-09-06 04:02:00 +00:00
|
|
|
}
|
|
|
|
if len(config.Services[0].Conditions) != 1 {
|
|
|
|
t.Errorf("There should have been %d conditions", 1)
|
|
|
|
}
|
|
|
|
if len(config.Services[1].Conditions) != 2 {
|
|
|
|
t.Errorf("There should have been %d conditions", 2)
|
|
|
|
}
|
|
|
|
}
|
2019-09-10 02:21:18 +00:00
|
|
|
|
2019-10-20 02:03:55 +00:00
|
|
|
func TestParseAndValidateConfigBytesDefault(t *testing.T) {
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(`
|
2019-09-10 02:21:18 +00:00
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
conditions:
|
2019-12-04 22:27:27 +00:00
|
|
|
- "[STATUS] == 200"
|
2019-09-10 02:21:18 +00:00
|
|
|
`))
|
2019-10-20 02:03:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
2020-08-22 18:15:21 +00:00
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
2019-11-16 20:47:56 +00:00
|
|
|
if config.Metrics {
|
|
|
|
t.Error("Metrics should've been false by default")
|
|
|
|
}
|
|
|
|
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
|
|
|
t.Errorf("URL should have been %s", "https://twinnation.org/actuator/health")
|
|
|
|
}
|
2020-09-01 16:46:23 +00:00
|
|
|
if config.Services[0].Interval != 60*time.Second {
|
|
|
|
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
2019-11-16 20:47:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseAndValidateConfigBytesWithMetrics(t *testing.T) {
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(`
|
|
|
|
metrics: true
|
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
conditions:
|
2019-12-04 22:27:27 +00:00
|
|
|
- "[STATUS] == 200"
|
2019-11-16 20:47:56 +00:00
|
|
|
`))
|
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
2020-08-22 18:15:21 +00:00
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
2019-11-16 20:47:56 +00:00
|
|
|
if !config.Metrics {
|
|
|
|
t.Error("Metrics should have been true")
|
|
|
|
}
|
2019-09-10 02:21:18 +00:00
|
|
|
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
|
|
|
t.Errorf("URL should have been %s", "https://twinnation.org/actuator/health")
|
|
|
|
}
|
2020-09-01 16:46:23 +00:00
|
|
|
if config.Services[0].Interval != 60*time.Second {
|
|
|
|
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
2019-09-10 02:21:18 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-20 02:03:55 +00:00
|
|
|
|
|
|
|
func TestParseAndValidateBadConfigBytes(t *testing.T) {
|
|
|
|
_, err := parseAndValidateConfigBytes([]byte(`
|
|
|
|
badconfig:
|
|
|
|
- asdsa: w0w
|
|
|
|
usadasdrl: asdxzczxc
|
|
|
|
asdas:
|
|
|
|
- soup
|
|
|
|
`))
|
|
|
|
if err == nil {
|
|
|
|
t.Error("An error should've been returned")
|
|
|
|
}
|
|
|
|
if err != ErrNoServiceInConfig {
|
|
|
|
t.Error("The error returned should have been of type ErrNoServiceInConfig")
|
|
|
|
}
|
|
|
|
}
|
2020-08-22 18:15:21 +00:00
|
|
|
|
|
|
|
func TestParseAndValidateConfigBytesWithAlerting(t *testing.T) {
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(`
|
|
|
|
alerting:
|
2020-09-19 20:22:12 +00:00
|
|
|
slack:
|
|
|
|
webhook-url: "http://example.com"
|
2020-09-24 23:52:59 +00:00
|
|
|
pagerduty:
|
|
|
|
integration-key: "00000000000000000000000000000000"
|
2020-08-22 18:15:21 +00:00
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
alerts:
|
|
|
|
- type: slack
|
|
|
|
enabled: true
|
2020-09-17 00:22:33 +00:00
|
|
|
failure-threshold: 7
|
2020-08-22 18:15:21 +00:00
|
|
|
description: "Healthcheck failed 7 times in a row"
|
|
|
|
conditions:
|
|
|
|
- "[STATUS] == 200"
|
|
|
|
`))
|
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Metrics {
|
|
|
|
t.Error("Metrics should've been false by default")
|
|
|
|
}
|
|
|
|
if config.Alerting == nil {
|
2020-09-24 23:52:59 +00:00
|
|
|
t.Fatal("config.Alerting shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Alerting.Slack == nil || !config.Alerting.Slack.IsValid() {
|
|
|
|
t.Fatal("Slack alerting config should've been valid")
|
2020-08-22 18:15:21 +00:00
|
|
|
}
|
2020-09-19 20:22:12 +00:00
|
|
|
if config.Alerting.Slack.WebhookUrl != "http://example.com" {
|
2020-09-24 23:52:59 +00:00
|
|
|
t.Errorf("Slack webhook should've been %s, but was %s", "http://example.com", config.Alerting.Slack.WebhookUrl)
|
|
|
|
}
|
|
|
|
if config.Alerting.PagerDuty == nil || !config.Alerting.PagerDuty.IsValid() {
|
|
|
|
t.Fatal("PagerDuty alerting config should've been valid")
|
|
|
|
}
|
|
|
|
if config.Alerting.PagerDuty.IntegrationKey != "00000000000000000000000000000000" {
|
|
|
|
t.Errorf("PagerDuty integration key should've been %s, but was %s", "00000000000000000000000000000000", config.Alerting.PagerDuty.IntegrationKey)
|
2020-08-22 18:15:21 +00:00
|
|
|
}
|
|
|
|
if len(config.Services) != 1 {
|
|
|
|
t.Error("There should've been 1 service")
|
|
|
|
}
|
|
|
|
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
|
|
|
t.Errorf("URL should have been %s", "https://twinnation.org/actuator/health")
|
|
|
|
}
|
2020-09-01 16:46:23 +00:00
|
|
|
if config.Services[0].Interval != 60*time.Second {
|
|
|
|
t.Errorf("Interval should have been %s, because it is the default value", 60*time.Second)
|
2020-08-22 18:15:21 +00:00
|
|
|
}
|
|
|
|
if config.Services[0].Alerts == nil {
|
|
|
|
t.Fatal("The service alerts shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if len(config.Services[0].Alerts) != 1 {
|
|
|
|
t.Fatal("There should've been 1 alert configured")
|
|
|
|
}
|
|
|
|
if !config.Services[0].Alerts[0].Enabled {
|
|
|
|
t.Error("The alert should've been enabled")
|
|
|
|
}
|
2020-09-17 00:22:33 +00:00
|
|
|
if config.Services[0].Alerts[0].FailureThreshold != 7 {
|
|
|
|
t.Errorf("The failure threshold of the alert should've been %d, but it was %d", 7, config.Services[0].Alerts[0].FailureThreshold)
|
|
|
|
}
|
|
|
|
if config.Services[0].Alerts[0].FailureThreshold != 7 {
|
|
|
|
t.Errorf("The success threshold of the alert should've been %d, but it was %d", 2, config.Services[0].Alerts[0].SuccessThreshold)
|
2020-08-22 18:15:21 +00:00
|
|
|
}
|
|
|
|
if config.Services[0].Alerts[0].Type != core.SlackAlert {
|
|
|
|
t.Errorf("The type of the alert should've been %s, but it was %s", core.SlackAlert, config.Services[0].Alerts[0].Type)
|
|
|
|
}
|
|
|
|
if config.Services[0].Alerts[0].Description != "Healthcheck failed 7 times in a row" {
|
|
|
|
t.Errorf("The type of the alert should've been %s, but it was %s", "Healthcheck failed 7 times in a row", config.Services[0].Alerts[0].Description)
|
|
|
|
}
|
|
|
|
}
|
2020-09-24 23:52:59 +00:00
|
|
|
|
|
|
|
func TestParseAndValidateConfigBytesWithInvalidPagerDutyAlertingConfig(t *testing.T) {
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(`
|
|
|
|
alerting:
|
|
|
|
pagerduty:
|
|
|
|
integration-key: "INVALID_KEY"
|
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
conditions:
|
|
|
|
- "[STATUS] == 200"
|
|
|
|
`))
|
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Alerting == nil {
|
|
|
|
t.Fatal("config.Alerting shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Alerting.PagerDuty == nil {
|
|
|
|
t.Fatal("PagerDuty alerting config shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Alerting.PagerDuty.IsValid() {
|
|
|
|
t.Fatal("PagerDuty alerting config should've been invalid")
|
|
|
|
}
|
|
|
|
}
|
2020-10-14 23:22:58 +00:00
|
|
|
|
|
|
|
func TestParseAndValidateConfigBytesWithInvalidSecurityConfig(t *testing.T) {
|
|
|
|
defer func() { recover() }()
|
|
|
|
_, _ = parseAndValidateConfigBytes([]byte(`
|
|
|
|
security:
|
|
|
|
basic:
|
|
|
|
username: "admin"
|
|
|
|
password-sha512: "invalid-sha512-hash"
|
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
conditions:
|
|
|
|
- "[STATUS] == 200"
|
|
|
|
`))
|
|
|
|
t.Error("Function should've panicked")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseAndValidateConfigBytesWithValidSecurityConfig(t *testing.T) {
|
|
|
|
const expectedUsername = "admin"
|
|
|
|
const expectedPasswordHash = "6b97ed68d14eb3f1aa959ce5d49c7dc612e1eb1dafd73b1e705847483fd6a6c809f2ceb4e8df6ff9984c6298ff0285cace6614bf8daa9f0070101b6c89899e22"
|
|
|
|
config, err := parseAndValidateConfigBytes([]byte(fmt.Sprintf(`
|
|
|
|
security:
|
|
|
|
basic:
|
|
|
|
username: "%s"
|
|
|
|
password-sha512: "%s"
|
|
|
|
services:
|
|
|
|
- name: twinnation
|
|
|
|
url: https://twinnation.org/actuator/health
|
|
|
|
conditions:
|
|
|
|
- "[STATUS] == 200"
|
|
|
|
`, expectedUsername, expectedPasswordHash)))
|
|
|
|
if err != nil {
|
|
|
|
t.Error("No error should've been returned")
|
|
|
|
}
|
|
|
|
if config == nil {
|
|
|
|
t.Fatal("Config shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Security == nil {
|
|
|
|
t.Fatal("config.Security shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if !config.Security.IsValid() {
|
|
|
|
t.Error("Security config should've been valid")
|
|
|
|
}
|
|
|
|
if config.Security.Basic == nil {
|
|
|
|
t.Fatal("config.Security.Basic shouldn't have been nil")
|
|
|
|
}
|
|
|
|
if config.Security.Basic.Username != expectedUsername {
|
|
|
|
t.Errorf("config.Security.Basic.Username should've been %s, but was %s", expectedUsername, config.Security.Basic.Username)
|
|
|
|
}
|
|
|
|
if config.Security.Basic.PasswordSha512Hash != expectedPasswordHash {
|
|
|
|
t.Errorf("config.Security.Basic.PasswordSha512Hash should've been %s, but was %s", expectedPasswordHash, config.Security.Basic.PasswordSha512Hash)
|
|
|
|
}
|
|
|
|
}
|