Skip to content

Commit

Permalink
Merge pull request #15479 from Tensho/workspaces-configurable-timeouts
Browse files Browse the repository at this point in the history
Add configurable timeouts to workspaces
  • Loading branch information
breathingdust authored Nov 9, 2020
2 parents 860dede + 5f6cce0 commit c718eeb
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 12 deletions.
12 changes: 6 additions & 6 deletions aws/internal/service/workspaces/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ func DirectoryDeregistered(conn *workspaces.WorkSpaces, directoryID string) (*wo
return nil, err
}

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

outputRaw, err := stateConf.WaitForState()
Expand All @@ -89,7 +89,7 @@ func WorkspaceAvailable(conn *workspaces.WorkSpaces, workspaceID string) (*works
return nil, err
}

func WorkspaceTerminated(conn *workspaces.WorkSpaces, workspaceID string) (*workspaces.Workspace, error) {
func WorkspaceTerminated(conn *workspaces.WorkSpaces, workspaceID string, timeout time.Duration) (*workspaces.Workspace, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{
workspaces.WorkspaceStatePending,
Expand All @@ -111,7 +111,7 @@ func WorkspaceTerminated(conn *workspaces.WorkSpaces, workspaceID string) (*work
},
Target: []string{},
Refresh: WorkspaceState(conn, workspaceID),
Timeout: WorkspaceTerminatedTimeout,
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForState()
Expand All @@ -123,7 +123,7 @@ func WorkspaceTerminated(conn *workspaces.WorkSpaces, workspaceID string) (*work
return nil, err
}

func WorkspaceUpdated(conn *workspaces.WorkSpaces, workspaceID string) (*workspaces.Workspace, error) {
func WorkspaceUpdated(conn *workspaces.WorkSpaces, workspaceID string, timeout time.Duration) (*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{
Expand All @@ -136,7 +136,7 @@ func WorkspaceUpdated(conn *workspaces.WorkSpaces, workspaceID string) (*workspa
},
Refresh: WorkspaceState(conn, workspaceID),
Delay: WorkspaceUpdatingDelay,
Timeout: WorkspaceUpdatingTimeout,
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForState()
Expand Down
16 changes: 11 additions & 5 deletions aws/resource_aws_workspaces_workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/workspaces"
Expand Down Expand Up @@ -132,6 +133,11 @@ func resourceAwsWorkspacesWorkspace() *schema.Resource {
},
"tags": tagsSchema(),
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(waiter.WorkspaceAvailableTimeout),
Update: schema.DefaultTimeout(waiter.WorkspaceUpdatingTimeout),
Delete: schema.DefaultTimeout(waiter.WorkspaceTerminatedTimeout),
},
}
}

Expand Down Expand Up @@ -171,7 +177,7 @@ func resourceAwsWorkspacesWorkspaceCreate(d *schema.ResourceData, meta interface
workspaceID := aws.StringValue(resp.PendingRequests[0].WorkspaceId)

log.Printf("[DEBUG] Waiting for workspace %q to be available...", workspaceID)
_, err = waiter.WorkspaceAvailable(conn, workspaceID)
_, err = waiter.WorkspaceAvailable(conn, workspaceID, d.Timeout(schema.TimeoutCreate))
if err != nil {
return fmt.Errorf("workspace %q is not available: %s", workspaceID, err)
}
Expand Down Expand Up @@ -272,15 +278,15 @@ func resourceAwsWorkspacesWorkspaceUpdate(d *schema.ResourceData, meta interface
func resourceAwsWorkspacesWorkspaceDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).workspacesconn

err := workspaceDelete(d.Id(), conn)
err := workspaceDelete(conn, d.Id(), d.Timeout(schema.TimeoutDelete))
if err != nil {
return err
}

return nil
}

func workspaceDelete(id string, conn *workspaces.WorkSpaces) error {
func workspaceDelete(conn *workspaces.WorkSpaces, id string, timeout time.Duration) error {
log.Printf("[DEBUG] Terminating workspace %q", id)
_, err := conn.TerminateWorkspaces(&workspaces.TerminateWorkspacesInput{
TerminateWorkspaceRequests: []*workspaces.TerminateRequest{
Expand All @@ -294,7 +300,7 @@ func workspaceDelete(id string, conn *workspaces.WorkSpaces) error {
}

log.Printf("[DEBUG] Waiting for workspace %q to be terminated", id)
_, err = waiter.WorkspaceTerminated(conn, id)
_, err = waiter.WorkspaceTerminated(conn, id, timeout)
if err != nil {
return fmt.Errorf("workspace %q was not terminated: %s", id, err)
}
Expand Down Expand Up @@ -347,7 +353,7 @@ func workspacePropertyUpdate(p string, conn *workspaces.WorkSpaces, d *schema.Re
}

log.Printf("[DEBUG] Waiting for workspace %q %s property to be modified...", d.Id(), p)
_, err = waiter.WorkspaceUpdated(conn, d.Id())
_, err = waiter.WorkspaceUpdated(conn, d.Id(), d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("error modifying workspace %q property %q was not modified: %w", d.Id(), p, err)
}
Expand Down
49 changes: 48 additions & 1 deletion aws/resource_aws_workspaces_workspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"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/workspaces/waiter"
)

func init() {
Expand All @@ -33,7 +34,7 @@ func testSweepWorkspacesWorkspace(region string) error {
input := &workspaces.DescribeWorkspacesInput{}
err = conn.DescribeWorkspacesPages(input, func(resp *workspaces.DescribeWorkspacesOutput, _ bool) bool {
for _, workspace := range resp.Workspaces {
err := workspaceDelete(aws.StringValue(workspace.WorkspaceId), conn)
err := workspaceDelete(conn, aws.StringValue(workspace.WorkspaceId), waiter.WorkspaceTerminatedTimeout)
if err != nil {
errors = multierror.Append(errors, err)
}
Expand Down Expand Up @@ -317,6 +318,33 @@ func TestAccAwsWorkspacesWorkspace_recreate(t *testing.T) {
})
}

func TestAccAwsWorkspacesWorkspace_timeout(t *testing.T) {
var v workspaces.Workspace
rName := acctest.RandString(8)

resourceName := "aws_workspaces_workspace.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckWorkspacesDirectory(t)
testAccPreCheckAWSDirectoryServiceSimpleDirectory(t)
testAccPreCheckHasIAMRole(t, "workspaces_DefaultRole")
},
Providers: testAccProviders,
CheckDestroy: testAccCheckAwsWorkspacesWorkspaceDestroy,
Steps: []resource.TestStep{
{
Destroy: false,
Config: testAccWorkspacesWorkspaceConfig_timeout(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAwsWorkspacesWorkspaceExists(resourceName, &v),
),
},
},
})
}

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

Expand Down Expand Up @@ -555,6 +583,25 @@ resource "aws_workspaces_workspace" "test" {
`
}

func testAccWorkspacesWorkspaceConfig_timeout(rName string) string {
return testAccAwsWorkspacesWorkspaceConfig_Prerequisites(rName) + `
resource "aws_workspaces_workspace" "test" {
bundle_id = data.aws_workspaces_bundle.test.id
directory_id = aws_workspaces_directory.test.id
# NOTE: WorkSpaces API doesn't allow creating users in the directory.
# However, "Administrator"" user is always present in a bare directory.
user_name = "Administrator"
timeouts {
create = "60m"
update = "30m"
delete = "30m"
}
}
`
}

func TestExpandWorkspaceProperties(t *testing.T) {
cases := []struct {
input []interface{}
Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/workspaces_workspace.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ The following arguments are supported:
* `running_mode_auto_stop_timeout_in_minutes` – (Optional) The time after a user logs off when WorkSpaces are automatically stopped. Configured in 60-minute intervals.
* `user_volume_size_gib` – (Optional) The size of the user storage.

### Timeouts

`aws_workspaces_workspace` provides the following
[Timeouts](/docs/configuration/resources.html#operation-timeouts) configuration options:

- `create` - (Default `30 minutes`) Used for WorkSpace creation.
- `update` - (Default `10 minutes`) Used for WorkSpace updating.
- `delete` - (Default `10 minutes`) Used for WorkSpace termination.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:
Expand Down

0 comments on commit c718eeb

Please sign in to comment.