From 5576ec6b107b4786b6879f6d2827d332b2ee7dbe Mon Sep 17 00:00:00 2001 From: Patrick Gray Date: Sun, 13 Sep 2015 03:27:07 -0400 Subject: [PATCH 1/4] implemented update function for aws_iam_user and it works but still causes transient error for aws_iam_group_membership --- .../providers/aws/resource_aws_iam_user.go | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/builtin/providers/aws/resource_aws_iam_user.go b/builtin/providers/aws/resource_aws_iam_user.go index c0ef4b8a4..e122e521e 100644 --- a/builtin/providers/aws/resource_aws_iam_user.go +++ b/builtin/providers/aws/resource_aws_iam_user.go @@ -14,9 +14,7 @@ func resourceAwsIamUser() *schema.Resource { return &schema.Resource{ Create: resourceAwsIamUserCreate, Read: resourceAwsIamUserRead, - // There is an UpdateUser API call, but goamz doesn't support it yet. - // XXX but we aren't using goamz anymore. - //Update: resourceAwsIamUserUpdate, + Update: resourceAwsIamUserUpdate, Delete: resourceAwsIamUserDelete, Schema: map[string]*schema.Schema{ @@ -39,7 +37,6 @@ func resourceAwsIamUser() *schema.Resource { "name": &schema.Schema{ Type: schema.TypeString, Required: true, - ForceNew: true, }, "path": &schema.Schema{ Type: schema.TypeString, @@ -54,9 +51,10 @@ func resourceAwsIamUser() *schema.Resource { func resourceAwsIamUserCreate(d *schema.ResourceData, meta interface{}) error { iamconn := meta.(*AWSClient).iamconn name := d.Get("name").(string) + path := d.Get("path").(string) request := &iam.CreateUserInput{ - Path: aws.String(d.Get("path").(string)), + Path: aws.String(path), UserName: aws.String(name), } @@ -69,9 +67,9 @@ func resourceAwsIamUserCreate(d *schema.ResourceData, meta interface{}) error { func resourceAwsIamUserRead(d *schema.ResourceData, meta interface{}) error { iamconn := meta.(*AWSClient).iamconn - + name := d.Get("name").(string) request := &iam.GetUserInput{ - UserName: aws.String(d.Id()), + UserName: aws.String(name), } getResp, err := iamconn.GetUser(request) @@ -102,6 +100,29 @@ func resourceAwsIamUserReadResult(d *schema.ResourceData, user *iam.User) error return nil } +func resourceAwsIamUserUpdate(d *schema.ResourceData, meta interface{}) error { + if d.HasChange("name") || d.HasChange("path") { + iamconn := meta.(*AWSClient).iamconn + on, nn := d.GetChange("name") + op, np := d.GetChange("path") + fmt.Println(on, nn, op, np) + request := &iam.UpdateUserInput{ + UserName: aws.String(on.(string)), + NewUserName: aws.String(nn.(string)), + NewPath: aws.String(np.(string)), + } + _, err := iamconn.UpdateUser(request) + if err != nil { + if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { + d.SetId("") + return nil + } + return fmt.Errorf("Error updating IAM User %s: %s", d.Id(), err) + } + return resourceAwsIamUserRead(d, meta) + } + return nil +} func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error { iamconn := meta.(*AWSClient).iamconn From 0ab12a54f138a9d70e9bc6ba97b955c58f57f874 Mon Sep 17 00:00:00 2001 From: Patrick Gray Date: Sun, 13 Sep 2015 03:37:45 -0400 Subject: [PATCH 2/4] handle error of trying to remove a user from a group when their name has already changed --- builtin/providers/aws/resource_aws_iam_group_membership.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builtin/providers/aws/resource_aws_iam_group_membership.go b/builtin/providers/aws/resource_aws_iam_group_membership.go index c90511cd6..14bdd3713 100644 --- a/builtin/providers/aws/resource_aws_iam_group_membership.go +++ b/builtin/providers/aws/resource_aws_iam_group_membership.go @@ -135,6 +135,9 @@ func removeUsersFromGroup(conn *iam.IAM, users []*string, group string) error { }) if err != nil { + if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { + return nil + } return err } } From 37e280f6be4de2b6983d869096198261159b64b8 Mon Sep 17 00:00:00 2001 From: Patrick Gray Date: Sun, 13 Sep 2015 03:52:40 -0400 Subject: [PATCH 3/4] add tests for updating a user --- builtin/providers/aws/resource_aws_iam_user_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/builtin/providers/aws/resource_aws_iam_user_test.go b/builtin/providers/aws/resource_aws_iam_user_test.go index 0dd2530a1..4a7939658 100644 --- a/builtin/providers/aws/resource_aws_iam_user_test.go +++ b/builtin/providers/aws/resource_aws_iam_user_test.go @@ -26,6 +26,13 @@ func TestAccAWSUser_basic(t *testing.T) { testAccCheckAWSUserAttributes(&conf), ), }, + resource.TestStep{ + Config: testAccAWSUserConfig2, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSUserExists("aws_iam_user.user", &conf), + testAccCheckAWSUserAttributes(&conf), + ), + }, }, }) } @@ -105,3 +112,9 @@ resource "aws_iam_user" "user" { path = "/" } ` +const testAccAWSUserConfig2 = ` +resource "aws_iam_user" "user" { + name = "test-user2" + path = "/balls/" +} +` From eadee6bd33e04a53c65792c36268905a7138f57c Mon Sep 17 00:00:00 2001 From: Patrick Gray Date: Tue, 10 Nov 2015 15:24:45 -0500 Subject: [PATCH 4/4] modify aws_iam_user_test to correctly check username and path for initial and changed username/path --- builtin/providers/aws/resource_aws_iam_user_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin/providers/aws/resource_aws_iam_user_test.go b/builtin/providers/aws/resource_aws_iam_user_test.go index 4a7939658..d1ff3889e 100644 --- a/builtin/providers/aws/resource_aws_iam_user_test.go +++ b/builtin/providers/aws/resource_aws_iam_user_test.go @@ -23,14 +23,14 @@ func TestAccAWSUser_basic(t *testing.T) { Config: testAccAWSUserConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSUserExists("aws_iam_user.user", &conf), - testAccCheckAWSUserAttributes(&conf), + testAccCheckAWSUserAttributes(&conf, "test-user", "/"), ), }, resource.TestStep{ Config: testAccAWSUserConfig2, Check: resource.ComposeTestCheckFunc( testAccCheckAWSUserExists("aws_iam_user.user", &conf), - testAccCheckAWSUserAttributes(&conf), + testAccCheckAWSUserAttributes(&conf, "test-user2", "/path2/"), ), }, }, @@ -92,13 +92,13 @@ func testAccCheckAWSUserExists(n string, res *iam.GetUserOutput) resource.TestCh } } -func testAccCheckAWSUserAttributes(user *iam.GetUserOutput) resource.TestCheckFunc { +func testAccCheckAWSUserAttributes(user *iam.GetUserOutput, name string, path string) resource.TestCheckFunc { return func(s *terraform.State) error { - if *user.User.UserName != "test-user" { + if *user.User.UserName != name { return fmt.Errorf("Bad name: %s", *user.User.UserName) } - if *user.User.Path != "/" { + if *user.User.Path != path { return fmt.Errorf("Bad path: %s", *user.User.Path) } @@ -115,6 +115,6 @@ resource "aws_iam_user" "user" { const testAccAWSUserConfig2 = ` resource "aws_iam_user" "user" { name = "test-user2" - path = "/balls/" + path = "/path2/" } `