diff --git a/README.md b/README.md
index c5b480270..0369d1527 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ For more details, see [Usage](#usage)
Have any feedback or want to share your good/bad experience with Gatus? Feel free to email me at [feedback@gatus.io](mailto:feedback@gatus.io)
## Table of Contents
+- [Table of Contents](#table-of-contents)
- [Why Gatus?](#why-gatus)
- [Features](#features)
- [Usage](#usage)
@@ -76,8 +77,8 @@ Have any feedback or want to share your good/bad experience with Gatus? Feel fre
- [Endpoint groups](#endpoint-groups)
- [Exposing Gatus on a custom port](#exposing-gatus-on-a-custom-port)
- [Badges](#badges)
- - [Uptime](#uptime)
- - [Response time](#response-time)
+ - [Uptime](#uptime)
+ - [Response time](#response-time)
- [API](#api)
- [High level design overview](#high-level-design-overview)
- [Sponsors](#sponsors)
@@ -436,17 +437,26 @@ endpoints:
**NOTE:** Some mail servers are painfully slow.
#### Configuring Google Chat alerts
-| Parameter | Description | Default |
-|:------------------------------------|:--------------------------------------------------------------------------------------------|:--------------|
-| `alerting.googlechat` | Configuration for alerts of type `googlechat` | `{}` |
-| `alerting.googlechat.webhook-url` | Google Chat Webhook URL | Required `""` |
-| `alerting.googlechat.client` | Client configuration.
See [Client configuration](#client-configuration). | `{}` |
-| `alerting.googlechat.default-alert` | Default alert configuration.
See [Setting a default alert](#setting-a-default-alert). | N/A |
+
+| Parameter | Description | Default |
+|:--------------------------------------------- |:------------------------------------------------------------------------------------------- |:------------- |
+| `alerting.googlechat` | Configuration for alerts of type `googlechat` | `{}` |
+| `alerting.googlechat.webhook-url` | Google Chat Webhook URL | Required `""` |
+| `alerting.googlechat.client` | Client configuration.
See [Client configuration](#client-configuration). | `{}` |
+| `alerting.googlechat.default-alert` | Default alert configuration.
See [Setting a default alert](#setting-a-default-alert). | N/A |
+| `alerting.googlechat.overrides` | List of overrides that may be prioritized over the default configuration | `[]` |
+| `alerting.googlechat.overrides[].group` | Endpoint group for which the configuration will be overridden by this configuration | `""` |
+| `alerting.googlechat.overrides[].webhook-url` | Teams Webhook URL | `""` |
```yaml
alerting:
googlechat:
webhook-url: "https://chat.googleapis.com/v1/spaces/*******/messages?key=**********&token=********"
+ # You can also add group-specific to keys, which will
+ # override the to key above for the specified groups
+ overrides:
+ - group: "core"
+ webhook-url: "https://chat.googleapis.com/v1/spaces/*******/messages?key=**********&token=********"
endpoints:
- name: website
@@ -461,6 +471,19 @@ endpoints:
enabled: true
description: "healthcheck failed"
send-on-resolved: true
+
+ - name: back-end
+ group: core
+ url: "https://example.org/"
+ interval: 5m
+ conditions:
+ - "[STATUS] == 200"
+ - "[CERTIFICATE_EXPIRATION] > 48h"
+ alerts:
+ - type: googlechat
+ enabled: true
+ description: "healthcheck failed"
+ send-on-resolved: true
```
#### Configuring Mattermost alerts
diff --git a/alerting/provider/googlechat/googlechat.go b/alerting/provider/googlechat/googlechat.go
index d6162ae42..405f41f40 100644
--- a/alerting/provider/googlechat/googlechat.go
+++ b/alerting/provider/googlechat/googlechat.go
@@ -20,6 +20,15 @@ type AlertProvider struct {
// DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type
DefaultAlert *alert.Alert `yaml:"default-alert,omitempty"`
+
+ // Overrides is a list of Override that may be prioritized over the default configuration
+ Overrides []Override `yaml:"overrides,omitempty"`
+}
+
+// Override is a case under which the default integration is overridden
+type Override struct {
+ Group string `yaml:"group"`
+ WebhookURL string `yaml:"webhook-url"`
}
// IsValid returns whether the provider's configuration is valid
@@ -27,13 +36,24 @@ func (provider *AlertProvider) IsValid() bool {
if provider.ClientConfig == nil {
provider.ClientConfig = client.GetDefaultConfig()
}
+
+ registeredGroups := make(map[string]bool)
+ if provider.Overrides != nil {
+ for _, override := range provider.Overrides {
+ if isAlreadyRegistered := registeredGroups[override.Group]; isAlreadyRegistered || override.Group == "" || len(override.WebhookURL) == 0 {
+ return false
+ }
+ registeredGroups[override.Group] = true
+ }
+ }
+
return len(provider.WebhookURL) > 0
}
// 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.WebhookURL, buffer)
+ request, err := http.NewRequest(http.MethodPost, provider.getWebhookURLForGroup(endpoint.Group), buffer)
if err != nil {
return err
}
@@ -118,6 +138,18 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
}`, endpoint.Name, endpoint.Group, message, description, results, endpoint.URL)
}
+// getWebhookURLForGroup returns the appropriate Webhook URL integration to for a given group
+func (provider *AlertProvider) getWebhookURLForGroup(group string) string {
+ if provider.Overrides != nil {
+ for _, override := range provider.Overrides {
+ if group == override.Group {
+ return override.WebhookURL
+ }
+ }
+ }
+ return provider.WebhookURL
+}
+
// GetDefaultAlert returns the provider's default alert configuration
func (provider AlertProvider) GetDefaultAlert() *alert.Alert {
return provider.DefaultAlert
diff --git a/alerting/provider/googlechat/googlechat_test.go b/alerting/provider/googlechat/googlechat_test.go
index 55126911c..543cee616 100644
--- a/alerting/provider/googlechat/googlechat_test.go
+++ b/alerting/provider/googlechat/googlechat_test.go
@@ -11,7 +11,7 @@ import (
"github.com/TwiN/gatus/v3/test"
)
-func TestAlertProvider_IsValid(t *testing.T) {
+func TestAlertDefaultProvider_IsValid(t *testing.T) {
invalidProvider := AlertProvider{WebhookURL: ""}
if invalidProvider.IsValid() {
t.Error("provider shouldn't have been valid")
@@ -22,6 +22,43 @@ func TestAlertProvider_IsValid(t *testing.T) {
}
}
+func TestAlertProvider_IsValidWithOverride(t *testing.T) {
+ providerWithInvalidOverrideGroup := AlertProvider{
+ Overrides: []Override{
+ {
+ WebhookURL: "http://example.com",
+ Group: "",
+ },
+ },
+ }
+ if providerWithInvalidOverrideGroup.IsValid() {
+ t.Error("provider Group shouldn't have been valid")
+ }
+ providerWithInvalidOverrideTo := AlertProvider{
+ Overrides: []Override{
+ {
+ WebhookURL: "",
+ Group: "group",
+ },
+ },
+ }
+ if providerWithInvalidOverrideTo.IsValid() {
+ t.Error("provider integration key shouldn't have been valid")
+ }
+ providerWithValidOverride := AlertProvider{
+ WebhookURL: "http://example.com",
+ Overrides: []Override{
+ {
+ WebhookURL: "http://example.com",
+ Group: "group",
+ },
+ },
+ }
+ if !providerWithValidOverride.IsValid() {
+ t.Error("provider should've been valid")
+ }
+}
+
func TestAlertProvider_Send(t *testing.T) {
defer client.InjectHTTPClient(nil)
firstDescription := "description-1"
@@ -158,3 +195,66 @@ func TestAlertProvider_GetDefaultAlert(t *testing.T) {
t.Error("expected default alert to be nil")
}
}
+
+func TestAlertProvider_getWebhookURLForGroup(t *testing.T) {
+ tests := []struct {
+ Name string
+ Provider AlertProvider
+ InputGroup string
+ ExpectedOutput string
+ }{
+ {
+ Name: "provider-no-override-specify-no-group-should-default",
+ Provider: AlertProvider{
+ WebhookURL: "http://example.com",
+ Overrides: nil,
+ },
+ InputGroup: "",
+ ExpectedOutput: "http://example.com",
+ },
+ {
+ Name: "provider-no-override-specify-group-should-default",
+ Provider: AlertProvider{
+ WebhookURL: "http://example.com",
+ Overrides: nil,
+ },
+ InputGroup: "group",
+ ExpectedOutput: "http://example.com",
+ },
+ {
+ Name: "provider-with-override-specify-no-group-should-default",
+ Provider: AlertProvider{
+ WebhookURL: "http://example.com",
+ Overrides: []Override{
+ {
+ Group: "group",
+ WebhookURL: "http://example01.com",
+ },
+ },
+ },
+ InputGroup: "",
+ ExpectedOutput: "http://example.com",
+ },
+ {
+ Name: "provider-with-override-specify-group-should-override",
+ Provider: AlertProvider{
+ WebhookURL: "http://example.com",
+ Overrides: []Override{
+ {
+ Group: "group",
+ WebhookURL: "http://example01.com",
+ },
+ },
+ },
+ InputGroup: "group",
+ ExpectedOutput: "http://example01.com",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.Name, func(t *testing.T) {
+ if got := tt.Provider.getWebhookURLForGroup(tt.InputGroup); got != tt.ExpectedOutput {
+ t.Errorf("AlertProvider.getToForGroup() = %v, want %v", got, tt.ExpectedOutput)
+ }
+ })
+ }
+}