Close #31: Support insecure parameter for custom alerting provider

This commit is contained in:
TwinProduction 2020-11-13 15:01:21 -05:00
parent 3773f952a8
commit 79c60d834e
4 changed files with 95 additions and 11 deletions

View File

@ -95,10 +95,10 @@ Note that you can also add environment variables in the configuration file (i.e.
| `services` | List of services to monitor | Required `[]` | | `services` | List of services to monitor | Required `[]` |
| `services[].name` | Name of the service. Can be anything. | Required `""` | | `services[].name` | Name of the service. Can be anything. | Required `""` |
| `services[].url` | URL to send the request to | Required `""` | | `services[].url` | URL to send the request to | Required `""` |
| `services[].conditions` | Conditions used to determine the health of the service | `[]` |
| `services[].insecure` | Whether to skip verifying the server's certificate chain and host name | `false` |
| `services[].interval` | Duration to wait between every status check | `60s` |
| `services[].method` | Request method | `GET` | | `services[].method` | Request method | `GET` |
| `services[].insecure` | Whether to skip verifying the server's certificate chain and host name | `false` |
| `services[].conditions` | Conditions used to determine the health of the service | `[]` |
| `services[].interval` | Duration to wait between every status check | `60s` |
| `services[].graphql` | Whether to wrap the body in a query param (`{"query":"$body"}`) | `false` | | `services[].graphql` | Whether to wrap the body in a query param (`{"query":"$body"}`) | `false` |
| `services[].body` | Request body | `""` | | `services[].body` | Request body | `""` |
| `services[].headers` | Request headers | `{}` | | `services[].headers` | Request headers | `{}` |
@ -120,6 +120,8 @@ Note that you can also add environment variables in the configuration file (i.e.
| `alerting.twilio.to` | Number to send twilio alerts to | Required `""` | | `alerting.twilio.to` | Number to send twilio alerts to | Required `""` |
| `alerting.custom` | Configuration for custom actions on failure or alerts | `{}` | | `alerting.custom` | Configuration for custom actions on failure or alerts | `{}` |
| `alerting.custom.url` | Custom alerting request url | Required `""` | | `alerting.custom.url` | Custom alerting request url | Required `""` |
| `alerting.custom.method` | Request method | `GET` |
| `alerting.custom.insecure` | Whether to skip verifying the server's certificate chain and host name | `false` |
| `alerting.custom.body` | Custom alerting request body. | `""` | | `alerting.custom.body` | Custom alerting request body. | `""` |
| `alerting.custom.headers` | Custom alerting request headers | `{}` | | `alerting.custom.headers` | Custom alerting request headers | `{}` |
| `security` | Security configuration | `{}` | | `security` | Security configuration | `{}` |

View File

@ -3,20 +3,22 @@ package custom
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/TwinProduction/gatus/client"
"github.com/TwinProduction/gatus/core"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
"github.com/TwinProduction/gatus/client"
"github.com/TwinProduction/gatus/core"
) )
// AlertProvider is the configuration necessary for sending an alert using a custom HTTP request // AlertProvider is the configuration necessary for sending an alert using a custom HTTP request
// Technically, all alert providers should be reachable using the custom alert provider // Technically, all alert providers should be reachable using the custom alert provider
type AlertProvider struct { type AlertProvider struct {
URL string `yaml:"url"` URL string `yaml:"url"`
Method string `yaml:"method,omitempty"` Method string `yaml:"method,omitempty"`
Body string `yaml:"body,omitempty"` Insecure bool `yaml:"insecure,omitempty"`
Headers map[string]string `yaml:"headers,omitempty"` Body string `yaml:"body,omitempty"`
Headers map[string]string `yaml:"headers,omitempty"`
} }
// IsValid returns whether the provider's configuration is valid // IsValid returns whether the provider's configuration is valid
@ -73,7 +75,7 @@ func (provider *AlertProvider) buildRequest(serviceName, alertDescription string
// Send a request to the alert provider and return the body // Send a request to the alert provider and return the body
func (provider *AlertProvider) Send(serviceName, alertDescription string, resolved bool) ([]byte, error) { func (provider *AlertProvider) Send(serviceName, alertDescription string, resolved bool) ([]byte, error) {
request := provider.buildRequest(serviceName, alertDescription, resolved) request := provider.buildRequest(serviceName, alertDescription, resolved)
response, err := client.GetHTTPClient(false).Do(request) response, err := client.GetHTTPClient(provider.Insecure).Do(request)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -265,6 +265,85 @@ services:
} }
} }
func TestParseAndValidateConfigBytesWithCustomAlertingConfig(t *testing.T) {
config, err := parseAndValidateConfigBytes([]byte(`
alerting:
custom:
url: "https://example.com"
body: |
{
"text": "[ALERT_TRIGGERED_OR_RESOLVED]: [SERVICE_NAME] - [ALERT_DESCRIPTION]"
}
services:
- name: twinnation
url: https://twinnation.org/actuator/health
alerts:
- type: custom
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.Custom == nil {
t.Fatal("PagerDuty alerting config shouldn't have been nil")
}
if !config.Alerting.Custom.IsValid() {
t.Fatal("Custom alerting config should've been valid")
}
if config.Alerting.Custom.Insecure {
t.Fatal("config.Alerting.Custom.Insecure shouldn't have been true")
}
}
func TestParseAndValidateConfigBytesWithCustomAlertingConfigThatHasInsecureSetToTrue(t *testing.T) {
config, err := parseAndValidateConfigBytes([]byte(`
alerting:
custom:
url: "https://example.com"
method: "POST"
insecure: true
body: |
{
"text": "[ALERT_TRIGGERED_OR_RESOLVED]: [SERVICE_NAME] - [ALERT_DESCRIPTION]"
}
services:
- name: twinnation
url: https://twinnation.org/actuator/health
alerts:
- type: custom
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.Custom == nil {
t.Fatal("PagerDuty alerting config shouldn't have been nil")
}
if !config.Alerting.Custom.IsValid() {
t.Error("Custom alerting config should've been valid")
}
if config.Alerting.Custom.Method != "POST" {
t.Error("config.Alerting.Custom.Method should've been POST")
}
if !config.Alerting.Custom.Insecure {
t.Error("config.Alerting.Custom.Insecure shouldn't have been true")
}
}
func TestParseAndValidateConfigBytesWithInvalidSecurityConfig(t *testing.T) { func TestParseAndValidateConfigBytesWithInvalidSecurityConfig(t *testing.T) {
defer func() { recover() }() defer func() { recover() }()
_, _ = parseAndValidateConfigBytes([]byte(` _, _ = parseAndValidateConfigBytes([]byte(`

View File

@ -2,9 +2,10 @@ package watchdog
import ( import (
"encoding/json" "encoding/json"
"log"
"github.com/TwinProduction/gatus/config" "github.com/TwinProduction/gatus/config"
"github.com/TwinProduction/gatus/core" "github.com/TwinProduction/gatus/core"
"log"
) )
// HandleAlerting takes care of alerts to resolve and alerts to trigger based on result success or failure // HandleAlerting takes care of alerts to resolve and alerts to trigger based on result success or failure