@@ -138,6 +138,27 @@ func cloudidentityGroupMembershipRolesSchema() *schema.Resource {
138
138
ValidateFunc : verify .ValidateEnum ([]string {"OWNER" , "MANAGER" , "MEMBER" }),
139
139
Description : `The name of the MembershipRole. Must be one of OWNER, MANAGER, MEMBER. Possible values: ["OWNER", "MANAGER", "MEMBER"]` ,
140
140
},
141
+ "expiry_detail" : {
142
+ Type : schema .TypeList ,
143
+ Optional : true ,
144
+ Description : `The MembershipRole expiry details, only supported for MEMBER role.
145
+ Other roles cannot be accompanied with MEMBER role having expiry.` ,
146
+ MaxItems : 1 ,
147
+ Elem : & schema.Resource {
148
+ Schema : map [string ]* schema.Schema {
149
+ "expire_time" : {
150
+ Type : schema .TypeString ,
151
+ Required : true ,
152
+ Description : `The time at which the MembershipRole will expire.
153
+
154
+ A timestamp in RFC3339 UTC "Zulu" format, with nanosecond
155
+ resolution and up to nine fractional digits.
156
+
157
+ Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".` ,
158
+ },
159
+ },
160
+ },
161
+ },
141
162
},
142
163
}
143
164
}
@@ -286,20 +307,6 @@ func resourceCloudIdentityGroupMembershipUpdate(d *schema.ResourceData, meta int
286
307
d .Partial (true )
287
308
288
309
if d .HasChange ("roles" ) {
289
- obj := make (map [string ]interface {})
290
-
291
- rolesProp , err := expandCloudIdentityGroupMembershipRoles (d .Get ("roles" ), d , config )
292
- if err != nil {
293
- return err
294
- } else if v , ok := d .GetOkExists ("roles" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , rolesProp )) {
295
- obj ["roles" ] = rolesProp
296
- }
297
-
298
- obj , err = resourceCloudIdentityGroupMembershipUpdateEncoder (d , meta , obj )
299
- if err != nil {
300
- return err
301
- }
302
-
303
310
url , err := tpgresource .ReplaceVars (d , config , "{{CloudIdentityBasePath}}{{name}}:modifyMembershipRoles" )
304
311
if err != nil {
305
312
return err
@@ -310,21 +317,106 @@ func resourceCloudIdentityGroupMembershipUpdate(d *schema.ResourceData, meta int
310
317
billingProject = bp
311
318
}
312
319
313
- res , err := transport_tpg .SendRequest (transport_tpg.SendRequestOptions {
314
- Config : config ,
315
- Method : "POST" ,
316
- Project : billingProject ,
317
- RawURL : url ,
318
- UserAgent : userAgent ,
319
- Body : obj ,
320
- Timeout : d .Timeout (schema .TimeoutUpdate ),
321
- })
322
- if err != nil {
323
- return fmt .Errorf ("Error updating GroupMembership %q: %s" , d .Id (), err )
324
- } else {
325
- log .Printf ("[DEBUG] Finished updating GroupMembership %q: %#v" , d .Id (), res )
320
+ // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`)
321
+ b , a := d .GetChange ("roles" )
322
+ before := b .(* schema.Set )
323
+ after := a .(* schema.Set )
324
+
325
+ ignoreUpdateR := make (map [string ]struct {})
326
+ addRoleList := after .Difference (before ).List ()
327
+ removeRoleList := before .Difference (after ).List ()
328
+
329
+ var updateRolesParams []map [string ]interface {}
330
+ for _ , addR := range addRoleList {
331
+ ar := addR .(map [string ]interface {})["name" ].(string )
332
+ ae := addR .(map [string ]interface {})["expiry_detail" ].([]interface {})
333
+ for _ , removeR := range removeRoleList {
334
+ if ar == removeR .(map [string ]interface {})["name" ].(string ) {
335
+ ignoreUpdateR [ar ] = struct {}{}
336
+ var updateR map [string ]interface {}
337
+ if len (ae ) == 0 {
338
+ updateR = map [string ]interface {}{"name" : ar }
339
+ } else {
340
+ updateR = map [string ]interface {}{"name" : ar , "expiry_detail" : ae [0 ]}
341
+ }
342
+ updateP := map [string ]interface {}{"field_mask" : "expiryDetail.expire_time" , "membership_role" : updateR }
343
+ updateRolesParams = append (updateRolesParams , updateP )
344
+ }
345
+ }
346
+ }
347
+
348
+ var addRoles []map [string ]interface {}
349
+ for _ , r := range addRoleList {
350
+ name := r .(map [string ]interface {})["name" ].(string )
351
+ if _ , ignore := ignoreUpdateR [name ]; ignore {
352
+ continue
353
+ }
354
+ expiryDetail := r .(map [string ]interface {})["expiry_detail" ].([]interface {})
355
+ if len (expiryDetail ) == 0 {
356
+ addRoles = append (addRoles , map [string ]interface {}{"name" : name })
357
+ } else {
358
+ addRoles = append (addRoles , map [string ]interface {}{"name" : name , "expiry_detail" : expiryDetail [0 ]})
359
+ }
360
+ }
361
+ var removeRoles []string
362
+ for _ , r := range removeRoleList {
363
+ name := r .(map [string ]interface {})["name" ].(string )
364
+ if _ , ignore := ignoreUpdateR [name ]; ignore {
365
+ continue
366
+ }
367
+ removeRoles = append (removeRoles , name )
326
368
}
327
369
370
+ // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body
371
+ // Only single operation per request is allowed.
372
+ if len (removeRoles ) > 0 {
373
+ res , err := transport_tpg .SendRequest (transport_tpg.SendRequestOptions {
374
+ Config : config ,
375
+ Method : "POST" ,
376
+ Project : billingProject ,
377
+ RawURL : url ,
378
+ UserAgent : userAgent ,
379
+ Body : map [string ]interface {}{"removeRoles" : removeRoles },
380
+ Timeout : d .Timeout (schema .TimeoutUpdate ),
381
+ })
382
+ if err != nil {
383
+ return fmt .Errorf ("Error removing GroupMembership %q: %s" , d .Id (), err )
384
+ } else {
385
+ log .Printf ("[DEBUG] Finished removing GroupMembership %q: %#v" , d .Id (), res )
386
+ }
387
+ }
388
+ if len (updateRolesParams ) > 0 {
389
+ res , err := transport_tpg .SendRequest (transport_tpg.SendRequestOptions {
390
+ Config : config ,
391
+ Method : "POST" ,
392
+ Project : billingProject ,
393
+ RawURL : url ,
394
+ UserAgent : userAgent ,
395
+ Body : map [string ]interface {}{"updateRolesParams" : updateRolesParams },
396
+ Timeout : d .Timeout (schema .TimeoutUpdate ),
397
+ })
398
+ if err != nil {
399
+ return fmt .Errorf ("Error updating GroupMembership %q: %s" , d .Id (), err )
400
+ } else {
401
+ log .Printf ("[DEBUG] Finished updating GroupMembership %q: %#v" , d .Id (), res )
402
+ }
403
+ }
404
+ if len (addRoles ) > 0 {
405
+ res , err := transport_tpg .SendRequest (transport_tpg.SendRequestOptions {
406
+ Config : config ,
407
+ Method : "POST" ,
408
+ Project : billingProject ,
409
+ RawURL : url ,
410
+ UserAgent : userAgent ,
411
+ Body : map [string ]interface {}{"addRoles" : addRoles },
412
+ Timeout : d .Timeout (schema .TimeoutUpdate ),
413
+ })
414
+ if err != nil {
415
+ return fmt .Errorf ("Error adding GroupMembership %q: %s" , d .Id (), err )
416
+ } else {
417
+ log .Printf ("[DEBUG] Finished adding GroupMembership %q: %#v" , d .Id (), res )
418
+ }
419
+ }
328
420
}
329
421
330
422
d .Partial (false )
@@ -443,7 +535,8 @@ func flattenCloudIdentityGroupMembershipRoles(v interface{}, d *schema.ResourceD
443
535
continue
444
536
}
445
537
transformed .Add (map [string ]interface {}{
446
- "name" : flattenCloudIdentityGroupMembershipRolesName (original ["name" ], d , config ),
538
+ "name" : flattenCloudIdentityGroupMembershipRolesName (original ["name" ], d , config ),
539
+ "expiry_detail" : flattenCloudIdentityGroupMembershipRolesExpiryDetail (original ["expiryDetail" ], d , config ),
447
540
})
448
541
}
449
542
return transformed
@@ -452,6 +545,23 @@ func flattenCloudIdentityGroupMembershipRolesName(v interface{}, d *schema.Resou
452
545
return v
453
546
}
454
547
548
+ func flattenCloudIdentityGroupMembershipRolesExpiryDetail (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
549
+ if v == nil {
550
+ return nil
551
+ }
552
+ original := v .(map [string ]interface {})
553
+ if len (original ) == 0 {
554
+ return nil
555
+ }
556
+ transformed := make (map [string ]interface {})
557
+ transformed ["expire_time" ] =
558
+ flattenCloudIdentityGroupMembershipRolesExpiryDetailExpireTime (original ["expireTime" ], d , config )
559
+ return []interface {}{transformed }
560
+ }
561
+ func flattenCloudIdentityGroupMembershipRolesExpiryDetailExpireTime (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
562
+ return v
563
+ }
564
+
455
565
func flattenCloudIdentityGroupMembershipType (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
456
566
return v
457
567
}
@@ -508,6 +618,13 @@ func expandCloudIdentityGroupMembershipRoles(v interface{}, d tpgresource.Terraf
508
618
transformed ["name" ] = transformedName
509
619
}
510
620
621
+ transformedExpiryDetail , err := expandCloudIdentityGroupMembershipRolesExpiryDetail (original ["expiry_detail" ], d , config )
622
+ if err != nil {
623
+ return nil , err
624
+ } else if val := reflect .ValueOf (transformedExpiryDetail ); val .IsValid () && ! tpgresource .IsEmptyValue (val ) {
625
+ transformed ["expiryDetail" ] = transformedExpiryDetail
626
+ }
627
+
511
628
req = append (req , transformed )
512
629
}
513
630
return req , nil
@@ -517,17 +634,25 @@ func expandCloudIdentityGroupMembershipRolesName(v interface{}, d tpgresource.Te
517
634
return v , nil
518
635
}
519
636
520
- func resourceCloudIdentityGroupMembershipUpdateEncoder (d * schema.ResourceData , meta interface {}, obj map [string ]interface {}) (map [string ]interface {}, error ) {
521
- // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`)
522
- b , a := d .GetChange ("roles" )
523
- before := b .(* schema.Set )
524
- after := a .(* schema.Set )
525
- // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body
526
- addRoles := after .Difference (before ).List ()
527
- var removeRoles []string
528
- for _ , r := range before .Difference (after ).List () {
529
- removeRoles = append (removeRoles , r .(map [string ]interface {})["name" ].(string ))
530
- }
531
- req := map [string ]interface {}{"addRoles" : addRoles , "removeRoles" : removeRoles }
532
- return req , nil
637
+ func expandCloudIdentityGroupMembershipRolesExpiryDetail (v interface {}, d tpgresource.TerraformResourceData , config * transport_tpg.Config ) (interface {}, error ) {
638
+ l := v .([]interface {})
639
+ if len (l ) == 0 || l [0 ] == nil {
640
+ return nil , nil
641
+ }
642
+ raw := l [0 ]
643
+ original := raw .(map [string ]interface {})
644
+ transformed := make (map [string ]interface {})
645
+
646
+ transformedExpireTime , err := expandCloudIdentityGroupMembershipRolesExpiryDetailExpireTime (original ["expire_time" ], d , config )
647
+ if err != nil {
648
+ return nil , err
649
+ } else if val := reflect .ValueOf (transformedExpireTime ); val .IsValid () && ! tpgresource .IsEmptyValue (val ) {
650
+ transformed ["expireTime" ] = transformedExpireTime
651
+ }
652
+
653
+ return transformed , nil
654
+ }
655
+
656
+ func expandCloudIdentityGroupMembershipRolesExpiryDetailExpireTime (v interface {}, d tpgresource.TerraformResourceData , config * transport_tpg.Config ) (interface {}, error ) {
657
+ return v , nil
533
658
}
0 commit comments