Skip to content

Commit

Permalink
feat: webhook payloads templates on honeycombio_webhook_recipient (#580)
Browse files Browse the repository at this point in the history
## Short description of the changes

Expands the honeycombio_webhook_recipient resource to be aware of custom
webhook templates. Follow-up PRs will include template variables and
custom headers.

---------

Co-authored-by: Jason Harley <[email protected]>
  • Loading branch information
brookesargent and jharley authored Nov 21, 2024
1 parent 6cbc7b6 commit 6aa970b
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 18 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Any new additions should be built with the Plugin Framework.
* The Plugin SDK-based code is contained in the `honeycombio/` directory in the root of the repository.
* The Plugin Framework-based code is contained in the `internal/provider` directory.

Any PRs reimplmenting Plugin SDKv2 resources or datasources in the Plugin Framework with be enthusiastically accepted. 🙏
Any PRs reimplementing Plugin SDKv2 resources or datasources in the Plugin Framework will be enthusiastically accepted. 🙏

### Preview document changes

Expand Down
16 changes: 16 additions & 0 deletions client/recipient.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,28 @@ type RecipientDetails struct {
WebhookURL string `json:"webhook_url,omitempty"`
// webhook only
WebhookSecret string `json:"webhook_secret,omitempty"`
// custom webhook
WebhookPayloads *WebhookPayloads `json:"webhook_payloads,omitempty"`
}

type NotificationRecipientDetails struct {
PDSeverity PagerDutySeverity `json:"pagerduty_severity,omitempty"`
}

type WebhookPayloads struct {
PayloadTemplates PayloadTemplates `json:"payload_templates"`
}

type PayloadTemplates struct {
Trigger *PayloadTemplate `json:"trigger,omitempty"`
ExhaustionTime *PayloadTemplate `json:"exhaustion_time,omitempty"`
BudgetRate *PayloadTemplate `json:"budget_rate,omitempty"`
}

type PayloadTemplate struct {
Body string `json:"body"`
}

// RecipientType holds all the possible recipient types.
type RecipientType string

Expand Down
51 changes: 51 additions & 0 deletions client/recipient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,57 @@ func TestRecipientsEmail(t *testing.T) {
})
}

func TestRecipientsCustomWebhook(t *testing.T) {
t.Parallel()

ctx := context.Background()
c := newTestClient(t)

body := `{"hello": "world"}`

testCases := []struct {
rcpt client.Recipient
expectErr bool
}{
{
rcpt: client.Recipient{
Type: client.RecipientTypeWebhook,
Details: client.RecipientDetails{
WebhookName: test.RandomStringWithPrefix("test.", 10),
WebhookURL: test.RandomURL(),
WebhookSecret: "secret",
WebhookPayloads: &client.WebhookPayloads{
PayloadTemplates: client.PayloadTemplates{Trigger: &client.PayloadTemplate{Body: body}}},
},
},
},
}

for _, tc := range testCases {
tr := tc.rcpt
t.Run(tr.Type.String(), func(t *testing.T) {
r, err := c.Recipients.Create(ctx, &tr)
t.Cleanup(func() {
_ = c.Recipients.Delete(ctx, r.ID)
})

if tc.expectErr {
require.Error(t, err, "expected error creating %s recipient", tr.Type)
return
}
require.NoError(t, err, "failed to create %s recipient", tr.Type)
r, err = c.Recipients.Get(ctx, r.ID)
require.NoError(t, err)

assert.Equal(t, tr.Type, r.Type)
assert.Equal(t, tr.Details.WebhookName, r.Details.WebhookName)
assert.Equal(t, tr.Details.WebhookURL, r.Details.WebhookURL)
assert.Equal(t, tr.Details.WebhookSecret, r.Details.WebhookSecret)
assert.Equal(t, tr.Details.WebhookPayloads, r.Details.WebhookPayloads)
})
}
}

func TestRecipientsWebhooksandMSTeams(t *testing.T) {
t.Parallel()

Expand Down
34 changes: 33 additions & 1 deletion docs/resources/webhook_recipient.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`honeycombio_webhook_recipient` allows you to define and manage a Webhook recipient that can be used by Triggers or BurnAlerts notifications.

## Example Usage
## Standard Webhook Example

```hcl
resource "honeycombio_webhook_recipient" "prod" {
Expand All @@ -12,13 +12,45 @@ resource "honeycombio_webhook_recipient" "prod" {
}
```

## Custom Webhook Example

```hcl
resource "honeycombio_webhook_recipient" "prod" {
name = "Production Alerts"
secret = "a63dab148496ecbe04a1a802ca9b95b8"
url = "https://my.url.corp.net"
template {
type = "trigger"
body = <<EOT
{
"name": " {{ .Name }}",
"id": " {{ .ID }}",
"description": " {{ .Description }}",
"threshold": {
"op": "{{ .Operator }}",
"value": "{{ .Threshold }}"
},
}
EOT
}
}
```

## Argument Reference

The following arguments are supported:

* `name` - (Required) The name of the Webhook Integration to create.
* `secret` - (Optional) The secret to include when sending the notification to the webhook.
* `url` - (Required) The URL of the endpoint to send the notification to.
* `template` - (Optional) Zero or more configuration blocks (described below) to customize the webhook payload if desired.

When configuring custom webhook payloads, use the `template` block, which accepts the following arguments:

* `type` - (Required) The template type, allowed types are `trigger`, `exhaustion_time`, and `budget_rate`. Only one template block of each type is allowed on a single recipient.
* `body` - (Required) A JSON formatted string to represent the webhook payload.


## Attribute Reference

Expand Down
20 changes: 16 additions & 4 deletions internal/models/recipients.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package models

import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
)

type WebhookRecipientModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Secret types.String `tfsdk:"secret"`
URL types.String `tfsdk:"url"`
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Secret types.String `tfsdk:"secret"`
URL types.String `tfsdk:"url"`
Templates types.Set `tfsdk:"template"` // WebhookTemplateModel
}

type WebhookTemplateModel struct {
Type types.String `tfsdk:"type"`
Body types.String `tfsdk:"body"`
}

var WebhookTemplateAttrType = map[string]attr.Type{
"type": types.StringType,
"body": types.StringType,
}
Loading

0 comments on commit 6aa970b

Please sign in to comment.