From 4382de6d140d3c550a07191a148b40045e2062f5 Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 16:44:52 -0400 Subject: [PATCH 1/7] Add basic resource for QuickSight user. --- aws/resource_aws_quicksight_user.go | 235 ++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 aws/resource_aws_quicksight_user.go diff --git a/aws/resource_aws_quicksight_user.go b/aws/resource_aws_quicksight_user.go new file mode 100644 index 00000000000..32275d36772 --- /dev/null +++ b/aws/resource_aws_quicksight_user.go @@ -0,0 +1,235 @@ +package aws + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/quicksight" +) + +func resourceAwsQuickSightUser() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsQuickSightUserCreate, + Read: resourceAwsQuickSightUserRead, + Update: resourceAwsQuickSightUserUpdate, + Delete: resourceAwsQuickSightUserDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "aws_account_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "email": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "iam_arn": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "identity_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "IAM", + "QUICKSIGHT", + }, false), + }, + + "namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "default", + ValidateFunc: validation.StringInSlice([]string{ + "default", + }, false), + }, + + "session_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + + "user_name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.NoZeroValues, + }, + + "user_role": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "READER", + "AUTHOR", + "ADMIN", + }, false), + }, + }, + } +} + +func resourceAwsQuickSightUserCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).quicksightconn + + awsAccountID := meta.(*AWSClient).accountid + + if v, ok := d.GetOk("aws_account_id"); ok { + awsAccountID = v.(string) + } + + createOpts := &quicksight.RegisterUserInput{ + AwsAccountId: aws.String(awsAccountID), + Email: aws.String(d.Get("email").(string)), + IdentityType: aws.String(d.Get("identity_type").(string)), + Namespace: aws.String(d.Get("namespace").(string)), + UserRole: aws.String(d.Get("user_role").(string)), + } + + if v, ok := d.GetOk("iam_arn"); ok { + createOpts.IamArn = aws.String(v.(string)) + } + + if v, ok := d.GetOk("session_name"); ok { + createOpts.SessionName = aws.String(v.(string)) + } + + if v, ok := d.GetOk("user_name"); ok { + createOpts.UserName = aws.String(v.(string)) + } + + resp, err := conn.RegisterUser(createOpts) + if err != nil { + return fmt.Errorf("Error registering user in QuickSight Group: %s", err) + } + + d.SetId(fmt.Sprintf("%s/%s/%s", awsAccountID, namespace, aws.StringValue(resp.User.UserName))) + + return resourceAwsQuickSightUserRead(d, meta) +} + +func resourceAwsQuickSightUserRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).quicksightconn + + awsAccountID, namespace, userName, err := resourceAwsQuickSightUserParseID(d.Id()) + if err != nil { + return err + } + + descOpts := &quicksight.DescribeUserInput{ + AwsAccountId: aws.String(awsAccountID), + Namespace: aws.String(namespace), + UserName: aws.String(userName), + } + + resp, err := conn.DescribeUser(descOpts) + if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] QuickSight User %s is not found", d.Id()) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("Error describing QuickSight User (%s): %s", d.Id(), err) + } + + d.Set("arn", resp.User.Arn) + d.Set("aws_account_id", awsAccountID) + d.Set("email", resp.User.email) + d.Set("identity_type", resp.User.IdentityType) + d.Set("namespace", namespace) + d.Set("user_role", resp.User.Role) + d.Set("user_name", resp.User.UserName) + + return nil +} + +func resourceAwsQuickSightUserUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).quicksightconn + + awsAccountID, namespace, userName, err := resourceAwsQuickSightUserParseID(d.Id()) + if err != nil { + return err + } + + updateOpts := &quicksight.UpdateUserInput{ + AwsAccountId: aws.String(awsAccountID), + Email: aws.String(d.Get("email").(string)), + Namespace: aws.String(namespace), + Role: aws.String(d.Get("user_role").(string)), + UserName: aws.String(userName) + } + + if v, ok := d.GetOk("user_name"); ok { + createOpts.UserName = aws.String(v.(string)) + } + + + _, err = conn.UpdateUser(updateOpts) + if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") { + log.Printf("[WARN] QuickSight User %s is not found", d.Id()) + d.SetId("") + return nil + } + if err != nil { + return fmt.Errorf("Error updating QuickSight User %s: %s", d.Id(), err) + } + + return resourceAwsQuickSightUserRead(d, meta) +} + +func resourceAwsQuickSightUserDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).quicksightconn + + awsAccountID, namespace, userName, err := resourceAwsQuickSightUserParseID(d.Id()) + if err != nil { + return err + } + + deleteOpts := &quicksight.DeleteGroupInput{ + AwsAccountId: aws.String(awsAccountID), + Namespace: aws.String(namespace), + UserName: aws.String(userName), + } + + if _, err := conn.DeleteUser(deleteOpts); err != nil { + if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") { + return nil + } + return fmt.Errorf("Error deleting QuickSight User %s: %s", d.Id(), err) + } + + return nil +} + +func resourceAwsQuickSightUserParseID(id string) (string, string, string, error) { + parts := strings.SplitN(id, "/", 3) + if len(parts) < 3 || parts[0] == "" || parts[1] == "" || parts[2] == "" { + return "", "", "", fmt.Errorf("unexpected format of ID (%s), expected AWS_ACCOUNT_ID/NAMESPACE/USER_NAME", id) + } + return parts[0], parts[1], parts[2], nil +} From af9878b23c6e624c4fb0e4d8919b33df0e4348b9 Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 16:58:19 -0400 Subject: [PATCH 2/7] Copy basic tests from QuickSight group resource. --- aws/resource_aws_quicksight_user_test.go | 223 +++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 aws/resource_aws_quicksight_user_test.go diff --git a/aws/resource_aws_quicksight_user_test.go b/aws/resource_aws_quicksight_user_test.go new file mode 100644 index 00000000000..5b0e892f496 --- /dev/null +++ b/aws/resource_aws_quicksight_user_test.go @@ -0,0 +1,223 @@ +package aws + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/quicksight" +) + +func TestAccAWSQuickSightUser_basic(t *testing.T) { + var user quicksight.User + resourceName := "aws_quicksight_user.default" + rName1 := acctest.RandomWithPrefix("tf-acc-test") + rName2 := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckQuickSightUserDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSQuickSightUserConfig(rName1), + Check: resource.ComposeTestCheckFunc( + testAccCheckQuickSightUserExists(resourceName, &user), + resource.TestCheckResourceAttr(resourceName, "user_name", rName1), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName1)), + ), + }, + { + Config: testAccAWSQuickSightUserConfig(rName2), + Check: resource.ComposeTestCheckFunc( + testAccCheckQuickSightUserExists(resourceName, &user), + resource.TestCheckResourceAttr(resourceName, "user_name", rName2), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName2)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { + var user quicksight.User + resourceName := "aws_quicksight_user.default" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckQuickSightUserDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSQuickSightUserEmail(rName, "nottarealemailbutworks"), + Check: resource.ComposeTestCheckFunc( + testAccCheckQuickSightUserExists(resourceName, &user), + resource.TestCheckResourceAttr(resourceName, "email", "nottarealemailbutworks"), + ), + }, + { + Config: testAccAWSQuickSightUserConfigWithEmail(rName, "nottarealemailbutworks2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckQuickSightUserExists(resourceName, &user), + resource.TestCheckResourceAttr(resourceName, "email", "nottarealemailbutworks2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSQuickSightUser *testing.T) { + var user quicksight.User + resourceName := "aws_quicksight_user.default" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckQuickSightUserDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSQuickSightUserConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckQuickSightUserExists(resourceName, &user), + testAccCheckQuickSightUserDisappears(&user), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckQuickSightUserExists(resourceName string, user *quicksight.User) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + awsAccountID, namespace, userName, err := resourceAwsQuickSightUserParseID(rs.Primary.ID) + if err != nil { + return err + } + + conn := testAccProvider.Meta().(*AWSClient).quicksightconn + + input := &quicksight.DescribeUserInput{ + AwsAccountId: aws.String(awsAccountID), + Namespace: aws.String(namespace), + UserName: aws.String(userName), + } + + output, err := conn.DescribeUser(input) + + if err != nil { + return err + } + + if output == nil || output.User == nil { + return fmt.Errorf("QuickSight User (%s) not found", rs.Primary.ID) + } + + *user = *output.User + + return nil + } +} + +func testAccCheckQuickSightUserDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).quicksightconn + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_quicksight_user" { + continue + } + + awsAccountID, namespace, userName, err := resourceAwsQuickSightUserParseID(rs.Primary.ID) + if err != nil { + return err + } + + _, err = conn.DescribeUser(&quicksight.DescribeUserInput{ + AwsAccountId: aws.String(awsAccountID), + Namespace: aws.String(namespace), + UserName: aws.String(userName), + }) + if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("QuickSight User '%s' was not deleted properly", rs.Primary.ID) + } + + return nil +} + +func testAccCheckQuickSightUserDisappears(v *quicksight.User) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).quicksightconn + + arn, err := arn.Parse(aws.StringValue(v.Arn)) + if err != nil { + return err + } + + parts := strings.SplitN(arn.Resource, "/", 3) + + input := &quicksight.DeleteUserInput{ + AwsAccountId: aws.String(arn.AccountID), + Namespace: aws.String(parts[1]), + UserName: v.UserName, + } + + if _, err := conn.DeleteUser(input); err != nil { + return err + } + + return nil + } +} + +func testAccAWSQuickSightUserConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_quicksight_user" "default" { + user_name = %[1]q + email = "fakeemail@example.com" + identity_type = "IAM" + user_role = "READER" +} +`, rName) +} + +func testAccAWSQuickSightUserConfigWithEmail(rName, email string) string { + return fmt.Sprintf(` +data "aws_caller_identity" "current" {} + +resource "aws_quicksight_user" "default" { + aws_account_id = "${data.aws_caller_identity.current.account_id}" + user_name = %[1]q + email = %[2]q + identity_type = "IAM" + user_role = "READER" +} +`, rName, email) +} From f01d5daba0cf480b28edebe0a8b6dbe53232e58b Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 16:59:43 -0400 Subject: [PATCH 3/7] Register aws_quicksight_user in provider.go. --- aws/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/aws/provider.go b/aws/provider.go index 0655be2d4c6..5a376501315 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -635,6 +635,7 @@ func Provider() terraform.ResourceProvider { "aws_placement_group": resourceAwsPlacementGroup(), "aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(), "aws_quicksight_group": resourceAwsQuickSightGroup(), + "aws_quicksight_user": resourceAwsQuickSightUser(), "aws_ram_principal_association": resourceAwsRamPrincipalAssociation(), "aws_ram_resource_association": resourceAwsRamResourceAssociation(), "aws_ram_resource_share": resourceAwsRamResourceShare(), From 953f292b8dad956a08a38968be08795e98b94e4b Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 17:19:09 -0400 Subject: [PATCH 4/7] Add docs and run `go fmt`. Fix minor issues here and there. --- aws/resource_aws_quicksight_user.go | 19 ++++---- aws/resource_aws_quicksight_user_test.go | 2 +- website/aws.erb | 3 ++ website/docs/r/quicksight_user.html.markdown | 49 ++++++++++++++++++++ 4 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 website/docs/r/quicksight_user.html.markdown diff --git a/aws/resource_aws_quicksight_user.go b/aws/resource_aws_quicksight_user.go index 32275d36772..7751bb9b0bf 100644 --- a/aws/resource_aws_quicksight_user.go +++ b/aws/resource_aws_quicksight_user.go @@ -75,8 +75,8 @@ func resourceAwsQuickSightUser() *schema.Resource { }, "user_name": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, ValidateFunc: validation.NoZeroValues, }, @@ -99,6 +99,8 @@ func resourceAwsQuickSightUserCreate(d *schema.ResourceData, meta interface{}) e awsAccountID := meta.(*AWSClient).accountid + namespace := d.Get("namespace").(string) + if v, ok := d.GetOk("aws_account_id"); ok { awsAccountID = v.(string) } @@ -107,7 +109,7 @@ func resourceAwsQuickSightUserCreate(d *schema.ResourceData, meta interface{}) e AwsAccountId: aws.String(awsAccountID), Email: aws.String(d.Get("email").(string)), IdentityType: aws.String(d.Get("identity_type").(string)), - Namespace: aws.String(d.Get("namespace").(string)), + Namespace: aws.String(namespace), UserRole: aws.String(d.Get("user_role").(string)), } @@ -159,7 +161,7 @@ func resourceAwsQuickSightUserRead(d *schema.ResourceData, meta interface{}) err d.Set("arn", resp.User.Arn) d.Set("aws_account_id", awsAccountID) - d.Set("email", resp.User.email) + d.Set("email", resp.User.Email) d.Set("identity_type", resp.User.IdentityType) d.Set("namespace", namespace) d.Set("user_role", resp.User.Role) @@ -181,14 +183,9 @@ func resourceAwsQuickSightUserUpdate(d *schema.ResourceData, meta interface{}) e Email: aws.String(d.Get("email").(string)), Namespace: aws.String(namespace), Role: aws.String(d.Get("user_role").(string)), - UserName: aws.String(userName) - } - - if v, ok := d.GetOk("user_name"); ok { - createOpts.UserName = aws.String(v.(string)) + UserName: aws.String(userName), } - _, err = conn.UpdateUser(updateOpts) if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") { log.Printf("[WARN] QuickSight User %s is not found", d.Id()) @@ -210,7 +207,7 @@ func resourceAwsQuickSightUserDelete(d *schema.ResourceData, meta interface{}) e return err } - deleteOpts := &quicksight.DeleteGroupInput{ + deleteOpts := &quicksight.DeleteUserInput{ AwsAccountId: aws.String(awsAccountID), Namespace: aws.String(namespace), UserName: aws.String(userName), diff --git a/aws/resource_aws_quicksight_user_test.go b/aws/resource_aws_quicksight_user_test.go index 5b0e892f496..a9f2aedb12a 100644 --- a/aws/resource_aws_quicksight_user_test.go +++ b/aws/resource_aws_quicksight_user_test.go @@ -83,7 +83,7 @@ func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { }) } -func TestAccAWSQuickSightUser *testing.T) { +func TestAccAWSQuickSightUser_basic(t *testing.T) { var user quicksight.User resourceName := "aws_quicksight_user.default" rName := acctest.RandomWithPrefix("tf-acc-test") diff --git a/website/aws.erb b/website/aws.erb index 8b880c6a1b0..bf22d8e7bd1 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -2244,6 +2244,9 @@
  • aws_quicksight_group
  • +
  • + aws_quicksight_user +
  • diff --git a/website/docs/r/quicksight_user.html.markdown b/website/docs/r/quicksight_user.html.markdown new file mode 100644 index 00000000000..5e7f9033c3d --- /dev/null +++ b/website/docs/r/quicksight_user.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "aws" +page_title: "AWS: aws_quicksight_user" +description: |- + Manages a Resource QuickSight User. +--- + +# Resource: aws_quicksight_user + +Resource for managing QuickSight User + +## Example Usage + +```hcl +resource "aws_quicksight_user" "example" { + user_name = "an-author" + email = "author@example.com" + identity_type = "IAM" + user_role = "AUTHOR" +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `email` - (Required) The email address of the user that you want to register. +* `identity_type` - (Required) Amazon QuickSight supports several ways of managing the identity of users. This parameter accepts two values: `IAM` and `QUICKSIGHT`. +* `user_role` - (Required) The Amazon QuickSight role of the user. The user role can be one of the following: `READER`, `AUTHOR`, or `ADMIN` +* `user_name` - (Optional) The Amazon QuickSight user name that you want to create for the user you are registering. +* `aws_account_id` - (Optional) The ID for the AWS account that the group is in. Currently, you use the ID for the AWS account that contains your Amazon QuickSight account. +* `iam_arn` - (Optional) The ARN of the IAM user or role that you are registering with Amazon QuickSight. +* `namespace` - (Optional) The namespace. Currently, you should set this to `default`. +* `session_name` - (Optional) The name of the IAM session to use when assuming roles that can embed QuickSight dashboards. + +## Attributes Reference + +All above attributes except for `session_name` are exported as well as: + +* `arn` - Amazon Resource Name (ARN) of the user + +## Import + +QuickSight User can be imported using the AWS account ID, namespace and user name separated by `/`. + +``` +$ terraform import aws_quicksight_user.example 123456789123/default/a-reader-user +``` From 3aede99e8c3db4f98a80f53fb6386e81f9f19231 Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 17:48:07 -0400 Subject: [PATCH 5/7] Fix test name. --- CHANGELOG.md | 4 ++++ aws/resource_aws_quicksight_user_test.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1526ab3351f..c9a423cd337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ NOTES: * provider: The underlying Terraform codebase dependency for the provider SDK and acceptance testing framework has been migrated from `github.com/hashicorp/terraform` to `github.com/hashicorp/terraform-plugin-sdk`. They are functionality equivalent and this should only impact codebase development to switch imports. For more information see the [Terraform Plugin SDK page in the Extending Terraform documentation](https://www.terraform.io/docs/extend/plugin-sdk.html). [GH-10367] +FEATURES: + +* **New Resource:** `aws_quicksight_users` + BUG FIXES: * resource/aws_s3_bucket: Prevent infinite deletion recursion with `force_destroy` argument and object keys with empty "directory" prefixes present since version 2.29.0 [GH-10388] diff --git a/aws/resource_aws_quicksight_user_test.go b/aws/resource_aws_quicksight_user_test.go index a9f2aedb12a..ce8276d88a3 100644 --- a/aws/resource_aws_quicksight_user_test.go +++ b/aws/resource_aws_quicksight_user_test.go @@ -83,7 +83,7 @@ func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { }) } -func TestAccAWSQuickSightUser_basic(t *testing.T) { +func TestAccAWSQuickSightUser_disappears(t *testing.T) { var user quicksight.User resourceName := "aws_quicksight_user.default" rName := acctest.RandomWithPrefix("tf-acc-test") From 3c20fce471f152b3ed2d05995e8d1a46dea252dd Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Sun, 6 Oct 2019 17:48:59 -0400 Subject: [PATCH 6/7] Fix test helper reference name. --- aws/resource_aws_quicksight_user_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_quicksight_user_test.go b/aws/resource_aws_quicksight_user_test.go index ce8276d88a3..b628bb44935 100644 --- a/aws/resource_aws_quicksight_user_test.go +++ b/aws/resource_aws_quicksight_user_test.go @@ -61,7 +61,7 @@ func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { CheckDestroy: testAccCheckQuickSightUserDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSQuickSightUserEmail(rName, "nottarealemailbutworks"), + Config: testAccAWSQuickSightUserConfigWithEmail(rName, "nottarealemailbutworks"), Check: resource.ComposeTestCheckFunc( testAccCheckQuickSightUserExists(resourceName, &user), resource.TestCheckResourceAttr(resourceName, "email", "nottarealemailbutworks"), From fd075180366a69137b1c2298a1b1510e6cd602eb Mon Sep 17 00:00:00 2001 From: Michael Gilliland Date: Thu, 10 Oct 2019 17:58:56 -0400 Subject: [PATCH 7/7] Address review comments for `aws_quicksight_user` by - Using go-sdk constants - Running, fixing and cleaning tests Here's my current test output ``` bash AWS_DEFAULT_REGION=us-east-1 AWS_PROFILE=default TF_ACC=1 go test ./aws -v -timeout 120m -parallel 20 -run='TestAccAWSQuickSightUser_' ``` > go: finding github.com/terraform-providers/terraform-provider-tls > v2.1.1+incompatible > go: finding github.com/terraform-providers/terraform-provider-tls > v2.1.1+incompatible > === RUN TestAccAWSQuickSightUser_basic > === PAUSE TestAccAWSQuickSightUser_basic > === RUN TestAccAWSQuickSightUser_withInvalidFormattedEmailStillWorks > === PAUSE TestAccAWSQuickSightUser_withInvalidFormattedEmailStillWorks > === RUN TestAccAWSQuickSightUser_disappears > === PAUSE TestAccAWSQuickSightUser_disappears > === CONT TestAccAWSQuickSightUser_basic > === CONT TestAccAWSQuickSightUser_disappears > === CONT TestAccAWSQuickSightUser_withInvalidFormattedEmailStillWorks > --- PASS: TestAccAWSQuickSightUser_disappears (14.19s) > --- PASS: TestAccAWSQuickSightUser_basic (25.44s) > --- PASS: TestAccAWSQuickSightUser_withInvalidFormattedEmailStillWorks > (26.08s) > PASS > ok github.com/terraform-providers/terraform-provider-aws/aws > 26.109s Note that the tests exposed that the `describe-user` QuickSight API does not return the schema that is documented. For example, when I run it via the CLI I get ``` json { "RequestId": "some-guid-looking-thing", "Status": 200, "User": { "Arn": "arn:aws:quicksight:us-west-2:01234567890:user/default/some_user", "PrincipalId": "federated/iam/some_user", "Email": "someemail@pfake.com", "Active": true, "Role": "ADMIN", "UserName": "some_user" } } ``` Notice that `IdentityType` is missing though documented! This means that I had to remove it from attributes and remove the importer :( since we can't reconcile that value. If there's a way around this please let me know. Also note that I couldn't use `acctest.RandomWithPrefix` because the resultant username was not valid in QuickSight. --- CHANGELOG.md | 4 -- aws/resource_aws_quicksight_user.go | 17 ++---- aws/resource_aws_quicksight_user_test.go | 58 +++++++------------- website/docs/r/quicksight_user.html.markdown | 8 +-- 4 files changed, 29 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9a423cd337..1526ab3351f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,6 @@ NOTES: * provider: The underlying Terraform codebase dependency for the provider SDK and acceptance testing framework has been migrated from `github.com/hashicorp/terraform` to `github.com/hashicorp/terraform-plugin-sdk`. They are functionality equivalent and this should only impact codebase development to switch imports. For more information see the [Terraform Plugin SDK page in the Extending Terraform documentation](https://www.terraform.io/docs/extend/plugin-sdk.html). [GH-10367] -FEATURES: - -* **New Resource:** `aws_quicksight_users` - BUG FIXES: * resource/aws_s3_bucket: Prevent infinite deletion recursion with `force_destroy` argument and object keys with empty "directory" prefixes present since version 2.29.0 [GH-10388] diff --git a/aws/resource_aws_quicksight_user.go b/aws/resource_aws_quicksight_user.go index 7751bb9b0bf..63f2145b8c8 100644 --- a/aws/resource_aws_quicksight_user.go +++ b/aws/resource_aws_quicksight_user.go @@ -19,10 +19,6 @@ func resourceAwsQuickSightUser() *schema.Resource { Update: resourceAwsQuickSightUserUpdate, Delete: resourceAwsQuickSightUserDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - Schema: map[string]*schema.Schema{ "arn": { Type: schema.TypeString, @@ -53,8 +49,8 @@ func resourceAwsQuickSightUser() *schema.Resource { Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ - "IAM", - "QUICKSIGHT", + quicksight.IdentityTypeIam, + quicksight.IdentityTypeQuicksight, }, false), }, @@ -85,9 +81,9 @@ func resourceAwsQuickSightUser() *schema.Resource { Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ - "READER", - "AUTHOR", - "ADMIN", + quicksight.UserRoleReader, + quicksight.UserRoleAuthor, + quicksight.UserRoleAdmin, }, false), }, }, @@ -127,7 +123,7 @@ func resourceAwsQuickSightUserCreate(d *schema.ResourceData, meta interface{}) e resp, err := conn.RegisterUser(createOpts) if err != nil { - return fmt.Errorf("Error registering user in QuickSight Group: %s", err) + return fmt.Errorf("Error registering QuickSight user: %s", err) } d.SetId(fmt.Sprintf("%s/%s/%s", awsAccountID, namespace, aws.StringValue(resp.User.UserName))) @@ -162,7 +158,6 @@ func resourceAwsQuickSightUserRead(d *schema.ResourceData, meta interface{}) err d.Set("arn", resp.User.Arn) d.Set("aws_account_id", awsAccountID) d.Set("email", resp.User.Email) - d.Set("identity_type", resp.User.IdentityType) d.Set("namespace", namespace) d.Set("user_role", resp.User.Role) d.Set("user_name", resp.User.UserName) diff --git a/aws/resource_aws_quicksight_user_test.go b/aws/resource_aws_quicksight_user_test.go index b628bb44935..d83438c8dc0 100644 --- a/aws/resource_aws_quicksight_user_test.go +++ b/aws/resource_aws_quicksight_user_test.go @@ -16,9 +16,10 @@ import ( func TestAccAWSQuickSightUser_basic(t *testing.T) { var user quicksight.User - resourceName := "aws_quicksight_user.default" - rName1 := acctest.RandomWithPrefix("tf-acc-test") - rName2 := acctest.RandomWithPrefix("tf-acc-test") + rName1 := "tfacctest" + acctest.RandString(10) + resourceName1 := "aws_quicksight_user." + rName1 + rName2 := "tfacctest" + acctest.RandString(10) + resourceName2 := "aws_quicksight_user." + rName2 resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -28,32 +29,27 @@ func TestAccAWSQuickSightUser_basic(t *testing.T) { { Config: testAccAWSQuickSightUserConfig(rName1), Check: resource.ComposeTestCheckFunc( - testAccCheckQuickSightUserExists(resourceName, &user), - resource.TestCheckResourceAttr(resourceName, "user_name", rName1), - testAccCheckResourceAttrRegionalARN(resourceName, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName1)), + testAccCheckQuickSightUserExists(resourceName1, &user), + resource.TestCheckResourceAttr(resourceName1, "user_name", rName1), + testAccCheckResourceAttrRegionalARN(resourceName1, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName1)), ), }, { Config: testAccAWSQuickSightUserConfig(rName2), Check: resource.ComposeTestCheckFunc( - testAccCheckQuickSightUserExists(resourceName, &user), - resource.TestCheckResourceAttr(resourceName, "user_name", rName2), - testAccCheckResourceAttrRegionalARN(resourceName, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName2)), + testAccCheckQuickSightUserExists(resourceName2, &user), + resource.TestCheckResourceAttr(resourceName2, "user_name", rName2), + testAccCheckResourceAttrRegionalARN(resourceName2, "arn", "quicksight", fmt.Sprintf("user/default/%s", rName2)), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, }, }) } -func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { +func TestAccAWSQuickSightUser_withInvalidFormattedEmailStillWorks(t *testing.T) { var user quicksight.User - resourceName := "aws_quicksight_user.default" - rName := acctest.RandomWithPrefix("tf-acc-test") + rName := "tfacctest" + acctest.RandString(10) + resourceName := "aws_quicksight_user." + rName resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -74,19 +70,14 @@ func TestAccAWSQuickSightUser_withRealEmail(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "email", "nottarealemailbutworks2"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, }, }) } func TestAccAWSQuickSightUser_disappears(t *testing.T) { var user quicksight.User - resourceName := "aws_quicksight_user.default" - rName := acctest.RandomWithPrefix("tf-acc-test") + rName := "tfacctest" + acctest.RandString(10) + resourceName := "aws_quicksight_user." + rName resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -197,27 +188,20 @@ func testAccCheckQuickSightUserDisappears(v *quicksight.User) resource.TestCheck } } -func testAccAWSQuickSightUserConfig(rName string) string { - return fmt.Sprintf(` -resource "aws_quicksight_user" "default" { - user_name = %[1]q - email = "fakeemail@example.com" - identity_type = "IAM" - user_role = "READER" -} -`, rName) -} - func testAccAWSQuickSightUserConfigWithEmail(rName, email string) string { return fmt.Sprintf(` data "aws_caller_identity" "current" {} -resource "aws_quicksight_user" "default" { +resource "aws_quicksight_user" %[1]q { aws_account_id = "${data.aws_caller_identity.current.account_id}" user_name = %[1]q email = %[2]q - identity_type = "IAM" + identity_type = "QUICKSIGHT" user_role = "READER" } `, rName, email) } + +func testAccAWSQuickSightUserConfig(rName string) string { + return testAccAWSQuickSightUserConfigWithEmail(rName, "fakeemail@example.com") +} diff --git a/website/docs/r/quicksight_user.html.markdown b/website/docs/r/quicksight_user.html.markdown index 5e7f9033c3d..47be99adf55 100644 --- a/website/docs/r/quicksight_user.html.markdown +++ b/website/docs/r/quicksight_user.html.markdown @@ -36,14 +36,10 @@ The following arguments are supported: ## Attributes Reference -All above attributes except for `session_name` are exported as well as: +All above attributes except for `session_name` and `identity_type` are exported as well as: * `arn` - Amazon Resource Name (ARN) of the user ## Import -QuickSight User can be imported using the AWS account ID, namespace and user name separated by `/`. - -``` -$ terraform import aws_quicksight_user.example 123456789123/default/a-reader-user -``` +Importing is currently not supported on this resource.