Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update WorkSpaces acceptance tests to use pre-existing IAM role #13327

Merged
merged 3 commits into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions aws/internal/service/workspaces/waiter/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package waiter

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/workspaces"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func DirectoryState(conn *workspaces.WorkSpaces, directoryID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := conn.DescribeWorkspaceDirectories(&workspaces.DescribeWorkspaceDirectoriesInput{
DirectoryIds: aws.StringSlice([]string{directoryID}),
})
if err != nil {
return nil, workspaces.WorkspaceDirectoryStateError, err
}

if len(output.Directories) == 0 {
return output, workspaces.WorkspaceDirectoryStateDeregistered, nil
}

directory := output.Directories[0]
return directory, aws.StringValue(directory.State), nil
}
}

func WorkspaceState(conn *workspaces.WorkSpaces, workspaceID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := conn.DescribeWorkspaces(&workspaces.DescribeWorkspacesInput{
WorkspaceIds: aws.StringSlice([]string{workspaceID}),
})
if err != nil {
return nil, workspaces.WorkspaceStateError, err
}

if len(output.Workspaces) == 0 {
return nil, workspaces.WorkspaceStateTerminated, nil
}

workspace := output.Workspaces[0]
return workspace, aws.StringValue(workspace.State), nil
}
}
151 changes: 151 additions & 0 deletions aws/internal/service/workspaces/waiter/waiter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package waiter

import (
"time"

"github.com/aws/aws-sdk-go/service/workspaces"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

const (
// Maximum amount of time to wait for a Directory to return Registered
DirectoryRegisteredTimeout = 10 * time.Minute

// Maximum amount of time to wait for a Directory to return Deregistered
DirectoryDeregisteredTimeout = 10 * time.Minute

// Maximum amount of time to wait for a WorkSpace to return Available
WorkspaceAvailableTimeout = 30 * time.Minute

// Maximum amount of time to wait for a WorkSpace while returning Updating
WorkspaceUpdatingTimeout = 10 * time.Minute

// Amount of time to delay before checking WorkSpace when updating
WorkspaceUpdatingDelay = 1 * time.Minute

// Maximum amount of time to wait for a WorkSpace to return Terminated
WorkspaceTerminatedTimeout = 10 * time.Minute
)

func DirectoryRegistered(conn *workspaces.WorkSpaces, directoryID string) (*workspaces.WorkspaceDirectory, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceDirectoryStateRegistering,
},
Target: []string{workspaces.WorkspaceDirectoryStateRegistered},
Refresh: DirectoryState(conn, directoryID),
Timeout: DirectoryRegisteredTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*workspaces.WorkspaceDirectory); ok {
return v, err
}

return nil, err
}

func DirectoryDeregistered(conn *workspaces.WorkSpaces, directoryID string) (*workspaces.WorkspaceDirectory, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceDirectoryStateRegistering,
workspaces.WorkspaceDirectoryStateRegistered,
workspaces.WorkspaceDirectoryStateDeregistering,
},
Target: []string{
workspaces.WorkspaceDirectoryStateDeregistered,
},
Refresh: DirectoryState(conn, directoryID),
Timeout: DirectoryDeregisteredTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*workspaces.WorkspaceDirectory); ok {
return v, err
}

return nil, err
}

func WorkspaceAvailable(conn *workspaces.WorkSpaces, workspaceID string) (*workspaces.Workspace, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceStatePending,
workspaces.WorkspaceStateStarting,
},
Target: []string{workspaces.WorkspaceStateAvailable},
Refresh: WorkspaceState(conn, workspaceID),
Timeout: WorkspaceAvailableTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*workspaces.Workspace); ok {
return v, err
}

return nil, err
}

func WorkspaceTerminated(conn *workspaces.WorkSpaces, workspaceID string) (*workspaces.Workspace, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceStatePending,
workspaces.WorkspaceStateAvailable,
workspaces.WorkspaceStateImpaired,
workspaces.WorkspaceStateUnhealthy,
workspaces.WorkspaceStateRebooting,
workspaces.WorkspaceStateStarting,
workspaces.WorkspaceStateRebuilding,
workspaces.WorkspaceStateRestoring,
workspaces.WorkspaceStateMaintenance,
workspaces.WorkspaceStateAdminMaintenance,
workspaces.WorkspaceStateSuspended,
workspaces.WorkspaceStateUpdating,
workspaces.WorkspaceStateStopping,
workspaces.WorkspaceStateStopped,
workspaces.WorkspaceStateTerminating,
workspaces.WorkspaceStateError,
},
Target: []string{
workspaces.WorkspaceStateTerminated,
},
Refresh: WorkspaceState(conn, workspaceID),
Timeout: WorkspaceTerminatedTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*workspaces.Workspace); ok {
return v, err
}

return nil, err
}

func WorkspaceUpdated(conn *workspaces.WorkSpaces, workspaceID string) (*workspaces.Workspace, error) {
// OperationInProgressException: The properties of this WorkSpace are currently under modification. Please try again in a moment.
// AWS Workspaces service doesn't change instance status to "Updating" during property modification. Respective AWS Support feature request has been created. Meanwhile, artificial delay is placed here as a workaround.
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceStateUpdating,
},
Target: []string{
workspaces.WorkspaceStateAvailable,
workspaces.WorkspaceStateStopped,
},
Refresh: WorkspaceState(conn, workspaceID),
Delay: WorkspaceUpdatingDelay,
Timeout: WorkspaceUpdatingTimeout,
}

outputRaw, err := stateConf.WaitForState()

if v, ok := outputRaw.(*workspaces.Workspace); ok {
return v, err
}

return nil, err
}
102 changes: 31 additions & 71 deletions aws/resource_aws_workspaces_directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package aws
import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/workspaces"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"

"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/service/workspaces/waiter"
)

func resourceAwsWorkspacesDirectory() *schema.Resource {
Expand Down Expand Up @@ -131,31 +130,21 @@ 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] Regestering WorkSpaces Directory...\n%#v\n", *input)
_, err := conn.RegisterWorkspaceDirectory(input)
if err != nil {
return err
}
d.SetId(directoryId)

log.Printf("[DEBUG] Waiting for workspaces directory %q to become registered...", d.Id())
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceDirectoryStateRegistering,
},
Target: []string{workspaces.WorkspaceDirectoryStateRegistered},
Refresh: workspacesDirectoryRefreshStateFunc(conn, directoryId),
PollInterval: 30 * time.Second,
Timeout: 10 * time.Minute,
}

_, err = stateConf.WaitForState()
log.Printf("[DEBUG] Waiting for WorkSpaces Directory %q to become registered...", directoryId)
_, err = waiter.DirectoryRegistered(conn, directoryId)
if err != nil {
return fmt.Errorf("error registering directory: %s", err)
}
log.Printf("[DEBUG] Workspaces directory %q is registered", d.Id())
log.Printf("[DEBUG] WorkSpaces Directory %q is registered", directoryId)

log.Printf("[DEBUG] Modifying workspaces directory %q self-service permissions...", d.Id())
log.Printf("[DEBUG] Modifying WorkSpaces Directory %q self-service permissions...", directoryId)
if v, ok := d.GetOk("self_service_permissions"); ok {
_, err := conn.ModifySelfservicePermissions(&workspaces.ModifySelfservicePermissionsInput{
ResourceId: aws.String(directoryId),
Expand All @@ -165,7 +154,7 @@ func resourceAwsWorkspacesDirectoryCreate(d *schema.ResourceData, meta interface
return fmt.Errorf("error setting self service permissions: %s", err)
}
}
log.Printf("[DEBUG] Workspaces directory %q self-service permissions are set", d.Id())
log.Printf("[DEBUG] WorkSpaces Directory %q self-service permissions are set", directoryId)

return resourceAwsWorkspacesDirectoryRead(d, meta)
}
Expand All @@ -174,36 +163,36 @@ func resourceAwsWorkspacesDirectoryRead(d *schema.ResourceData, meta interface{}
conn := meta.(*AWSClient).workspacesconn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

raw, state, err := workspacesDirectoryRefreshStateFunc(conn, d.Id())()
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): %s", d.Id(), err)
}
if state == workspaces.WorkspaceDirectoryStateDeregistered {
log.Printf("[WARN] workspaces directory (%s) not found, removing from state", d.Id())
log.Printf("[WARN] WorkSpaces Directory (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

dir := raw.(*workspaces.WorkspaceDirectory)
d.Set("directory_id", dir.DirectoryId)
if err := d.Set("subnet_ids", flattenStringSet(dir.SubnetIds)); err != nil {
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)
}
d.Set("workspace_security_group_id", dir.WorkspaceSecurityGroupId)
d.Set("iam_role_id", dir.IamRoleId)
d.Set("registration_code", dir.RegistrationCode)
d.Set("directory_name", dir.DirectoryName)
d.Set("directory_type", dir.DirectoryType)
d.Set("alias", dir.Alias)
if err := d.Set("self_service_permissions", flattenSelfServicePermissions(dir.SelfservicePermissions)); err != nil {
d.Set("workspace_security_group_id", directory.WorkspaceSecurityGroupId)
d.Set("iam_role_id", directory.IamRoleId)
d.Set("registration_code", directory.RegistrationCode)
d.Set("directory_name", directory.DirectoryName)
d.Set("directory_type", directory.DirectoryType)
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)
}

if err := d.Set("ip_group_ids", flattenStringSet(dir.IpGroupIds)); err != nil {
if err := d.Set("ip_group_ids", flattenStringSet(directory.IpGroupIds)); err != nil {
return fmt.Errorf("error setting ip_group_ids: %s", err)
}

if err := d.Set("dns_ip_addresses", flattenStringSet(dir.DnsIpAddresses)); err != nil {
if err := d.Set("dns_ip_addresses", flattenStringSet(directory.DnsIpAddresses)); err != nil {
return fmt.Errorf("error setting dns_ip_addresses: %s", err)
}

Expand All @@ -223,7 +212,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 %q self-service permissions...", d.Id())
permissions := d.Get("self_service_permissions").([]interface{})

_, err := conn.ModifySelfservicePermissions(&workspaces.ModifySelfservicePermissionsInput{
Expand All @@ -233,7 +222,7 @@ func resourceAwsWorkspacesDirectoryUpdate(d *schema.ResourceData, meta interface
if err != nil {
return fmt.Errorf("error updating self service permissions: %s", err)
}
log.Printf("[DEBUG] Workspaces directory %q self-service permissions are set", d.Id())
log.Printf("[DEBUG] WorkSpaces Directory %q self-service permissions are set", d.Id())
}

if d.HasChange("tags") {
Expand All @@ -251,60 +240,31 @@ 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): %s", d.Id(), err)
}

return nil
}

func workspacesDirectoryDelete(id string, conn *workspaces.WorkSpaces) error {
log.Printf("[DEBUG] Deregistering Workspace Directory %q", id)
log.Printf("[DEBUG] Deregistering WorkSpaces Directory %q", id)
_, err := conn.DeregisterWorkspaceDirectory(&workspaces.DeregisterWorkspaceDirectoryInput{
DirectoryId: aws.String(id),
})
if err != nil {
return fmt.Errorf("error deregistering Workspace Directory %q: %w", id, err)
return fmt.Errorf("error deregistering WorkSpaces Directory %q: %w", id, err)
}

log.Printf("[DEBUG] Waiting for Workspace Directory %q to be deregistered", id)
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceDirectoryStateRegistering,
workspaces.WorkspaceDirectoryStateRegistered,
workspaces.WorkspaceDirectoryStateDeregistering,
},
Target: []string{
workspaces.WorkspaceDirectoryStateDeregistered,
},
Refresh: workspacesDirectoryRefreshStateFunc(conn, id),
PollInterval: 30 * time.Second,
Timeout: 10 * time.Minute,
}
_, err = stateConf.WaitForState()
log.Printf("[DEBUG] Waiting for WorkSpaces Directory %q to be deregistered", id)
_, err = waiter.DirectoryDeregistered(conn, id)
if err != nil {
return fmt.Errorf("error waiting for Workspace Directory %q to be deregistered: %w", id, err)
return fmt.Errorf("error waiting for WorkSpaces Directory %q to be deregistered: %w", id, err)
}
log.Printf("[DEBUG] Workspaces Directory %q is deregistered", id)
log.Printf("[DEBUG] WorkSpaces Directory %q is deregistered", id)

return nil
}

func workspacesDirectoryRefreshStateFunc(conn *workspaces.WorkSpaces, directoryID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeWorkspaceDirectories(&workspaces.DescribeWorkspaceDirectoriesInput{
DirectoryIds: []*string{aws.String(directoryID)},
})
if err != nil {
return nil, workspaces.WorkspaceDirectoryStateError, err
}
if len(resp.Directories) == 0 {
return resp, workspaces.WorkspaceDirectoryStateDeregistered, nil
}
directory := resp.Directories[0]
return directory, aws.StringValue(directory.State), nil
}
}

func expandSelfServicePermissions(permissions []interface{}) *workspaces.SelfservicePermissions {
if len(permissions) == 0 || permissions[0] == nil {
return nil
Expand Down
Loading