@@ -78,10 +78,11 @@ func joinMapKeys(mapToJoin *map[int]bool) string {
78
78
79
79
func resourceCloudFunctionsFunction () * schema.Resource {
80
80
return & schema.Resource {
81
- Create : resourceCloudFunctionsCreate ,
82
- Read : resourceCloudFunctionsRead ,
83
- Update : resourceCloudFunctionsUpdate ,
84
- Delete : resourceCloudFunctionsDestroy ,
81
+ Create : resourceCloudFunctionsCreate ,
82
+ Read : resourceCloudFunctionsRead ,
83
+ Update : resourceCloudFunctionsUpdate ,
84
+ Delete : resourceCloudFunctionsDestroy ,
85
+ CustomizeDiff : resourceCloudFunctionsCustomizeDiff ,
85
86
86
87
Importer : & schema.ResourceImporter {
87
88
State : schema .ImportStatePassthrough ,
@@ -177,7 +178,8 @@ func resourceCloudFunctionsFunction() *schema.Resource {
177
178
"trigger_bucket" : {
178
179
Type : schema .TypeString ,
179
180
Optional : true ,
180
- ForceNew : true ,
181
+ Computed : true ,
182
+ Deprecated : "This field is deprecated. Use `event_trigger` instead." ,
181
183
ConflictsWith : []string {"trigger_http" , "trigger_topic" },
182
184
},
183
185
@@ -191,10 +193,46 @@ func resourceCloudFunctionsFunction() *schema.Resource {
191
193
"trigger_topic" : {
192
194
Type : schema .TypeString ,
193
195
Optional : true ,
194
- ForceNew : true ,
196
+ Computed : true ,
197
+ Deprecated : "This field is deprecated. Use `event_trigger` instead." ,
195
198
ConflictsWith : []string {"trigger_http" , "trigger_bucket" },
196
199
},
197
200
201
+ "event_trigger" : {
202
+ Type : schema .TypeList ,
203
+ Optional : true ,
204
+ Computed : true ,
205
+ ConflictsWith : []string {"trigger_http" , "retry_on_failure" , "trigger_topic" , "trigger_http" },
206
+ MaxItems : 1 ,
207
+ Elem : & schema.Resource {
208
+ Schema : map [string ]* schema.Schema {
209
+ "event_type" : {
210
+ Type : schema .TypeString ,
211
+ ForceNew : true ,
212
+ Required : true ,
213
+ },
214
+ "resource" : {
215
+ Type : schema .TypeString ,
216
+ Required : true ,
217
+ },
218
+ "failure_policy" : {
219
+ Type : schema .TypeList ,
220
+ Optional : true ,
221
+ Computed : true ,
222
+ MaxItems : 1 ,
223
+ Elem : & schema.Resource {
224
+ Schema : map [string ]* schema.Schema {
225
+ "retry" : {
226
+ Type : schema .TypeBool ,
227
+ // not strictly required, but this way an empty block can't be specified
228
+ Required : true ,
229
+ },
230
+ }},
231
+ },
232
+ },
233
+ },
234
+ },
235
+
198
236
"https_trigger_url" : {
199
237
Type : schema .TypeString ,
200
238
Optional : true ,
@@ -204,6 +242,8 @@ func resourceCloudFunctionsFunction() *schema.Resource {
204
242
"retry_on_failure" : {
205
243
Type : schema .TypeBool ,
206
244
Optional : true ,
245
+ Computed : true ,
246
+ Deprecated : "This field is deprecated. Use `event_trigger.failure_policy.retry` instead." ,
207
247
ConflictsWith : []string {"trigger_http" },
208
248
},
209
249
@@ -225,6 +265,28 @@ func resourceCloudFunctionsFunction() *schema.Resource {
225
265
}
226
266
}
227
267
268
+ func resourceCloudFunctionsCustomizeDiff (diff * schema.ResourceDiff , meta interface {}) error {
269
+ if diff .HasChange ("trigger_topic" ) {
270
+ _ , n := diff .GetChange ("trigger_topic" )
271
+ if n == "" {
272
+ diff .Clear ("trigger_topic" )
273
+ } else {
274
+ diff .ForceNew ("trigger_topic" )
275
+ }
276
+ }
277
+
278
+ if diff .HasChange ("trigger_bucket" ) {
279
+ _ , n := diff .GetChange ("trigger_bucket" )
280
+ if n == "" {
281
+ diff .Clear ("trigger_bucket" )
282
+ } else {
283
+ diff .ForceNew ("trigger_bucket" )
284
+ }
285
+ }
286
+
287
+ return nil
288
+ }
289
+
228
290
func resourceCloudFunctionsCreate (d * schema.ResourceData , meta interface {}) error {
229
291
config := meta .(* Config )
230
292
@@ -253,7 +315,8 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro
253
315
}
254
316
255
317
function := & cloudfunctions.CloudFunction {
256
- Name : cloudFuncId .cloudFunctionId (),
318
+ Name : cloudFuncId .cloudFunctionId (),
319
+ ForceSendFields : []string {},
257
320
}
258
321
259
322
sourceArchiveBucket := d .Get ("source_archive_bucket" ).(string )
@@ -277,13 +340,11 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro
277
340
function .Timeout = fmt .Sprintf ("%vs" , v .(int ))
278
341
}
279
342
280
- v , triggHttpOk := d .GetOk ("trigger_http" )
281
- if triggHttpOk && v .(bool ) {
343
+ if v , ok := d .GetOk ("event_trigger" ); ok {
344
+ function .EventTrigger = expandEventTrigger (v .([]interface {}), project )
345
+ } else if v , ok := d .GetOk ("trigger_http" ); ok && v .(bool ) {
282
346
function .HttpsTrigger = & cloudfunctions.HttpsTrigger {}
283
- }
284
-
285
- v , triggTopicOk := d .GetOk ("trigger_topic" )
286
- if triggTopicOk {
347
+ } else if v , ok := d .GetOk ("trigger_topic" ); ok {
287
348
// Make PubSub event publish as in https://cloud.google.com/functions/docs/calling/pubsub
288
349
function .EventTrigger = & cloudfunctions.EventTrigger {
289
350
// Other events are not supported
@@ -297,10 +358,7 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro
297
358
Retry : & cloudfunctions.Retry {},
298
359
}
299
360
}
300
- }
301
-
302
- v , triggBucketOk := d .GetOk ("trigger_bucket" )
303
- if triggBucketOk {
361
+ } else if v , ok := d .GetOk ("trigger_bucket" ); ok {
304
362
// Make Storage event as in https://cloud.google.com/functions/docs/calling/storage
305
363
function .EventTrigger = & cloudfunctions.EventTrigger {
306
364
EventType : "providers/cloud.storage/eventTypes/object.change" ,
@@ -313,10 +371,8 @@ func resourceCloudFunctionsCreate(d *schema.ResourceData, meta interface{}) erro
313
371
Retry : & cloudfunctions.Retry {},
314
372
}
315
373
}
316
- }
317
-
318
- if ! triggHttpOk && ! triggTopicOk && ! triggBucketOk {
319
- return fmt .Errorf ("One of arguments [trigger_topic, trigger_bucket, trigger_http] is required: " +
374
+ } else {
375
+ return fmt .Errorf ("One of `event_trigger` or `trigger_http` is required: " +
320
376
"You must specify a trigger when deploying a new function." )
321
377
}
322
378
@@ -389,16 +445,24 @@ func resourceCloudFunctionsRead(d *schema.ResourceData, meta interface{}) error
389
445
d .Set ("https_trigger_url" , function .HttpsTrigger .Url )
390
446
}
391
447
448
+ d .Set ("event_trigger" , flattenEventTrigger (function .EventTrigger ))
392
449
if function .EventTrigger != nil {
393
450
switch function .EventTrigger .EventType {
394
451
// From https://github.com/google/google-api-go-client/blob/master/cloudfunctions/v1/cloudfunctions-gen.go#L335
395
452
case "google.pubsub.topic.publish" :
396
- d .Set ("trigger_topic" , GetResourceNameFromSelfLink (function .EventTrigger .Resource ))
453
+ if _ , ok := d .GetOk ("trigger_topic" ); ok {
454
+ d .Set ("trigger_topic" , GetResourceNameFromSelfLink (function .EventTrigger .Resource ))
455
+ }
397
456
case "providers/cloud.storage/eventTypes/object.change" :
398
- d .Set ("trigger_bucket" , GetResourceNameFromSelfLink (function .EventTrigger .Resource ))
457
+ if _ , ok := d .GetOk ("trigger_bucket" ); ok {
458
+ d .Set ("trigger_bucket" , GetResourceNameFromSelfLink (function .EventTrigger .Resource ))
459
+ }
460
+ }
461
+
462
+ if _ , ok := d .GetOk ("retry_on_failure" ); ok {
463
+ retry := function .EventTrigger .FailurePolicy != nil && function .EventTrigger .FailurePolicy .Retry != nil
464
+ d .Set ("retry_on_failure" , retry )
399
465
}
400
- retry := function .EventTrigger .FailurePolicy != nil && function .EventTrigger .FailurePolicy .Retry != nil
401
- d .Set ("retry_on_failure" , retry )
402
466
}
403
467
d .Set ("region" , cloudFuncId .Region )
404
468
d .Set ("project" , cloudFuncId .Project )
@@ -410,6 +474,11 @@ func resourceCloudFunctionsUpdate(d *schema.ResourceData, meta interface{}) erro
410
474
log .Printf ("[DEBUG]: Updating google_cloudfunctions_function" )
411
475
config := meta .(* Config )
412
476
477
+ project , err := getProject (d , config )
478
+ if err != nil {
479
+ return err
480
+ }
481
+
413
482
cloudFuncId , err := parseCloudFunctionId (d .Id (), config )
414
483
if err != nil {
415
484
return err
@@ -455,6 +524,7 @@ func resourceCloudFunctionsUpdate(d *schema.ResourceData, meta interface{}) erro
455
524
updateMaskArr = append (updateMaskArr , "environment_variables" )
456
525
}
457
526
527
+ // Event trigger will run after failure policy and take precedence
458
528
if d .HasChange ("retry_on_failure" ) {
459
529
if d .Get ("retry_on_failure" ).(bool ) {
460
530
if function .EventTrigger == nil {
@@ -467,6 +537,11 @@ func resourceCloudFunctionsUpdate(d *schema.ResourceData, meta interface{}) erro
467
537
updateMaskArr = append (updateMaskArr , "eventTrigger.failurePolicy.retry" )
468
538
}
469
539
540
+ if d .HasChange ("event_trigger" ) {
541
+ function .EventTrigger = expandEventTrigger (d .Get ("event_trigger" ).([]interface {}), project )
542
+ updateMaskArr = append (updateMaskArr , "eventTrigger" , "eventTrigger.failurePolicy.retry" )
543
+ }
544
+
470
545
if len (updateMaskArr ) > 0 {
471
546
log .Printf ("[DEBUG] Send Patch CloudFunction Configuration request: %#v" , function )
472
547
updateMask := strings .Join (updateMaskArr , "," )
@@ -509,3 +584,70 @@ func resourceCloudFunctionsDestroy(d *schema.ResourceData, meta interface{}) err
509
584
510
585
return nil
511
586
}
587
+
588
+ func expandEventTrigger (configured []interface {}, project string ) * cloudfunctions.EventTrigger {
589
+ if len (configured ) == 0 {
590
+ return nil
591
+ }
592
+
593
+ if data , ok := configured [0 ].(map [string ]interface {}); ok {
594
+ eventType := data ["event_type" ].(string )
595
+ shape := ""
596
+ switch {
597
+ case strings .HasPrefix (eventType , "providers/cloud.storage/eventTypes/" ):
598
+ shape = "projects/%s/buckets/%s"
599
+ case strings .HasPrefix (eventType , "providers/cloud.pubsub/eventTypes/" ):
600
+ shape = "projects/%s/topics/%s"
601
+ }
602
+
603
+ return & cloudfunctions.EventTrigger {
604
+ EventType : eventType ,
605
+ Resource : fmt .Sprintf (shape , project , data ["resource" ].(string )),
606
+ FailurePolicy : expandFailurePolicy (data ["failure_policy" ].([]interface {})),
607
+ }
608
+ }
609
+
610
+ return nil
611
+ }
612
+
613
+ func flattenEventTrigger (eventTrigger * cloudfunctions.EventTrigger ) []map [string ]interface {} {
614
+ result := make ([]map [string ]interface {}, 0 , 1 )
615
+ if eventTrigger == nil {
616
+ return result
617
+ }
618
+
619
+ result = append (result , map [string ]interface {}{
620
+ "event_type" : eventTrigger .EventType ,
621
+ "resource" : GetResourceNameFromSelfLink (eventTrigger .Resource ),
622
+ "failure_policy" : flattenFailurePolicy (eventTrigger .FailurePolicy ),
623
+ })
624
+
625
+ return result
626
+ }
627
+
628
+ func expandFailurePolicy (configured []interface {}) * cloudfunctions.FailurePolicy {
629
+ if len (configured ) == 0 {
630
+ return & cloudfunctions.FailurePolicy {}
631
+ }
632
+
633
+ if data , ok := configured [0 ].(map [string ]interface {}); ok && data ["retry" ].(bool ) {
634
+ return & cloudfunctions.FailurePolicy {
635
+ Retry : & cloudfunctions.Retry {},
636
+ }
637
+ }
638
+
639
+ return nil
640
+ }
641
+
642
+ func flattenFailurePolicy (failurePolicy * cloudfunctions.FailurePolicy ) []map [string ]interface {} {
643
+ result := make ([]map [string ]interface {}, 0 , 1 )
644
+ if failurePolicy == nil {
645
+ return nil
646
+ }
647
+
648
+ result = append (result , map [string ]interface {}{
649
+ "retry" : failurePolicy .Retry != nil ,
650
+ })
651
+
652
+ return result
653
+ }
0 commit comments