From 69810af532bcc043c884aa8f3851a7983c422277 Mon Sep 17 00:00:00 2001 From: Andrew Babichev Date: Tue, 17 Nov 2020 15:59:21 +0200 Subject: [PATCH 1/3] aws_workspaces_directory: Assign IP group --- aws/resource_aws_workspaces_directory.go | 42 ++++++++++ aws/resource_aws_workspaces_directory_test.go | 80 +++++++++++++++++++ aws/resource_aws_workspaces_ip_group.go | 42 +++++++++- .../docs/r/workspaces_directory.html.markdown | 19 ++++- 4 files changed, 179 insertions(+), 4 deletions(-) diff --git a/aws/resource_aws_workspaces_directory.go b/aws/resource_aws_workspaces_directory.go index a9d148e0c4aa..f3aaaeeb6965 100644 --- a/aws/resource_aws_workspaces_directory.go +++ b/aws/resource_aws_workspaces_directory.go @@ -55,6 +55,7 @@ func resourceAwsWorkspacesDirectory() *schema.Resource { Type: schema.TypeSet, Elem: &schema.Schema{Type: schema.TypeString}, Computed: true, + Optional: true, }, "registration_code": { Type: schema.TypeString, @@ -200,6 +201,19 @@ func resourceAwsWorkspacesDirectoryCreate(d *schema.ResourceData, meta interface log.Printf("[DEBUG] WorkSpaces Directory %q creation properties are set", directoryId) } + if v, ok := d.GetOk("ip_group_ids"); ok && v.(*schema.Set).Len() > 0 { + ipGroupIds := v.(*schema.Set) + log.Printf("[DEBUG] Associate WorkSpaces Directory %q with IP Groups %s...", directoryId, ipGroupIds.List()) + _, err := conn.AssociateIpGroups(&workspaces.AssociateIpGroupsInput{ + DirectoryId: aws.String(directoryId), + GroupIds: expandStringSet(ipGroupIds), + }) + if err != nil { + return fmt.Errorf("error asassociating ip groups: %s", err) + } + log.Printf("[DEBUG] WorkSpaces Directory %q IP Groups are set", directoryId) + } + return resourceAwsWorkspacesDirectoryRead(d, meta) } @@ -288,6 +302,34 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface log.Printf("[DEBUG] WorkSpaces Directory %q creation properties are set", d.Id()) } + if d.HasChange("ip_group_ids") { + o, n := d.GetChange("ip_group_ids") + old := o.(*schema.Set) + new := n.(*schema.Set) + added := new.Difference(old) + removed := old.Difference(new) + + log.Printf("[DEBUG] Associate IP Groups %s from WorkSpaces Directory %q...", added.GoString(), d.Id()) + _, err := conn.AssociateIpGroups(&workspaces.AssociateIpGroupsInput{ + DirectoryId: aws.String(d.Id()), + GroupIds: expandStringSet(added), + }) + if err != nil { + return fmt.Errorf("error asassociating ip groups: %s", err) + } + + log.Printf("[DEBUG] Disassociate IP Groups %s from WorkSpaces Directory %q...", removed.GoString(), d.Id()) + _, err = conn.DisassociateIpGroups(&workspaces.DisassociateIpGroupsInput{ + DirectoryId: aws.String(d.Id()), + GroupIds: expandStringSet(removed), + }) + if err != nil { + return fmt.Errorf("error disasassociating ip groups: %s", err) + } + + log.Printf("[DEBUG] WorkSpaces Directory %q IP Groups are set", d.Id()) + } + if d.HasChange("tags") { o, n := d.GetChange("tags") if err := keyvaluetags.WorkspacesUpdateTags(conn, d.Id(), o, n); err != nil { diff --git a/aws/resource_aws_workspaces_directory_test.go b/aws/resource_aws_workspaces_directory_test.go index 3dffc6b8b006..9c18ea9f803a 100644 --- a/aws/resource_aws_workspaces_directory_test.go +++ b/aws/resource_aws_workspaces_directory_test.go @@ -283,6 +283,45 @@ func TestAccAwsWorkspacesDirectory_workspaceCreationProperties(t *testing.T) { }) } +func TestAccAwsWorkspacesDirectory_ipGroupIds(t *testing.T) { + var v workspaces.WorkspaceDirectory + rName := acctest.RandString(8) + + resourceName := "aws_workspaces_directory.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckHasIAMRole(t, "workspaces_DefaultRole") }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsWorkspacesDirectoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccWorkspacesDirectoryConfig_ipGroupIds_create(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsWorkspacesDirectoryExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccWorkspacesDirectoryConfig_ipGroupIds_update(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsWorkspacesDirectoryExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccPreCheckHasIAMRole(t *testing.T, roleName string) { conn := testAccProvider.Meta().(*AWSClient).iamconn @@ -618,3 +657,44 @@ resource "aws_workspaces_directory" "main" { } `, rName)) } + +func testAccWorkspacesDirectoryConfig_ipGroupIds_create(rName string) string { + return composeConfig( + testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), + fmt.Sprintf(` +resource "aws_workspaces_ip_group" "test_alpha" { + name = "%[1]s-alpha" +} + +resource "aws_workspaces_directory" "test" { + directory_id = aws_directory_service_directory.main.id + + ip_group_ids = [ + aws_workspaces_ip_group.test_alpha.id + ] +} +`, rName)) +} + +func testAccWorkspacesDirectoryConfig_ipGroupIds_update(rName string) string { + return composeConfig( + testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), + fmt.Sprintf(` +resource "aws_workspaces_ip_group" "test_beta" { + name = "%[1]s-beta" +} + +resource "aws_workspaces_ip_group" "test_gamma" { + name = "%[1]s-gamma" +} + +resource "aws_workspaces_directory" "test" { + directory_id = aws_directory_service_directory.main.id + + ip_group_ids = [ + aws_workspaces_ip_group.test_beta.id, + aws_workspaces_ip_group.test_gamma.id + ] +} +`, rName)) +} diff --git a/aws/resource_aws_workspaces_ip_group.go b/aws/resource_aws_workspaces_ip_group.go index 841f7d12dd9a..b21914cf7138 100644 --- a/aws/resource_aws_workspaces_ip_group.go +++ b/aws/resource_aws_workspaces_ip_group.go @@ -148,13 +148,49 @@ func resourceAwsWorkspacesIpGroupUpdate(d *schema.ResourceData, meta interface{} func resourceAwsWorkspacesIpGroupDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).workspacesconn - log.Printf("[INFO] Deleting Workspaces IP Group") - _, err := conn.DeleteIpGroup(&workspaces.DeleteIpGroupInput{ + var directoryID *string + + log.Printf("[DEBUG] Finding directory associated with Workspaces IP Group %q", d.Id()) + err := conn.DescribeWorkspaceDirectoriesPages(nil, + func(page *workspaces.DescribeWorkspaceDirectoriesOutput, lastPage bool) bool { + for _, dir := range page.Directories { + for _, ipg := range dir.IpGroupIds { + if aws.StringValue(ipg) == d.Id() { + directoryID = dir.DirectoryId + return true + } + } + } + return !lastPage + }, + ) + if err != nil { + return fmt.Errorf("error describing Workspaces IP Groups: %s", err) + } + + if directoryID == nil { + log.Printf("[DEBUG] Workspaces IP Group %q is not associated with any Directory", d.Id()) + } else { + log.Printf("[DEBUG] Workspaces IP Group %q is associated with Directory %q", d.Id(), aws.StringValue(directoryID)) + log.Printf("[INFO] Disassociating Workspaces IP Group %q from Directory %q", d.Id(), aws.StringValue(directoryID)) + _, err = conn.DisassociateIpGroups(&workspaces.DisassociateIpGroupsInput{ + DirectoryId: directoryID, + GroupIds: aws.StringSlice([]string{d.Id()}), + }) + if err != nil { + return fmt.Errorf("error disassociating Workspaces IP Group: %s", err) + } + log.Printf("[INFO] Workspaces IP Group %q has been successfully disassociated from Directory %q", d.Id(), aws.StringValue(directoryID)) + } + + log.Printf("[INFO] Deleting Workspaces IP Group %q", d.Id()) + _, err = conn.DeleteIpGroup(&workspaces.DeleteIpGroupInput{ GroupId: aws.String(d.Id()), }) if err != nil { - return fmt.Errorf("Error Deleting Workspaces IP Group: %s", err) + return fmt.Errorf("error deleting Workspaces IP Group: %s", err) } + log.Printf("[INFO] Workspaces IP Group %q has been successfully deleted", d.Id()) return nil } diff --git a/website/docs/r/workspaces_directory.html.markdown b/website/docs/r/workspaces_directory.html.markdown index aa4431be6a6b..ea87bec8ff0b 100644 --- a/website/docs/r/workspaces_directory.html.markdown +++ b/website/docs/r/workspaces_directory.html.markdown @@ -116,12 +116,29 @@ resource "aws_subnet" "example_d" { } ``` +### IP Groups + +```hcl +resource "aws_workspaces_directory" "example" { + directory_id = aws_directory_service_directory.example.id + + ip_group_ids = [ + aws_workspaces_ip_group.example.id, + ] +} + +resource "aws_workspaces_ip_group" "example" { + name = "example" +} +``` + ## Arguments Reference The following arguments are supported: * `directory_id` - (Required) The directory identifier for registration in WorkSpaces service. -* `subnet_ids` - (Optional) The subnets identifiers where the workspaces are created. +* `subnet_ids` - (Optional) The identifiers of the subnets where the directory resides. +* `ip_group_ids` - The identifiers of the IP access control groups associated with the directory. * `tags` – (Optional) A map of tags assigned to the WorkSpaces directory. * `self_service_permissions` – (Optional) Permissions to enable or disable self-service capabilities. Defined below. * `workspace_creation_properties` – (Optional) Default properties that are used for creating WorkSpaces. Defined below. From 8cb3093faf17a15772ff3a62cf8b4b9358aa3fe9 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Tue, 17 Nov 2020 17:23:03 -0800 Subject: [PATCH 2/3] Cleanup --- aws/resource_aws_workspaces_directory.go | 92 +++++++++---------- aws/resource_aws_workspaces_directory_test.go | 13 +-- aws/resource_aws_workspaces_ip_group.go | 12 +-- aws/resource_aws_workspaces_ip_group_test.go | 2 +- 4 files changed, 58 insertions(+), 61 deletions(-) diff --git a/aws/resource_aws_workspaces_directory.go b/aws/resource_aws_workspaces_directory.go index f3aaaeeb6965..d00cbfd05f85 100644 --- a/aws/resource_aws_workspaces_directory.go +++ b/aws/resource_aws_workspaces_directory.go @@ -147,12 +147,12 @@ func resourceAwsWorkspacesDirectory() *schema.Resource { func resourceAwsWorkspacesDirectoryCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).workspacesconn - directoryId := d.Get("directory_id").(string) + directoryID := d.Get("directory_id").(string) tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WorkspacesTags() input := &workspaces.RegisterWorkspaceDirectoryInput{ - DirectoryId: aws.String(directoryId), + DirectoryId: aws.String(directoryID), EnableSelfService: aws.Bool(false), // this is handled separately below EnableWorkDocs: aws.Bool(false), Tenancy: aws.String(workspaces.TenancyShared), @@ -163,55 +163,55 @@ func resourceAwsWorkspacesDirectoryCreate(d *schema.ResourceData, meta interface input.SubnetIds = expandStringSet(v.(*schema.Set)) } - log.Printf("[DEBUG] Regestering WorkSpaces Directory...\n%#v\n", *input) + log.Printf("[DEBUG] Registering WorkSpaces Directory: %s", *input) _, err := conn.RegisterWorkspaceDirectory(input) if err != nil { return err } - d.SetId(directoryId) + d.SetId(directoryID) - log.Printf("[DEBUG] Waiting for WorkSpaces Directory %q to become registered...", directoryId) - _, err = waiter.DirectoryRegistered(conn, directoryId) + log.Printf("[DEBUG] Waiting for WorkSpaces Directory (%s) to be registered", directoryID) + _, err = waiter.DirectoryRegistered(conn, directoryID) if err != nil { - return fmt.Errorf("error registering directory: %s", err) + return fmt.Errorf("error registering WorkSpaces Directory (%s): %w", directoryID, err) } - log.Printf("[DEBUG] WorkSpaces Directory %q is registered", directoryId) + log.Printf("[INFO] WorkSpaces Directory (%s) registered", directoryID) if v, ok := d.GetOk("self_service_permissions"); ok { - log.Printf("[DEBUG] Modifying WorkSpaces Directory %q self-service permissions...", directoryId) + log.Printf("[DEBUG] Modifying WorkSpaces Directory (%s) self-service permissions", directoryID) _, err := conn.ModifySelfservicePermissions(&workspaces.ModifySelfservicePermissionsInput{ - ResourceId: aws.String(directoryId), + ResourceId: aws.String(directoryID), SelfservicePermissions: expandSelfServicePermissions(v.([]interface{})), }) if err != nil { - return fmt.Errorf("error setting self service permissions: %s", err) + return fmt.Errorf("error setting WorkSpaces Directory (%s) self service permissions: %w", directoryID, err) } - log.Printf("[DEBUG] WorkSpaces Directory %q self-service permissions are set", directoryId) + log.Printf("[INFO] Modified WorkSpaces Directory (%s) self-service permissions", directoryID) } if v, ok := d.GetOk("workspace_creation_properties"); ok { - log.Printf("[DEBUG] Modifying WorkSpaces Directory %q creation properties...", directoryId) + log.Printf("[DEBUG] Modifying WorkSpaces Directory (%s) creation properties", directoryID) _, err := conn.ModifyWorkspaceCreationProperties(&workspaces.ModifyWorkspaceCreationPropertiesInput{ - ResourceId: aws.String(directoryId), + ResourceId: aws.String(directoryID), WorkspaceCreationProperties: expandWorkspaceCreationProperties(v.([]interface{})), }) if err != nil { - return fmt.Errorf("error setting creation properties: %s", err) + return fmt.Errorf("error setting WorkSpaces Directory (%s) creation properties: %w", directoryID, err) } - log.Printf("[DEBUG] WorkSpaces Directory %q creation properties are set", directoryId) + log.Printf("[INFO] Modified WorkSpaces Directory (%s) creation properties", directoryID) } if v, ok := d.GetOk("ip_group_ids"); ok && v.(*schema.Set).Len() > 0 { ipGroupIds := v.(*schema.Set) - log.Printf("[DEBUG] Associate WorkSpaces Directory %q with IP Groups %s...", directoryId, ipGroupIds.List()) + log.Printf("[DEBUG] Associating WorkSpaces Directory (%s) with IP Groups %s", directoryID, ipGroupIds.List()) _, err := conn.AssociateIpGroups(&workspaces.AssociateIpGroupsInput{ - DirectoryId: aws.String(directoryId), + DirectoryId: aws.String(directoryID), GroupIds: expandStringSet(ipGroupIds), }) if err != nil { - return fmt.Errorf("error asassociating ip groups: %s", err) + return fmt.Errorf("error asassociating WorkSpaces Directory (%s) ip groups: %w", directoryID, err) } - log.Printf("[DEBUG] WorkSpaces Directory %q IP Groups are set", directoryId) + log.Printf("[INFO] Associated WorkSpaces Directory (%s) IP Groups", directoryID) } return resourceAwsWorkspacesDirectoryRead(d, meta) @@ -223,7 +223,7 @@ func resourceAwsWorkspacesDirectoryRead(d *schema.ResourceData, meta interface{} rawOutput, state, err := waiter.DirectoryState(conn, d.Id())() if err != nil { - return fmt.Errorf("error getting WorkSpaces Directory (%s): %s", d.Id(), err) + return fmt.Errorf("error getting WorkSpaces Directory (%s): %w", d.Id(), err) } if state == workspaces.WorkspaceDirectoryStateDeregistered { log.Printf("[WARN] WorkSpaces Directory (%s) not found, removing from state", d.Id()) @@ -234,7 +234,7 @@ func resourceAwsWorkspacesDirectoryRead(d *schema.ResourceData, meta interface{} directory := rawOutput.(*workspaces.WorkspaceDirectory) d.Set("directory_id", directory.DirectoryId) if err := d.Set("subnet_ids", flattenStringSet(directory.SubnetIds)); err != nil { - return fmt.Errorf("error setting subnet_ids: %s", err) + return fmt.Errorf("error setting subnet_ids: %w", err) } d.Set("workspace_security_group_id", directory.WorkspaceSecurityGroupId) d.Set("iam_role_id", directory.IamRoleId) @@ -244,28 +244,28 @@ func resourceAwsWorkspacesDirectoryRead(d *schema.ResourceData, meta interface{} d.Set("alias", directory.Alias) if err := d.Set("self_service_permissions", flattenSelfServicePermissions(directory.SelfservicePermissions)); err != nil { - return fmt.Errorf("error setting self_service_permissions: %s", err) + return fmt.Errorf("error setting self_service_permissions: %w", err) } if err := d.Set("workspace_creation_properties", flattenWorkspaceCreationProperties(directory.WorkspaceCreationProperties)); err != nil { - return fmt.Errorf("error setting workspace_creation_properties: %s", err) + return fmt.Errorf("error setting workspace_creation_properties: %w", err) } if err := d.Set("ip_group_ids", flattenStringSet(directory.IpGroupIds)); err != nil { - return fmt.Errorf("error setting ip_group_ids: %s", err) + return fmt.Errorf("error setting ip_group_ids: %w", err) } if err := d.Set("dns_ip_addresses", flattenStringSet(directory.DnsIpAddresses)); err != nil { - return fmt.Errorf("error setting dns_ip_addresses: %s", err) + return fmt.Errorf("error setting dns_ip_addresses: %w", err) } tags, err := keyvaluetags.WorkspacesListTags(conn, d.Id()) if err != nil { - return fmt.Errorf("error listing tags: %s", err) + return fmt.Errorf("error listing tags: %w", err) } if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + return fmt.Errorf("error setting tags: %w", err) } return nil @@ -275,7 +275,7 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface conn := meta.(*AWSClient).workspacesconn if d.HasChange("self_service_permissions") { - log.Printf("[DEBUG] Modifying WorkSpaces Directory %q self-service permissions...", d.Id()) + log.Printf("[DEBUG] Modifying WorkSpaces Directory (%s) self-service permissions", d.Id()) permissions := d.Get("self_service_permissions").([]interface{}) _, err := conn.ModifySelfservicePermissions(&workspaces.ModifySelfservicePermissionsInput{ @@ -283,13 +283,13 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface SelfservicePermissions: expandSelfServicePermissions(permissions), }) if err != nil { - return fmt.Errorf("error updating self service permissions: %s", err) + return fmt.Errorf("error updating WorkSpaces Directory (%s) self service permissions: %w", d.Id(), err) } - log.Printf("[DEBUG] WorkSpaces Directory %q self-service permissions are set", d.Id()) + log.Printf("[INFO] Modified WorkSpaces Directory (%s) self-service permissions", d.Id()) } if d.HasChange("workspace_creation_properties") { - log.Printf("[DEBUG] Modifying WorkSpaces Directory %q creation properties...", d.Id()) + log.Printf("[DEBUG] Modifying WorkSpaces Directory (%s) creation properties", d.Id()) properties := d.Get("workspace_creation_properties").([]interface{}) _, err := conn.ModifyWorkspaceCreationProperties(&workspaces.ModifyWorkspaceCreationPropertiesInput{ @@ -297,9 +297,9 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface WorkspaceCreationProperties: expandWorkspaceCreationProperties(properties), }) if err != nil { - return fmt.Errorf("error updating creation properties: %s", err) + return fmt.Errorf("error updating WorkSpaces Directory (%s) creation properties: %w", d.Id(), err) } - log.Printf("[DEBUG] WorkSpaces Directory %q creation properties are set", d.Id()) + log.Printf("[INFO] Modified WorkSpaces Directory (%s) creation properties", d.Id()) } if d.HasChange("ip_group_ids") { @@ -309,31 +309,31 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface added := new.Difference(old) removed := old.Difference(new) - log.Printf("[DEBUG] Associate IP Groups %s from WorkSpaces Directory %q...", added.GoString(), d.Id()) + log.Printf("[DEBUG] Associating WorkSpaces Directory (%s) with IP Groups %s", d.Id(), added.GoString()) _, err := conn.AssociateIpGroups(&workspaces.AssociateIpGroupsInput{ DirectoryId: aws.String(d.Id()), GroupIds: expandStringSet(added), }) if err != nil { - return fmt.Errorf("error asassociating ip groups: %s", err) + return fmt.Errorf("error asassociating WorkSpaces Directory (%s) IP Groups: %w", d.Id(), err) } - log.Printf("[DEBUG] Disassociate IP Groups %s from WorkSpaces Directory %q...", removed.GoString(), d.Id()) + log.Printf("[DEBUG] Disassociating WorkSpaces Directory (%s) with IP Groups %s", d.Id(), removed.GoString()) _, err = conn.DisassociateIpGroups(&workspaces.DisassociateIpGroupsInput{ DirectoryId: aws.String(d.Id()), GroupIds: expandStringSet(removed), }) if err != nil { - return fmt.Errorf("error disasassociating ip groups: %s", err) + return fmt.Errorf("error disasassociating WorkSpaces Directory (%s) IP Groups: %w", d.Id(), err) } - log.Printf("[DEBUG] WorkSpaces Directory %q IP Groups are set", d.Id()) + log.Printf("[INFO] Updated WorkSpaces Directory (%s) IP Groups", d.Id()) } if d.HasChange("tags") { o, n := d.GetChange("tags") if err := keyvaluetags.WorkspacesUpdateTags(conn, d.Id(), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("error updating tags: %w", err) } } @@ -345,27 +345,27 @@ func resourceAwsWorkspacesDirectoryDelete(d *schema.ResourceData, meta interface err := workspacesDirectoryDelete(d.Id(), conn) if err != nil { - return fmt.Errorf("error deleting WorkSpaces Directory (%s): %s", d.Id(), err) + return fmt.Errorf("error deleting WorkSpaces Directory (%s): %w", d.Id(), err) } return nil } func workspacesDirectoryDelete(id string, conn *workspaces.WorkSpaces) error { - log.Printf("[DEBUG] Deregistering WorkSpaces Directory %q", id) + log.Printf("[DEBUG] Deregistering WorkSpaces Directory (%s)", id) _, err := conn.DeregisterWorkspaceDirectory(&workspaces.DeregisterWorkspaceDirectoryInput{ DirectoryId: aws.String(id), }) if err != nil { - return fmt.Errorf("error deregistering WorkSpaces Directory %q: %w", id, err) + return fmt.Errorf("error deregistering WorkSpaces Directory (%s): %w", id, err) } - log.Printf("[DEBUG] Waiting for WorkSpaces Directory %q to be deregistered", id) + log.Printf("[DEBUG] Waiting for WorkSpaces Directory (%s) to be deregistered", id) _, err = waiter.DirectoryDeregistered(conn, id) if err != nil { - return fmt.Errorf("error waiting for WorkSpaces Directory %q to be deregistered: %w", id, err) + return fmt.Errorf("error waiting for WorkSpaces Directory (%s) to be deregistered: %w", id, err) } - log.Printf("[DEBUG] WorkSpaces Directory %q is deregistered", id) + log.Printf("[INFO] WorkSpaces Directory (%s) deregistered", id) return nil } diff --git a/aws/resource_aws_workspaces_directory_test.go b/aws/resource_aws_workspaces_directory_test.go index 9c18ea9f803a..e21610806958 100644 --- a/aws/resource_aws_workspaces_directory_test.go +++ b/aws/resource_aws_workspaces_directory_test.go @@ -38,7 +38,6 @@ func testSweepWorkspacesDirectories(region string) error { if err != nil { errors = multierror.Append(errors, err) } - } return true }) @@ -47,7 +46,7 @@ func testSweepWorkspacesDirectories(region string) error { return errors // In case we have completed some pages, but had errors } if err != nil { - errors = multierror.Append(errors, fmt.Errorf("error listing Workspace Directories: %s", err)) + errors = multierror.Append(errors, fmt.Errorf("error listing WorkSpaces Directories: %w", err)) } return errors @@ -90,6 +89,7 @@ func TestAccAwsWorkspacesDirectory_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "self_service_permissions.0.switch_running_mode", "false"), resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + // resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.#", "1"), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.0.custom_security_group_id", ""), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.0.default_ou", ""), @@ -565,8 +565,7 @@ resource "aws_directory_service_directory" "main" { func testAccWorkspacesDirectoryConfig(rName string) string { return composeConfig( - testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), - ` + testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), ` resource "aws_workspaces_directory" "main" { directory_id = aws_directory_service_directory.main.id } @@ -579,8 +578,7 @@ data "aws_iam_role" "workspaces-default" { func testAccWorkspacesDirectory_selfServicePermissions(rName string) string { return composeConfig( - testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), - ` + testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), ` resource "aws_workspaces_directory" "main" { directory_id = aws_directory_service_directory.main.id @@ -597,8 +595,7 @@ resource "aws_workspaces_directory" "main" { func testAccWorkspacesDirectoryConfig_subnetIds(rName string) string { return composeConfig( - testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), - ` + testAccAwsWorkspacesDirectoryConfig_Prerequisites(rName), ` resource "aws_workspaces_directory" "main" { directory_id = aws_directory_service_directory.main.id subnet_ids = [aws_subnet.primary.id, aws_subnet.secondary.id] diff --git a/aws/resource_aws_workspaces_ip_group.go b/aws/resource_aws_workspaces_ip_group.go index b21914cf7138..20d8644f2d90 100644 --- a/aws/resource_aws_workspaces_ip_group.go +++ b/aws/resource_aws_workspaces_ip_group.go @@ -109,11 +109,11 @@ func resourceAwsWorkspacesIpGroupRead(d *schema.ResourceData, meta interface{}) tags, err := keyvaluetags.WorkspacesListTags(conn, d.Id()) if err != nil { - return fmt.Errorf("error listing tags for Workspaces IP Group (%q): %s", d.Id(), err) + return fmt.Errorf("error listing tags for Workspaces IP Group (%s): %w", d.Id(), err) } if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { - return fmt.Errorf("error setting tags: %s", err) + return fmt.Errorf("error setting tags: %w", err) } return nil @@ -138,7 +138,7 @@ func resourceAwsWorkspacesIpGroupUpdate(d *schema.ResourceData, meta interface{} if d.HasChange("tags") { o, n := d.GetChange("tags") if err := keyvaluetags.WorkspacesUpdateTags(conn, d.Id(), o, n); err != nil { - return fmt.Errorf("error updating tags: %s", err) + return fmt.Errorf("error updating tags: %w", err) } } @@ -165,7 +165,7 @@ func resourceAwsWorkspacesIpGroupDelete(d *schema.ResourceData, meta interface{} }, ) if err != nil { - return fmt.Errorf("error describing Workspaces IP Groups: %s", err) + return fmt.Errorf("error describing Workspaces IP Groups: %w", err) } if directoryID == nil { @@ -178,7 +178,7 @@ func resourceAwsWorkspacesIpGroupDelete(d *schema.ResourceData, meta interface{} GroupIds: aws.StringSlice([]string{d.Id()}), }) if err != nil { - return fmt.Errorf("error disassociating Workspaces IP Group: %s", err) + return fmt.Errorf("error disassociating Workspaces IP Group: %w", err) } log.Printf("[INFO] Workspaces IP Group %q has been successfully disassociated from Directory %q", d.Id(), aws.StringValue(directoryID)) } @@ -188,7 +188,7 @@ func resourceAwsWorkspacesIpGroupDelete(d *schema.ResourceData, meta interface{} GroupId: aws.String(d.Id()), }) if err != nil { - return fmt.Errorf("error deleting Workspaces IP Group: %s", err) + return fmt.Errorf("error deleting Workspaces IP Group: %w", err) } log.Printf("[INFO] Workspaces IP Group %q has been successfully deleted", d.Id()) diff --git a/aws/resource_aws_workspaces_ip_group_test.go b/aws/resource_aws_workspaces_ip_group_test.go index 9394c0f1f5c4..7978af0b2a2e 100644 --- a/aws/resource_aws_workspaces_ip_group_test.go +++ b/aws/resource_aws_workspaces_ip_group_test.go @@ -136,7 +136,7 @@ func testAccCheckAwsWorkspacesIpGroupDestroy(s *terraform.State) error { }) if err != nil { - return fmt.Errorf("Error Describing Workspaces IP Group: %s", err) + return fmt.Errorf("error Describing Workspaces IP Group: %w", err) } // Return nil if the IP Group is already destroyed (does not exist) From 72a332b680e892554f4ce0e08cceb477d45f63c4 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Wed, 18 Nov 2020 13:02:10 -0800 Subject: [PATCH 3/3] Handles deletion of IP Group attached to multiple Directories --- aws/resource_aws_workspaces_directory_test.go | 5 +- aws/resource_aws_workspaces_ip_group.go | 69 ++++++++++--------- aws/resource_aws_workspaces_ip_group_test.go | 55 +++++++++++++++ 3 files changed, 94 insertions(+), 35 deletions(-) diff --git a/aws/resource_aws_workspaces_directory_test.go b/aws/resource_aws_workspaces_directory_test.go index e21610806958..0b4f927003a4 100644 --- a/aws/resource_aws_workspaces_directory_test.go +++ b/aws/resource_aws_workspaces_directory_test.go @@ -89,7 +89,7 @@ func TestAccAwsWorkspacesDirectory_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "self_service_permissions.0.switch_running_mode", "false"), resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "2"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), - // resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "0"), + resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "0"), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.#", "1"), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.0.custom_security_group_id", ""), resource.TestCheckResourceAttr(resourceName, "workspace_creation_properties.0.default_ou", ""), @@ -299,6 +299,7 @@ func TestAccAwsWorkspacesDirectory_ipGroupIds(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAwsWorkspacesDirectoryExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "ip_group_ids.*", "aws_workspaces_ip_group.test_alpha", "id"), ), }, { @@ -311,6 +312,8 @@ func TestAccAwsWorkspacesDirectory_ipGroupIds(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAwsWorkspacesDirectoryExists(resourceName, &v), resource.TestCheckResourceAttr(resourceName, "ip_group_ids.#", "2"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "ip_group_ids.*", "aws_workspaces_ip_group.test_beta", "id"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "ip_group_ids.*", "aws_workspaces_ip_group.test_gamma", "id"), ), }, { diff --git a/aws/resource_aws_workspaces_ip_group.go b/aws/resource_aws_workspaces_ip_group.go index 20d8644f2d90..f17e43e3e1c8 100644 --- a/aws/resource_aws_workspaces_ip_group.go +++ b/aws/resource_aws_workspaces_ip_group.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/workspaces" + multierror "github.com/hashicorp/go-multierror" "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/keyvaluetags" @@ -85,7 +86,7 @@ func resourceAwsWorkspacesIpGroupRead(d *schema.ResourceData, meta interface{}) }) if err != nil { if len(resp.Result) == 0 { - log.Printf("[WARN] Workspaces Ip Group (%s) not found, removing from state", d.Id()) + log.Printf("[WARN] WorkSpaces Ip Group (%s) not found, removing from state", d.Id()) d.SetId("") return nil } @@ -96,7 +97,7 @@ func resourceAwsWorkspacesIpGroupRead(d *schema.ResourceData, meta interface{}) ipGroups := resp.Result if len(ipGroups) == 0 { - log.Printf("[WARN] Workspaces Ip Group (%s) not found, removing from state", d.Id()) + log.Printf("[WARN] WorkSpaces Ip Group (%s) not found, removing from state", d.Id()) d.SetId("") return nil } @@ -109,7 +110,7 @@ func resourceAwsWorkspacesIpGroupRead(d *schema.ResourceData, meta interface{}) tags, err := keyvaluetags.WorkspacesListTags(conn, d.Id()) if err != nil { - return fmt.Errorf("error listing tags for Workspaces IP Group (%s): %w", d.Id(), err) + return fmt.Errorf("error listing tags for WorkSpaces IP Group (%s): %w", d.Id(), err) } if err := d.Set("tags", tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil { @@ -125,7 +126,7 @@ func resourceAwsWorkspacesIpGroupUpdate(d *schema.ResourceData, meta interface{} if d.HasChange("rules") { rules := d.Get("rules").(*schema.Set).List() - log.Printf("[INFO] Updating Workspaces IP Group Rules") + log.Printf("[INFO] Updating WorkSpaces IP Group Rules") _, err := conn.UpdateRulesOfIpGroup(&workspaces.UpdateRulesOfIpGroupInput{ GroupId: aws.String(d.Id()), UserRules: expandIpGroupRules(rules), @@ -148,49 +149,49 @@ func resourceAwsWorkspacesIpGroupUpdate(d *schema.ResourceData, meta interface{} func resourceAwsWorkspacesIpGroupDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).workspacesconn - var directoryID *string - - log.Printf("[DEBUG] Finding directory associated with Workspaces IP Group %q", d.Id()) - err := conn.DescribeWorkspaceDirectoriesPages(nil, - func(page *workspaces.DescribeWorkspaceDirectoriesOutput, lastPage bool) bool { - for _, dir := range page.Directories { - for _, ipg := range dir.IpGroupIds { - if aws.StringValue(ipg) == d.Id() { - directoryID = dir.DirectoryId - return true + var found bool + var sweeperErrs *multierror.Error + log.Printf("[DEBUG] Finding directories associated with WorkSpaces IP Group (%s)", d.Id()) + err := conn.DescribeWorkspaceDirectoriesPages(nil, func(page *workspaces.DescribeWorkspaceDirectoriesOutput, lastPage bool) bool { + for _, dir := range page.Directories { + for _, ipg := range dir.IpGroupIds { + groupID := aws.StringValue(ipg) + if groupID == d.Id() { + found = true + log.Printf("[DEBUG] WorkSpaces IP Group (%s) associated with WorkSpaces Directory (%s), disassociating", groupID, aws.StringValue(dir.DirectoryId)) + _, err := conn.DisassociateIpGroups(&workspaces.DisassociateIpGroupsInput{ + DirectoryId: dir.DirectoryId, + GroupIds: aws.StringSlice([]string{d.Id()}), + }) + if err != nil { + sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error disassociating WorkSpaces IP Group (%s) from WorkSpaces Directory (%s): %w", d.Id(), aws.StringValue(dir.DirectoryId), err)) + continue } + log.Printf("[INFO] WorkSpaces IP Group (%s) disassociated from WorkSpaces Directory (%s)", d.Id(), aws.StringValue(dir.DirectoryId)) } } - return !lastPage - }, - ) + } + return !lastPage + }) if err != nil { - return fmt.Errorf("error describing Workspaces IP Groups: %w", err) + return multierror.Append(sweeperErrs, fmt.Errorf("error describing WorkSpaces Directories: %w", err)) + } + if sweeperErrs.ErrorOrNil() != nil { + return sweeperErrs } - if directoryID == nil { - log.Printf("[DEBUG] Workspaces IP Group %q is not associated with any Directory", d.Id()) - } else { - log.Printf("[DEBUG] Workspaces IP Group %q is associated with Directory %q", d.Id(), aws.StringValue(directoryID)) - log.Printf("[INFO] Disassociating Workspaces IP Group %q from Directory %q", d.Id(), aws.StringValue(directoryID)) - _, err = conn.DisassociateIpGroups(&workspaces.DisassociateIpGroupsInput{ - DirectoryId: directoryID, - GroupIds: aws.StringSlice([]string{d.Id()}), - }) - if err != nil { - return fmt.Errorf("error disassociating Workspaces IP Group: %w", err) - } - log.Printf("[INFO] Workspaces IP Group %q has been successfully disassociated from Directory %q", d.Id(), aws.StringValue(directoryID)) + if !found { + log.Printf("[DEBUG] WorkSpaces IP Group (%s) not associated with any WorkSpaces Directories", d.Id()) } - log.Printf("[INFO] Deleting Workspaces IP Group %q", d.Id()) + log.Printf("[DEBUG] Deleting WorkSpaces IP Group (%s)", d.Id()) _, err = conn.DeleteIpGroup(&workspaces.DeleteIpGroupInput{ GroupId: aws.String(d.Id()), }) if err != nil { - return fmt.Errorf("error deleting Workspaces IP Group: %w", err) + return fmt.Errorf("error deleting WorkSpaces IP Group (%s): %w", d.Id(), err) } - log.Printf("[INFO] Workspaces IP Group %q has been successfully deleted", d.Id()) + log.Printf("[INFO] WorkSpaces IP Group (%s) deleted", d.Id()) return nil } diff --git a/aws/resource_aws_workspaces_ip_group_test.go b/aws/resource_aws_workspaces_ip_group_test.go index 7978af0b2a2e..acb4ac5bab11 100644 --- a/aws/resource_aws_workspaces_ip_group_test.go +++ b/aws/resource_aws_workspaces_ip_group_test.go @@ -124,6 +124,35 @@ func TestAccAwsWorkspacesIpGroup_disappears(t *testing.T) { }) } +func TestAccAwsWorkspacesIpGroup_MultipleDirectories(t *testing.T) { + var v workspaces.IpGroup + var d1, d2 workspaces.WorkspaceDirectory + + ipGroupName := acctest.RandomWithPrefix("tf-acc-test") + + resourceName := "aws_workspaces_ip_group.test" + directoryResourceName1 := "aws_workspaces_directory.test1" + directoryResourceName2 := "aws_workspaces_directory.test2" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAwsWorkspacesIpGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsWorkspacesIpGroupConfigMultipleDirectories(ipGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAwsWorkspacesIpGroupExists(resourceName, &v), + testAccCheckAwsWorkspacesDirectoryExists(directoryResourceName1, &d1), + resource.TestCheckTypeSetElemAttrPair(directoryResourceName1, "ip_group_ids.*", "aws_workspaces_ip_group.test", "id"), + testAccCheckAwsWorkspacesDirectoryExists(directoryResourceName2, &d2), + resource.TestCheckTypeSetElemAttrPair(directoryResourceName2, "ip_group_ids.*", "aws_workspaces_ip_group.test", "id"), + ), + }, + }, + }) +} + func testAccCheckAwsWorkspacesIpGroupDestroy(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "aws_workspaces_ip_group" { @@ -254,3 +283,29 @@ resource "aws_workspaces_ip_group" "test" { } `, name, tagKey1, tagValue1, tagKey2, tagValue2) } + +func testAccAwsWorkspacesIpGroupConfigMultipleDirectories(name string) string { + return composeConfig( + testAccAwsWorkspacesDirectoryConfig_Prerequisites(name), + fmt.Sprintf(` +resource "aws_workspaces_ip_group" "test" { + name = %q +} + +resource "aws_workspaces_directory" "test1" { + directory_id = aws_directory_service_directory.main.id + + ip_group_ids = [ + aws_workspaces_ip_group.test.id + ] +} + +resource "aws_workspaces_directory" "test2" { + directory_id = aws_directory_service_directory.main.id + + ip_group_ids = [ + aws_workspaces_ip_group.test.id + ] +} + `, name)) +}