From 99e22c7486539bdb4a05df82fb47a4d18d7cca4d Mon Sep 17 00:00:00 2001 From: Devon Bleak Date: Mon, 9 Apr 2018 18:40:06 -0700 Subject: [PATCH 1/5] Add acceptance tests for resource/aws_iam_user_group_membership --- ...urce_aws_iam_user_group_membership_test.go | 331 ++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 aws/resource_aws_iam_user_group_membership_test.go diff --git a/aws/resource_aws_iam_user_group_membership_test.go b/aws/resource_aws_iam_user_group_membership_test.go new file mode 100644 index 000000000000..1929e9863553 --- /dev/null +++ b/aws/resource_aws_iam_user_group_membership_test.go @@ -0,0 +1,331 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSUserGroupMembership_basic(t *testing.T) { + rString := acctest.RandString(8) + userName1 := fmt.Sprintf("tf-acc-ugm-basic-user1-%s", rString) + userName2 := fmt.Sprintf("tf-acc-ugm-basic-user2-%s", rString) + groupName1 := fmt.Sprintf("tf-acc-ugm-basic-group1-%s", rString) + groupName2 := fmt.Sprintf("tf-acc-ugm-basic-group2-%s", rString) + groupName3 := fmt.Sprintf("tf-acc-ugm-basic-group3-%s", rString) + membershipName := fmt.Sprintf("tf-acc-ugm-basic-membership-%s", rString) + + usersAndGroupsConfig := testAccAWSUserGroupMembershipConfigUsersAndGroups(userName1, userName2, groupName1, groupName2, groupName3) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccAWSUserGroupMembershipDestroy, + Steps: []resource.TestStep{ + // simplest test + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigInit(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1}, []string{groupName2, groupName3}), + ), + }, + // test adding an additional group to an existing resource + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddOne(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName2}, []string{groupName3}), + ), + }, + // test adding multiple resources for the same user, and resources with the same groups for another user + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test1", "user", userName2), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test2", "user", userName2), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName2, groupName3}, []string{}), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName2, []string{groupName1, groupName2, groupName3}, []string{}), + ), + }, + // test that nothing happens when we apply the same config again + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test1", "user", userName2), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test2", "user", userName2), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName2, groupName3}, []string{}), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName2, []string{groupName1, groupName2, groupName3}, []string{}), + ), + }, + // test removing a group + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigRemoveGroup(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test1", "user", userName2), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test2", "user", userName2), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName3}, []string{groupName2}), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName2, []string{groupName1, groupName2}, []string{groupName3}), + ), + }, + // test removing a resource + resource.TestStep{ + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigDeleteResource(membershipName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), + resource.TestCheckResourceAttr("aws_iam_user_group_membership.user2_test1", "user", userName2), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName3}, []string{groupName2}), + testAccAWSUserGroupMembershipCheckGroupListForUser(userName2, []string{groupName1}, []string{groupName2, groupName3}), + ), + }, + }, + }) +} + +func testAccAWSUserGroupMembershipDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).iamconn + + // check that all users and groups have been destroyed + for _, rs := range s.RootModule().Resources { + if rs.Type == "aws_iam_user" { + userName := rs.Primary.Attributes["name"] + + _, err := conn.GetUser(&iam.GetUserInput{ + UserName: &userName, + }) + if err != nil { + if ae, ok := err.(awserr.Error); ok && ae.Code() == "NoSuchEntity" { + continue + } + return err + } + + return fmt.Errorf("User %s still exists", userName) + } + + if rs.Type == "aws_iam_group" { + groupName := rs.Primary.Attributes["name"] + + _, err := conn.GetGroup(&iam.GetGroupInput{ + GroupName: &groupName, + }) + if err != nil { + if ae, ok := err.(awserr.Error); ok && ae.Code() == "NoSuchEntity" { + continue + } + return err + } + + return fmt.Errorf("Group %s still exists", groupName) + } + } + + return nil +} + +func testAccAWSUserGroupMembershipCheckGroupListForUser(userName string, groups []string, groupsNeg []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).iamconn + + // get list of groups for user + userGroupList, err := conn.ListGroupsForUser(&iam.ListGroupsForUserInput{ + UserName: &userName, + }) + if err != nil { + return fmt.Errorf("Error validing user group list for %s: %s", userName, err) + } + + // check required groups + GROUP: + for _, group := range groups { + for _, groupFound := range userGroupList.Groups { + if group == *groupFound.GroupName { + continue GROUP // found our group, start checking the next one + } + } + // group not found, return an error + return fmt.Errorf("Required group not found for %s: %s", userName, group) + } + + // check that none of groupsNeg are present + for _, group := range groupsNeg { + for _, groupFound := range userGroupList.Groups { + if group == *groupFound.GroupName { + return fmt.Errorf("Required negative group found for %s: %s", userName, group) + } + } + } + + return nil + } +} + +// users and groups for all other tests +func testAccAWSUserGroupMembershipConfigUsersAndGroups(userName1, userName2, groupName1, groupName2, groupName3 string) string { + return fmt.Sprintf(` +resource "aws_iam_user" "user1" { + name = "%s" + force_destroy = true +} + +resource "aws_iam_user" "user2" { + name = "%s" + force_destroy = true +} + +resource "aws_iam_group" "group1" { + name = "%s" +} + +resource "aws_iam_group" "group2" { + name = "%s" +} + +resource "aws_iam_group" "group3" { + name = "%s" +} +`, userName1, userName2, groupName1, groupName2, groupName3) +} + +// associate users and groups +func testAccAWSUserGroupMembershipConfigInit(membershipName string) string { + return fmt.Sprintf(` +resource "aws_iam_user_group_membership" "user1_test1" { + name = "%s-user1_test1" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} +`, membershipName) +} + +func testAccAWSUserGroupMembershipConfigAddOne(membershipName string) string { + return fmt.Sprintf(` +resource "aws_iam_user_group_membership" "user1_test1" { + name = "%s-user1_test1" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group1.name}", + "${aws_iam_group.group2.name}", + ] +} +`, membershipName) +} + +func testAccAWSUserGroupMembershipConfigAddAll(membershipName string) string { + return fmt.Sprintf(` +resource "aws_iam_user_group_membership" "user1_test1" { + name = "%s-user1_test1" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group1.name}", + "${aws_iam_group.group2.name}", + ] +} + +resource "aws_iam_user_group_membership" "user1_test2" { + name = "%s-user1_test2" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group3.name}", + ] +} + +resource "aws_iam_user_group_membership" "user2_test1" { + name = "%s-user2_test1" + user = "${aws_iam_user.user2.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} + +resource "aws_iam_user_group_membership" "user2_test2" { + name = "%s-user2_test2" + user = "${aws_iam_user.user2.name}" + groups = [ + "${aws_iam_group.group2.name}", + "${aws_iam_group.group3.name}", + ] +} +`, membershipName, membershipName, membershipName, membershipName) +} + +// test removing a group +func testAccAWSUserGroupMembershipConfigRemoveGroup(membershipName string) string { + return fmt.Sprintf(` +resource "aws_iam_user_group_membership" "user1_test1" { + name = "%s-user1_test1" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} + +resource "aws_iam_user_group_membership" "user1_test2" { + name = "%s-user1_test2" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group3.name}", + ] +} + +resource "aws_iam_user_group_membership" "user2_test1" { + name = "%s-user2_test1" + user = "${aws_iam_user.user2.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} + +resource "aws_iam_user_group_membership" "user2_test2" { + name = "%s-user2_test2" + user = "${aws_iam_user.user2.name}" + groups = [ + "${aws_iam_group.group2.name}", + ] +} +`, membershipName, membershipName, membershipName, membershipName) +} + +// test deleting an entity +func testAccAWSUserGroupMembershipConfigDeleteResource(membershipName string) string { + return fmt.Sprintf(` +resource "aws_iam_user_group_membership" "user1_test1" { + name = "%s-user1_test1" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} + +resource "aws_iam_user_group_membership" "user1_test2" { + name = "%s-user1_test2" + user = "${aws_iam_user.user1.name}" + groups = [ + "${aws_iam_group.group3.name}", + ] +} + +resource "aws_iam_user_group_membership" "user2_test1" { + name = "%s-user2_test1" + user = "${aws_iam_user.user2.name}" + groups = [ + "${aws_iam_group.group1.name}", + ] +} +`, membershipName, membershipName, membershipName) +} From 98a6430abc073459e941a4d06abfe8958cfbd989 Mon Sep 17 00:00:00 2001 From: Devon Bleak Date: Tue, 10 Apr 2018 18:01:44 -0700 Subject: [PATCH 2/5] Add resource code --- aws/provider.go | 1 + aws/resource_aws_iam_user_group_membership.go | 175 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 aws/resource_aws_iam_user_group_membership.go diff --git a/aws/provider.go b/aws/provider.go index 1891e6418ba1..c093890c444a 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -416,6 +416,7 @@ func Provider() terraform.ResourceProvider { "aws_iam_saml_provider": resourceAwsIamSamlProvider(), "aws_iam_server_certificate": resourceAwsIAMServerCertificate(), "aws_iam_service_linked_role": resourceAwsIamServiceLinkedRole(), + "aws_iam_user_group_membership": resourceAwsIamUserGroupMembership(), "aws_iam_user_policy_attachment": resourceAwsIamUserPolicyAttachment(), "aws_iam_user_policy": resourceAwsIamUserPolicy(), "aws_iam_user_ssh_key": resourceAwsIamUserSshKey(), diff --git a/aws/resource_aws_iam_user_group_membership.go b/aws/resource_aws_iam_user_group_membership.go new file mode 100644 index 000000000000..01aa97236e7d --- /dev/null +++ b/aws/resource_aws_iam_user_group_membership.go @@ -0,0 +1,175 @@ +package aws + +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsIamUserGroupMembership() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsIamUserGroupMembershipCreate, + Read: resourceAwsIamUserGroupMembershipRead, + Update: resourceAwsIamUserGroupMembershipUpdate, + Delete: resourceAwsIamUserGroupMembershipDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "user": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "groups": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + } +} + +func resourceAwsIamUserGroupMembershipCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + user := d.Get("user").(string) + groupList := expandStringList(d.Get("groups").(*schema.Set).List()) + + if err := addUserToGroups(conn, user, groupList); err != nil { + return err + } + + d.SetId(d.Get("name").(string)) + + return resourceAwsIamUserGroupMembershipRead(d, meta) +} + +func resourceAwsIamUserGroupMembershipRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + user := d.Get("user").(string) + groups := d.Get("groups").(*schema.Set) + var gl []string + var marker *string + + for { + resp, err := conn.ListGroupsForUser(&iam.ListGroupsForUserInput{ + UserName: &user, + Marker: marker, + }) + if err != nil { + // unwrap aws-specific error + if awsErr, ok := err.(awserr.Error); ok { + if awsErr.Code() == "NoSuchEntity" { + // no such user + d.SetId("") + return nil + } + } + return err + } + + for _, g := range resp.Groups { + // only read in the groups we care about + if groups.Contains(*g.GroupName) { + gl = append(gl, *g.GroupName) + } + } + + if !*resp.IsTruncated { + break + } + + marker = resp.Marker + } + + if err := d.Set("groups", gl); err != nil { + return fmt.Errorf("[WARN] Error setting group list from IAM (%s), error: %s", user, err) + } + + return nil +} + +func resourceAwsIamUserGroupMembershipUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + + if d.HasChange("groups") { + user := d.Get("user").(string) + + o, n := d.GetChange("groups") + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + + os := o.(*schema.Set) + ns := n.(*schema.Set) + remove := expandStringList(os.Difference(ns).List()) + add := expandStringList(ns.Difference(os).List()) + + if err := removeUserFromGroups(conn, user, remove); err != nil { + return err + } + + if err := addUserToGroups(conn, user, add); err != nil { + return err + } + } + + return resourceAwsIamUserGroupMembershipRead(d, meta) +} + +func resourceAwsIamUserGroupMembershipDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).iamconn + user := d.Get("user").(string) + groups := expandStringList(d.Get("groups").(*schema.Set).List()) + + if err := removeUserFromGroups(conn, user, groups); err != nil { + return err + } + + return nil +} + +func removeUserFromGroups(conn *iam.IAM, user string, groups []*string) error { + for _, group := range groups { + _, err := conn.RemoveUserFromGroup(&iam.RemoveUserFromGroupInput{ + UserName: &user, + GroupName: group, + }) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoSuchEntity" { + continue + } + return err + } + } + + return nil +} + +func addUserToGroups(conn *iam.IAM, user string, groups []*string) error { + for _, group := range groups { + _, err := conn.AddUserToGroup(&iam.AddUserToGroupInput{ + UserName: &user, + GroupName: group, + }) + if err != nil { + return err + } + } + + return nil +} From 01a3425dbc697c85db7a51985988abec0dbadcf7 Mon Sep 17 00:00:00 2001 From: Devon Bleak Date: Fri, 13 Apr 2018 15:59:05 -0700 Subject: [PATCH 3/5] Add documentation --- website/aws.erb | 4 ++ .../docs/r/iam_group_membership.html.markdown | 4 +- .../r/iam_user_group_membership.html.markdown | 70 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 website/docs/r/iam_user_group_membership.html.markdown diff --git a/website/aws.erb b/website/aws.erb index 616605551f5b..3e08ecf2ac21 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -1211,6 +1211,10 @@ aws_iam_user + > + aws_iam_user_group_membership + + > aws_iam_user_login_profile diff --git a/website/docs/r/iam_group_membership.html.markdown b/website/docs/r/iam_group_membership.html.markdown index 054d4c45f9ce..bc93a7b2c5f6 100644 --- a/website/docs/r/iam_group_membership.html.markdown +++ b/website/docs/r/iam_group_membership.html.markdown @@ -12,6 +12,8 @@ Provides a top level resource to manage IAM Group membership for IAM Users. For more information on managing IAM Groups or IAM Users, see [IAM Groups][1] or [IAM Users][2] +~> **Note:** `aws_iam_group_membership` will conflict with itself if used more than once with the same group. + ## Example Usage ```hcl @@ -49,7 +51,7 @@ The following arguments are supported: ## Attributes Reference -* `name` - The name to identifing the Group Membership +* `name` - The name to identify the Group Membership * `users` - list of IAM User names * `group` – IAM Group name diff --git a/website/docs/r/iam_user_group_membership.html.markdown b/website/docs/r/iam_user_group_membership.html.markdown new file mode 100644 index 000000000000..ebace65ec795 --- /dev/null +++ b/website/docs/r/iam_user_group_membership.html.markdown @@ -0,0 +1,70 @@ +--- +layout: "aws" +page_title: "AWS: aws_iam_user_group_membership" +sidebar_current: "docs-aws-resource-iam-user-group-membership" +description: |- + Provides a resource for adding an IAM User to IAM Groups without conflicting + with itself. +--- + +# aws_iam_user_group_membership + +Provides a resource for adding an [IAM User][2] to [IAM Groups][1]. This +resource will not conflict with itself when used multiple times for the same +user. + +## Example usage + +```hcl +resource "aws_iam_user_group_membership" { + name = "user-group-membership-1" + user = "${aws_iam_user.user1.name}" + + groups = [ + "${aws_iam_group.group1.name}", + "${aws_iam_group.group2.name}", + ] +} + +resource "aws_iam_user_group_membership" { + name = "user-group-membership-2" + user = "${aws_iam_user.user1.name}" + + groups = [ + "${aws_iam_group.group3.name}", + ] +} + +resource "aws_iam_user" "user1" { + name = "user1" +} + +resource "aws_iam_group" "group1" { + name = "group1" +} + +resource "aws_iam_group" "group2" { + name = "group2" +} + +resource "aws_iam_group" "group3" { + name = "group3" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name to identify the user group Membership +* `user` - (Required) The name of the [IAM User][2] to add to groups +* `groups` - (Required) A list of [IAM Groups][1] to add the user to + +## Attributes Reference + +* `name` - The name to identify the user group membership +* `user` - The name of the IAM User +* `groups` - The list of IAM Groups + +[1]: /docs/providers/aws/r/iam_group.html +[2]: /docs/providers/aws/r/iam_user.html From e7ff7a17bd51be73ab03fae993426b88e7cfdddf Mon Sep 17 00:00:00 2001 From: Devon Bleak Date: Mon, 30 Apr 2018 23:01:24 -0700 Subject: [PATCH 4/5] Remove unnecessary argument "name", update to current standards --- aws/resource_aws_iam_user_group_membership.go | 14 ++--- ...urce_aws_iam_user_group_membership_test.go | 56 ++++++------------- .../r/iam_user_group_membership.html.markdown | 4 -- 3 files changed, 20 insertions(+), 54 deletions(-) diff --git a/aws/resource_aws_iam_user_group_membership.go b/aws/resource_aws_iam_user_group_membership.go index 01aa97236e7d..e8863f7ba72f 100644 --- a/aws/resource_aws_iam_user_group_membership.go +++ b/aws/resource_aws_iam_user_group_membership.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/iam" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) @@ -17,23 +18,16 @@ func resourceAwsIamUserGroupMembership() *schema.Resource { Delete: resourceAwsIamUserGroupMembershipDelete, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "user": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "user": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "groups": &schema.Schema{ + "groups": { Type: schema.TypeSet, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, }, } @@ -49,7 +43,7 @@ func resourceAwsIamUserGroupMembershipCreate(d *schema.ResourceData, meta interf return err } - d.SetId(d.Get("name").(string)) + d.SetId(resource.UniqueId()) return resourceAwsIamUserGroupMembershipRead(d, meta) } diff --git a/aws/resource_aws_iam_user_group_membership_test.go b/aws/resource_aws_iam_user_group_membership_test.go index 1929e9863553..d59862bb61e3 100644 --- a/aws/resource_aws_iam_user_group_membership_test.go +++ b/aws/resource_aws_iam_user_group_membership_test.go @@ -19,7 +19,6 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { groupName1 := fmt.Sprintf("tf-acc-ugm-basic-group1-%s", rString) groupName2 := fmt.Sprintf("tf-acc-ugm-basic-group2-%s", rString) groupName3 := fmt.Sprintf("tf-acc-ugm-basic-group3-%s", rString) - membershipName := fmt.Sprintf("tf-acc-ugm-basic-membership-%s", rString) usersAndGroupsConfig := testAccAWSUserGroupMembershipConfigUsersAndGroups(userName1, userName2, groupName1, groupName2, groupName3) @@ -30,7 +29,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { Steps: []resource.TestStep{ // simplest test resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigInit(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigInit, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1}, []string{groupName2, groupName3}), @@ -38,7 +37,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { }, // test adding an additional group to an existing resource resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddOne(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddOne, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), testAccAWSUserGroupMembershipCheckGroupListForUser(userName1, []string{groupName1, groupName2}, []string{groupName3}), @@ -46,7 +45,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { }, // test adding multiple resources for the same user, and resources with the same groups for another user resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), @@ -58,7 +57,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { }, // test that nothing happens when we apply the same config again resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigAddAll, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), @@ -70,7 +69,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { }, // test removing a group resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigRemoveGroup(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigRemoveGroup, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), @@ -82,7 +81,7 @@ func TestAccAWSUserGroupMembership_basic(t *testing.T) { }, // test removing a resource resource.TestStep{ - Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigDeleteResource(membershipName), + Config: usersAndGroupsConfig + testAccAWSUserGroupMembershipConfigDeleteResource, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test1", "user", userName1), resource.TestCheckResourceAttr("aws_iam_user_group_membership.user1_test2", "user", userName1), @@ -201,35 +200,27 @@ resource "aws_iam_group" "group3" { } // associate users and groups -func testAccAWSUserGroupMembershipConfigInit(membershipName string) string { - return fmt.Sprintf(` +const testAccAWSUserGroupMembershipConfigInit = ` resource "aws_iam_user_group_membership" "user1_test1" { - name = "%s-user1_test1" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group1.name}", ] } -`, membershipName) -} +` -func testAccAWSUserGroupMembershipConfigAddOne(membershipName string) string { - return fmt.Sprintf(` +const testAccAWSUserGroupMembershipConfigAddOne = ` resource "aws_iam_user_group_membership" "user1_test1" { - name = "%s-user1_test1" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group1.name}", "${aws_iam_group.group2.name}", ] } -`, membershipName) -} +` -func testAccAWSUserGroupMembershipConfigAddAll(membershipName string) string { - return fmt.Sprintf(` +const testAccAWSUserGroupMembershipConfigAddAll = ` resource "aws_iam_user_group_membership" "user1_test1" { - name = "%s-user1_test1" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group1.name}", @@ -238,7 +229,6 @@ resource "aws_iam_user_group_membership" "user1_test1" { } resource "aws_iam_user_group_membership" "user1_test2" { - name = "%s-user1_test2" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group3.name}", @@ -246,7 +236,6 @@ resource "aws_iam_user_group_membership" "user1_test2" { } resource "aws_iam_user_group_membership" "user2_test1" { - name = "%s-user2_test1" user = "${aws_iam_user.user2.name}" groups = [ "${aws_iam_group.group1.name}", @@ -254,21 +243,17 @@ resource "aws_iam_user_group_membership" "user2_test1" { } resource "aws_iam_user_group_membership" "user2_test2" { - name = "%s-user2_test2" user = "${aws_iam_user.user2.name}" groups = [ "${aws_iam_group.group2.name}", "${aws_iam_group.group3.name}", ] } -`, membershipName, membershipName, membershipName, membershipName) -} +` // test removing a group -func testAccAWSUserGroupMembershipConfigRemoveGroup(membershipName string) string { - return fmt.Sprintf(` +const testAccAWSUserGroupMembershipConfigRemoveGroup = ` resource "aws_iam_user_group_membership" "user1_test1" { - name = "%s-user1_test1" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group1.name}", @@ -276,7 +261,6 @@ resource "aws_iam_user_group_membership" "user1_test1" { } resource "aws_iam_user_group_membership" "user1_test2" { - name = "%s-user1_test2" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group3.name}", @@ -284,7 +268,6 @@ resource "aws_iam_user_group_membership" "user1_test2" { } resource "aws_iam_user_group_membership" "user2_test1" { - name = "%s-user2_test1" user = "${aws_iam_user.user2.name}" groups = [ "${aws_iam_group.group1.name}", @@ -292,20 +275,16 @@ resource "aws_iam_user_group_membership" "user2_test1" { } resource "aws_iam_user_group_membership" "user2_test2" { - name = "%s-user2_test2" user = "${aws_iam_user.user2.name}" groups = [ "${aws_iam_group.group2.name}", ] } -`, membershipName, membershipName, membershipName, membershipName) -} +` // test deleting an entity -func testAccAWSUserGroupMembershipConfigDeleteResource(membershipName string) string { - return fmt.Sprintf(` +const testAccAWSUserGroupMembershipConfigDeleteResource = ` resource "aws_iam_user_group_membership" "user1_test1" { - name = "%s-user1_test1" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group1.name}", @@ -313,7 +292,6 @@ resource "aws_iam_user_group_membership" "user1_test1" { } resource "aws_iam_user_group_membership" "user1_test2" { - name = "%s-user1_test2" user = "${aws_iam_user.user1.name}" groups = [ "${aws_iam_group.group3.name}", @@ -321,11 +299,9 @@ resource "aws_iam_user_group_membership" "user1_test2" { } resource "aws_iam_user_group_membership" "user2_test1" { - name = "%s-user2_test1" user = "${aws_iam_user.user2.name}" groups = [ "${aws_iam_group.group1.name}", ] } -`, membershipName, membershipName, membershipName) -} +` diff --git a/website/docs/r/iam_user_group_membership.html.markdown b/website/docs/r/iam_user_group_membership.html.markdown index ebace65ec795..d5f204ca0e13 100644 --- a/website/docs/r/iam_user_group_membership.html.markdown +++ b/website/docs/r/iam_user_group_membership.html.markdown @@ -17,7 +17,6 @@ user. ```hcl resource "aws_iam_user_group_membership" { - name = "user-group-membership-1" user = "${aws_iam_user.user1.name}" groups = [ @@ -27,7 +26,6 @@ resource "aws_iam_user_group_membership" { } resource "aws_iam_user_group_membership" { - name = "user-group-membership-2" user = "${aws_iam_user.user1.name}" groups = [ @@ -56,13 +54,11 @@ resource "aws_iam_group" "group3" { The following arguments are supported: -* `name` - (Required) The name to identify the user group Membership * `user` - (Required) The name of the [IAM User][2] to add to groups * `groups` - (Required) A list of [IAM Groups][1] to add the user to ## Attributes Reference -* `name` - The name to identify the user group membership * `user` - The name of the IAM User * `groups` - The list of IAM Groups From a468666c0742eee58678ca3c012cb2e5624a3707 Mon Sep 17 00:00:00 2001 From: Devon Bleak Date: Mon, 30 Apr 2018 23:21:03 -0700 Subject: [PATCH 5/5] Use isAWSErr helper, copy updates --- aws/resource_aws_iam_user_group_membership.go | 16 +++++++--------- ...esource_aws_iam_user_group_membership_test.go | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/aws/resource_aws_iam_user_group_membership.go b/aws/resource_aws_iam_user_group_membership.go index e8863f7ba72f..83ef39df1f07 100644 --- a/aws/resource_aws_iam_user_group_membership.go +++ b/aws/resource_aws_iam_user_group_membership.go @@ -2,8 +2,8 @@ package aws import ( "fmt" + "log" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/iam" "github.com/hashicorp/terraform/helper/resource" @@ -62,13 +62,11 @@ func resourceAwsIamUserGroupMembershipRead(d *schema.ResourceData, meta interfac Marker: marker, }) if err != nil { - // unwrap aws-specific error - if awsErr, ok := err.(awserr.Error); ok { - if awsErr.Code() == "NoSuchEntity" { - // no such user - d.SetId("") - return nil - } + if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") { + // no such user + log.Printf("[WARN] Groups not found for user (%s), removing from state", user) + d.SetId("") + return nil } return err } @@ -144,7 +142,7 @@ func removeUserFromGroups(conn *iam.IAM, user string, groups []*string) error { GroupName: group, }) if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoSuchEntity" { + if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") { continue } return err diff --git a/aws/resource_aws_iam_user_group_membership_test.go b/aws/resource_aws_iam_user_group_membership_test.go index d59862bb61e3..450f5717577f 100644 --- a/aws/resource_aws_iam_user_group_membership_test.go +++ b/aws/resource_aws_iam_user_group_membership_test.go @@ -163,7 +163,7 @@ func testAccAWSUserGroupMembershipCheckGroupListForUser(userName string, groups for _, group := range groupsNeg { for _, groupFound := range userGroupList.Groups { if group == *groupFound.GroupName { - return fmt.Errorf("Required negative group found for %s: %s", userName, group) + return fmt.Errorf("Unexpected group found for %s: %s", userName, group) } } }