Skip to content

Commit

Permalink
chore(webhooks): add support for providing allowed response codes (#286)
Browse files Browse the repository at this point in the history
  • Loading branch information
shini4i authored May 1, 2024
1 parent 3cf9a3a commit b787e81
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 18 deletions.
11 changes: 6 additions & 5 deletions cmd/argo-watcher/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ type DatabaseConfig struct {
}

type WebhookConfig struct {
Enabled bool `env:"WEBHOOK_ENABLED" envDefault:"false" json:"enabled"`
Url string `env:"WEBHOOK_URL" json:"url,omitempty"`
Format string `env:"WEBHOOK_FORMAT" json:"format,omitempty"`
AuthorizationHeader string `env:"WEBHOOK_AUTHORIZATION_HEADER_NAME" envDefault:"Authorization" json:"authorization_header,omitempty"`
Token string `env:"WEBHOOK_AUTHORIZATION_HEADER_VALUE" envDefault:"" json:"-"`
Enabled bool `env:"WEBHOOK_ENABLED" envDefault:"false" json:"enabled"`
Url string `env:"WEBHOOK_URL" json:"url,omitempty"`
Format string `env:"WEBHOOK_FORMAT" json:"format,omitempty"`
AuthorizationHeader string `env:"WEBHOOK_AUTHORIZATION_HEADER_NAME" envDefault:"Authorization" json:"authorization_header,omitempty"`
Token string `env:"WEBHOOK_AUTHORIZATION_HEADER_VALUE" envDefault:"" json:"-"`
AllowedResponseCodes []int `env:"WEBHOOK_ALLOWED_RESPONSE_CODES" envDefault:"200" json:"allowed_response_codes,omitempty"`
}

type ServerConfig struct {
Expand Down
4 changes: 3 additions & 1 deletion cmd/argo-watcher/notifications/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"text/template"

"github.com/shini4i/argo-watcher/internal/helpers"

"github.com/rs/zerolog/log"

"github.com/shini4i/argo-watcher/cmd/argo-watcher/config"
Expand Down Expand Up @@ -62,7 +64,7 @@ func (service *WebhookService) SendWebhook(task models.Task) error {
}
}(resp.Body)

if resp.StatusCode != http.StatusOK {
if !helpers.Contains(service.config.AllowedResponseCodes, resp.StatusCode) {
return fmt.Errorf("received non-OK status code: %v", resp.StatusCode)
}

Expand Down
31 changes: 25 additions & 6 deletions cmd/argo-watcher/notifications/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,43 @@ func TestSendWebhook(t *testing.T) {
defer testServer.Close()

webhookConfig := config.WebhookConfig{
Url: testServer.URL,
Format: `{"id": "{{.Id}}","app": "{{.App}}","status": "{{.Status}}"}`,
AuthorizationHeader: "Authorization",
Token: expectedAuthToken,
Url: testServer.URL,
Format: `{"id": "{{.Id}}","app": "{{.App}}","status": "{{.Status}}"}`,
AuthorizationHeader: "Authorization",
Token: expectedAuthToken,
AllowedResponseCodes: []int{200},
}

service := NewWebhookService(&webhookConfig)
err := service.SendWebhook(mockTask)
assert.NoError(t, err)
})

t.Run("Test webhook payload with wrong response code", func(t *testing.T) {
testServer := setupTestServer(t)
defer testServer.Close()

webhookConfig := config.WebhookConfig{
Url: testServer.URL,
Format: `{"id": "{{.Id}}","app": "{{.App}}","status": "{{.Status}}"}`,
AuthorizationHeader: "Authorization",
Token: expectedAuthToken,
AllowedResponseCodes: []int{202, 204},
}

service := NewWebhookService(&webhookConfig)
err := service.SendWebhook(mockTask)
assert.Error(t, err)
})

t.Run("Test error response", func(t *testing.T) {
testServer := setupErrorTestServer()
defer testServer.Close()

webhookConfig := config.WebhookConfig{
Url: testServer.URL,
Format: `{"id": "{{.Id}}","app": "{{.App}}","status": "{{.Status}}"}`,
Url: testServer.URL,
Format: `{"id": "{{.Id}}","app": "{{.App}}","status": "{{.Status}}"}`,
AllowedResponseCodes: []int{200},
}

service := NewWebhookService(&webhookConfig)
Expand Down
1 change: 1 addition & 0 deletions docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The following configuration options are available:
| `WEBHOOK_FORMAT` | A format string to send the WebHook | | `{"app": "{{.App}}","status": "{{.Status}}"}` |
| `WEBHOOK_AUTHORIZATION_HEADER_NAME` | The name of the authorization header | Authorization | |
| `WEBHOOK_AUTHORIZATION_HEADER_VALUE` | The value of the authorization header | | Bearer token |
| `WEBHOOK_ALLOWED_RESPONSE_CODES` | A list of allowed response codes | 200 | 200,201,202 |

#### Available template variables

Expand Down
11 changes: 5 additions & 6 deletions internal/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import (
"crypto/sha256"
)

// Contains is a simple utility function that checks if a given string (s) exists in a slice of strings (slice).
// It iterates through the elements in the slice and returns true if it finds a match,
// indicating that the string exists in the slice; otherwise, it returns false, indicating that the string is not present.
func Contains(slice []string, s string) bool {
for _, item := range slice {
if item == s {
// Contains is a utility function that checks if a given item exists in a slice.
// It uses Go's generics to handle different types (string, int, etc.).
func Contains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
Expand Down

0 comments on commit b787e81

Please sign in to comment.