diff --git a/.changelog/24861.txt b/.changelog/24861.txt new file mode 100644 index 00000000000..607f2933c14 --- /dev/null +++ b/.changelog/24861.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_connect_instance: Configurable Create and Delete timeouts +``` \ No newline at end of file diff --git a/internal/service/connect/contact_flow.go b/internal/service/connect/contact_flow.go index 3e607421b62..a41b481ca4c 100644 --- a/internal/service/connect/contact_flow.go +++ b/internal/service/connect/contact_flow.go @@ -31,10 +31,6 @@ func ResourceContactFlow() *schema.Resource { Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(contactFlowCreateTimeout), - Update: schema.DefaultTimeout(contactFlowUpdateTimeout), - }, CustomizeDiff: verify.SetTagsDiff, Schema: map[string]*schema.Schema{ "arn": { diff --git a/internal/service/connect/enum.go b/internal/service/connect/enum.go index a2a8f397136..64b9ce6c7f4 100644 --- a/internal/service/connect/enum.go +++ b/internal/service/connect/enum.go @@ -2,9 +2,6 @@ package connect import "github.com/aws/aws-sdk-go/service/connect" -const InstanceStatusStatusNotFound = "ResourceNotFoundException" -const BotAssociationStatusNotFound = "ResourceNotFoundException" - const ( ListInstancesMaxResults = 10 // MaxResults Valid Range: Minimum value of 1. Maximum value of 1000 diff --git a/internal/service/connect/hours_of_operation_test.go b/internal/service/connect/hours_of_operation_test.go index 300c918b2cc..d67eedaa1ef 100644 --- a/internal/service/connect/hours_of_operation_test.go +++ b/internal/service/connect/hours_of_operation_test.go @@ -18,8 +18,9 @@ import ( //Serialized acceptance tests due to Connect account limits (max 2 parallel tests) func TestAccConnectHoursOfOperation_serial(t *testing.T) { testCases := map[string]func(t *testing.T){ - "basic": testAccHoursOfOperation_basic, - "disappears": testAccHoursOfOperation_disappears, + "basic": testAccHoursOfOperation_basic, + "disappears": testAccHoursOfOperation_disappears, + "update_config": testAccHoursOfOperation_updateConfig, } for name, tc := range testCases { @@ -34,6 +35,9 @@ func testAccHoursOfOperation_basic(t *testing.T) { var v connect.DescribeHoursOfOperationOutput rName := sdkacctest.RandomWithPrefix("resource-test-terraform") rName2 := sdkacctest.RandomWithPrefix("resource-test-terraform") + originalDescription := "original description" + updatedDescription := "updated description" + resourceName := "aws_connect_hours_of_operation.test" resource.Test(t, resource.TestCase{ @@ -43,20 +47,28 @@ func testAccHoursOfOperation_basic(t *testing.T) { CheckDestroy: testAccCheckHoursOfOperationDestroy, Steps: []resource.TestStep{ { - Config: testAccHoursOfOperationConfig_basic(rName, rName2, "Created"), + Config: testAccHoursOfOperationConfig_basic(rName, rName2, originalDescription), Check: resource.ComposeTestCheckFunc( testAccCheckHoursOfOperationExists(resourceName, &v), resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "config.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "config.*", map[string]string{ + "day": "MONDAY", + "end_time.#": "1", + "end_time.0.hours": "23", + "end_time.0.minutes": "8", + "start_time.#": "1", + "start_time.0.hours": "8", + "start_time.0.minutes": "0", + }), + resource.TestCheckResourceAttr(resourceName, "description", originalDescription), resource.TestCheckResourceAttrSet(resourceName, "hours_of_operation_arn"), // Deprecated resource.TestCheckResourceAttrSet(resourceName, "hours_of_operation_id"), - resource.TestCheckResourceAttrSet(resourceName, "instance_id"), - resource.TestCheckResourceAttrSet(resourceName, "name"), - resource.TestCheckResourceAttrSet(resourceName, "description"), - resource.TestCheckResourceAttrSet(resourceName, "time_zone"), - - resource.TestCheckResourceAttr(resourceName, "config.#", "2"), - + resource.TestCheckResourceAttrPair(resourceName, "instance_id", "aws_connect_instance.test", "id"), + resource.TestCheckResourceAttr(resourceName, "name", rName2), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", "Test Hours of Operation"), + resource.TestCheckResourceAttr(resourceName, "time_zone", "EST"), ), }, { @@ -65,20 +77,92 @@ func testAccHoursOfOperation_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccHoursOfOperationConfig_basic(rName, rName2, "Updated"), + Config: testAccHoursOfOperationConfig_basic(rName, rName2, updatedDescription), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckHoursOfOperationExists(resourceName, &v), resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "config.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "config.*", map[string]string{ + "day": "MONDAY", + "end_time.#": "1", + "end_time.0.hours": "23", + "end_time.0.minutes": "8", + "start_time.#": "1", + "start_time.0.hours": "8", + "start_time.0.minutes": "0", + }), + resource.TestCheckResourceAttr(resourceName, "description", updatedDescription), resource.TestCheckResourceAttrSet(resourceName, "hours_of_operation_arn"), // Deprecated resource.TestCheckResourceAttrSet(resourceName, "hours_of_operation_id"), - resource.TestCheckResourceAttrSet(resourceName, "instance_id"), - resource.TestCheckResourceAttrSet(resourceName, "name"), - resource.TestCheckResourceAttr(resourceName, "description", "Updated"), - resource.TestCheckResourceAttrSet(resourceName, "time_zone"), + resource.TestCheckResourceAttrPair(resourceName, "instance_id", "aws_connect_instance.test", "id"), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", "Test Hours of Operation"), + resource.TestCheckResourceAttr(resourceName, "time_zone", "EST"), + ), + }, + }, + }) +} - resource.TestCheckResourceAttr(resourceName, "config.#", "2"), +func testAccHoursOfOperation_updateConfig(t *testing.T) { + var v connect.DescribeHoursOfOperationOutput + rName := sdkacctest.RandomWithPrefix("resource-test-terraform") + rName2 := sdkacctest.RandomWithPrefix("resource-test-terraform") + description := "example description" - resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resourceName := "aws_connect_hours_of_operation.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, connect.EndpointsID), + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccCheckHoursOfOperationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccHoursOfOperationConfig_basic(rName, rName2, description), + Check: resource.ComposeTestCheckFunc( + testAccCheckHoursOfOperationExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "config.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "config.*", map[string]string{ + "day": "MONDAY", + "end_time.#": "1", + "end_time.0.hours": "23", + "end_time.0.minutes": "8", + "start_time.#": "1", + "start_time.0.hours": "8", + "start_time.0.minutes": "0", + }), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccHoursOfOperationConfig_multipleConfig(rName, rName2, description), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckHoursOfOperationExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "config.#", "2"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "config.*", map[string]string{ + "day": "MONDAY", + "end_time.#": "1", + "end_time.0.hours": "23", + "end_time.0.minutes": "8", + "start_time.#": "1", + "start_time.0.hours": "8", + "start_time.0.minutes": "0", + }), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "config.*", map[string]string{ + "day": "TUESDAY", + "end_time.#": "1", + "end_time.0.hours": "21", + "end_time.0.minutes": "0", + "start_time.#": "1", + "start_time.0.hours": "9", + "start_time.0.minutes": "0", + }), ), }, }, @@ -211,6 +295,37 @@ resource "aws_connect_hours_of_operation" "test" { } } + tags = { + "Name" = "Test Hours of Operation" + } +} +`, rName2, label)) +} + +func testAccHoursOfOperationConfig_multipleConfig(rName, rName2, label string) string { + return acctest.ConfigCompose( + testAccHoursOfOperationBaseConfig(rName), + fmt.Sprintf(` +resource "aws_connect_hours_of_operation" "test" { + instance_id = aws_connect_instance.test.id + name = %[1]q + description = %[2]q + time_zone = "EST" + + config { + day = "MONDAY" + + end_time { + hours = 23 + minutes = 8 + } + + start_time { + hours = 8 + minutes = 0 + } + } + config { day = "TUESDAY" diff --git a/internal/service/connect/instance.go b/internal/service/connect/instance.go index e2dad709327..832225fb620 100644 --- a/internal/service/connect/instance.go +++ b/internal/service/connect/instance.go @@ -136,7 +136,7 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, meta in d.SetId(aws.StringValue(output.Id)) - if _, err := waitInstanceCreated(ctx, conn, d.Id()); err != nil { + if _, err := waitInstanceCreated(ctx, conn, d.Timeout(schema.TimeoutCreate), d.Id()); err != nil { return diag.FromErr(fmt.Errorf("error waiting for Connect instance creation (%s): %w", d.Id(), err)) } @@ -238,7 +238,7 @@ func resourceInstanceDelete(ctx context.Context, d *schema.ResourceData, meta in return diag.FromErr(fmt.Errorf("error deleting Connect Instance (%s): %s", d.Id(), err)) } - if _, err := waitInstanceDeleted(ctx, conn, d.Id()); err != nil { + if _, err := waitInstanceDeleted(ctx, conn, d.Timeout(schema.TimeoutCreate), d.Id()); err != nil { return diag.FromErr(fmt.Errorf("error waiting for Connect Instance deletion (%s): %s", d.Id(), err)) } return nil diff --git a/internal/service/connect/queue_data_source_test.go b/internal/service/connect/queue_data_source_test.go index dcd4a58c9fc..a49d454b7b8 100644 --- a/internal/service/connect/queue_data_source_test.go +++ b/internal/service/connect/queue_data_source_test.go @@ -12,6 +12,7 @@ import ( func TestAccConnectQueueDataSource_queueID(t *testing.T) { rName := sdkacctest.RandomWithPrefix("resource-test-terraform") + rName2 := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_queue.test" datasourceName := "data.aws_connect_queue.test" outboundCallerConfigName := "exampleOutboundCallerConfigName" @@ -22,7 +23,7 @@ func TestAccConnectQueueDataSource_queueID(t *testing.T) { ProviderFactories: acctest.ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccQueueDataSourceConfig_id(rName, resourceName, outboundCallerConfigName), + Config: testAccQueueDataSourceConfig_id(rName, rName2, outboundCallerConfigName), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttrPair(datasourceName, "arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(datasourceName, "description", resourceName, "description"), diff --git a/internal/service/connect/quick_connect_data_source_test.go b/internal/service/connect/quick_connect_data_source_test.go index 775212f133d..6e89641b313 100644 --- a/internal/service/connect/quick_connect_data_source_test.go +++ b/internal/service/connect/quick_connect_data_source_test.go @@ -12,6 +12,7 @@ import ( func TestAccConnectQuickConnectDataSource_id(t *testing.T) { rName := sdkacctest.RandomWithPrefix("resource-test-terraform") + rName2 := sdkacctest.RandomWithPrefix("resource-test-terraform") resourceName := "aws_connect_quick_connect.test" datasourceName := "data.aws_connect_quick_connect.test" phoneNumber := "+12345678912" @@ -22,7 +23,7 @@ func TestAccConnectQuickConnectDataSource_id(t *testing.T) { ProviderFactories: acctest.ProviderFactories, Steps: []resource.TestStep{ { - Config: testAccQuickConnectDataSourceConfig_id(rName, resourceName, phoneNumber), + Config: testAccQuickConnectDataSourceConfig_id(rName, rName2, phoneNumber), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttrPair(datasourceName, "arn", resourceName, "arn"), resource.TestCheckResourceAttrPair(datasourceName, "description", resourceName, "description"), diff --git a/internal/service/connect/status.go b/internal/service/connect/status.go index 5b613054d3b..a4c49f98032 100644 --- a/internal/service/connect/status.go +++ b/internal/service/connect/status.go @@ -17,8 +17,8 @@ func statusInstance(ctx context.Context, conn *connect.Connect, instanceId strin output, err := conn.DescribeInstanceWithContext(ctx, input) - if tfawserr.ErrCodeEquals(err, InstanceStatusStatusNotFound) { - return output, InstanceStatusStatusNotFound, nil + if tfawserr.ErrCodeEquals(err, connect.ErrCodeResourceNotFoundException) { + return output, connect.ErrCodeResourceNotFoundException, nil } if err != nil { diff --git a/internal/service/connect/wait.go b/internal/service/connect/wait.go index 802c8c7e5d1..014d5a277a2 100644 --- a/internal/service/connect/wait.go +++ b/internal/service/connect/wait.go @@ -13,18 +13,15 @@ const ( instanceCreatedTimeout = 5 * time.Minute instanceDeletedTimeout = 5 * time.Minute - contactFlowCreateTimeout = 5 * time.Minute - contactFlowUpdateTimeout = 5 * time.Minute - botAssociationCreateTimeout = 5 * time.Minute ) -func waitInstanceCreated(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { +func waitInstanceCreated(ctx context.Context, conn *connect.Connect, timeout time.Duration, instanceId string) (*connect.DescribeInstanceOutput, error) { stateConf := &resource.StateChangeConf{ Pending: []string{connect.InstanceStatusCreationInProgress}, Target: []string{connect.InstanceStatusActive}, Refresh: statusInstance(ctx, conn, instanceId), - Timeout: instanceCreatedTimeout, + Timeout: timeout, } outputRaw, err := stateConf.WaitForState() @@ -39,12 +36,12 @@ func waitInstanceCreated(ctx context.Context, conn *connect.Connect, instanceId // We don't have a PENDING_DELETION or DELETED for the Connect instance. // If the Connect Instance has an associated EXISTING DIRECTORY, removing the connect instance // will cause an error because it is still has authorized applications. -func waitInstanceDeleted(ctx context.Context, conn *connect.Connect, instanceId string) (*connect.DescribeInstanceOutput, error) { +func waitInstanceDeleted(ctx context.Context, conn *connect.Connect, timeout time.Duration, instanceId string) (*connect.DescribeInstanceOutput, error) { stateConf := &resource.StateChangeConf{ Pending: []string{connect.InstanceStatusActive}, - Target: []string{InstanceStatusStatusNotFound}, + Target: []string{connect.ErrCodeResourceNotFoundException}, Refresh: statusInstance(ctx, conn, instanceId), - Timeout: instanceDeletedTimeout, + Timeout: timeout, } outputRaw, err := stateConf.WaitForState() diff --git a/website/docs/r/connect_contact_flow.html.markdown b/website/docs/r/connect_contact_flow.html.markdown index 781ff9ce802..127058acff7 100644 --- a/website/docs/r/connect_contact_flow.html.markdown +++ b/website/docs/r/connect_contact_flow.html.markdown @@ -110,13 +110,6 @@ In addition to all arguments above, the following attributes are exported: * `contact_flow_id` - The identifier of the Contact Flow. * `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). -### Timeouts - -The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: - -* `create` - (Defaults to 5 min) Used when creating the Contact Flow. -* `update` - (Defaults to 5 min) Used when updating the Contact Flow. - ## Import Amazon Connect Contact Flows can be imported using the `instance_id` and `contact_flow_id` separated by a colon (`:`), e.g.,