Skip to content

Commit

Permalink
Merge pull request #20687 from StateFarmIns/f_quicksight_group_member…
Browse files Browse the repository at this point in the history
…ship_resource

Add quicksight group membership resource
  • Loading branch information
anGie44 authored Sep 7, 2021
2 parents de8c9d2 + d69cc39 commit 4a5c16e
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/20687.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_quicksight_group_membership
```
33 changes: 33 additions & 0 deletions aws/internal/service/quicksight/finder/finder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package finder

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/quicksight"
)

func GroupMembership(conn *quicksight.QuickSight, listInput *quicksight.ListGroupMembershipsInput, userName string) (bool, error) {

found := false

for {
resp, err := conn.ListGroupMemberships(listInput)
if err != nil {
return false, err
}

for _, member := range resp.GroupMemberList {
if aws.StringValue(member.MemberName) == userName {
found = true
break
}
}

if found || resp.NextToken == nil {
break
}

listInput.NextToken = resp.NextToken
}

return found, nil
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,7 @@ func Provider() *schema.Provider {
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
"aws_qldb_ledger": resourceAwsQLDBLedger(),
"aws_quicksight_group": resourceAwsQuickSightGroup(),
"aws_quicksight_group_membership": resourceAwsQuickSightGroupMembership(),
"aws_quicksight_user": resourceAwsQuickSightUser(),
"aws_ram_principal_association": resourceAwsRamPrincipalAssociation(),
"aws_ram_resource_association": resourceAwsRamResourceAssociation(),
Expand Down
158 changes: 158 additions & 0 deletions aws/resource_aws_quicksight_group_membership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package aws

import (
"context"
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/quicksight"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/quicksight/finder"
)

func resourceAwsQuickSightGroupMembership() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceAwsQuickSightGroupMembershipCreate,
ReadWithoutTimeout: resourceAwsQuickSightGroupMembershipRead,
DeleteWithoutTimeout: resourceAwsQuickSightGroupMembershipDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},

"aws_account_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},

"member_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"namespace": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: "default",
ValidateFunc: validation.StringInSlice([]string{
"default",
}, false),
},
},
}
}

func resourceAwsQuickSightGroupMembershipCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).quicksightconn

awsAccountID := meta.(*AWSClient).accountid
namespace := d.Get("namespace").(string)
groupName := d.Get("group_name").(string)
memberName := d.Get("member_name").(string)

if v, ok := d.GetOk("aws_account_id"); ok {
awsAccountID = v.(string)
}

createOpts := &quicksight.CreateGroupMembershipInput{
AwsAccountId: aws.String(awsAccountID),
GroupName: aws.String(groupName),
MemberName: aws.String(memberName),
Namespace: aws.String(namespace),
}

resp, err := conn.CreateGroupMembershipWithContext(ctx, createOpts)
if err != nil {
return diag.Errorf("error adding QuickSight user (%s) to group (%s): %s", memberName, groupName, err)
}

d.SetId(fmt.Sprintf("%s/%s/%s/%s", awsAccountID, namespace, groupName, aws.StringValue(resp.GroupMember.MemberName)))

return resourceAwsQuickSightGroupMembershipRead(ctx, d, meta)
}

func resourceAwsQuickSightGroupMembershipRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).quicksightconn

awsAccountID, namespace, groupName, userName, err := resourceAwsQuickSightGroupMembershipParseID(d.Id())
if err != nil {
return diag.Errorf("%s", err)
}

listInput := &quicksight.ListGroupMembershipsInput{
AwsAccountId: aws.String(awsAccountID),
Namespace: aws.String(namespace),
GroupName: aws.String(groupName),
}

found, err := finder.GroupMembership(conn, listInput, userName)
if err != nil {
return diag.Errorf("Error listing QuickSight Group Memberships (%s): %s", d.Id(), err)
}

if !found {
log.Printf("[WARN] QuickSight User-group membership %s is not found, removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("aws_account_id", awsAccountID)
d.Set("namespace", namespace)
d.Set("member_name", userName)
d.Set("group_name", groupName)

return nil
}

func resourceAwsQuickSightGroupMembershipDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*AWSClient).quicksightconn

awsAccountID, namespace, groupName, userName, err := resourceAwsQuickSightGroupMembershipParseID(d.Id())
if err != nil {
return diag.Errorf("%s", err)
}

deleteOpts := &quicksight.DeleteGroupMembershipInput{
AwsAccountId: aws.String(awsAccountID),
Namespace: aws.String(namespace),
MemberName: aws.String(userName),
GroupName: aws.String(groupName),
}

if _, err := conn.DeleteGroupMembershipWithContext(ctx, deleteOpts); err != nil {
if isAWSErr(err, quicksight.ErrCodeResourceNotFoundException, "") {
return nil
}
return diag.Errorf("Error deleting QuickSight User-group membership %s: %s", d.Id(), err)
}

return nil
}

func resourceAwsQuickSightGroupMembershipParseID(id string) (string, string, string, string, error) {
parts := strings.SplitN(id, "/", 4)
if len(parts) < 4 || parts[0] == "" || parts[1] == "" || parts[2] == "" || parts[3] == "" {
return "", "", "", "", fmt.Errorf("unexpected format of ID (%s), expected AWS_ACCOUNT_ID/NAMESPACE/GROUP_NAME/USER_NAME", id)
}
return parts[0], parts[1], parts[2], parts[3], nil
}
141 changes: 141 additions & 0 deletions aws/resource_aws_quicksight_group_membership_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/quicksight"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/quicksight/finder"
)

func TestAccAWSQuickSightGroupMembership_basic(t *testing.T) {
groupName := acctest.RandomWithPrefix("tf-acc-test")
memberName := "tfacctest" + acctest.RandString(10)
resourceName := "aws_quicksight_group_membership.default"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, quicksight.EndpointsID),
CheckDestroy: testAccCheckQuickSightGroupMembershipDestroy,
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSQuickSightGroupMembershipConfig(groupName, memberName),
Check: resource.ComposeTestCheckFunc(
testAccCheckQuickSightGroupMembershipExists(resourceName),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSQuickSightGroupMembership_disappears(t *testing.T) {
groupName := acctest.RandomWithPrefix("tf-acc-test")
memberName := "tfacctest" + acctest.RandString(10)
resourceName := "aws_quicksight_group_membership.default"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, quicksight.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckQuickSightGroupMembershipDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSQuickSightGroupMembershipConfig(groupName, memberName),
Check: resource.ComposeTestCheckFunc(
testAccCheckQuickSightGroupMembershipExists(resourceName),
testAccCheckResourceDisappears(testAccProvider, resourceAwsQuickSightGroupMembership(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccCheckQuickSightGroupMembershipDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).quicksightconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_quicksight_group_membership" {
continue
}
awsAccountID, namespace, groupName, userName, err := resourceAwsQuickSightGroupMembershipParseID(rs.Primary.ID)
if err != nil {
return err
}
listInput := &quicksight.ListGroupMembershipsInput{
AwsAccountId: aws.String(awsAccountID),
Namespace: aws.String(namespace),
GroupName: aws.String(groupName),
}

found, err := finder.GroupMembership(conn, listInput, userName)

if tfawserr.ErrCodeEquals(err, quicksight.ErrCodeResourceNotFoundException) {
continue
}
if err != nil {
return err
}
if found {
return fmt.Errorf("QuickSight Group (%s) still exists", rs.Primary.ID)
}
}

return nil
}

func testAccCheckQuickSightGroupMembershipExists(resourceName string) 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, groupName, userName, err := resourceAwsQuickSightGroupMembershipParseID(rs.Primary.ID)
if err != nil {
return err
}

conn := testAccProvider.Meta().(*AWSClient).quicksightconn

listInput := &quicksight.ListGroupMembershipsInput{
AwsAccountId: aws.String(awsAccountID),
Namespace: aws.String(namespace),
GroupName: aws.String(groupName),
}

found, err := finder.GroupMembership(conn, listInput, userName)
if err != nil {
return fmt.Errorf("Error listing QuickSight Group Memberships: %s", err)
}

if !found {
return fmt.Errorf("QuickSight Group Membership (%s) not found", rs.Primary.ID)
}

return nil
}
}

func testAccAWSQuickSightGroupMembershipConfig(groupName string, memberName string) string {
return composeConfig(
testAccAWSQuickSightGroupConfig(groupName),
testAccAWSQuickSightUserConfig(memberName),
fmt.Sprintf(`
resource "aws_quicksight_group_membership" "default" {
group_name = aws_quicksight_group.default.group_name
member_name = aws_quicksight_user.%s.user_name
}
`, memberName))
}
41 changes: 41 additions & 0 deletions website/docs/r/quicksight_group_membership.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
subcategory: "QuickSight"
layout: "aws"
page_title: "AWS: aws_quicksight_group_membership"
description: |-
Manages a Resource QuickSight Group Membership.
---

# Resource: aws_quicksight_group_membership

Resource for managing QuickSight Group Membership

## Example Usage

```terraform
resource "aws_quicksight_group_membership" "example" {
group_name = "all-access-users"
member_name = "john_smith"
}
```

## Argument Reference

The following arguments are supported:

* `group_name` - (Required) The name of the group in which the member will be added.
* `member_name` - (Required) The name of the member to add to the group.
* `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.
* `namespace` - (Required) The namespace. Defaults to `default`. Currently only `default` is supported.

## Attributes Reference

All arguments above are exported.

## Import

QuickSight Group membership can be imported using the AWS account ID, namespace, group name and member name separated by `/`.

```
$ terraform import aws_quicksight_group_membership.example 123456789123/default/all-access-users/john_smith
```

0 comments on commit 4a5c16e

Please sign in to comment.