From 67c37d9f294deb6881feb20a2c362b7cbec0e030 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Thu, 3 Nov 2022 16:43:36 +0000 Subject: [PATCH] Made cloud identity groups updatable and updated documentation (#6687) Signed-off-by: Modular Magician --- .changelog/6687.txt | 3 ++ google/common_polling.go | 12 +++++++ google/resource_cloud_identity_group.go | 33 ++++++++++++++++--- google/resource_cloud_identity_group_test.go | 1 + .../docs/r/cloud_identity_group.html.markdown | 9 ++--- 5 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 .changelog/6687.txt diff --git a/.changelog/6687.txt b/.changelog/6687.txt new file mode 100644 index 0000000000..4e1a68a0d5 --- /dev/null +++ b/.changelog/6687.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cloudidentity: for group resource, made security label settable by making labels updatable +``` diff --git a/google/common_polling.go b/google/common_polling.go index f5e1bf9564..85aa3a5d5f 100644 --- a/google/common_polling.go +++ b/google/common_polling.go @@ -129,6 +129,18 @@ func PollCheckForExistenceWith403(_ map[string]interface{}, respErr error) PollR return SuccessPollResult() } +// PollCheckForAbsence waits for a 404/403 response, continues polling on a successful +// response, and returns any other error. +func PollCheckForAbsenceWith403(_ map[string]interface{}, respErr error) PollResult { + if respErr != nil { + if isGoogleApiErrorWithCode(respErr, 404) || isGoogleApiErrorWithCode(respErr, 403) { + return SuccessPollResult() + } + return ErrorPollResult(respErr) + } + return PendingStatusPollResult("found") +} + // PollCheckForAbsence waits for a 404 response, continues polling on a successful // response, and returns any other error. func PollCheckForAbsence(_ map[string]interface{}, respErr error) PollResult { diff --git a/google/resource_cloud_identity_group.go b/google/resource_cloud_identity_group.go index 7d52d19650..f1113b0374 100644 --- a/google/resource_cloud_identity_group.go +++ b/google/resource_cloud_identity_group.go @@ -83,12 +83,15 @@ and must be in the form of 'identitysources/{identity_source_id}'.`, "labels": { Type: schema.TypeMap, Required: true, - ForceNew: true, - Description: `The labels that apply to the Group. + Description: `One or more label entries that apply to the Group. Currently supported labels contain a key with an empty value. + +Google Groups are the default type of group and have a label with a key of cloudidentity.googleapis.com/groups.discussion_forum and an empty value. + +Existing Google Groups can have an additional label with a key of cloudidentity.googleapis.com/groups.security and an empty value added to them. This is an immutable change and the security label cannot be removed once added. -Must not contain more than one entry. Must contain the entry -'cloudidentity.googleapis.com/groups.discussion_forum': '' if the Group is a Google Group or -'system/groups/external': '' if the Group is an external-identity-mapped group.`, +Dynamic groups have a label with a key of cloudidentity.googleapis.com/groups.dynamic. + +Identity-mapped groups for Cloud Search have a label with a key of system/groups/external and an empty value.`, Elem: &schema.Schema{Type: schema.TypeString}, }, "parent": { @@ -342,6 +345,12 @@ func resourceCloudIdentityGroupUpdate(d *schema.ResourceData, meta interface{}) } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { obj["description"] = descriptionProp } + labelsProp, err := expandCloudIdentityGroupLabels(d.Get("labels"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("labels"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + obj["labels"] = labelsProp + } url, err := replaceVars(d, config, "{{CloudIdentityBasePath}}{{name}}") if err != nil { @@ -358,6 +367,10 @@ func resourceCloudIdentityGroupUpdate(d *schema.ResourceData, meta interface{}) if d.HasChange("description") { updateMask = append(updateMask, "description") } + + if d.HasChange("labels") { + updateMask = append(updateMask, "labels") + } // updateMask is a URL parameter but not present in the schema, so replaceVars // won't set it url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) @@ -378,6 +391,11 @@ func resourceCloudIdentityGroupUpdate(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Finished updating Group %q: %#v", d.Id(), res) } + err = PollingWaitTime(resourceCloudIdentityGroupPollRead(d, meta), PollCheckForExistenceWith403, "Updating Group", d.Timeout(schema.TimeoutUpdate), 10) + if err != nil { + return err + } + return resourceCloudIdentityGroupRead(d, meta) } @@ -408,6 +426,11 @@ func resourceCloudIdentityGroupDelete(d *schema.ResourceData, meta interface{}) return handleNotFoundError(err, d, "Group") } + err = PollingWaitTime(resourceCloudIdentityGroupPollRead(d, meta), PollCheckForAbsenceWith403, "Deleting Group", d.Timeout(schema.TimeoutCreate), 10) + if err != nil { + return fmt.Errorf("Error waiting to delete Group: %s", err) + } + log.Printf("[DEBUG] Finished deleting Group %q: %#v", d.Id(), res) return nil } diff --git a/google/resource_cloud_identity_group_test.go b/google/resource_cloud_identity_group_test.go index 31d2ead0e8..2ce5d7a4e4 100644 --- a/google/resource_cloud_identity_group_test.go +++ b/google/resource_cloud_identity_group_test.go @@ -44,6 +44,7 @@ resource "google_cloud_identity_group" "cloud_identity_group_basic" { labels = { "cloudidentity.googleapis.com/groups.discussion_forum" = "" + "cloudidentity.googleapis.com/groups.security" = "" } } `, context) diff --git a/website/docs/r/cloud_identity_group.html.markdown b/website/docs/r/cloud_identity_group.html.markdown index 84efd245f9..a3472951c4 100644 --- a/website/docs/r/cloud_identity_group.html.markdown +++ b/website/docs/r/cloud_identity_group.html.markdown @@ -74,10 +74,11 @@ The following arguments are supported: * `labels` - (Required) - The labels that apply to the Group. - Must not contain more than one entry. Must contain the entry - 'cloudidentity.googleapis.com/groups.discussion_forum': '' if the Group is a Google Group or - 'system/groups/external': '' if the Group is an external-identity-mapped group. + One or more label entries that apply to the Group. Currently supported labels contain a key with an empty value. + Google Groups are the default type of group and have a label with a key of cloudidentity.googleapis.com/groups.discussion_forum and an empty value. + Existing Google Groups can have an additional label with a key of cloudidentity.googleapis.com/groups.security and an empty value added to them. This is an immutable change and the security label cannot be removed once added. + Dynamic groups have a label with a key of cloudidentity.googleapis.com/groups.dynamic. + Identity-mapped groups for Cloud Search have a label with a key of system/groups/external and an empty value. The `group_key` block supports: