feat: Set minimum interval for endpoints with [DOMAIN_EXPIRATION] to 5m
This commit is contained in:
parent
33ce0e99b5
commit
38054f57e5
@ -1356,8 +1356,8 @@ endpoints:
|
|||||||
|
|
||||||
**NOTE**: The usage of the `[DOMAIN_EXPIRATION]` placeholder requires Gatus to send a request to the official IANA WHOIS service [through a library](https://github.com/TwiN/whois)
|
**NOTE**: The usage of the `[DOMAIN_EXPIRATION]` placeholder requires Gatus to send a request to the official IANA WHOIS service [through a library](https://github.com/TwiN/whois)
|
||||||
and in some cases, a secondary request to a TLD-specific WHOIS server (e.g. `whois.nic.sh`).
|
and in some cases, a secondary request to a TLD-specific WHOIS server (e.g. `whois.nic.sh`).
|
||||||
You are also responsible for sending requests at a reasonable rate, as the WHOIS service may throttle your IP address if you send too many requests.
|
To prevent the WHOIS service from throttling your IP address if you send too many requests, Gatus will prevent you from
|
||||||
The duration taken by the WHOIS request(s) is excluded from the request's response time.
|
using the `[DOMAIN_EXPIRATION]` placeholder on an endpoint with an interval of less than `5m`.
|
||||||
|
|
||||||
|
|
||||||
### disable-monitoring-lock
|
### disable-monitoring-lock
|
||||||
|
@ -58,6 +58,12 @@ var (
|
|||||||
|
|
||||||
// ErrUnknownEndpointType is the error with which Gatus will panic if an endpoint has an unknown type
|
// ErrUnknownEndpointType is the error with which Gatus will panic if an endpoint has an unknown type
|
||||||
ErrUnknownEndpointType = errors.New("unknown endpoint type")
|
ErrUnknownEndpointType = errors.New("unknown endpoint type")
|
||||||
|
|
||||||
|
// ErrInvalidEndpointIntervalForDomainExpirationPlaceholder is the error with which Gatus will panic if an endpoint
|
||||||
|
// has both an interval smaller than 5 minutes and a condition with DomainExpirationPlaceholder.
|
||||||
|
// This is because the free whois service we are using should not be abused, especially considering the fact that
|
||||||
|
// the data takes a while to be updated.
|
||||||
|
ErrInvalidEndpointIntervalForDomainExpirationPlaceholder = errors.New("the minimum interval for an endpoint with a condition using the " + DomainExpirationPlaceholder + " placeholder is 300s (5m)")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Endpoint is the configuration of a monitored
|
// Endpoint is the configuration of a monitored
|
||||||
@ -191,6 +197,13 @@ func (endpoint *Endpoint) ValidateAndSetDefaults() error {
|
|||||||
if len(endpoint.Conditions) == 0 {
|
if len(endpoint.Conditions) == 0 {
|
||||||
return ErrEndpointWithNoCondition
|
return ErrEndpointWithNoCondition
|
||||||
}
|
}
|
||||||
|
if endpoint.Interval < 5*time.Minute {
|
||||||
|
for _, condition := range endpoint.Conditions {
|
||||||
|
if condition.hasDomainExpirationPlaceholder() {
|
||||||
|
return ErrInvalidEndpointIntervalForDomainExpirationPlaceholder
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if endpoint.DNS != nil {
|
if endpoint.DNS != nil {
|
||||||
return endpoint.DNS.validateAndSetDefault()
|
return endpoint.DNS.validateAndSetDefault()
|
||||||
}
|
}
|
||||||
|
@ -372,11 +372,10 @@ func TestEndpoint_ValidateAndSetDefaults(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEndpoint_ValidateAndSetDefaultsWithClientConfig(t *testing.T) {
|
func TestEndpoint_ValidateAndSetDefaultsWithClientConfig(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
|
||||||
endpoint := Endpoint{
|
endpoint := Endpoint{
|
||||||
Name: "website-health",
|
Name: "website-health",
|
||||||
URL: "https://twin.sh/health",
|
URL: "https://twin.sh/health",
|
||||||
Conditions: []Condition{condition},
|
Conditions: []Condition{Condition("[STATUS] == 200")},
|
||||||
ClientConfig: &client.Config{
|
ClientConfig: &client.Config{
|
||||||
Insecure: true,
|
Insecure: true,
|
||||||
IgnoreRedirect: true,
|
IgnoreRedirect: true,
|
||||||
@ -399,51 +398,10 @@ func TestEndpoint_ValidateAndSetDefaultsWithClientConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEndpoint_ValidateAndSetDefaultsWithNoName(t *testing.T) {
|
|
||||||
defer func() { recover() }()
|
|
||||||
condition := Condition("[STATUS] == 200")
|
|
||||||
endpoint := &Endpoint{
|
|
||||||
Name: "",
|
|
||||||
URL: "http://example.com",
|
|
||||||
Conditions: []Condition{condition},
|
|
||||||
}
|
|
||||||
err := endpoint.ValidateAndSetDefaults()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Should've returned an error because endpoint didn't have a name, which is a mandatory field")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndpoint_ValidateAndSetDefaultsWithNoUrl(t *testing.T) {
|
|
||||||
defer func() { recover() }()
|
|
||||||
condition := Condition("[STATUS] == 200")
|
|
||||||
endpoint := &Endpoint{
|
|
||||||
Name: "example",
|
|
||||||
URL: "",
|
|
||||||
Conditions: []Condition{condition},
|
|
||||||
}
|
|
||||||
err := endpoint.ValidateAndSetDefaults()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Should've returned an error because endpoint didn't have an url, which is a mandatory field")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndpoint_ValidateAndSetDefaultsWithNoConditions(t *testing.T) {
|
|
||||||
defer func() { recover() }()
|
|
||||||
endpoint := &Endpoint{
|
|
||||||
Name: "example",
|
|
||||||
URL: "http://example.com",
|
|
||||||
Conditions: nil,
|
|
||||||
}
|
|
||||||
err := endpoint.ValidateAndSetDefaults()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Should've returned an error because endpoint didn't have at least 1 condition")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndpoint_ValidateAndSetDefaultsWithDNS(t *testing.T) {
|
func TestEndpoint_ValidateAndSetDefaultsWithDNS(t *testing.T) {
|
||||||
endpoint := &Endpoint{
|
endpoint := &Endpoint{
|
||||||
Name: "dns-test",
|
Name: "dns-test",
|
||||||
URL: "http://example.com",
|
URL: "https://example.com",
|
||||||
DNS: &DNS{
|
DNS: &DNS{
|
||||||
QueryType: "A",
|
QueryType: "A",
|
||||||
QueryName: "example.com",
|
QueryName: "example.com",
|
||||||
@ -452,13 +410,70 @@ func TestEndpoint_ValidateAndSetDefaultsWithDNS(t *testing.T) {
|
|||||||
}
|
}
|
||||||
err := endpoint.ValidateAndSetDefaults()
|
err := endpoint.ValidateAndSetDefaults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
t.Error("did not expect an error, got", err)
|
||||||
}
|
}
|
||||||
if endpoint.DNS.QueryName != "example.com." {
|
if endpoint.DNS.QueryName != "example.com." {
|
||||||
t.Error("Endpoint.dns.query-name should be formatted with . suffix")
|
t.Error("Endpoint.dns.query-name should be formatted with . suffix")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEndpoint_ValidateAndSetDefaultsWithSimpleErrors(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
endpoint *Endpoint
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
endpoint: &Endpoint{
|
||||||
|
Name: "",
|
||||||
|
URL: "https://example.com",
|
||||||
|
Conditions: []Condition{Condition("[STATUS] == 200")},
|
||||||
|
},
|
||||||
|
expectedErr: ErrEndpointWithNoName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: &Endpoint{
|
||||||
|
Name: "endpoint-with-no-url",
|
||||||
|
URL: "",
|
||||||
|
Conditions: []Condition{Condition("[STATUS] == 200")},
|
||||||
|
},
|
||||||
|
expectedErr: ErrEndpointWithNoURL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: &Endpoint{
|
||||||
|
Name: "endpoint-with-no-conditions",
|
||||||
|
URL: "https://example.com",
|
||||||
|
Conditions: nil,
|
||||||
|
},
|
||||||
|
expectedErr: ErrEndpointWithNoCondition,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: &Endpoint{
|
||||||
|
Name: "domain-expiration-with-bad-interval",
|
||||||
|
URL: "https://example.com",
|
||||||
|
Interval: time.Minute,
|
||||||
|
Conditions: []Condition{Condition("[DOMAIN_EXPIRATION] > 720h")},
|
||||||
|
},
|
||||||
|
expectedErr: ErrInvalidEndpointIntervalForDomainExpirationPlaceholder,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint: &Endpoint{
|
||||||
|
Name: "domain-expiration-with-good-interval",
|
||||||
|
URL: "https://example.com",
|
||||||
|
Interval: 5 * time.Minute,
|
||||||
|
Conditions: []Condition{Condition("[DOMAIN_EXPIRATION] > 720h")},
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(scenario.endpoint.Name, func(t *testing.T) {
|
||||||
|
if err := scenario.endpoint.ValidateAndSetDefaults(); err != scenario.expectedErr {
|
||||||
|
t.Errorf("Expected error %v, got %v", scenario.expectedErr, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEndpoint_buildHTTPRequest(t *testing.T) {
|
func TestEndpoint_buildHTTPRequest(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
endpoint := Endpoint{
|
endpoint := Endpoint{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user