Skip to content

Commit

Permalink
Fix cloud_identity_group_membership to properly handle 403 responses …
Browse files Browse the repository at this point in the history
…when membership does not exist (#6999)
  • Loading branch information
roaks3 authored Dec 22, 2022
1 parent d13ca0a commit 927d9e9
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
1 change: 1 addition & 0 deletions mmv1/products/cloudidentity/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides
post_create: templates/terraform/post_create/set_computed_name.erb
custom_import: templates/terraform/custom_import/set_id_name_with_slashes.go.erb
GroupMembership: !ruby/object:Overrides::Terraform::ResourceOverride
read_error_transform: "transformCloudIdentityGroupMembershipReadError"
docs: !ruby/object:Provider::Terraform::Docs
warning: |
If you are using User ADCs (Application Default Credentials) with this resource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"google.golang.org/api/iam/v1"
)

func TestAccCloudIdentityGroupMembership_update(t *testing.T) {
Expand Down Expand Up @@ -176,6 +177,87 @@ resource "google_cloud_identity_group_membership" "basic" {
`, context)
}

func TestAccCloudIdentityGroupMembership_membershipDoesNotExist(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"org_domain": getTestOrgDomainFromEnv(t),
"cust_id": getTestCustIdFromEnv(t),
"random_suffix": randString(t, 10),
}

saId := "tf-test-sa-" + randString(t, 10)
project := getTestProjectFromEnv()
config := BootstrapConfig(t)

r := &iam.CreateServiceAccountRequest{
AccountId: saId,
ServiceAccount: &iam.ServiceAccount{},
}

sa, err := config.NewIamClient(config.userAgent).Projects.ServiceAccounts.Create("projects/" + project, r).Do()
if err != nil {
t.Errorf("Error creating service account: %s", err)
}

context["member_id"] = sa.Email

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudIdentityGroupMembershipDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccCloudIdentityGroupMembership_dne(context),
},
{
PreConfig: func() {
config := googleProviderConfig(t)

_, err := config.NewIamClient(config.userAgent).Projects.ServiceAccounts.Delete(sa.Name).Do()
if err != nil {
t.Errorf("cannot delete service account %s: %v", sa.Name, err)
return
}
},
Config: testAccCloudIdentityGroupMembership_dne(context),
PlanOnly: true,
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccCloudIdentityGroupMembership_dne(context map[string]interface{}) string {
return Nprintf(`
resource "google_cloud_identity_group" "group" {
display_name = "tf-test-my-identity-group-%{random_suffix}"

parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group-%{random_suffix}@%{org_domain}"
}

labels = {
"cloudidentity.googleapis.com/groups.discussion_forum" = ""
}
}

resource "google_cloud_identity_group_membership" "basic" {
group = google_cloud_identity_group.group.id

preferred_member_key {
id = "%{member_id}"
}

roles {
name = "MEMBER"
}
}
`, context)
}

<% unless version == 'ga' -%>
func TestAccCloudIdentityGroupMembership_cloudIdentityGroupMembershipWithMemberKey(t *testing.T) {
t.Parallel()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package google

import (
"log"
"strings"

"github.com/hashicorp/errwrap"
"google.golang.org/api/googleapi"
)

func transformCloudIdentityGroupMembershipReadError(err error) error {
if gErr, ok := errwrap.GetType(err, &googleapi.Error{}).(*googleapi.Error); ok {
if gErr.Code == 403 && strings.Contains(gErr.Message, "(or it may not exist)") {
// This error occurs when either the group membership does not exist, or permission is denied. It is
// deliberately ambiguous so that existence information is not revealed to the caller. However, for
// the Read function, we can only assume that the membership does not exist, and proceed with attempting
// other operations. Since handleNotFoundError(...) expects an error code of 404 when a resource does not
// exist, to get the desired behavior, we modify the error code to be 404.
gErr.Code = 404
}

log.Printf("[DEBUG] Transformed CloudIdentityGroupMembership error")
return gErr
}

return err
}

0 comments on commit 927d9e9

Please sign in to comment.