Skip to content

Commit

Permalink
chore: migrate r/webhook_recipient to Framework (#568)
Browse files Browse the repository at this point in the history
This migrates `r/webhook_recipient` from the Plugin SDKv2 to the Plugin
Framework.

In the process, also updates `secret` to be optional to match the
upstream change.
  • Loading branch information
jharley authored Nov 15, 2024
1 parent bec5669 commit f76fe07
Show file tree
Hide file tree
Showing 15 changed files with 548 additions and 93 deletions.
2 changes: 1 addition & 1 deletion docs/resources/webhook_recipient.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ resource "honeycombio_webhook_recipient" "prod" {
The following arguments are supported:

* `name` - (Required) The name of the Webhook Integration to create.
* `secret` - (Required) The secret to include when sending the notification to the webhook.
* `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.

## Attribute Reference
Expand Down
1 change: 0 additions & 1 deletion honeycombio/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ func Provider(version string) *schema.Provider {
"honeycombio_msteams_recipient": newMSTeamsRecipient(), // deprecated
"honeycombio_msteams_workflow_recipient": newMSTeamsWorkflowRecipient(),
"honeycombio_slack_recipient": newSlackRecipient(),
"honeycombio_webhook_recipient": newWebhookRecipient(),
"honeycombio_slo": newSLO(),
},
}
Expand Down
60 changes: 0 additions & 60 deletions honeycombio/resource_webhook_recipient.go

This file was deleted.

13 changes: 6 additions & 7 deletions internal/helper/validation/divisible_by_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"

"github.com/honeycombio/terraform-provider-honeycombio/internal/helper/validation"
)
Expand Down Expand Up @@ -54,13 +55,11 @@ func Test_BetweenValidator(t *testing.T) {
response := validator.Int64Response{}
validation.Int64DivisibleBy(test.divisor).ValidateInt64(context.Background(), request, &response)

if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
assert.Equal(t,
test.expectError,
response.Diagnostics.HasError(),
"unexpected error: %s", response.Diagnostics,
)
})
}
}
13 changes: 6 additions & 7 deletions internal/helper/validation/precision_at_most_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"

"github.com/honeycombio/terraform-provider-honeycombio/internal/helper/validation"
)
Expand Down Expand Up @@ -64,13 +65,11 @@ func TestValidation_PrecisionAtMost(t *testing.T) {
response := validator.Float64Response{}
validation.Float64PrecisionAtMost(test.maxPrecision).ValidateFloat64(context.Background(), request, &response)

if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
assert.Equal(t,
test.expectError,
response.Diagnostics.HasError(),
"unexpected error: %s", response.Diagnostics,
)
})
}
}
13 changes: 6 additions & 7 deletions internal/helper/validation/query_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"

"github.com/honeycombio/terraform-provider-honeycombio/internal/helper/validation"
)
Expand Down Expand Up @@ -48,13 +49,11 @@ func Test_QuerySpecValidator(t *testing.T) {
response := validator.StringResponse{}
validation.ValidQuerySpec().ValidateString(context.Background(), request, &response)

if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
assert.Equal(t,
test.expectError,
response.Diagnostics.HasError(),
"unexpected error: %s", response.Diagnostics,
)
})
}
}
13 changes: 6 additions & 7 deletions internal/helper/validation/valid_regex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"

"github.com/honeycombio/terraform-provider-honeycombio/internal/helper/validation"
)
Expand Down Expand Up @@ -45,13 +46,11 @@ func Test_IsValidRegexValidator(t *testing.T) {
response := validator.StringResponse{}
validation.IsValidRegExp().ValidateString(context.Background(), request, &response)

if !response.Diagnostics.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if response.Diagnostics.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %s", response.Diagnostics)
}
assert.Equal(t,
test.expectError,
response.Diagnostics.HasError(),
"unexpected error: %s", response.Diagnostics,
)
})
}
}
66 changes: 66 additions & 0 deletions internal/helper/validation/valid_url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package validation

import (
"context"
"fmt"
"net/url"
"slices"
"strings"

"github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)

var _ validator.String = isValidURLValidator{}

type isValidURLValidator struct {
schemes []string
}

func (v isValidURLValidator) Description(_ context.Context) string {
return "value must be a valid URL"
}

func (v isValidURLValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

func (v isValidURLValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) {
if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() {
return
}

u, err := url.Parse(request.ConfigValue.ValueString())
if err != nil {
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
request.Path,
v.Description(ctx),
fmt.Sprintf("%q: %s", request.ConfigValue.ValueString(), err.Error()),
))
return
}

if u.Host == "" {
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
request.Path,
v.Description(ctx)+" but is missing a host",
request.ConfigValue.ValueString(),
))
}

if !slices.Contains(v.schemes, u.Scheme) {
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
request.Path,
fmt.Sprintf("%s with a schema of %q", v.Description(ctx), strings.Join(v.schemes, ",")),
request.ConfigValue.ValueString(),
))
}
}

// IsURLWithHTTPorHTTPS returns an AttributeValidator which ensures that any configured
// attribute value is a valid HTTP or HTTPS URL.
//
// Null (unconfigured) and unknown (known after apply) values are skipped.
func IsURLWithHTTPorHTTPS() validator.String {
return isValidURLValidator{[]string{"http", "https"}}
}
73 changes: 73 additions & 0 deletions internal/helper/validation/valid_url_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package validation_test

import (
"context"
"testing"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stretchr/testify/assert"

"github.com/honeycombio/terraform-provider-honeycombio/internal/helper/validation"
)

func Test_IsURLWithHTTPorHTTPS(t *testing.T) {
t.Parallel()
ctx := context.Background()

type testCase struct {
val types.String
expectError bool
}
tests := map[string]testCase{
"unknown": {
val: types.StringUnknown(),
},
"null": {
val: types.StringNull(),
},
"valid http": {
val: types.StringValue("http://sub.example.com/a/b/c/d?e=f#g"),
},
"valid https": {
val: types.StringValue("https://sub.example.com/a/b/c/d?e=f#g"),
},
"empty": {
val: types.StringValue(""),
expectError: true,
},
"garbage": {
val: types.StringValue("not-a-url"),
expectError: true,
},
"missing host": {
val: types.StringValue("http:///a/b/c/d?e=f#g"),
expectError: true,
},
"invalid scheme": {
val: types.StringValue("ftp://sub.example.com/"),
expectError: true,
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()

request := validator.StringRequest{
Path: path.Root("test"),
PathExpression: path.MatchRoot("test"),
ConfigValue: test.val,
}
response := validator.StringResponse{}
validation.IsURLWithHTTPorHTTPS().ValidateString(ctx, request, &response)

assert.Equal(t,
test.expectError,
response.Diagnostics.HasError(),
"unexpected error: %s", response.Diagnostics,
)
})
}
}
12 changes: 12 additions & 0 deletions internal/models/recipients.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package models

import (
"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"`
}
3 changes: 1 addition & 2 deletions internal/provider/dataset_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,7 @@ resource "honeycombio_dataset" "test" {
}`, name),
},
},
},
)
})
}

func testAccConfigBasicDatasetTest(name, description string, jsonDepth int, protected bool) string {
Expand Down
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ func (p *HoneycombioProvider) Resources(ctx context.Context) []func() resource.R
NewDatasetResource,
NewTriggerResource,
NewQueryResource,
NewWebhookRecipientResource,
NewAPIKeyResource,
NewEnvironmentResource,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/query_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func TestAcc_QueryResourceUpgradeFromVersion022(t *testing.T) {
})
}

// TestAcc_QueryResourceEquivalentQuerySpecSupressed tests the behavior of the
// TestAcc_QueryResourceEquivalentQuerySpecSupressed tests the behavior of the
// resource when an equivalent query is suppressed by the plan modifier.
func TestAcc_QueryResourceEquivalentQuerySpecSupressed(t *testing.T) {
dataset := testAccDataset()
Expand Down
Loading

0 comments on commit f76fe07

Please sign in to comment.