diff --git a/docs/resources/rule_amqp_external.md b/docs/resources/rule_amqp_external.md
index 669b40e..8b85bea 100644
--- a/docs/resources/rule_amqp_external.md
+++ b/docs/resources/rule_amqp_external.md
@@ -77,6 +77,7 @@ Optional:
Required:
+- `exchange` (String) The RabbitMQ exchange, if needed supports interpolation; see https://faqs.ably.com/what-is-the-format-of-the-routingkey-for-an-amqp-or-kinesis-reactor-rule for more info. If you don't use RabbitMQ exchanges, leave this blank.
- `mandatory_route` (Boolean) Reject delivery of the message if the route does not exist, otherwise fail silently.
- `persistent_messages` (Boolean) Marks the message as persistent, instructing the broker to write it to disk if it is in a durable queue.
- `routing_key` (String) The Kafka partition key. This is used to determine which partition a message should be routed to, where a topic has been partitioned. routingKey should be in the format topic:key where topic is the topic to publish to, and key is the value to use as the message key
diff --git a/docs/resources/rule_http.md b/docs/resources/rule_http.md
index 963150e..7cb05c2 100644
--- a/docs/resources/rule_http.md
+++ b/docs/resources/rule_http.md
@@ -35,6 +35,9 @@ resource "ably_rule_http" "rule0" {
signing_key_id = ably_api_key.api_key_0.id
enveloped = true
format = "json"
+ # Note, "enveloped" can only be set to true for "single" request_mode.
+ # "batch" request_mode is automatically enveloped.
+ enveloped = false
}
}
```
@@ -78,6 +81,7 @@ Required:
Optional:
+- `enveloped` (Boolean) Delivered messages are wrapped in an Ably envelope by default that contains metadata about the message and its payload. The form of the envelope depends on whether it is part of a Webhook/Function or a Queue/Firehose rule. For everything besides Webhooks, you can ensure you only get the raw payload by unchecking "Enveloped" when setting up the rule.
- `format` (String) JSON provides a text-based encoding, whereas MsgPack provides a more efficient binary encoding
- `headers` (Attributes List) If you have additional information to send, you'll need to include the relevant headers (see [below for nested schema](#nestedatt--target--headers))
- `signing_key_id` (String) The signing key ID for use in batch mode. Ably will optionally sign the payload using an API key ensuring your servers can validate the payload using the private API key. See the [webhook security docs](https://ably.com/docs/general/webhooks#security) for more information
diff --git a/examples/playground/README.md b/examples/playground/README.md
index 53eb74d..2006518 100644
--- a/examples/playground/README.md
+++ b/examples/playground/README.md
@@ -8,8 +8,8 @@
| Name | Version |
|------|---------|
-| [ably](#provider\_ably) | 0.4.2 |
-| [tls](#provider\_tls) | 4.0.3 |
+| [ably](#provider\_ably) | 0.5.0 |
+| [tls](#provider\_tls) | 4.0.5 |
## Modules
@@ -25,6 +25,8 @@ No modules.
| [ably_app.app1](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/app) | resource |
| [ably_namespace.namespace0](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/namespace) | resource |
| [ably_queue.example_queue](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/queue) | resource |
+| [ably_rule_amqp.rule0](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/rule_amqp) | resource |
+| [ably_rule_amqp_external.rule0](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/rule_amqp_external) | resource |
| [ably_rule_azure_function.rule0](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/rule_azure_function) | resource |
| [ably_rule_cloudflare_worker.rule0](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/rule_cloudflare_worker) | resource |
| [ably_rule_google_function.google_function](https://registry.terraform.io/providers/ably/ably/latest/docs/resources/rule_google_function) | resource |
diff --git a/examples/playground/rule_amqp.tf b/examples/playground/rule_amqp.tf
index b241712..dbcf73a 100644
--- a/examples/playground/rule_amqp.tf
+++ b/examples/playground/rule_amqp.tf
@@ -1,13 +1,13 @@
resource "ably_rule_amqp" "rule0" {
- app_id = ably_app.app0.id
- status = "enabled"
- source = {
- channel_filter = "^my-channel.*",
- type = "channel.message"
- }
- request_mode = "single"
- target = {
- queue_id = ably_queue.example_queue.id
+ app_id = ably_app.app0.id
+ status = "enabled"
+ source = {
+ channel_filter = "^my-channel.*",
+ type = "channel.message"
+ }
+ request_mode = "single"
+ target = {
+ queue_id = ably_queue.example_queue.id
headers = [
{
name : "User-Agent",
@@ -19,8 +19,8 @@ resource "ably_rule_amqp" "rule0" {
},
]
- enveloped = false
- format = "json"
- }
+ enveloped = false
+ format = "json"
}
+}
diff --git a/examples/playground/rule_amqp_external.tf b/examples/playground/rule_amqp_external.tf
index 07722ef..0239df6 100644
--- a/examples/playground/rule_amqp_external.tf
+++ b/examples/playground/rule_amqp_external.tf
@@ -1,17 +1,18 @@
resource "ably_rule_amqp_external" "rule0" {
- app_id = ably_app.app0.id
- status = "enabled"
+ app_id = ably_app.app0.id
+ status = "enabled"
request_mode = "single"
source = {
channel_filter = "^my-channel.*",
type = "channel.message"
}
target = {
- url = "amqps://test.com"
- routing_key = "new:key"
- mandatory_route = true
+ url = "amqps://test.com"
+ routing_key = "new:key"
+ exchange = "testexchange"
+ mandatory_route = true
persistent_messages = true
- message_ttl = 55
+ message_ttl = 55
headers = [
{
name : "User-Agent",
@@ -23,7 +24,7 @@ resource "ably_rule_amqp_external" "rule0" {
},
]
signing_key_id = ably_api_key.api_key_1.id
- enveloped = false
- format = "json"
+ enveloped = false
+ format = "json"
}
}
diff --git a/examples/playground/rule_http.tf b/examples/playground/rule_http.tf
index 9916372..5b27210 100644
--- a/examples/playground/rule_http.tf
+++ b/examples/playground/rule_http.tf
@@ -22,6 +22,6 @@ resource "ably_rule_http" "rule0" {
format = "json"
# Note, "enveloped" can only be set to true for "single" request_mode.
# "batch" request_mode is automatically enveloped.
- enveloped = false
+ enveloped = false
}
}
diff --git a/go.mod b/go.mod
index 13819a6..dba4927 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/ably/terraform-provider-ably
go 1.19
require (
- github.com/ably/ably-control-go v0.1.0
+ github.com/ably/ably-control-go v0.1.1-0.20231213094545-a41bf3d025ef
github.com/hashicorp/terraform-plugin-docs v0.13.0
github.com/hashicorp/terraform-plugin-framework v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.21.0
diff --git a/go.sum b/go.sum
index 9f20ee1..5522d39 100644
--- a/go.sum
+++ b/go.sum
@@ -14,6 +14,10 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/ably/ably-control-go v0.1.0 h1:flhd5ZiJZyWs+RxOK//ozsev6VpmRrqOmvXhVvgon3I=
github.com/ably/ably-control-go v0.1.0/go.mod h1:TP7gWAy+ga++gX6OZ0DtjwH8oVKKdiaIGQvZvxDKNdk=
+github.com/ably/ably-control-go v0.1.1-0.20231211162000-164517f286eb h1:WVq8ysFKqCc8OtM77GnWF7s+cyEcRBT5+i2iirOZeoQ=
+github.com/ably/ably-control-go v0.1.1-0.20231211162000-164517f286eb/go.mod h1:TP7gWAy+ga++gX6OZ0DtjwH8oVKKdiaIGQvZvxDKNdk=
+github.com/ably/ably-control-go v0.1.1-0.20231213094545-a41bf3d025ef h1:tJthta4QnJVvbH/gR1G8hkdHQi/djOd8fkU8QS7IXx0=
+github.com/ably/ably-control-go v0.1.1-0.20231213094545-a41bf3d025ef/go.mod h1:TP7gWAy+ga++gX6OZ0DtjwH8oVKKdiaIGQvZvxDKNdk=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
diff --git a/internal/provider/models.go b/internal/provider/models.go
index 0ccc586..055c0e5 100644
--- a/internal/provider/models.go
+++ b/internal/provider/models.go
@@ -214,6 +214,7 @@ type AblyRuleTargetAmqp struct {
type AblyRuleTargetAmqpExternal struct {
Url string `tfsdk:"url"`
RoutingKey string `tfsdk:"routing_key"`
+ Exchange string `tfsdk:"exchange"`
MandatoryRoute bool `tfsdk:"mandatory_route"`
PersistentMessages bool `tfsdk:"persistent_messages"`
MessageTtl types.Int64 `tfsdk:"message_ttl"`
diff --git a/internal/provider/resource_ably_rule_amqp_external.go b/internal/provider/resource_ably_rule_amqp_external.go
index fd10844..e7a7278 100644
--- a/internal/provider/resource_ably_rule_amqp_external.go
+++ b/internal/provider/resource_ably_rule_amqp_external.go
@@ -27,6 +27,11 @@ func (r resourceRuleAmqpExternal) GetSchema(_ context.Context) (tfsdk.Schema, di
Required: true,
Description: "The Kafka partition key. This is used to determine which partition a message should be routed to, where a topic has been partitioned. routingKey should be in the format topic:key where topic is the topic to publish to, and key is the value to use as the message key",
},
+ "exchange": {
+ Type: types.StringType,
+ Required: true,
+ Description: "The RabbitMQ exchange, if needed supports interpolation; see https://faqs.ably.com/what-is-the-format-of-the-routingkey-for-an-amqp-or-kinesis-reactor-rule for more info. If you don't use RabbitMQ exchanges, leave this blank.",
+ },
"mandatory_route": {
Type: types.BoolType,
Required: true,
diff --git a/internal/provider/resource_ably_rule_amqp_external_test.go b/internal/provider/resource_ably_rule_amqp_external_test.go
index 0a17ad4..d23d9fd 100644
--- a/internal/provider/resource_ably_rule_amqp_external_test.go
+++ b/internal/provider/resource_ably_rule_amqp_external_test.go
@@ -42,6 +42,7 @@ func TestAccAblyRuleAmqpExternal(t *testing.T) {
"channel.message",
"amqps://test.example",
"topic:key",
+ "exchange",
true,
true,
44,
@@ -55,6 +56,7 @@ func TestAccAblyRuleAmqpExternal(t *testing.T) {
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "source.channel_filter", "^my-channel.*"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "source.type", "channel.message"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.routing_key", "topic:key"),
+ resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.exchange", "exchange"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.enveloped", "true"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.format", "json"),
),
@@ -68,6 +70,7 @@ func TestAccAblyRuleAmqpExternal(t *testing.T) {
"channel.message",
"amqps://test.example",
"newtopic:key",
+ "newexchange",
false,
false,
23,
@@ -81,6 +84,7 @@ func TestAccAblyRuleAmqpExternal(t *testing.T) {
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "source.channel_filter", "^my-channel.*"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "source.type", "channel.message"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.routing_key", "newtopic:key"),
+ resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.exchange", "newexchange"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.enveloped", "false"),
resource.TestCheckResourceAttr("ably_rule_amqp_external.rule0", "target.format", "msgpack"),
),
@@ -98,6 +102,7 @@ func testAccAblyRuleAmqpExternalConfig(
sourceType string,
targetUrl string,
targetRoutingKey string,
+ targetExchange string,
targetManditoryRoute bool,
targetPersistentMessages bool,
targetMessageTtl int,
@@ -133,13 +138,15 @@ resource "ably_rule_amqp_external" "rule0" {
target = {
url = %[5]q
routing_key = %[6]q,
- mandatory_route = %[7]t
- persistent_messages = %[8]t
- message_ttl = %[9]d
- headers = %[10]s
- enveloped = %[11]s,
- format = %[12]q,
+ exchange = %[7]q,
+ mandatory_route = %[8]t
+ persistent_messages = %[9]t
+ message_ttl = %[10]d
+ headers = %[11]s
+ enveloped = %[12]s,
+ format = %[13]q,
+
}
}
-`, appName, ruleStatus, channelFilter, sourceType, targetUrl, targetRoutingKey, targetManditoryRoute, targetPersistentMessages, targetMessageTtl, targetHeaders, targetEnveloped, targetFormat)
+`, appName, ruleStatus, channelFilter, sourceType, targetUrl, targetRoutingKey, targetExchange, targetManditoryRoute, targetPersistentMessages, targetMessageTtl, targetHeaders, targetEnveloped, targetFormat)
}
diff --git a/internal/provider/rules.go b/internal/provider/rules.go
index ce80695..82de97d 100644
--- a/internal/provider/rules.go
+++ b/internal/provider/rules.go
@@ -163,6 +163,7 @@ func GetPlanRule(plan AblyRule) ably_control_go.NewRule {
target = &ably_control_go.AmqpExternalTarget{
Url: t.Url,
RoutingKey: t.RoutingKey,
+ Exchange: t.Exchange,
MandatoryRoute: t.MandatoryRoute,
PersistentMessages: t.PersistentMessages,
MessageTTL: int(t.MessageTtl.ValueInt64()),