Skip to content

Commit

Permalink
feat: add support for burn alert description (#563)
Browse files Browse the repository at this point in the history
Adds the ability to set and update the description on a burn alert.

---------

Co-authored-by: Krista LaFentres <lafentres@users.noreply.github.com>
Co-authored-by: Jason Harley <jason@honeycomb.io>
  • Loading branch information
3 people authored Nov 5, 2024
1 parent b3d290a commit c429944
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 15 deletions.
1 change: 1 addition & 0 deletions client/burn_alert.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type BurnAlert struct {
ExhaustionMinutes *int `json:"exhaustion_minutes,omitempty"`
BudgetRateWindowMinutes *int `json:"budget_rate_window_minutes,omitempty"`
BudgetRateDecreaseThresholdPerMillion *int `json:"budget_rate_decrease_threshold_per_million,omitempty"`
Description string `json:"description,omitempty"`
SLO SLORef `json:"slo"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
Expand Down
8 changes: 8 additions & 0 deletions client/burn_alert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func TestBurnAlerts(t *testing.T) {
var defaultBurnAlert *client.BurnAlert
exhaustionMinutes24Hours := 24 * 60
defaultBurnAlertCreateRequest := client.BurnAlert{
Description: "default burn alert",
ExhaustionMinutes: &exhaustionMinutes24Hours,
SLO: client.SLORef{ID: slo.ID},
Recipients: []client.NotificationRecipient{
Expand All @@ -67,6 +68,7 @@ func TestBurnAlerts(t *testing.T) {
exhaustionMinutes1Hour := 60
defaultBurnAlertUpdateRequest := client.BurnAlert{
ExhaustionMinutes: &exhaustionMinutes1Hour,
Description: "updated default burn alert",
SLO: client.SLORef{ID: slo.ID},
Recipients: []client.NotificationRecipient{
{
Expand All @@ -80,6 +82,7 @@ func TestBurnAlerts(t *testing.T) {
exhaustionMinutes0Minutes := 0
exhaustionTimeBurnAlertCreateRequest := client.BurnAlert{
AlertType: client.BurnAlertAlertTypeExhaustionTime,
Description: "exhaustion time burn alert",
ExhaustionMinutes: &exhaustionMinutes0Minutes,
SLO: client.SLORef{ID: slo.ID},
Recipients: []client.NotificationRecipient{
Expand All @@ -92,6 +95,7 @@ func TestBurnAlerts(t *testing.T) {
exhaustionMinutes4Hours := 4 * 60
exhaustionTimeBurnAlertUpdateRequest := client.BurnAlert{
AlertType: client.BurnAlertAlertTypeExhaustionTime,
Description: "updated exhaustion time burn alert",
ExhaustionMinutes: &exhaustionMinutes4Hours,
SLO: client.SLORef{ID: slo.ID},
Recipients: []client.NotificationRecipient{
Expand All @@ -107,6 +111,7 @@ func TestBurnAlerts(t *testing.T) {
budgetRateDecreaseThresholdPerMillion1Percent := 10000
budgetRateBurnAlertCreateRequest := client.BurnAlert{
AlertType: client.BurnAlertAlertTypeBudgetRate,
Description: "budget rate burn alert",
BudgetRateWindowMinutes: &budgetRateWindowMinutes1Hour,
BudgetRateDecreaseThresholdPerMillion: &budgetRateDecreaseThresholdPerMillion1Percent,
SLO: client.SLORef{ID: slo.ID},
Expand All @@ -121,6 +126,7 @@ func TestBurnAlerts(t *testing.T) {
budgetRateDecreaseThresholdPerMillion5Percent := 10000
budgetRateBurnAlertUpdateRequest := client.BurnAlert{
AlertType: client.BurnAlertAlertTypeBudgetRate,
Description: "updated budget rate burn alert",
BudgetRateWindowMinutes: &budgetRateWindowMinutes2Hours,
BudgetRateDecreaseThresholdPerMillion: &budgetRateDecreaseThresholdPerMillion5Percent,
SLO: client.SLORef{ID: slo.ID},
Expand All @@ -134,6 +140,7 @@ func TestBurnAlerts(t *testing.T) {

testCases := map[string]struct {
alertType client.BurnAlertAlertType
Description string
createRequest client.BurnAlert
updateRequest client.BurnAlert
burnAlert *client.BurnAlert
Expand Down Expand Up @@ -170,6 +177,7 @@ func TestBurnAlerts(t *testing.T) {
assert.NotNil(t, burnAlert.CreatedAt, "created at is empty")
assert.NotNil(t, burnAlert.UpdatedAt, "updated at is empty")
assert.Equal(t, testCase.alertType, burnAlert.AlertType)
assert.Equal(t, testCase.createRequest.Description, burnAlert.Description)

// copy dynamic fields before asserting equality
data.AlertType = burnAlert.AlertType
Expand Down
4 changes: 4 additions & 0 deletions docs/resources/burn_alert.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ variable "slo_id" {
resource "honeycombio_burn_alert" "example_alert" {
alert_type = "exhaustion_time"
exhaustion_minutes = 480
description = "Exhaustion burn alert description"
dataset = var.dataset
slo_id = var.slo_id
Expand Down Expand Up @@ -51,6 +52,7 @@ resource "honeycombio_burn_alert" "example_alert" {
alert_type = "budget_rate"
budget_rate_window_minutes = 480
budget_rate_decrease_percent = 1
description = "my example description"
dataset = var.dataset
slo_id = var.slo_id
Expand Down Expand Up @@ -84,6 +86,7 @@ data "honeycombio_recipient" "pd_prod" {
resource "honeycombio_burn_alert" "example_alert" {
exhaustion_minutes = 60
description = "Burn alert description"
dataset = var.dataset
slo_id = var.slo_id
Expand All @@ -103,6 +106,7 @@ resource "honeycombio_burn_alert" "example_alert" {
The following arguments are supported:
* `slo_id` - (Required) ID of the SLO this burn alert is associated with.
* `dataset` - (Required) The dataset this burn alert is associated with.
* `description` - (Optional) A description for this Burn Alert.
* `alert_type` - (Optional) Type of the burn alert. Valid values are `exhaustion_time` and `budget_rate`.
Defaults to `exhaustion_time`.
* `budget_rate_window_minutes` - (Optional) The time period, in minutes, over which a budget rate will be calculated.
Expand Down
1 change: 1 addition & 0 deletions internal/models/burn_alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type BurnAlertResourceModel struct {
AlertType types.String `tfsdk:"alert_type"`
BudgetRateWindowMinutes types.Int64 `tfsdk:"budget_rate_window_minutes"`
BudgetRateDecreasePercent types.Float64 `tfsdk:"budget_rate_decrease_percent"`
Description types.String `tfsdk:"description"`
Dataset types.String `tfsdk:"dataset"`
SLOID types.String `tfsdk:"slo_id"`
ExhaustionMinutes types.Int64 `tfsdk:"exhaustion_minutes"`
Expand Down
28 changes: 21 additions & 7 deletions internal/provider/burn_alert_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ func (*burnAlertResource) Schema(_ context.Context, _ resource.SchemaRequest, re
stringplanmodifier.RequiresReplace(),
},
},
"description": schema.StringAttribute{
Description: "A description for this Burn Alert.",
Computed: true,
Optional: true,
Default: stringdefault.StaticString(""),
Validators: []validator.String{
stringvalidator.LengthAtMost(1023),
},
},
"exhaustion_minutes": schema.Int64Attribute{
Optional: true,
Description: "The amount of time, in minutes, remaining before the SLO's error budget will be exhausted and the alert will fire.",
Expand Down Expand Up @@ -235,9 +244,10 @@ func (r *burnAlertResource) Create(ctx context.Context, req resource.CreateReque

// Get attributes from config and construct the create request
createRequest := &client.BurnAlert{
AlertType: client.BurnAlertAlertType(plan.AlertType.ValueString()),
Recipients: expandNotificationRecipients(ctx, plan.Recipients, &resp.Diagnostics),
SLO: client.SLORef{ID: plan.SLOID.ValueString()},
AlertType: client.BurnAlertAlertType(plan.AlertType.ValueString()),
Recipients: expandNotificationRecipients(ctx, plan.Recipients, &resp.Diagnostics),
SLO: client.SLORef{ID: plan.SLOID.ValueString()},
Description: plan.Description.ValueString(),
}

// Process any attributes that could be nil and add them to the create request
Expand All @@ -264,6 +274,7 @@ func (r *burnAlertResource) Create(ctx context.Context, req resource.CreateReque
state.ID = types.StringValue(burnAlert.ID)
state.AlertType = types.StringValue(string(burnAlert.AlertType))
state.Dataset = plan.Dataset
state.Description = types.StringValue(burnAlert.Description)
// we created them as authored so to avoid matching type-target or ID we can just use the same value
state.Recipients = config.Recipients
state.SLOID = types.StringValue(burnAlert.SLO.ID)
Expand Down Expand Up @@ -322,6 +333,7 @@ func (r *burnAlertResource) Read(ctx context.Context, req resource.ReadRequest,
state.AlertType = types.StringValue(string(burnAlert.AlertType))
state.SLOID = types.StringValue(burnAlert.SLO.ID)
state.Recipients = reconcileReadNotificationRecipientState(ctx, burnAlert.Recipients, state.Recipients, &resp.Diagnostics)
state.Description = types.StringValue(burnAlert.Description)

// Process any attributes that could be nil and add them to the state values
if burnAlert.ExhaustionMinutes != nil {
Expand Down Expand Up @@ -351,10 +363,11 @@ func (r *burnAlertResource) Update(ctx context.Context, req resource.UpdateReque

// Get attributes from config and construct the update request
updateRequest := &client.BurnAlert{
ID: plan.ID.ValueString(),
AlertType: client.BurnAlertAlertType(plan.AlertType.ValueString()),
Recipients: expandNotificationRecipients(ctx, plan.Recipients, &resp.Diagnostics),
SLO: client.SLORef{ID: plan.SLOID.ValueString()},
ID: plan.ID.ValueString(),
AlertType: client.BurnAlertAlertType(plan.AlertType.ValueString()),
Recipients: expandNotificationRecipients(ctx, plan.Recipients, &resp.Diagnostics),
SLO: client.SLORef{ID: plan.SLOID.ValueString()},
Description: plan.Description.ValueString(),
}

// Process any attributes that could be nil and add them to the update request
Expand Down Expand Up @@ -390,6 +403,7 @@ func (r *burnAlertResource) Update(ctx context.Context, req resource.UpdateReque
// we created them as authored so to avoid matching type-target or ID we can just use the same value
state.Recipients = config.Recipients
state.SLOID = types.StringValue(burnAlert.SLO.ID)
state.Description = types.StringValue(burnAlert.Description)

// Process any attributes that could be nil and add them to the state values
if burnAlert.ExhaustionMinutes != nil {
Expand Down
49 changes: 41 additions & 8 deletions internal/provider/burn_alert_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"github.com/honeycombio/terraform-provider-honeycombio/client"
)

const testBADescription = "burn alert description"

func TestAcc_BurnAlertResource_defaultBasic(t *testing.T) {
dataset, sloID := burnAlertAccTestSetup(t)
burnAlert := &client.BurnAlert{}
Expand Down Expand Up @@ -213,7 +215,7 @@ func TestAcc_BurnAlertResourceUpgradeFromVersion015(t *testing.T) {
dataset, sloID := burnAlertAccTestSetup(t)
burnAlert := &client.BurnAlert{}

config := testAccConfigBurnAlertDefault_basic(60, dataset, sloID, "info")
config := testAccConfigBurnAlert_withoutDescription(60, dataset, sloID, "info")

resource.Test(t, resource.TestCase{
Steps: []resource.TestStep{
Expand Down Expand Up @@ -491,11 +493,13 @@ func testAccEnsureSuccessExhaustionTimeAlert(t *testing.T, burnAlert *client.Bur

// Check that the burn alert has the correct values in state
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "slo_id", sloID),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "description", testBADescription),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "alert_type", "exhaustion_time"),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "exhaustion_minutes", fmt.Sprintf("%d", exhaustionMinutes)),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "recipient.#", "1"),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "recipient.0.notification_details.#", "1"),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "recipient.0.notification_details.0.pagerduty_severity", pagerdutySeverity),

// Budget rate attributes should not be set
resource.TestCheckNoResourceAttr("honeycombio_burn_alert.test", "budget_rate_window_minutes"),
resource.TestCheckNoResourceAttr("honeycombio_burn_alert.test", "budget_rate_decrease_percent"),
Expand All @@ -513,6 +517,7 @@ func testAccEnsureSuccessBudgetRateAlert(t *testing.T, burnAlert *client.BurnAle

// Check that the burn alert has the correct values in state
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "slo_id", sloID),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "description", testBADescription),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "alert_type", "budget_rate"),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "budget_rate_window_minutes", fmt.Sprintf("%d", budgetRateWindowMinutes)),
resource.TestCheckResourceAttr("honeycombio_burn_alert.test", "budget_rate_decrease_percent", helper.FloatToPercentString(budgetRateDecreasePercent)),
Expand Down Expand Up @@ -650,7 +655,7 @@ func burnAlertAccTestSetup(t *testing.T) (string, string) {
return dataset, slo.ID
}

func testAccConfigBurnAlertDefault_basic(exhaustionMinutes int, dataset, sloID, pdseverity string) string {
func testAccConfigBurnAlert_withoutDescription(exhaustionMinutes int, dataset, sloID, pdseverity string) string {
return fmt.Sprintf(`
resource "honeycombio_pagerduty_recipient" "test" {
integration_key = "08b9d4cacd68933151a1ef1028b67da2"
Expand All @@ -662,7 +667,6 @@ resource "honeycombio_burn_alert" "test" {
dataset = "%[2]s"
slo_id = "%[3]s"
recipient {
id = honeycombio_pagerduty_recipient.test.id
Expand All @@ -673,6 +677,30 @@ resource "honeycombio_burn_alert" "test" {
}`, exhaustionMinutes, dataset, sloID, pdseverity)
}

func testAccConfigBurnAlertDefault_basic(exhaustionMinutes int, dataset, sloID, pdseverity string) string {
return fmt.Sprintf(`
resource "honeycombio_pagerduty_recipient" "test" {
integration_key = "08b9d4cacd68933151a1ef1028b67da2"
integration_name = "test.pd-basic"
}
resource "honeycombio_burn_alert" "test" {
exhaustion_minutes = %[1]d
dataset = "%[2]s"
slo_id = "%[3]s"
description = "%[5]s"
recipient {
id = honeycombio_pagerduty_recipient.test.id
notification_details {
pagerduty_severity = "%[4]s"
}
}
}`, exhaustionMinutes, dataset, sloID, pdseverity, testBADescription)
}

func testAccConfigBurnAlertDefault_validateAttributesWhenAlertTypeIsExhaustionTime(dataset, sloID string) string {
return fmt.Sprintf(`
resource "honeycombio_burn_alert" "test" {
Expand All @@ -698,6 +726,7 @@ resource "honeycombio_pagerduty_recipient" "test" {
resource "honeycombio_burn_alert" "test" {
alert_type = "exhaustion_time"
description = "%[5]s"
exhaustion_minutes = %[1]d
dataset = "%[2]s"
Expand All @@ -710,7 +739,7 @@ resource "honeycombio_burn_alert" "test" {
pagerduty_severity = "%[4]s"
}
}
}`, exhaustionMinutes, dataset, sloID, pdseverity)
}`, exhaustionMinutes, dataset, sloID, pdseverity, testBADescription)
}

func testAccConfigBurnAlertExhaustionTime_validateAttributesWhenAlertTypeIsExhaustionTime(dataset, sloID string) string {
Expand Down Expand Up @@ -739,6 +768,7 @@ resource "honeycombio_pagerduty_recipient" "test" {
resource "honeycombio_burn_alert" "test" {
alert_type = "budget_rate"
description = "%[6]s"
budget_rate_window_minutes = %[1]d
budget_rate_decrease_percent = %[2]s
Expand All @@ -752,7 +782,7 @@ resource "honeycombio_burn_alert" "test" {
pagerduty_severity = "%[5]s"
}
}
}`, budgetRateWindowMinutes, helper.FloatToPercentString(budgetRateDecreasePercent), dataset, sloID, pdseverity)
}`, budgetRateWindowMinutes, helper.FloatToPercentString(budgetRateDecreasePercent), dataset, sloID, pdseverity, testBADescription)
}

func testAccConfigBurnAlertBudgetRate_trailingZeros(dataset, sloID string) string {
Expand All @@ -764,6 +794,7 @@ resource "honeycombio_pagerduty_recipient" "test" {
resource "honeycombio_burn_alert" "test" {
alert_type = "budget_rate"
description = "%[3]s"
budget_rate_window_minutes = 60
budget_rate_decrease_percent = 5.00000
Expand All @@ -777,7 +808,7 @@ resource "honeycombio_burn_alert" "test" {
pagerduty_severity = "info"
}
}
}`, dataset, sloID)
}`, dataset, sloID, testBADescription)
}

func testAccConfigBurnAlertBudgetRate_validateAttributesWhenAlertTypeIsBudgetRate(dataset, sloID string) string {
Expand Down Expand Up @@ -813,6 +844,7 @@ resource "honeycombio_burn_alert" "test" {
dataset = "%[1]s"
slo_id = "%[2]s"
description = "%[3]s"
recipient {
id = honeycombio_pagerduty_recipient.test.id
Expand All @@ -821,7 +853,7 @@ resource "honeycombio_burn_alert" "test" {
pagerduty_severity = "info"
}
}
}`, dataset, sloID)
}`, dataset, sloID, testBADescription)
}

func testAccConfigBurnAlertWithSlackRecipient(dataset, sloID, channel string) string {
Expand All @@ -831,12 +863,13 @@ resource "honeycombio_burn_alert" "test" {
dataset = "%[1]s"
slo_id = "%[2]s"
description = "%[4]s"
recipient {
type = "slack"
target = "%[3]s"
}
}`, dataset, sloID, channel)
}`, dataset, sloID, channel, testBADescription)
}

func testAccConfigBurnAlertWithDynamicRecipient(dataset, sloID string) string {
Expand Down

0 comments on commit c429944

Please sign in to comment.