Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .githooks/pre-commit
100644 → 100755
Empty file.
3 changes: 0 additions & 3 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ testacc:
generate:
go generate ./...

generate-codegen:
go generate ./cmd/codegen/...

generate-tfdocs:
go generate ./cmd/tfdocs/...

Expand Down
40 changes: 37 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ terraform {
required_providers {
hookdeck = {
source = "hookdeck/hookdeck"
version = "~> 0.2"
}
}
}
Expand All @@ -40,7 +39,10 @@ resource "hookdeck_source" "my_source" {
# Configure a destination
resource "hookdeck_destination" "my_destination" {
name = "my_destination"
url = "https://mock.hookdeck.com"
type = "HTTP"
config = jsonencode({
url = "https://myapp.example.com/api"
})
}

# Configure a connection
Expand All @@ -50,9 +52,11 @@ resource "hookdeck_connection" "my_connection" {
}
```

For [Source `config`](https://hookdeck.com/docs/api#source-object) and [Destination `config`](https://hookdeck.com/docs/api#destination-object) you must provide a JSON object. This means you do not get validation on the `config` property within your IDE or when running `terraform plan`. However, when running `terraform apply` the Hookdeck API will provide error responses if invalid configuration is received.

## Dependencies

This provider uses [Hookdeck API](https://hookdeck.com/docs/api) and [Hookdeck Go SDK](https://github.com/hookdeck/hookdeck-go-sdk) under the hood.
This provider is built on top of the [Hookdeck API](https://hookdeck.com/docs/api).

## Development

Expand All @@ -68,6 +72,36 @@ Code generation was [introduced in October 2024](https://github.com/hookdeck/ter

The Hookdeck Go SDK is generated using the Hookdeck Open API spec. Therefore, Hookdeck Terraform Provider code generation must be based on the same OpenAPI spec version used to generate the Go SDK.

### Running locally

See https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider#prepare-terraform-for-local-provider-install

### Brief details

Build and install:

```
go build
go install
```

Override the provider in a `~/.terraformrc`:

```
provider_installation {

dev_overrides {
"hookdeck/hookdeck" = "/Users/leggetter/go/bin"
}

# For all other providers, install them directly from their origin provider
# registries as normal. If you omit this, Terraform will _only_ use
# the dev_overrides block, and so no other providers will be available.
direct {}
}
```


### Release

Released are managed via [GitHub Releases](https://github.com/hookdeck/terraform-provider-hookdeck/releases).
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/destination.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data "hookdeck_destination" "example" {

### Read-Only

- `config` (String) Destination configuration
- `config` (String, Sensitive) Destination configuration
- `created_at` (String) Date the destination was created
- `description` (String) Description for the destination
- `disabled_at` (String) Date the destination was disabled
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/source.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data "hookdeck_source" "example" {

### Read-Only

- `config` (String) Source configuration
- `config` (String, Sensitive) Source configuration
- `created_at` (String) Date the source was created
- `description` (String) Description for the source
- `disabled_at` (String) Date the source was disabled
Expand Down
46 changes: 15 additions & 31 deletions docs/guides/register-external-webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Let's start with a Hookdeck connection to start listening to incoming webhooks f
```hcl
resource "hookdeck_source" "stripe" {
name = "stripe"
type = "STRIPE"
}

resource "hookdeck_destination" "payment_service" {
Expand All @@ -34,24 +35,17 @@ resource "hookdeck_connection" "stripe_payment_service" {
Stripe provides API endpoints to [create a new webhook](https://stripe.com/docs/api/webhook_endpoints/create) and [delete an existing webhook](https://stripe.com/docs/api/webhook_endpoints/delete), which we will use in this example.

```hcl
resource "webhook_registration" "stripe" {
resource "hookdeck_webhook_registration" "stripe_webhook_registration" {
provider = hookdeck

register = {
request = {
method = "POST"
url = "https://api.stripe.com/v1/webhook_endpoints"
headers = jsonencode({
"content-type" = "application/json"
authorization = "Bearer <STRIPE_SECRET_KEY>"
})
body = jsonencode({
url = hookdeck_source.stripe.url
enabled_events = [
"charge.failed",
"charge.succeeded"
]
})
body = "url=${hookdeck_source.stripe.url}&enabled_events[]=charge.failed&enabled_events[]=charge.succeeded"
}
}
unregister = {
Expand All @@ -70,16 +64,14 @@ For many APIs, you will need the ID of the registered webhook to unregister. You

## Use webhook secret to verify with Hookdeck

Another way you can use the `webhook_registration` resource is to configure Hookdeck [source verification](https://hookdeck.com/docs/signature-verification) as part of your Terraform workflow. With the `webhook_registration` resource above, you can now configure Hookdeck verification like so:
Another way you can use the `hookdeck_webhook_registration` resource is to configure Hookdeck [source verification](https://hookdeck.com/docs/signature-verification) as part of your Terraform workflow. With the `hookdeck_webhook_registration` resource above, you can now configure Hookdeck verification like so:

```hcl
resource "hookdeck_source_verification" "stripe_verification" {
resource "hookdeck_source_auth" "stripe_source_auth" {
source_id = hookdeck_source.stripe.id
verification = {
stripe = {
webhook_secret_key = jsondecode(webhook_registration.stripe.register.response).body.secret
}
}
auth = jsonencode({
webhook_secret_key = jsondecode(hookdeck_webhook_registration.stripe_webhook_registration.register.response).body.secret
})
}
```

Expand All @@ -92,6 +84,7 @@ Putting everything together to register Stripe webhook with Hookdeck source with

resource "hookdeck_source" "stripe" {
name = "stripe"
type = "STRIPE"
}

resource "hookdeck_destination" "payment_service" {
Expand All @@ -106,24 +99,17 @@ resource "hookdeck_connection" "stripe_payment_service" {

# Register Stripe webhook

resource "webhook_registration" "stripe" {
resource "hookdeck_webhook_registration" "stripe_webhook_registration" {
provider = hookdeck

register = {
request = {
method = "POST"
url = "https://api.stripe.com/v1/webhook_endpoints"
headers = jsonencode({
"content-type" = "application/json"
authorization = "Bearer <STRIPE_SECRET_KEY>"
})
body = jsonencode({
url = hookdeck_source.stripe.url
enabled_events = [
"charge.failed",
"charge.succeeded"
]
})
body = "url=${hookdeck_source.stripe.url}&enabled_events[]=charge.failed&enabled_events[]=charge.succeeded"
}
}
unregister = {
Expand All @@ -139,12 +125,10 @@ resource "webhook_registration" "stripe" {

# Configure source verification

resource "hookdeck_source_verification" "stripe_verification" {
resource "hookdeck_source_auth" "stripe_source_auth" {
source_id = hookdeck_source.stripe.id
verification = {
stripe = {
webhook_secret_key = jsondecode(webhook_registration.stripe.register.response).body.secret
}
}
auth = jsonencode({
webhook_secret_key = jsondecode(hookdeck_webhook_registration.stripe_webhook_registration.register.response).body.secret
})
}
```
118 changes: 118 additions & 0 deletions docs/guides/v0.x-to-v1-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
page_title: "Migrating from v0.x to v1.x"
description: "How to migrate from v0.x to v1.x of the Hookdeck Terraform Provider"
---

The Hookdeck API version `2025-01-01` introduces several [breaking changes](https://hookdeck.com/docs/api#2025-01-01) to support the new concepts of Source and Destination Types. Consequently, we made updates to the Hookdeck Terraform Provider to align with this new model.

This guide highlights the Hookdeck Terraform Provider breaking changes and identifies the changes you should make to your Terraform configuration to move to the v1.0 version.

## Breaking Changes

### `hookdeck_source` and `hookdeck_destination` changes

`hookdeck_source` and `hookdeck_destination` resources implement the Source and Destination Types model.

- Added `type` property to the [Source](https://hookdeck.com/docs/api#sources) and [Destination](https://hookdeck.com/docs/api#destinations) objects, which can be set when creating or updating them.
- Added `config` property to contain a JSON representation of all type-dependent configuration options, including authentication methods, custom responses, and HTTP method restrictions.
- `config` is a JSON representation, so Terraform cannot validate the contents. Validation is performed by the API upon running `terraform apply`.
- Since `config` can contain sensitive information, the contents of it are marked as sensitive.
- See the [source object](https://hookdeck.com/docs/api#source-object) for more details on each Type configuration.

### `hookdeck_source` changes

- The Source `type` property defaults to `WEBHOOK` and has no required `config` property.
- The `custom_response`, `allowed_http_methods` properties have been moved to the Source to the `config` object for the supported `type`.
- The `verification` has been moved to the `config` object and the `verification.type` property is now `config.auth_type` and the `verification.config` property is `config.auth`.

### `hookdeck_destination` changes

- The Destination `type` property defaults to `HTTP` and requires a `config.url` property.
- The Destination properties `url`, `rate_limit`, `rate_limit_period`, `disabled_path_forwarding` and `http_method` have been moved to the `config` object for the supported `type`.
- The Destination `cli_path` property has been renamed to `path` and has been moved to the `config` object when `type` is `CLI`.
- When `type` is `CLI` the `rate_limit` and `rate_limit_period` properties are not supported.

### `hookdeck_source_verification` has been replaced with `hookdeck_source_auth`

- `auth_type` has been added to identify the type of authentication. It defaults to `WEBHOOK`. See the [Source object](https://hookdeck.com/docs/api#source-object) for all the supported values.
- `verification` is replaced with `auth` and `auth` is a `jsonencode` value. The value contents depend on the `auth_type`.
- `auth` is a JSON representation, so Terraform it cannot validate the contents. Validation is performed by the API upon running `terraform apply`.
- Since `auth` can contain sensitive information, the contents of it are marked as sensitive.
- See the [Source object](https://hookdeck.com/docs/api#source-object) for all the supported values.

## Example Migration

Here is a v0.x example:

```hcl
resource "hookdeck_source" "my_source" {
name = "my_source"
}

resource "hookdeck_source_verification" "my_source_verification" {
source_id = hookdeck_source.my_source.id
verification = {
basic_auth = {
username = "username"
password = "username"
}
}
}

resource "hookdeck_destination" "my_destination" {
name = "my_destination"
url = "https://my.example.com/api"
auth_method = {
basic_auth = {
username = "username"
password = "password"
}
}
rate_limit = {
period = "concurrent"
limit = 10
}
}
```

And the same example in v1.0 onwards:

```hcl
resource "hookdeck_source" "my_source" {
name = "my_source"

# new optional `type` property. Defaults to a value of `WEBHOOK`
type = "HTTP"
}

# `hookdeck_source_auth` replaces `hookdeck_source_verification`
resource "hookdeck_source_auth" "my_source_auth" {
source_id = hookdeck_source.my_source.id
auth_type = "BASIC_AUTH"
auth = jsonencode({
username = "username"
password = "password"
})
}

resource "hookdeck_destination" "my_destination" {
name = "my_destination"

# new `type` property
type = "HTTP"

# new `config` property with all values set via `jsonencode`
config = jsonencode({
url = "https://mock.hookdeck.com"
auth_type = "BASIC_AUTH"
auth = {
username = "username"
password = "password"
}

# `rate_limit` properties move out of object to match API
rate_limit = 10
rate_limit_period = "concurrent"
})
}
```
2 changes: 1 addition & 1 deletion docs/resources/destination.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ resource "hookdeck_destination" "example" {

### Optional

- `config` (String) Destination configuration
- `config` (String, Sensitive) Destination configuration
- `description` (String) Description for the destination
- `disabled_at` (String) Date the destination was disabled
- `type` (String) Type of the destination
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/source.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ resource "hookdeck_source" "example" {

### Optional

- `config` (String) Source configuration
- `config` (String, Sensitive) Source configuration
- `description` (String) Description for the source
- `type` (String) Type of the source

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/source_auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Source Auth Resource

### Required

- `auth` (String) Source auth
- `auth` (String, Sensitive) Source auth
- `source_id` (String) ID of the source

### Optional
Expand Down
5 changes: 1 addition & 4 deletions docs/resources/webhook_registration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ resource "hookdeck_webhook_registration" "webhook_stripe" {
"content-type" = "application/json"
authorization = "Bearer ${var.stripe_secret_key}"
})
body = jsonencode({
url = hookdeck_source.source_example.url
enabled_events = ["charge.failed", "charge.succeeded"]
})
body = "url=${hookdeck_source.source_example.url}&enabled_events[]=charge.failed&enabled_events[]=charge.succeeded"
}
}
unregister = {
Expand Down
1 change: 1 addition & 0 deletions examples/full/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform.tfvars
Loading
Loading