@@ -93,6 +93,54 @@ for the call to the push endpoint.
9393If the subscriber never acknowledges the message, the Pub/Sub system
9494will eventually redeliver the message.` ,
9595 },
96+ "dead_letter_policy" : {
97+ Type : schema .TypeList ,
98+ Optional : true ,
99+ Description : `A policy that specifies the conditions for dead lettering messages in
100+ this subscription. If dead_letter_policy is not set, dead lettering
101+ is disabled.
102+
103+ The Cloud Pub/Sub service account associated with this subscriptions's
104+ parent project (i.e.,
105+ service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have
106+ permission to Acknowledge() messages on this subscription.` ,
107+ MaxItems : 1 ,
108+ Elem : & schema.Resource {
109+ Schema : map [string ]* schema.Schema {
110+ "dead_letter_topic" : {
111+ Type : schema .TypeString ,
112+ Optional : true ,
113+ Description : `The name of the topic to which dead letter messages should be published.
114+ Format is 'projects/{project}/topics/{topic}'.
115+
116+ The Cloud Pub/Sub service\naccount associated with the enclosing subscription's
117+ parent project (i.e.,
118+ service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have
119+ permission to Publish() to this topic.
120+
121+ The operation will fail if the topic does not exist.
122+ Users should ensure that there is a subscription attached to this topic
123+ since messages published to a topic with no subscriptions are lost.` ,
124+ },
125+ "max_delivery_attempts" : {
126+ Type : schema .TypeInt ,
127+ Optional : true ,
128+ Description : `The maximum number of delivery attempts for any message. The value must be
129+ between 5 and 100.
130+
131+ The number of delivery attempts is defined as 1 + (the sum of number of
132+ NACKs and number of times the acknowledgement deadline has been exceeded for the message).
133+
134+ A NACK is any call to ModifyAckDeadline with a 0 deadline. Note that
135+ client libraries may automatically extend ack_deadlines.
136+
137+ This field will be honored on a best effort basis.
138+
139+ If this parameter is 0, a default value of 5 is used.` ,
140+ },
141+ },
142+ },
143+ },
96144 "expiration_policy" : {
97145 Type : schema .TypeList ,
98146 Computed : true ,
@@ -290,6 +338,12 @@ func resourcePubsubSubscriptionCreate(d *schema.ResourceData, meta interface{})
290338 } else if v , ok := d .GetOkExists ("expiration_policy" ); ok || ! reflect .DeepEqual (v , expirationPolicyProp ) {
291339 obj ["expirationPolicy" ] = expirationPolicyProp
292340 }
341+ deadLetterPolicyProp , err := expandPubsubSubscriptionDeadLetterPolicy (d .Get ("dead_letter_policy" ), d , config )
342+ if err != nil {
343+ return err
344+ } else if v , ok := d .GetOkExists ("dead_letter_policy" ); ok || ! reflect .DeepEqual (v , deadLetterPolicyProp ) {
345+ obj ["deadLetterPolicy" ] = deadLetterPolicyProp
346+ }
293347
294348 obj , err = resourcePubsubSubscriptionEncoder (d , meta , obj )
295349 if err != nil {
@@ -418,6 +472,9 @@ func resourcePubsubSubscriptionRead(d *schema.ResourceData, meta interface{}) er
418472 if err := d .Set ("expiration_policy" , flattenPubsubSubscriptionExpirationPolicy (res ["expirationPolicy" ], d , config )); err != nil {
419473 return fmt .Errorf ("Error reading Subscription: %s" , err )
420474 }
475+ if err := d .Set ("dead_letter_policy" , flattenPubsubSubscriptionDeadLetterPolicy (res ["deadLetterPolicy" ], d , config )); err != nil {
476+ return fmt .Errorf ("Error reading Subscription: %s" , err )
477+ }
421478
422479 return nil
423480}
@@ -467,6 +524,12 @@ func resourcePubsubSubscriptionUpdate(d *schema.ResourceData, meta interface{})
467524 } else if v , ok := d .GetOkExists ("expiration_policy" ); ok || ! reflect .DeepEqual (v , expirationPolicyProp ) {
468525 obj ["expirationPolicy" ] = expirationPolicyProp
469526 }
527+ deadLetterPolicyProp , err := expandPubsubSubscriptionDeadLetterPolicy (d .Get ("dead_letter_policy" ), d , config )
528+ if err != nil {
529+ return err
530+ } else if v , ok := d .GetOkExists ("dead_letter_policy" ); ok || ! reflect .DeepEqual (v , deadLetterPolicyProp ) {
531+ obj ["deadLetterPolicy" ] = deadLetterPolicyProp
532+ }
470533
471534 obj , err = resourcePubsubSubscriptionUpdateEncoder (d , meta , obj )
472535 if err != nil {
@@ -504,6 +567,10 @@ func resourcePubsubSubscriptionUpdate(d *schema.ResourceData, meta interface{})
504567 if d .HasChange ("expiration_policy" ) {
505568 updateMask = append (updateMask , "expirationPolicy" )
506569 }
570+
571+ if d .HasChange ("dead_letter_policy" ) {
572+ updateMask = append (updateMask , "deadLetterPolicy" )
573+ }
507574 // updateMask is a URL parameter but not present in the schema, so replaceVars
508575 // won't set it
509576 url , err = addQueryParams (url , map [string ]string {"updateMask" : strings .Join (updateMask , "," )})
@@ -669,6 +736,42 @@ func flattenPubsubSubscriptionExpirationPolicyTtl(v interface{}, d *schema.Resou
669736 return v
670737}
671738
739+ func flattenPubsubSubscriptionDeadLetterPolicy (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
740+ if v == nil {
741+ return nil
742+ }
743+ original := v .(map [string ]interface {})
744+ if len (original ) == 0 {
745+ return nil
746+ }
747+ transformed := make (map [string ]interface {})
748+ transformed ["dead_letter_topic" ] =
749+ flattenPubsubSubscriptionDeadLetterPolicyDeadLetterTopic (original ["deadLetterTopic" ], d , config )
750+ transformed ["max_delivery_attempts" ] =
751+ flattenPubsubSubscriptionDeadLetterPolicyMaxDeliveryAttempts (original ["maxDeliveryAttempts" ], d , config )
752+ return []interface {}{transformed }
753+ }
754+ func flattenPubsubSubscriptionDeadLetterPolicyDeadLetterTopic (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
755+ return v
756+ }
757+
758+ func flattenPubsubSubscriptionDeadLetterPolicyMaxDeliveryAttempts (v interface {}, d * schema.ResourceData , config * Config ) interface {} {
759+ // Handles the string fixed64 format
760+ if strVal , ok := v .(string ); ok {
761+ if intVal , err := strconv .ParseInt (strVal , 10 , 64 ); err == nil {
762+ return intVal
763+ }
764+ }
765+
766+ // number values are represented as float64
767+ if floatVal , ok := v .(float64 ); ok {
768+ intVal := int (floatVal )
769+ return intVal
770+ }
771+
772+ return v // let terraform core handle it otherwise
773+ }
774+
672775func expandPubsubSubscriptionName (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
673776 return replaceVars (d , config , "projects/{{project}}/subscriptions/{{name}}" )
674777}
@@ -826,6 +929,40 @@ func expandPubsubSubscriptionExpirationPolicyTtl(v interface{}, d TerraformResou
826929 return v , nil
827930}
828931
932+ func expandPubsubSubscriptionDeadLetterPolicy (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
933+ l := v .([]interface {})
934+ if len (l ) == 0 || l [0 ] == nil {
935+ return nil , nil
936+ }
937+ raw := l [0 ]
938+ original := raw .(map [string ]interface {})
939+ transformed := make (map [string ]interface {})
940+
941+ transformedDeadLetterTopic , err := expandPubsubSubscriptionDeadLetterPolicyDeadLetterTopic (original ["dead_letter_topic" ], d , config )
942+ if err != nil {
943+ return nil , err
944+ } else if val := reflect .ValueOf (transformedDeadLetterTopic ); val .IsValid () && ! isEmptyValue (val ) {
945+ transformed ["deadLetterTopic" ] = transformedDeadLetterTopic
946+ }
947+
948+ transformedMaxDeliveryAttempts , err := expandPubsubSubscriptionDeadLetterPolicyMaxDeliveryAttempts (original ["max_delivery_attempts" ], d , config )
949+ if err != nil {
950+ return nil , err
951+ } else if val := reflect .ValueOf (transformedMaxDeliveryAttempts ); val .IsValid () && ! isEmptyValue (val ) {
952+ transformed ["maxDeliveryAttempts" ] = transformedMaxDeliveryAttempts
953+ }
954+
955+ return transformed , nil
956+ }
957+
958+ func expandPubsubSubscriptionDeadLetterPolicyDeadLetterTopic (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
959+ return v , nil
960+ }
961+
962+ func expandPubsubSubscriptionDeadLetterPolicyMaxDeliveryAttempts (v interface {}, d TerraformResourceData , config * Config ) (interface {}, error ) {
963+ return v , nil
964+ }
965+
829966func resourcePubsubSubscriptionEncoder (d * schema.ResourceData , meta interface {}, obj map [string ]interface {}) (map [string ]interface {}, error ) {
830967 delete (obj , "name" )
831968 return obj , nil
0 commit comments