From 31dc01b59aef916f46d14c451eeac36cd172097a Mon Sep 17 00:00:00 2001 From: Jack McBride Date: Thu, 25 Sep 2025 10:37:14 +0000 Subject: [PATCH 1/4] 34787 Make sqs wait times configurable --- CHANGELOG.md | 1 + docs/retries-and-waiters.md | 66 +++++++ internal/conns/awsclient.go | 9 +- internal/conns/config.go | 7 + internal/provider/sdkv2/provider.go | 33 ++++ .../sdkv2/provider_sqs_wait_times_test.go | 78 ++++++++ ...provider_sqs_wait_times_validation_test.go | 77 ++++++++ internal/service/sqs/queue.go | 24 ++- internal/service/sqs/queue_test.go | 170 ++++++++++++++++++ internal/service/sqs/queue_wait_times_test.go | 142 +++++++++++++++ 10 files changed, 596 insertions(+), 11 deletions(-) create mode 100644 internal/provider/sdkv2/provider_sqs_wait_times_test.go create mode 100644 internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go create mode 100644 internal/service/sqs/queue_wait_times_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index b638851bf3d7..77cbd941b7dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ FEATURES: ENHANCEMENTS: +* provider: Add `sqs_wait_times` configuration block to customize SQS queue operation wait times for local development environments ([#34787](https://github.com/hashicorp/terraform-provider-aws/issues/34787)) * resource/aws_connect_instance: Add resource identity support ([#44346](https://github.com/hashicorp/terraform-provider-aws/issues/44346)) * resource/aws_connect_phone_number: Add resource identity support ([#44365](https://github.com/hashicorp/terraform-provider-aws/issues/44365)) * resource/aws_dsql_cluster: Adds attribute `force_destroy`. ([#44406](https://github.com/hashicorp/terraform-provider-aws/issues/44406)) diff --git a/docs/retries-and-waiters.md b/docs/retries-and-waiters.md index 8943b5744338..b3248d7ebfc4 100644 --- a/docs/retries-and-waiters.md +++ b/docs/retries-and-waiters.md @@ -601,3 +601,69 @@ func waitThingDeleted(ctx context.Context, conn *example.Example, id string, tim ``` Typically, the AWS Go SDK should include constants for various status field values (e.g., `StatusCreating` for `CREATING`). If not, create them in a file named `internal/service/{SERVICE}/consts.go`. + +## Configurable Wait Times + +Some AWS services require configurable wait times to accommodate different environments and use cases. For example, SQS queue operations have different propagation characteristics in local development environments (like LocalStack) compared to production AWS environments. + +### SQS Wait Times Configuration + +The SQS service supports configurable wait times through the provider configuration to optimize performance for different environments: + +```hcl +provider "aws" { + # ... other provider configuration ... + + sqs_wait_times { + create_continuous_target_occurrence = 1 # Default: 6 (30 seconds) + delete_continuous_target_occurrence = 2 # Default: 15 (45 seconds) + } +} +``` + +#### Configuration Options + +- **`create_continuous_target_occurrence`** (Optional, Number): Number of consecutive successful checks required during SQS queue creation. Default is 6, which results in approximately 30 seconds of wait time (6 checks × 5 seconds). Lower values speed up local development environments. + +- **`delete_continuous_target_occurrence`** (Optional, Number): Number of consecutive successful checks required during SQS queue deletion. Default is 15, which results in approximately 45 seconds of wait time (15 checks × 3 seconds). Lower values speed up local development environments. + +#### Use Cases + +**Local Development (LocalStack):** +```hcl +provider "aws" { + # LocalStack configuration + access_key = "test" + secret_key = "test" + region = "us-east-1" + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + + # Fast wait times for local development + sqs_wait_times { + create_continuous_target_occurrence = 1 # ~5 seconds + delete_continuous_target_occurrence = 2 # ~6 seconds + } + + endpoints { + sqs = "http://localhost:4566" + } +} +``` + +**Production AWS:** +```hcl +provider "aws" { + # Production configuration uses default wait times + # (no sqs_wait_times block needed) +} +``` + +#### Implementation Notes + +- Default values are designed to accommodate various AWS regions including GovCloud, commercial, and China regions +- Lower values should only be used in controlled environments where eventual consistency is not a concern +- The configuration affects both `aws_sqs_queue` resource creation and deletion operations +- Changes to wait times do not affect existing resources, only new operations diff --git a/internal/conns/awsclient.go b/internal/conns/awsclient.go index 93aca9b3ee53..2a7c037a786a 100644 --- a/internal/conns/awsclient.go +++ b/internal/conns/awsclient.go @@ -39,10 +39,11 @@ type AWSClient struct { partition endpoints.Partition servicePackages map[string]ServicePackage s3ExpressClient *s3.Client - s3UsePathStyle bool // From provider configuration. - s3USEast1RegionalEndpoint string // From provider configuration. - stsRegion string // From provider configuration. - terraformVersion string // From provider configuration. + s3UsePathStyle bool // From provider configuration. + s3USEast1RegionalEndpoint string // From provider configuration. + sqsWaitTimes *SQSWaitTimesConfig // From provider configuration. + stsRegion string // From provider configuration. + terraformVersion string // From provider configuration. } func (c *AWSClient) SetServicePackages(_ context.Context, servicePackages map[string]ServicePackage) { diff --git a/internal/conns/config.go b/internal/conns/config.go index 6c47241c1150..e87bf9829694 100644 --- a/internal/conns/config.go +++ b/internal/conns/config.go @@ -61,6 +61,12 @@ type Config struct { TokenBucketRateLimiterCapacity int UseDualStackEndpoint bool UseFIPSEndpoint bool + SQSWaitTimes *SQSWaitTimesConfig +} + +type SQSWaitTimesConfig struct { + CreateContinuousTargetOccurrence int + DeleteContinuousTargetOccurrence int } // ConfigureProvider configures the provided provider Meta (instance data). @@ -203,6 +209,7 @@ func (c *Config) ConfigureProvider(ctx context.Context, client *AWSClient) (*AWS client.logger = logger client.s3UsePathStyle = c.S3UsePathStyle client.s3USEast1RegionalEndpoint = c.S3USEast1RegionalEndpoint + client.sqsWaitTimes = c.SQSWaitTimes client.stsRegion = c.STSRegion return client, diags diff --git a/internal/provider/sdkv2/provider.go b/internal/provider/sdkv2/provider.go index f6b44b7c2bc1..3713f1d25417 100644 --- a/internal/provider/sdkv2/provider.go +++ b/internal/provider/sdkv2/provider.go @@ -243,6 +243,30 @@ func NewProvider(ctx context.Context) (*schema.Provider, error) { Description: "Skip requesting the account ID. " + "Used for AWS API implementations that do not have IAM/STS API and/or metadata API.", }, + "sqs_wait_times": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "Configuration block for SQS wait times. Useful for local development environments like LocalStack.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "create_continuous_target_occurrence": { + Type: schema.TypeInt, + Optional: true, + Default: 6, + ValidateFunc: validation.IntAtLeast(1), + Description: "Number of consecutive successful checks required during SQS queue creation. Default is 6 (30 seconds). Lower values speed up local development.", + }, + "delete_continuous_target_occurrence": { + Type: schema.TypeInt, + Optional: true, + Default: 15, + ValidateFunc: validation.IntAtLeast(1), + Description: "Number of consecutive successful checks required during SQS queue deletion. Default is 15 (45 seconds). Lower values speed up local development.", + }, + }, + }, + }, "sts_region": { Type: schema.TypeString, Optional: true, @@ -485,6 +509,15 @@ func (p *sdkProvider) configure(ctx context.Context, d *schema.ResourceData) (an } } + // Parse SQS wait times configuration + if v, ok := d.GetOk("sqs_wait_times"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { + sqsWaitTimes := v.([]any)[0].(map[string]any) + config.SQSWaitTimes = &conns.SQSWaitTimesConfig{ + CreateContinuousTargetOccurrence: sqsWaitTimes["create_continuous_target_occurrence"].(int), + DeleteContinuousTargetOccurrence: sqsWaitTimes["delete_continuous_target_occurrence"].(int), + } + } + var c *conns.AWSClient if v, ok := p.provider.Meta().(*conns.AWSClient); ok { c = v diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_test.go new file mode 100644 index 000000000000..f33c0dae24f3 --- /dev/null +++ b/internal/provider/sdkv2/provider_sqs_wait_times_test.go @@ -0,0 +1,78 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sdkv2 + +import ( + "context" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccProvider_sqsWaitTimesConfiguration(t *testing.T) { + ctx := acctest.Context(t) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccProviderConfig_sqsWaitTimes(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), + ), + }, + }, + }) +} + +// Test that the provider configuration is properly parsed and stored +func TestProvider_sqsWaitTimesConfigurationParsing(t *testing.T) { + ctx := context.Background() + + config := &conns.Config{ + SQSWaitTimes: &conns.SQSWaitTimesConfig{ + CreateContinuousTargetOccurrence: 1, + DeleteContinuousTargetOccurrence: 2, + }, + } + + client := &conns.AWSClient{} + configuredClient, diags := config.ConfigureProvider(ctx, client) + + if diags.HasError() { + t.Fatalf("Expected no errors, got: %v", diags) + } + + if configuredClient.SQSWaitTimes == nil { + t.Fatal("Expected SQSWaitTimes to be set") + } + + if configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { + t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence) + } + + if configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { + t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence) + } +} + +func testAccProviderConfig_sqsWaitTimes() string { + return ` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = 1 + delete_continuous_target_occurrence = 2 + } +} + +resource "aws_sqs_queue" "test" { + name = "test-queue" +} +` +} diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go new file mode 100644 index 000000000000..bc6e5177fd68 --- /dev/null +++ b/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go @@ -0,0 +1,77 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sdkv2 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccProvider_sqsWaitTimesConfigurationValidation(t *testing.T) { + ctx := acctest.Context(t) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccProviderConfig_sqsWaitTimesMinValues(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), + ), + }, + }, + }) +} + +func TestAccProvider_sqsWaitTimesConfigurationDefaults(t *testing.T) { + ctx := acctest.Context(t) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccProviderConfig_sqsWaitTimesDefaults(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), + ), + }, + }, + }) +} + +func testAccProviderConfig_sqsWaitTimesMinValues() string { + return ` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = 1 + delete_continuous_target_occurrence = 1 + } +} + +resource "aws_sqs_queue" "test" { + name = "test-queue" +} +` +} + +func testAccProviderConfig_sqsWaitTimesDefaults() string { + return ` +provider "aws" { + sqs_wait_times { + # Using default values + } +} + +resource "aws_sqs_queue" "test" { + name = "test-queue" +} +` +} diff --git a/internal/service/sqs/queue.go b/internal/service/sqs/queue.go index 1491c8c5330b..ae949257a51b 100644 --- a/internal/service/sqs/queue.go +++ b/internal/service/sqs/queue.go @@ -256,7 +256,7 @@ func resourceQueueCreate(ctx context.Context, d *schema.ResourceData, meta any) d.SetId(aws.ToString(outputRaw.(*sqs.CreateQueueOutput).QueueUrl)) - if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, deadline.Remaining()); err != nil { + if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, deadline.Remaining(), meta); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for SQS Queue (%s) attributes create: %s", d.Id(), err) } @@ -342,7 +342,7 @@ func resourceQueueUpdate(ctx context.Context, d *schema.ResourceData, meta any) return sdkdiag.AppendErrorf(diags, "updating SQS Queue (%s) attributes: %s", d.Id(), err) } - if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, d.Timeout(schema.TimeoutUpdate)); err != nil { + if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, d.Timeout(schema.TimeoutUpdate), meta); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for SQS Queue (%s) attributes update: %s", d.Id(), err) } } @@ -367,7 +367,7 @@ func resourceQueueDelete(ctx context.Context, d *schema.ResourceData, meta any) return sdkdiag.AppendErrorf(diags, "deleting SQS Queue (%s): %s", d.Id(), err) } - if err := waitQueueDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { + if err := waitQueueDeleted(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete), meta); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for SQS Queue (%s) delete: %s", d.Id(), err) } @@ -600,13 +600,18 @@ func statusQueueAttributeState(ctx context.Context, conn *sqs.Client, url string } } -func waitQueueAttributesPropagated(ctx context.Context, conn *sqs.Client, url string, expected map[types.QueueAttributeName]string, timeout time.Duration) error { +func waitQueueAttributesPropagated(ctx context.Context, conn *sqs.Client, url string, expected map[types.QueueAttributeName]string, timeout time.Duration, meta any) error { + continuousTargetOccurrence := 6 + if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes != nil { + continuousTargetOccurrence = awsClient.SQSWaitTimes.CreateContinuousTargetOccurrence + } + stateConf := &retry.StateChangeConf{ Pending: []string{queueAttributeStateNotEqual}, Target: []string{queueAttributeStateEqual}, Refresh: statusQueueAttributeState(ctx, conn, url, expected), Timeout: timeout, - ContinuousTargetOccurence: 6, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering + ContinuousTargetOccurence: continuousTargetOccurrence, MinTimeout: 5 * time.Second, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering NotFoundChecks: 10, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering } @@ -616,13 +621,18 @@ func waitQueueAttributesPropagated(ctx context.Context, conn *sqs.Client, url st return err } -func waitQueueDeleted(ctx context.Context, conn *sqs.Client, url string, timeout time.Duration) error { +func waitQueueDeleted(ctx context.Context, conn *sqs.Client, url string, timeout time.Duration, meta any) error { + continuousTargetOccurrence := 15 + if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes != nil { + continuousTargetOccurrence = awsClient.SQSWaitTimes.DeleteContinuousTargetOccurrence + } + stateConf := &retry.StateChangeConf{ Pending: []string{queueStateExists}, Target: []string{}, Refresh: statusQueueState(ctx, conn, url), Timeout: timeout, - ContinuousTargetOccurence: 15, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering + ContinuousTargetOccurence: continuousTargetOccurrence, MinTimeout: 3 * time.Second, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering NotFoundChecks: 5, // set to accommodate GovCloud, commercial, China, etc. - avoid lowering } diff --git a/internal/service/sqs/queue_test.go b/internal/service/sqs/queue_test.go index 8b68b06d3838..a5737f6ff455 100644 --- a/internal/service/sqs/queue_test.go +++ b/internal/service/sqs/queue_test.go @@ -1380,3 +1380,173 @@ resource "aws_sqs_queue" "test" { } `, rName) } + +func TestAccSQSQueue_waitTimesConfiguration(t *testing.T) { + ctx := acctest.Context(t) + var queueAttributes map[types.QueueAttributeName]string + resourceName := "aws_sqs_queue.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimes(rName, 1, 2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckQueueExists(ctx, resourceName, &queueAttributes), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSQSQueue_waitTimesConfigurationUpdate(t *testing.T) { + ctx := acctest.Context(t) + var queueAttributes map[types.QueueAttributeName]string + resourceName := "aws_sqs_queue.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimes(rName, 1, 2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckQueueExists(ctx, resourceName, &queueAttributes), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + { + Config: testAccQueueConfig_waitTimes(rName, 3, 5), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckQueueExists(ctx, resourceName, &queueAttributes), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + }, + }) +} + +func TestAccSQSQueue_waitTimesConfigurationLocalStack(t *testing.T) { + ctx := acctest.Context(t) + var queueAttributes map[types.QueueAttributeName]string + resourceName := "aws_sqs_queue.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + // Skip this test if not running against LocalStack + // This test is designed to demonstrate LocalStack configuration + // but will work with regular AWS as well + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimesLocalStack(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckQueueExists(ctx, resourceName, &queueAttributes), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSQSQueue_waitTimesConfigurationFIFO(t *testing.T) { + ctx := acctest.Context(t) + var queueAttributes map[types.QueueAttributeName]string + resourceName := "aws_sqs_queue.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimesFIFO(rName, 1, 2), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckQueueExists(ctx, resourceName, &queueAttributes), + acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + resource.TestCheckResourceAttr(resourceName, "fifo_queue", acctest.CtTrue), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccQueueConfig_waitTimes(rName string, createOccurrence, deleteOccurrence int) string { + return fmt.Sprintf(` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = %[2]d + delete_continuous_target_occurrence = %[3]d + } +} + +resource "aws_sqs_queue" "test" { + name = %[1]q +} +`, rName, createOccurrence, deleteOccurrence) +} + +func testAccQueueConfig_waitTimesLocalStack(rName string) string { + return fmt.Sprintf(` +provider "aws" { + # LocalStack-like configuration with optimized wait times + sqs_wait_times { + create_continuous_target_occurrence = 1 + delete_continuous_target_occurrence = 2 + } +} + +resource "aws_sqs_queue" "test" { + name = %[1]q +} +`, rName) +} + +func testAccQueueConfig_waitTimesFIFO(rName string, createOccurrence, deleteOccurrence int) string { + return fmt.Sprintf(` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = %[2]d + delete_continuous_target_occurrence = %[3]d + } +} + +resource "aws_sqs_queue" "test" { + name = %[1]q + fifo_queue = true +} +`, rName, createOccurrence, deleteOccurrence) +} diff --git a/internal/service/sqs/queue_wait_times_test.go b/internal/service/sqs/queue_wait_times_test.go new file mode 100644 index 000000000000..9a724f6a7b41 --- /dev/null +++ b/internal/service/sqs/queue_wait_times_test.go @@ -0,0 +1,142 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package sqs_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccSQSQueue_waitTimesPerformance(t *testing.T) { + ctx := acctest.Context(t) + + if testing.Short() { + t.Skip("skipping timing test in short mode") + } + + resourceName := "aws_sqs_queue.test" + rName := acctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimesPerformance(rName, 1, 2), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + }, + }) +} + +func TestAccSQSQueue_waitTimesConfigurationEdgeCases(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_sqs_queue.test" + rName := acctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckQueueDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccQueueConfig_waitTimesEdgeCases(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), + ), + }, + }, + }) +} + +func TestSQSQueue_waitTimesConfigurationIntegration(t *testing.T) { + ctx := context.Background() + + // Test with custom wait times + config := &conns.Config{ + SQSWaitTimes: &conns.SQSWaitTimesConfig{ + CreateContinuousTargetOccurrence: 1, + DeleteContinuousTargetOccurrence: 2, + }, + } + + client := &conns.AWSClient{} + configuredClient, diags := config.ConfigureProvider(ctx, client) + + if diags.HasError() { + t.Fatalf("Expected no errors, got: %v", diags) + } + + if configuredClient.SQSWaitTimes == nil { + t.Fatal("Expected SQSWaitTimes to be set") + } + + if configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { + t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence) + } + + if configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { + t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence) + } +} + +func TestSQSQueue_waitTimesConfigurationDefaults(t *testing.T) { + ctx := context.Background() + + config := &conns.Config{ + SQSWaitTimes: nil, + } + + client := &conns.AWSClient{} + configuredClient, diags := config.ConfigureProvider(ctx, client) + + if diags.HasError() { + t.Fatalf("Expected no errors, got: %v", diags) + } + + if configuredClient.SQSWaitTimes != nil { + t.Fatal("Expected SQSWaitTimes to be nil when not configured") + } +} + +func testAccQueueConfig_waitTimesPerformance(rName string, createOccurrence, deleteOccurrence int) string { + return fmt.Sprintf(` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = %[2]d + delete_continuous_target_occurrence = %[3]d + } +} + +resource "aws_sqs_queue" "test" { + name = %[1]q +} +`, rName, createOccurrence, deleteOccurrence) +} + +func testAccQueueConfig_waitTimesEdgeCases(rName string) string { + return fmt.Sprintf(` +provider "aws" { + sqs_wait_times { + create_continuous_target_occurrence = 1 + delete_continuous_target_occurrence = 1 + } +} + +resource "aws_sqs_queue" "test" { + name = %[1]q +} +`, rName) +} From fc6fd659a81af0db4dc8df11e4a872244fd64049 Mon Sep 17 00:00:00 2001 From: Jack McBride Date: Thu, 25 Sep 2025 12:51:02 +0000 Subject: [PATCH 2/4] Remove over testing --- internal/conns/awsclient.go | 2 +- internal/conns/config.go | 2 +- internal/provider/sdkv2/provider.go | 1 - .../sdkv2/provider_sqs_wait_times_test.go | 71 ++------ ...provider_sqs_wait_times_validation_test.go | 77 -------- internal/service/sqs/attribute_funcs.go | 4 +- internal/service/sqs/queue_test.go | 170 ------------------ internal/service/sqs/queue_wait_times_test.go | 142 --------------- 8 files changed, 22 insertions(+), 447 deletions(-) delete mode 100644 internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go delete mode 100644 internal/service/sqs/queue_wait_times_test.go diff --git a/internal/conns/awsclient.go b/internal/conns/awsclient.go index 2a7c037a786a..bd84dfc6e92f 100644 --- a/internal/conns/awsclient.go +++ b/internal/conns/awsclient.go @@ -41,7 +41,7 @@ type AWSClient struct { s3ExpressClient *s3.Client s3UsePathStyle bool // From provider configuration. s3USEast1RegionalEndpoint string // From provider configuration. - sqsWaitTimes *SQSWaitTimesConfig // From provider configuration. + SQSWaitTimes *SQSWaitTimesConfig // From provider configuration. stsRegion string // From provider configuration. terraformVersion string // From provider configuration. } diff --git a/internal/conns/config.go b/internal/conns/config.go index e87bf9829694..80a28f747ddc 100644 --- a/internal/conns/config.go +++ b/internal/conns/config.go @@ -209,7 +209,7 @@ func (c *Config) ConfigureProvider(ctx context.Context, client *AWSClient) (*AWS client.logger = logger client.s3UsePathStyle = c.S3UsePathStyle client.s3USEast1RegionalEndpoint = c.S3USEast1RegionalEndpoint - client.sqsWaitTimes = c.SQSWaitTimes + client.SQSWaitTimes = c.SQSWaitTimes client.stsRegion = c.STSRegion return client, diags diff --git a/internal/provider/sdkv2/provider.go b/internal/provider/sdkv2/provider.go index 3713f1d25417..08425433660f 100644 --- a/internal/provider/sdkv2/provider.go +++ b/internal/provider/sdkv2/provider.go @@ -509,7 +509,6 @@ func (p *sdkProvider) configure(ctx context.Context, d *schema.ResourceData) (an } } - // Parse SQS wait times configuration if v, ok := d.GetOk("sqs_wait_times"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil { sqsWaitTimes := v.([]any)[0].(map[string]any) config.SQSWaitTimes = &conns.SQSWaitTimesConfig{ diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_test.go index f33c0dae24f3..e80e5bb4e22c 100644 --- a/internal/provider/sdkv2/provider_sqs_wait_times_test.go +++ b/internal/provider/sdkv2/provider_sqs_wait_times_test.go @@ -4,75 +4,40 @@ package sdkv2 import ( - "context" "testing" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/names" ) -func TestAccProvider_sqsWaitTimesConfiguration(t *testing.T) { - ctx := acctest.Context(t) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccProviderConfig_sqsWaitTimes(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), - ), - }, - }, - }) -} - -// Test that the provider configuration is properly parsed and stored func TestProvider_sqsWaitTimesConfigurationParsing(t *testing.T) { - ctx := context.Background() + // Test that the configuration struct can be created and accessed + config := &conns.SQSWaitTimesConfig{ + CreateContinuousTargetOccurrence: 1, + DeleteContinuousTargetOccurrence: 2, + } - config := &conns.Config{ - SQSWaitTimes: &conns.SQSWaitTimesConfig{ - CreateContinuousTargetOccurrence: 1, - DeleteContinuousTargetOccurrence: 2, - }, + if config.CreateContinuousTargetOccurrence != 1 { + t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", config.CreateContinuousTargetOccurrence) } - client := &conns.AWSClient{} - configuredClient, diags := config.ConfigureProvider(ctx, client) + if config.DeleteContinuousTargetOccurrence != 2 { + t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", config.DeleteContinuousTargetOccurrence) + } - if diags.HasError() { - t.Fatalf("Expected no errors, got: %v", diags) + // Test that the AWSClient can hold the configuration + client := &conns.AWSClient{ + SQSWaitTimes: config, } - if configuredClient.SQSWaitTimes == nil { + if client.SQSWaitTimes == nil { t.Fatal("Expected SQSWaitTimes to be set") } - if configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { - t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence) + if client.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { + t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", client.SQSWaitTimes.CreateContinuousTargetOccurrence) } - if configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { - t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence) + if client.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { + t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", client.SQSWaitTimes.DeleteContinuousTargetOccurrence) } } - -func testAccProviderConfig_sqsWaitTimes() string { - return ` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = 1 - delete_continuous_target_occurrence = 2 - } -} - -resource "aws_sqs_queue" "test" { - name = "test-queue" -} -` -} diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go deleted file mode 100644 index bc6e5177fd68..000000000000 --- a/internal/provider/sdkv2/provider_sqs_wait_times_validation_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package sdkv2 - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-provider-aws/internal/acctest" - "github.com/hashicorp/terraform-provider-aws/names" -) - -func TestAccProvider_sqsWaitTimesConfigurationValidation(t *testing.T) { - ctx := acctest.Context(t) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccProviderConfig_sqsWaitTimesMinValues(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), - ), - }, - }, - }) -} - -func TestAccProvider_sqsWaitTimesConfigurationDefaults(t *testing.T) { - ctx := acctest.Context(t) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - Steps: []resource.TestStep{ - { - Config: testAccProviderConfig_sqsWaitTimesDefaults(), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("aws_sqs_queue.test", "name", "test-queue"), - ), - }, - }, - }) -} - -func testAccProviderConfig_sqsWaitTimesMinValues() string { - return ` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = 1 - delete_continuous_target_occurrence = 1 - } -} - -resource "aws_sqs_queue" "test" { - name = "test-queue" -} -` -} - -func testAccProviderConfig_sqsWaitTimesDefaults() string { - return ` -provider "aws" { - sqs_wait_times { - # Using default values - } -} - -resource "aws_sqs_queue" "test" { - name = "test-queue" -} -` -} diff --git a/internal/service/sqs/attribute_funcs.go b/internal/service/sqs/attribute_funcs.go index db799f2fd136..f9a6e987b591 100644 --- a/internal/service/sqs/attribute_funcs.go +++ b/internal/service/sqs/attribute_funcs.go @@ -59,7 +59,7 @@ func (h *queueAttributeHandler) Upsert(ctx context.Context, d *schema.ResourceDa d.SetId(url) - if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, deadline.Remaining()); err != nil { + if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, deadline.Remaining(), meta); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for SQS Queue (%s) attribute (%s) create: %s", d.Id(), h.AttributeName, err) } @@ -123,7 +123,7 @@ func (h *queueAttributeHandler) Delete(ctx context.Context, d *schema.ResourceDa return sdkdiag.AppendErrorf(diags, "deleting SQS Queue (%s) attribute (%s): %s", d.Id(), h.AttributeName, err) } - if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, d.Timeout(schema.TimeoutDelete)); err != nil { + if err := waitQueueAttributesPropagated(ctx, conn, d.Id(), attributes, d.Timeout(schema.TimeoutDelete), meta); err != nil { return sdkdiag.AppendErrorf(diags, "waiting for SQS Queue (%s) attribute (%s) delete: %s", d.Id(), h.AttributeName, err) } diff --git a/internal/service/sqs/queue_test.go b/internal/service/sqs/queue_test.go index a5737f6ff455..8b68b06d3838 100644 --- a/internal/service/sqs/queue_test.go +++ b/internal/service/sqs/queue_test.go @@ -1380,173 +1380,3 @@ resource "aws_sqs_queue" "test" { } `, rName) } - -func TestAccSQSQueue_waitTimesConfiguration(t *testing.T) { - ctx := acctest.Context(t) - var queueAttributes map[types.QueueAttributeName]string - resourceName := "aws_sqs_queue.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimes(rName, 1, 2), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckQueueExists(ctx, resourceName, &queueAttributes), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccSQSQueue_waitTimesConfigurationUpdate(t *testing.T) { - ctx := acctest.Context(t) - var queueAttributes map[types.QueueAttributeName]string - resourceName := "aws_sqs_queue.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimes(rName, 1, 2), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckQueueExists(ctx, resourceName, &queueAttributes), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - { - Config: testAccQueueConfig_waitTimes(rName, 3, 5), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckQueueExists(ctx, resourceName, &queueAttributes), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - }, - }) -} - -func TestAccSQSQueue_waitTimesConfigurationLocalStack(t *testing.T) { - ctx := acctest.Context(t) - var queueAttributes map[types.QueueAttributeName]string - resourceName := "aws_sqs_queue.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - // Skip this test if not running against LocalStack - // This test is designed to demonstrate LocalStack configuration - // but will work with regular AWS as well - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimesLocalStack(rName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckQueueExists(ctx, resourceName, &queueAttributes), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccSQSQueue_waitTimesConfigurationFIFO(t *testing.T) { - ctx := acctest.Context(t) - var queueAttributes map[types.QueueAttributeName]string - resourceName := "aws_sqs_queue.test" - rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimesFIFO(rName, 1, 2), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckQueueExists(ctx, resourceName, &queueAttributes), - acctest.CheckResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "sqs", rName), - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - resource.TestCheckResourceAttr(resourceName, "fifo_queue", acctest.CtTrue), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccQueueConfig_waitTimes(rName string, createOccurrence, deleteOccurrence int) string { - return fmt.Sprintf(` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = %[2]d - delete_continuous_target_occurrence = %[3]d - } -} - -resource "aws_sqs_queue" "test" { - name = %[1]q -} -`, rName, createOccurrence, deleteOccurrence) -} - -func testAccQueueConfig_waitTimesLocalStack(rName string) string { - return fmt.Sprintf(` -provider "aws" { - # LocalStack-like configuration with optimized wait times - sqs_wait_times { - create_continuous_target_occurrence = 1 - delete_continuous_target_occurrence = 2 - } -} - -resource "aws_sqs_queue" "test" { - name = %[1]q -} -`, rName) -} - -func testAccQueueConfig_waitTimesFIFO(rName string, createOccurrence, deleteOccurrence int) string { - return fmt.Sprintf(` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = %[2]d - delete_continuous_target_occurrence = %[3]d - } -} - -resource "aws_sqs_queue" "test" { - name = %[1]q - fifo_queue = true -} -`, rName, createOccurrence, deleteOccurrence) -} diff --git a/internal/service/sqs/queue_wait_times_test.go b/internal/service/sqs/queue_wait_times_test.go deleted file mode 100644 index 9a724f6a7b41..000000000000 --- a/internal/service/sqs/queue_wait_times_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package sqs_test - -import ( - "context" - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-provider-aws/internal/acctest" - "github.com/hashicorp/terraform-provider-aws/internal/conns" - "github.com/hashicorp/terraform-provider-aws/names" -) - -func TestAccSQSQueue_waitTimesPerformance(t *testing.T) { - ctx := acctest.Context(t) - - if testing.Short() { - t.Skip("skipping timing test in short mode") - } - - resourceName := "aws_sqs_queue.test" - rName := acctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimesPerformance(rName, 1, 2), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - }, - }) -} - -func TestAccSQSQueue_waitTimesConfigurationEdgeCases(t *testing.T) { - ctx := acctest.Context(t) - resourceName := "aws_sqs_queue.test" - rName := acctest.RandomWithPrefix(acctest.ResourcePrefix) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acctest.PreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, names.SQSServiceID), - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, - CheckDestroy: testAccCheckQueueDestroy(ctx), - Steps: []resource.TestStep{ - { - Config: testAccQueueConfig_waitTimesEdgeCases(rName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, names.AttrName, rName), - ), - }, - }, - }) -} - -func TestSQSQueue_waitTimesConfigurationIntegration(t *testing.T) { - ctx := context.Background() - - // Test with custom wait times - config := &conns.Config{ - SQSWaitTimes: &conns.SQSWaitTimesConfig{ - CreateContinuousTargetOccurrence: 1, - DeleteContinuousTargetOccurrence: 2, - }, - } - - client := &conns.AWSClient{} - configuredClient, diags := config.ConfigureProvider(ctx, client) - - if diags.HasError() { - t.Fatalf("Expected no errors, got: %v", diags) - } - - if configuredClient.SQSWaitTimes == nil { - t.Fatal("Expected SQSWaitTimes to be set") - } - - if configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { - t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", configuredClient.SQSWaitTimes.CreateContinuousTargetOccurrence) - } - - if configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { - t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", configuredClient.SQSWaitTimes.DeleteContinuousTargetOccurrence) - } -} - -func TestSQSQueue_waitTimesConfigurationDefaults(t *testing.T) { - ctx := context.Background() - - config := &conns.Config{ - SQSWaitTimes: nil, - } - - client := &conns.AWSClient{} - configuredClient, diags := config.ConfigureProvider(ctx, client) - - if diags.HasError() { - t.Fatalf("Expected no errors, got: %v", diags) - } - - if configuredClient.SQSWaitTimes != nil { - t.Fatal("Expected SQSWaitTimes to be nil when not configured") - } -} - -func testAccQueueConfig_waitTimesPerformance(rName string, createOccurrence, deleteOccurrence int) string { - return fmt.Sprintf(` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = %[2]d - delete_continuous_target_occurrence = %[3]d - } -} - -resource "aws_sqs_queue" "test" { - name = %[1]q -} -`, rName, createOccurrence, deleteOccurrence) -} - -func testAccQueueConfig_waitTimesEdgeCases(rName string) string { - return fmt.Sprintf(` -provider "aws" { - sqs_wait_times { - create_continuous_target_occurrence = 1 - delete_continuous_target_occurrence = 1 - } -} - -resource "aws_sqs_queue" "test" { - name = %[1]q -} -`, rName) -} From 2bfc619627efab73764d9dc67b2af9f817af7523 Mon Sep 17 00:00:00 2001 From: Jack McBride Date: Thu, 25 Sep 2025 13:08:48 +0000 Subject: [PATCH 3/4] Update changelog to correct format, make sqs lowercase --- .changelog/34787.txt | 3 +++ .changelog/TBD.txt | 3 +++ CHANGELOG.md | 1 - internal/conns/awsclient.go | 7 ++++++- internal/conns/config.go | 2 +- .../provider/sdkv2/provider_sqs_wait_times_test.go | 14 ++++++-------- internal/service/sqs/queue.go | 8 ++++---- 7 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 .changelog/34787.txt create mode 100644 .changelog/TBD.txt diff --git a/.changelog/34787.txt b/.changelog/34787.txt new file mode 100644 index 000000000000..36bbd4e1bae7 --- /dev/null +++ b/.changelog/34787.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +provider: Add `sqs_wait_times` configuration block to customize SQS queue operation wait times for local development environments +``` diff --git a/.changelog/TBD.txt b/.changelog/TBD.txt new file mode 100644 index 000000000000..36bbd4e1bae7 --- /dev/null +++ b/.changelog/TBD.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +provider: Add `sqs_wait_times` configuration block to customize SQS queue operation wait times for local development environments +``` diff --git a/CHANGELOG.md b/CHANGELOG.md index 77cbd941b7dd..b638851bf3d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ FEATURES: ENHANCEMENTS: -* provider: Add `sqs_wait_times` configuration block to customize SQS queue operation wait times for local development environments ([#34787](https://github.com/hashicorp/terraform-provider-aws/issues/34787)) * resource/aws_connect_instance: Add resource identity support ([#44346](https://github.com/hashicorp/terraform-provider-aws/issues/44346)) * resource/aws_connect_phone_number: Add resource identity support ([#44365](https://github.com/hashicorp/terraform-provider-aws/issues/44365)) * resource/aws_dsql_cluster: Adds attribute `force_destroy`. ([#44406](https://github.com/hashicorp/terraform-provider-aws/issues/44406)) diff --git a/internal/conns/awsclient.go b/internal/conns/awsclient.go index bd84dfc6e92f..64f710e27dff 100644 --- a/internal/conns/awsclient.go +++ b/internal/conns/awsclient.go @@ -41,7 +41,7 @@ type AWSClient struct { s3ExpressClient *s3.Client s3UsePathStyle bool // From provider configuration. s3USEast1RegionalEndpoint string // From provider configuration. - SQSWaitTimes *SQSWaitTimesConfig // From provider configuration. + sqsWaitTimes *SQSWaitTimesConfig // From provider configuration. stsRegion string // From provider configuration. terraformVersion string // From provider configuration. } @@ -413,3 +413,8 @@ func client[T any](ctx context.Context, c *AWSClient, servicePackageName string, return client, nil } + +// SQSWaitTimes returns the SQS wait times configuration +func (c *AWSClient) SQSWaitTimes() *SQSWaitTimesConfig { + return c.sqsWaitTimes +} diff --git a/internal/conns/config.go b/internal/conns/config.go index 80a28f747ddc..e87bf9829694 100644 --- a/internal/conns/config.go +++ b/internal/conns/config.go @@ -209,7 +209,7 @@ func (c *Config) ConfigureProvider(ctx context.Context, client *AWSClient) (*AWS client.logger = logger client.s3UsePathStyle = c.S3UsePathStyle client.s3USEast1RegionalEndpoint = c.S3USEast1RegionalEndpoint - client.SQSWaitTimes = c.SQSWaitTimes + client.sqsWaitTimes = c.SQSWaitTimes client.stsRegion = c.STSRegion return client, diags diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_test.go index e80e5bb4e22c..b5693bfae5af 100644 --- a/internal/provider/sdkv2/provider_sqs_wait_times_test.go +++ b/internal/provider/sdkv2/provider_sqs_wait_times_test.go @@ -10,7 +10,6 @@ import ( ) func TestProvider_sqsWaitTimesConfigurationParsing(t *testing.T) { - // Test that the configuration struct can be created and accessed config := &conns.SQSWaitTimesConfig{ CreateContinuousTargetOccurrence: 1, DeleteContinuousTargetOccurrence: 2, @@ -24,20 +23,19 @@ func TestProvider_sqsWaitTimesConfigurationParsing(t *testing.T) { t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", config.DeleteContinuousTargetOccurrence) } - // Test that the AWSClient can hold the configuration client := &conns.AWSClient{ - SQSWaitTimes: config, + sqsWaitTimes: config, } - if client.SQSWaitTimes == nil { + if client.SQSWaitTimes() == nil { t.Fatal("Expected SQSWaitTimes to be set") } - if client.SQSWaitTimes.CreateContinuousTargetOccurrence != 1 { - t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", client.SQSWaitTimes.CreateContinuousTargetOccurrence) + if client.SQSWaitTimes().CreateContinuousTargetOccurrence != 1 { + t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", client.SQSWaitTimes().CreateContinuousTargetOccurrence) } - if client.SQSWaitTimes.DeleteContinuousTargetOccurrence != 2 { - t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", client.SQSWaitTimes.DeleteContinuousTargetOccurrence) + if client.SQSWaitTimes().DeleteContinuousTargetOccurrence != 2 { + t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", client.SQSWaitTimes().DeleteContinuousTargetOccurrence) } } diff --git a/internal/service/sqs/queue.go b/internal/service/sqs/queue.go index ae949257a51b..b4ceca0607fa 100644 --- a/internal/service/sqs/queue.go +++ b/internal/service/sqs/queue.go @@ -602,8 +602,8 @@ func statusQueueAttributeState(ctx context.Context, conn *sqs.Client, url string func waitQueueAttributesPropagated(ctx context.Context, conn *sqs.Client, url string, expected map[types.QueueAttributeName]string, timeout time.Duration, meta any) error { continuousTargetOccurrence := 6 - if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes != nil { - continuousTargetOccurrence = awsClient.SQSWaitTimes.CreateContinuousTargetOccurrence + if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes() != nil { + continuousTargetOccurrence = awsClient.SQSWaitTimes().CreateContinuousTargetOccurrence } stateConf := &retry.StateChangeConf{ @@ -623,8 +623,8 @@ func waitQueueAttributesPropagated(ctx context.Context, conn *sqs.Client, url st func waitQueueDeleted(ctx context.Context, conn *sqs.Client, url string, timeout time.Duration, meta any) error { continuousTargetOccurrence := 15 - if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes != nil { - continuousTargetOccurrence = awsClient.SQSWaitTimes.DeleteContinuousTargetOccurrence + if awsClient, ok := meta.(*conns.AWSClient); ok && awsClient.SQSWaitTimes() != nil { + continuousTargetOccurrence = awsClient.SQSWaitTimes().DeleteContinuousTargetOccurrence } stateConf := &retry.StateChangeConf{ From 26404e52cb716af07f192a1a76a0e8bff7e20135 Mon Sep 17 00:00:00 2001 From: Jack McBride Date: Thu, 25 Sep 2025 13:14:41 +0000 Subject: [PATCH 4/4] Remove TBD.txt remove bad tests --- .changelog/TBD.txt | 3 -- .../sdkv2/provider_sqs_wait_times_test.go | 41 ------------------- 2 files changed, 44 deletions(-) delete mode 100644 .changelog/TBD.txt delete mode 100644 internal/provider/sdkv2/provider_sqs_wait_times_test.go diff --git a/.changelog/TBD.txt b/.changelog/TBD.txt deleted file mode 100644 index 36bbd4e1bae7..000000000000 --- a/.changelog/TBD.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:enhancement -provider: Add `sqs_wait_times` configuration block to customize SQS queue operation wait times for local development environments -``` diff --git a/internal/provider/sdkv2/provider_sqs_wait_times_test.go b/internal/provider/sdkv2/provider_sqs_wait_times_test.go deleted file mode 100644 index b5693bfae5af..000000000000 --- a/internal/provider/sdkv2/provider_sqs_wait_times_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package sdkv2 - -import ( - "testing" - - "github.com/hashicorp/terraform-provider-aws/internal/conns" -) - -func TestProvider_sqsWaitTimesConfigurationParsing(t *testing.T) { - config := &conns.SQSWaitTimesConfig{ - CreateContinuousTargetOccurrence: 1, - DeleteContinuousTargetOccurrence: 2, - } - - if config.CreateContinuousTargetOccurrence != 1 { - t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", config.CreateContinuousTargetOccurrence) - } - - if config.DeleteContinuousTargetOccurrence != 2 { - t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", config.DeleteContinuousTargetOccurrence) - } - - client := &conns.AWSClient{ - sqsWaitTimes: config, - } - - if client.SQSWaitTimes() == nil { - t.Fatal("Expected SQSWaitTimes to be set") - } - - if client.SQSWaitTimes().CreateContinuousTargetOccurrence != 1 { - t.Errorf("Expected CreateContinuousTargetOccurrence to be 1, got %d", client.SQSWaitTimes().CreateContinuousTargetOccurrence) - } - - if client.SQSWaitTimes().DeleteContinuousTargetOccurrence != 2 { - t.Errorf("Expected DeleteContinuousTargetOccurrence to be 2, got %d", client.SQSWaitTimes().DeleteContinuousTargetOccurrence) - } -}