Skip to content

Commit 41143bb

Browse files
feat: Add Pub/Sub Subscription support for push payload unwrapping (no wrapper) (#8464) (#15334)
* feat: Add Pub/Sub Subscription support for payload unwrapping (no_wrapper) * Add no_wrapper test/example * Update Subscription.yaml * Update Subscription.yaml Signed-off-by: Modular Magician <[email protected]>
1 parent c356ff7 commit 41143bb

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

.changelog/8464.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
pubsub: added `no_wrapper` field to `google_pubsub_subscription` resource
3+
```

google/resource_pubsub_subscription_test.go

+64
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,31 @@ func TestAccPubsubSubscription_push(t *testing.T) {
120120
})
121121
}
122122

123+
func TestAccPubsubSubscription_pushNoWrapper(t *testing.T) {
124+
t.Parallel()
125+
126+
topicFoo := fmt.Sprintf("tf-test-topic-foo-%s", acctest.RandString(t, 10))
127+
subscription := fmt.Sprintf("tf-test-sub-foo-%s", acctest.RandString(t, 10))
128+
saAccount := fmt.Sprintf("tf-test-pubsub-%s", acctest.RandString(t, 10))
129+
130+
acctest.VcrTest(t, resource.TestCase{
131+
PreCheck: func() { acctest.AccTestPreCheck(t) },
132+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
133+
CheckDestroy: testAccCheckPubsubSubscriptionDestroyProducer(t),
134+
Steps: []resource.TestStep{
135+
{
136+
Config: testAccPubsubSubscription_pushNoWrapper(topicFoo, saAccount, subscription),
137+
},
138+
{
139+
ResourceName: "google_pubsub_subscription.foo",
140+
ImportStateId: subscription,
141+
ImportState: true,
142+
ImportStateVerify: true,
143+
},
144+
},
145+
})
146+
}
147+
123148
// Context: hashicorp/terraform-provider-google#4993
124149
// This test makes a call to GET an subscription before it is actually created.
125150
// The PubSub API negative-caches responses so this tests we are
@@ -215,6 +240,45 @@ resource "google_pubsub_subscription" "foo" {
215240
`, saAccount, topicFoo, subscription)
216241
}
217242

243+
func testAccPubsubSubscription_pushNoWrapper(topicFoo, saAccount, subscription string) string {
244+
return fmt.Sprintf(`
245+
data "google_project" "project" { }
246+
247+
resource "google_service_account" "pub_sub_service_account" {
248+
account_id = "%s"
249+
}
250+
251+
data "google_iam_policy" "admin" {
252+
binding {
253+
role = "roles/projects.topics.publish"
254+
255+
members = [
256+
"serviceAccount:${google_service_account.pub_sub_service_account.email}",
257+
]
258+
}
259+
}
260+
261+
resource "google_pubsub_topic" "foo" {
262+
name = "%s"
263+
}
264+
265+
resource "google_pubsub_subscription" "foo" {
266+
name = "%s"
267+
topic = google_pubsub_topic.foo.name
268+
ack_deadline_seconds = 10
269+
push_config {
270+
push_endpoint = "https://${data.google_project.project.project_id}.appspot.com"
271+
oidc_token {
272+
service_account_email = google_service_account.pub_sub_service_account.email
273+
}
274+
no_wrapper {
275+
write_metadata = true
276+
}
277+
}
278+
}
279+
`, saAccount, topicFoo, subscription)
280+
}
281+
218282
func testAccPubsubSubscription_basic(topic, subscription, label string, deadline int, exactlyOnceDelivery bool) string {
219283
return fmt.Sprintf(`
220284
resource "google_pubsub_topic" "foo" {

google/services/pubsub/resource_pubsub_subscription.go

+67
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,24 @@ The possible values for this attribute are:
302302
- v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API.`,
303303
Elem: &schema.Schema{Type: schema.TypeString},
304304
},
305+
"no_wrapper": {
306+
Type: schema.TypeList,
307+
Optional: true,
308+
Description: `When set, the payload to the push endpoint is not wrapped.Sets the
309+
'data' field as the HTTP body for delivery.`,
310+
MaxItems: 1,
311+
Elem: &schema.Resource{
312+
Schema: map[string]*schema.Schema{
313+
"write_metadata": {
314+
Type: schema.TypeBool,
315+
Required: true,
316+
Description: `When true, writes the Pub/Sub message metadata to
317+
'x-goog-pubsub-<KEY>:<VAL>' headers of the HTTP request. Writes the
318+
Pub/Sub message attributes to '<KEY>:<VAL>' headers of the HTTP request.`,
319+
},
320+
},
321+
},
322+
},
305323
"oidc_token": {
306324
Type: schema.TypeList,
307325
Optional: true,
@@ -950,6 +968,8 @@ func flattenPubsubSubscriptionPushConfig(v interface{}, d *schema.ResourceData,
950968
flattenPubsubSubscriptionPushConfigPushEndpoint(original["pushEndpoint"], d, config)
951969
transformed["attributes"] =
952970
flattenPubsubSubscriptionPushConfigAttributes(original["attributes"], d, config)
971+
transformed["no_wrapper"] =
972+
flattenPubsubSubscriptionPushConfigNoWrapper(original["noWrapper"], d, config)
953973
return []interface{}{transformed}
954974
}
955975
func flattenPubsubSubscriptionPushConfigOidcToken(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
@@ -983,6 +1003,23 @@ func flattenPubsubSubscriptionPushConfigAttributes(v interface{}, d *schema.Reso
9831003
return v
9841004
}
9851005

1006+
func flattenPubsubSubscriptionPushConfigNoWrapper(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1007+
if v == nil {
1008+
return nil
1009+
}
1010+
original := v.(map[string]interface{})
1011+
if len(original) == 0 {
1012+
return nil
1013+
}
1014+
transformed := make(map[string]interface{})
1015+
transformed["write_metadata"] =
1016+
flattenPubsubSubscriptionPushConfigNoWrapperWriteMetadata(original["writeMetadata"], d, config)
1017+
return []interface{}{transformed}
1018+
}
1019+
func flattenPubsubSubscriptionPushConfigNoWrapperWriteMetadata(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1020+
return v
1021+
}
1022+
9861023
func flattenPubsubSubscriptionAckDeadlineSeconds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
9871024
// Handles the string fixed64 format
9881025
if strVal, ok := v.(string); ok {
@@ -1216,6 +1253,13 @@ func expandPubsubSubscriptionPushConfig(v interface{}, d tpgresource.TerraformRe
12161253
transformed["attributes"] = transformedAttributes
12171254
}
12181255

1256+
transformedNoWrapper, err := expandPubsubSubscriptionPushConfigNoWrapper(original["no_wrapper"], d, config)
1257+
if err != nil {
1258+
return nil, err
1259+
} else if val := reflect.ValueOf(transformedNoWrapper); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1260+
transformed["noWrapper"] = transformedNoWrapper
1261+
}
1262+
12191263
return transformed, nil
12201264
}
12211265

@@ -1268,6 +1312,29 @@ func expandPubsubSubscriptionPushConfigAttributes(v interface{}, d tpgresource.T
12681312
return m, nil
12691313
}
12701314

1315+
func expandPubsubSubscriptionPushConfigNoWrapper(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1316+
l := v.([]interface{})
1317+
if len(l) == 0 || l[0] == nil {
1318+
return nil, nil
1319+
}
1320+
raw := l[0]
1321+
original := raw.(map[string]interface{})
1322+
transformed := make(map[string]interface{})
1323+
1324+
transformedWriteMetadata, err := expandPubsubSubscriptionPushConfigNoWrapperWriteMetadata(original["write_metadata"], d, config)
1325+
if err != nil {
1326+
return nil, err
1327+
} else if val := reflect.ValueOf(transformedWriteMetadata); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1328+
transformed["writeMetadata"] = transformedWriteMetadata
1329+
}
1330+
1331+
return transformed, nil
1332+
}
1333+
1334+
func expandPubsubSubscriptionPushConfigNoWrapperWriteMetadata(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1335+
return v, nil
1336+
}
1337+
12711338
func expandPubsubSubscriptionAckDeadlineSeconds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
12721339
return v, nil
12731340
}

website/docs/r/pubsub_subscription.html.markdown

+14
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,12 @@ The following arguments are supported:
386386
- v1beta1: uses the push format defined in the v1beta1 Pub/Sub API.
387387
- v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API.
388388

389+
* `no_wrapper` -
390+
(Optional)
391+
When set, the payload to the push endpoint is not wrapped.Sets the
392+
`data` field as the HTTP body for delivery.
393+
Structure is [documented below](#nested_no_wrapper).
394+
389395

390396
<a name="nested_oidc_token"></a>The `oidc_token` block supports:
391397

@@ -405,6 +411,14 @@ The following arguments are supported:
405411
token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3
406412
Note: if not specified, the Push endpoint URL will be used.
407413

414+
<a name="nested_no_wrapper"></a>The `no_wrapper` block supports:
415+
416+
* `write_metadata` -
417+
(Required)
418+
When true, writes the Pub/Sub message metadata to
419+
`x-goog-pubsub-<KEY>:<VAL>` headers of the HTTP request. Writes the
420+
Pub/Sub message attributes to `<KEY>:<VAL>` headers of the HTTP request.
421+
408422
<a name="nested_expiration_policy"></a>The `expiration_policy` block supports:
409423

410424
* `ttl` -

0 commit comments

Comments
 (0)