fix(alerting): Resolve issue with blank GoogleChat messages (#364)

* debug: Print GoogleChat request body

* chore: Update TwiN/whois to v1.1.0

* fix: Add missing client changes

* test: Improve DNS tests

* chore: Remove accidental change

* docs: Add note for future change to default behavior

* fix(alerting): Don't include URL in Google Chat alert if endpoint type isn't HTTP

Fixes #362
This commit is contained in:
TwiN 2022-11-22 20:12:26 -05:00 committed by GitHub
parent 4f569b7a0e
commit f8140e0d96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 15 deletions

View File

@ -79,6 +79,7 @@ func (alert Alert) GetDescription() string {
// IsEnabled returns whether an alert is enabled or not // IsEnabled returns whether an alert is enabled or not
func (alert Alert) IsEnabled() bool { func (alert Alert) IsEnabled() bool {
if alert.Enabled == nil { if alert.Enabled == nil {
// TODO: Default to true in v5.0.0 (unless default-alert.enabled is set to false)
return false return false
} }
return *alert.Enabled return *alert.Enabled

View File

@ -37,7 +37,6 @@ func (provider *AlertProvider) IsValid() bool {
if provider.ClientConfig == nil { if provider.ClientConfig == nil {
provider.ClientConfig = client.GetDefaultConfig() provider.ClientConfig = client.GetDefaultConfig()
} }
registeredGroups := make(map[string]bool) registeredGroups := make(map[string]bool)
if provider.Overrides != nil { if provider.Overrides != nil {
for _, override := range provider.Overrides { for _, override := range provider.Overrides {
@ -47,7 +46,6 @@ func (provider *AlertProvider) IsValid() bool {
registeredGroups[override.Group] = true registeredGroups[override.Group] = true
} }
} }
return len(provider.WebhookURL) > 0 return len(provider.WebhookURL) > 0
} }
@ -137,7 +135,7 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
if alertDescription := alert.GetDescription(); len(alertDescription) > 0 { if alertDescription := alert.GetDescription(); len(alertDescription) > 0 {
description = ":: " + alertDescription description = ":: " + alertDescription
} }
body, _ := json.Marshal(Body{ payload := Body{
Cards: []Cards{ Cards: []Cards{
{ {
Sections: []Sections{ Sections: []Sections{
@ -160,7 +158,17 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
Icon: "DESCRIPTION", Icon: "DESCRIPTION",
}, },
}, },
{ },
},
},
},
},
}
if endpoint.Type() == core.EndpointTypeHTTP {
// 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
payload.Cards[0].Sections[0].Widgets = append(payload.Cards[0].Sections[0].Widgets, Widgets{
Buttons: []Buttons{ Buttons: []Buttons{
{ {
TextButton: TextButton{ TextButton: TextButton{
@ -169,13 +177,9 @@ func (provider *AlertProvider) buildRequestBody(endpoint *core.Endpoint, alert *
}, },
}, },
}, },
},
},
},
},
},
},
}) })
}
body, _ := json.Marshal(payload)
return body return body
} }

View File

@ -141,6 +141,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
secondDescription := "description-2" secondDescription := "description-2"
scenarios := []struct { scenarios := []struct {
Name string Name string
Endpoint core.Endpoint
Provider AlertProvider Provider AlertProvider
Alert alert.Alert Alert alert.Alert
Resolved bool Resolved bool
@ -148,6 +149,7 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}{ }{
{ {
Name: "triggered", Name: "triggered",
Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{}, Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false, Resolved: false,
@ -155,16 +157,33 @@ func TestAlertProvider_buildRequestBody(t *testing.T) {
}, },
{ {
Name: "resolved", Name: "resolved",
Endpoint: core.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
Provider: AlertProvider{}, Provider: AlertProvider{},
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3}, Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: true, Resolved: true,
ExpectedBody: `{"cards":[{"sections":[{"widgets":[{"keyValue":{"topLabel":"endpoint-name","content":"\u003cfont color='#36A64F'\u003eAn alert has been resolved after passing successfully 5 time(s) in a row\u003c/font\u003e","contentMultiline":"true","bottomLabel":":: description-2","icon":"BOOKMARK"}},{"keyValue":{"topLabel":"Condition results","content":"✅ [CONNECTED] == true\u003cbr\u003e✅ [STATUS] == 200\u003cbr\u003e","contentMultiline":"true","icon":"DESCRIPTION"}},{"buttons":[{"textButton":{"text":"URL","onClick":{"openLink":{"url":"https://example.org"}}}}]}]}]}]}`, ExpectedBody: `{"cards":[{"sections":[{"widgets":[{"keyValue":{"topLabel":"endpoint-name","content":"\u003cfont color='#36A64F'\u003eAn alert has been resolved after passing successfully 5 time(s) in a row\u003c/font\u003e","contentMultiline":"true","bottomLabel":":: description-2","icon":"BOOKMARK"}},{"keyValue":{"topLabel":"Condition results","content":"✅ [CONNECTED] == true\u003cbr\u003e✅ [STATUS] == 200\u003cbr\u003e","contentMultiline":"true","icon":"DESCRIPTION"}},{"buttons":[{"textButton":{"text":"URL","onClick":{"openLink":{"url":"https://example.org"}}}}]}]}]}]}`,
}, },
{
Name: "icmp-should-not-include-url", // See https://github.com/TwiN/gatus/issues/362
Endpoint: core.Endpoint{Name: "endpoint-name", URL: "icmp://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: `{"cards":[{"sections":[{"widgets":[{"keyValue":{"topLabel":"endpoint-name","content":"\u003cfont color='#DD0000'\u003eAn alert has been triggered due to having failed 3 time(s) in a row\u003c/font\u003e","contentMultiline":"true","bottomLabel":":: description-1","icon":"BOOKMARK"}},{"keyValue":{"topLabel":"Condition results","content":"❌ [CONNECTED] == true\u003cbr\u003e❌ [STATUS] == 200\u003cbr\u003e","contentMultiline":"true","icon":"DESCRIPTION"}}]}]}]}`,
},
{
Name: "tcp-should-not-include-url", // See https://github.com/TwiN/gatus/issues/362
Endpoint: core.Endpoint{Name: "endpoint-name", URL: "tcp://example.org"},
Provider: AlertProvider{},
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
Resolved: false,
ExpectedBody: `{"cards":[{"sections":[{"widgets":[{"keyValue":{"topLabel":"endpoint-name","content":"\u003cfont color='#DD0000'\u003eAn alert has been triggered due to having failed 3 time(s) in a row\u003c/font\u003e","contentMultiline":"true","bottomLabel":":: description-1","icon":"BOOKMARK"}},{"keyValue":{"topLabel":"Condition results","content":"❌ [CONNECTED] == true\u003cbr\u003e❌ [STATUS] == 200\u003cbr\u003e","contentMultiline":"true","icon":"DESCRIPTION"}}]}]}]}`,
},
} }
for _, scenario := range scenarios { for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) { t.Run(scenario.Name, func(t *testing.T) {
body := scenario.Provider.buildRequestBody( body := scenario.Provider.buildRequestBody(
&core.Endpoint{Name: "endpoint-name", URL: "https://example.org"}, &scenario.Endpoint,
&scenario.Alert, &scenario.Alert,
&core.Result{ &core.Result{
ConditionResults: []*core.ConditionResult{ ConditionResults: []*core.ConditionResult{