From 08dfecd2300850889a16251595a0bbca320b73a6 Mon Sep 17 00:00:00 2001 From: Suhong Qin <51539171+sqin2019@users.noreply.github.com> Date: Thu, 30 Nov 2023 13:46:54 -0800 Subject: [PATCH] add expiryDetail to google_cloud_identity_group_membership (#9427) --- .../cloudidentity/GroupMembership.yaml | 18 ++- .../cloud_identity_group_membership.go.erb | 139 ++++++++++++++++++ .../cloud_identity_group_membership.tf.erb | 2 +- .../cloud_identity_group_membership.go.erb | 26 ---- ...loud_identity_group_membership_test.go.erb | 3 + 5 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb delete mode 100644 mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb diff --git a/mmv1/products/cloudidentity/GroupMembership.yaml b/mmv1/products/cloudidentity/GroupMembership.yaml index 029ccea4bba9..bca79a961574 100644 --- a/mmv1/products/cloudidentity/GroupMembership.yaml +++ b/mmv1/products/cloudidentity/GroupMembership.yaml @@ -59,7 +59,7 @@ examples: custom_code: !ruby/object:Provider::Terraform::CustomCode post_create: templates/terraform/post_create/set_computed_name.erb post_import: templates/terraform/post_import/cloud_identity_group_membership.go.erb - update_encoder: templates/terraform/update_encoder/cloud_identity_group_membership.go.erb + custom_update: templates/terraform/custom_update/cloud_identity_group_membership.go.erb parameters: - !ruby/object:Api::Type::ResourceRef @@ -180,6 +180,22 @@ properties: - :OWNER - :MANAGER - :MEMBER + - !ruby/object:Api::Type::NestedObject + name: 'expiryDetail' + description: | + The MembershipRole expiry details, only supported for MEMBER role. + Other roles cannot be accompanied with MEMBER role having expiry. + properties: + - !ruby/object:Api::Type::String + name: 'expireTime' + required: true + description: | + The time at which the MembershipRole will expire. + + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond + resolution and up to nine fractional digits. + + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". - !ruby/object:Api::Type::String name: 'type' output: true diff --git a/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb b/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb new file mode 100644 index 000000000000..b2320d173b6d --- /dev/null +++ b/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb @@ -0,0 +1,139 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + d.Partial(true) + + if d.HasChange("roles") { + url, err := tpgresource.ReplaceVars(d, config, "{{CloudIdentityBasePath}}{{name}}:modifyMembershipRoles") + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`) + b, a := d.GetChange("roles") + before := b.(*schema.Set) + after := a.(*schema.Set) + + ignoreUpdateR := make(map[string]struct{}) + addRoleList := after.Difference(before).List() + removeRoleList := before.Difference(after).List() + + var updateRolesParams []map[string]interface{} + for _, addR := range addRoleList { + ar := addR.(map[string]interface{})["name"].(string) + ae := addR.(map[string]interface{})["expiry_detail"].([]interface {}) + for _, removeR := range removeRoleList { + if ar == removeR.(map[string]interface{})["name"].(string) { + ignoreUpdateR[ar] = struct{}{} + var updateR map[string]interface{} + if len(ae) == 0 { + updateR = map[string]interface{}{"name": ar} + } else { + updateR = map[string]interface{}{"name": ar, "expiry_detail": ae[0]} + } + updateP := map[string]interface{}{"field_mask": "expiryDetail.expire_time", "membership_role": updateR} + updateRolesParams = append(updateRolesParams, updateP) + } + } + } + + var addRoles []map[string]interface{} + for _, r := range addRoleList { + name := r.(map[string]interface{})["name"].(string) + if _, ignore := ignoreUpdateR[name]; ignore { + continue + } + expiryDetail := r.(map[string]interface{})["expiry_detail"].([]interface {}) + if len(expiryDetail) == 0 { + addRoles = append(addRoles, map[string]interface{}{"name": name}) + } else { + addRoles = append(addRoles, map[string]interface{}{"name": name, "expiry_detail": expiryDetail[0]}) + } + } + var removeRoles []string + for _, r := range removeRoleList { + name := r.(map[string]interface{})["name"].(string) + if _, ignore := ignoreUpdateR[name]; ignore { + continue + } + removeRoles = append(removeRoles, name) + } + + // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body + // Only single operation per request is allowed. + if len(removeRoles) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"removeRoles": removeRoles}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error removing GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished removing GroupMembership %q: %#v", d.Id(), res) + } + } + if len(updateRolesParams) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"updateRolesParams": updateRolesParams}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error updating GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating GroupMembership %q: %#v", d.Id(), res) + } + } + if len(addRoles) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"addRoles": addRoles}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error adding GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished adding GroupMembership %q: %#v", d.Id(), res) + } + } + } + + d.Partial(false) + + return resourceCloudIdentityGroupMembershipRead(d, meta) diff --git a/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb b/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb index e259fdb2344f..ce660ca58e69 100644 --- a/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb +++ b/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb @@ -34,6 +34,6 @@ resource "google_cloud_identity_group_membership" "<%= ctx[:primary_resource_id] } roles { - name = "MEMBER" + name = "MEMBER" } } diff --git a/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb b/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb deleted file mode 100644 index 5f7357f1570d..000000000000 --- a/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2019 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> - // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`) - b, a := d.GetChange("roles") - before := b.(*schema.Set) - after := a.(*schema.Set) - // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body - addRoles := after.Difference(before).List() - var removeRoles []string - for _, r := range before.Difference(after).List() { - removeRoles = append(removeRoles, r.(map[string]interface{})["name"].(string)) - } - req := map[string]interface{}{"addRoles": addRoles, "removeRoles": removeRoles} - return req, nil diff --git a/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb b/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb index b4fcf66ecea6..08cb7d45b924 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb @@ -81,6 +81,9 @@ resource "google_cloud_identity_group_membership" "basic" { roles { name = "MEMBER" + expiry_detail { + expire_time = "2215-10-02T15:01:23Z" + } } }