diff --git a/go.mod b/go.mod index ad28b281097..66da96a787c 100644 --- a/go.mod +++ b/go.mod @@ -77,6 +77,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/medialive v1.44.1 github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.7 github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.7.7 + github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.6 github.com/aws/aws-sdk-go-v2/service/mq v1.20.7 github.com/aws/aws-sdk-go-v2/service/oam v1.7.7 github.com/aws/aws-sdk-go-v2/service/opensearchserverless v1.9.6 diff --git a/go.sum b/go.sum index 16d676a07a4..91ff548500c 100644 --- a/go.sum +++ b/go.sum @@ -188,6 +188,8 @@ github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.7 h1:vdaaK74RcQKM7Db8GAE github.com/aws/aws-sdk-go-v2/service/mediapackage v1.28.7/go.mod h1:02B7Q0lKo1j+EXy5xJdiQ1WXHSstaZzeP1pWaSngHEM= github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.7.7 h1:7K4U+KzcPCZFsnJdUtDYDeufXpCR94XWvGe7NDToUt4= github.com/aws/aws-sdk-go-v2/service/mediapackagev2 v1.7.7/go.mod h1:pKEbhmBUQhflog7rfoQPSi6b/8+skFWq6CQQ5UOgsDQ= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.6 h1:8iy67SQ3gJDytDEOmkMXxCqXMwb4QVBuXjieDxS/iNY= +github.com/aws/aws-sdk-go-v2/service/mediastore v1.18.6/go.mod h1:mjWnSGMBWSh9DOju44R6t8U3i9XlDxl9PlSnOPb2WTk= github.com/aws/aws-sdk-go-v2/service/mq v1.20.7 h1:d4hynfHB+JsY5zcek4ITxVnVEkkxa7ZZDJW6OOPwEeQ= github.com/aws/aws-sdk-go-v2/service/mq v1.20.7/go.mod h1:PHzqJZbmPmkFXCZiaOdEY9KoGFYWD2lVO2Rv8Om1hSg= github.com/aws/aws-sdk-go-v2/service/oam v1.7.7 h1:b9/KbZcdS1XmP6vjKj+62bVoRbY+9fcf3iDDBxS4yKU= diff --git a/internal/conns/awsclient_gen.go b/internal/conns/awsclient_gen.go index 9aa5a3aab98..bbd04175b73 100644 --- a/internal/conns/awsclient_gen.go +++ b/internal/conns/awsclient_gen.go @@ -71,6 +71,7 @@ import ( medialive_sdkv2 "github.com/aws/aws-sdk-go-v2/service/medialive" mediapackage_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackage" mediapackagev2_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediapackagev2" + mediastore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediastore" mq_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mq" oam_sdkv2 "github.com/aws/aws-sdk-go-v2/service/oam" opensearchserverless_sdkv2 "github.com/aws/aws-sdk-go-v2/service/opensearchserverless" @@ -200,7 +201,6 @@ import ( locationservice_sdkv1 "github.com/aws/aws-sdk-go/service/locationservice" macie2_sdkv1 "github.com/aws/aws-sdk-go/service/macie2" managedgrafana_sdkv1 "github.com/aws/aws-sdk-go/service/managedgrafana" - mediastore_sdkv1 "github.com/aws/aws-sdk-go/service/mediastore" memorydb_sdkv1 "github.com/aws/aws-sdk-go/service/memorydb" mwaa_sdkv1 "github.com/aws/aws-sdk-go/service/mwaa" neptune_sdkv1 "github.com/aws/aws-sdk-go/service/neptune" @@ -841,8 +841,8 @@ func (c *AWSClient) MediaPackageV2Client(ctx context.Context) *mediapackagev2_sd return errs.Must(client[*mediapackagev2_sdkv2.Client](ctx, c, names.MediaPackageV2, make(map[string]any))) } -func (c *AWSClient) MediaStoreConn(ctx context.Context) *mediastore_sdkv1.MediaStore { - return errs.Must(conn[*mediastore_sdkv1.MediaStore](ctx, c, names.MediaStore, make(map[string]any))) +func (c *AWSClient) MediaStoreClient(ctx context.Context) *mediastore_sdkv2.Client { + return errs.Must(client[*mediastore_sdkv2.Client](ctx, c, names.MediaStore, make(map[string]any))) } func (c *AWSClient) MemoryDBConn(ctx context.Context) *memorydb_sdkv1.MemoryDB { diff --git a/internal/service/mediastore/container.go b/internal/service/mediastore/container.go index 20376b9cacf..e5cf9ec23ec 100644 --- a/internal/service/mediastore/container.go +++ b/internal/service/mediastore/container.go @@ -5,19 +5,20 @@ package mediastore import ( "context" - "fmt" "log" "time" "github.com/YakDriver/regexache" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/mediastore" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/mediastore" + awstypes "github.com/aws/aws-sdk-go-v2/service/mediastore/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/enum" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -61,30 +62,22 @@ func ResourceContainer() *schema.Resource { func resourceContainerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) input := &mediastore.CreateContainerInput{ ContainerName: aws.String(d.Get("name").(string)), Tags: getTagsIn(ctx), } - resp, err := conn.CreateContainerWithContext(ctx, input) + resp, err := conn.CreateContainer(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "creating MediaStore Container: %s", err) } - d.SetId(aws.StringValue(resp.Container.Name)) + d.SetId(aws.ToString(resp.Container.Name)) - stateConf := &retry.StateChangeConf{ - Pending: []string{mediastore.ContainerStatusCreating}, - Target: []string{mediastore.ContainerStatusActive}, - Refresh: containerRefreshStatusFunc(ctx, conn, d.Id()), - Timeout: 10 * time.Minute, - Delay: 10 * time.Second, - MinTimeout: 3 * time.Second, - } + _, err = waitContainerActive(ctx, conn, d.Id()) - _, err = stateConf.WaitForStateContext(ctx) if err != nil { return sdkdiag.AppendErrorf(diags, "creating MediaStore Container (%s): waiting for completion: %s", d.Id(), err) } @@ -94,25 +87,24 @@ func resourceContainerCreate(ctx context.Context, d *schema.ResourceData, meta i func resourceContainerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) - input := &mediastore.DescribeContainerInput{ - ContainerName: aws.String(d.Id()), - } - resp, err := conn.DescribeContainerWithContext(ctx, input) - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { + resp, err := findContainerByName(ctx, conn, d.Id()) + + if tfresource.NotFound(err) { log.Printf("[WARN] No Container found: %s, removing from state", d.Id()) d.SetId("") return diags } + if err != nil { return sdkdiag.AppendErrorf(diags, "reading MediaStore Container %s: %s", d.Id(), err) } - arn := aws.StringValue(resp.Container.ARN) + arn := aws.ToString(resp.ARN) d.Set("arn", arn) - d.Set("name", resp.Container.Name) - d.Set("endpoint", resp.Container.Endpoint) + d.Set("name", resp.Name) + d.Set("endpoint", resp.Endpoint) return diags } @@ -127,35 +119,23 @@ func resourceContainerUpdate(ctx context.Context, d *schema.ResourceData, meta i func resourceContainerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) input := &mediastore.DeleteContainerInput{ ContainerName: aws.String(d.Id()), } - _, err := conn.DeleteContainerWithContext(ctx, input) + _, err := conn.DeleteContainer(ctx, input) + + if errs.IsA[*awstypes.ContainerNotFoundException](err) { + return diags + } + if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - return diags - } return sdkdiag.AppendErrorf(diags, "deleting MediaStore Container (%s): %s", d.Id(), err) } - dcinput := &mediastore.DescribeContainerInput{ - ContainerName: aws.String(d.Id()), - } - err = retry.RetryContext(ctx, 5*time.Minute, func() *retry.RetryError { - _, err := conn.DescribeContainerWithContext(ctx, dcinput) - if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - return nil - } - return retry.NonRetryableError(err) - } - return retry.RetryableError(fmt.Errorf("Media Store Container (%s) still exists", d.Id())) - }) - if tfresource.TimedOut(err) { - _, err = conn.DescribeContainerWithContext(ctx, dcinput) - } + _, err = waitContainerDeleted(ctx, conn, d.Id()) + if err != nil { return sdkdiag.AppendErrorf(diags, "deleting MediaStore Container (%s): waiting for completion: %s", d.Id(), err) } @@ -163,15 +143,79 @@ func resourceContainerDelete(ctx context.Context, d *schema.ResourceData, meta i return diags } -func containerRefreshStatusFunc(ctx context.Context, conn *mediastore.MediaStore, cn string) retry.StateRefreshFunc { +func containerRefreshStatusFunc(ctx context.Context, conn *mediastore.Client, cn string) retry.StateRefreshFunc { return func() (interface{}, string, error) { - input := &mediastore.DescribeContainerInput{ - ContainerName: aws.String(cn), + resp, err := findContainerByName(ctx, conn, cn) + + if tfresource.NotFound(err) { + return nil, "", nil } - resp, err := conn.DescribeContainerWithContext(ctx, input) + if err != nil { - return nil, "failed", err + return nil, "", err + } + + return resp, string(resp.Status), nil + } +} + +func findContainerByName(ctx context.Context, conn *mediastore.Client, id string) (*awstypes.Container, error) { + input := &mediastore.DescribeContainerInput{ + ContainerName: aws.String(id), + } + + output, err := conn.DescribeContainer(ctx, input) + + if errs.IsA[*awstypes.ContainerNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, } - return resp, *resp.Container.Status, nil } + + if err != nil { + return nil, err + } + + if output == nil || output.Container == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output.Container, nil +} + +func waitContainerActive(ctx context.Context, conn *mediastore.Client, id string) (*awstypes.Container, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.ContainerStatusCreating), + Target: enum.Slice(awstypes.ContainerStatusActive), + Refresh: containerRefreshStatusFunc(ctx, conn, id), + Timeout: 10 * time.Minute, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if v, ok := outputRaw.(*awstypes.Container); ok { + return v, err + } + + return nil, err +} + +func waitContainerDeleted(ctx context.Context, conn *mediastore.Client, id string) (*awstypes.Container, error) { + stateConf := &retry.StateChangeConf{ + Pending: enum.Slice(awstypes.ContainerStatusDeleting), + Target: []string{}, + Refresh: containerRefreshStatusFunc(ctx, conn, id), + Timeout: 10 * time.Minute, + Delay: 10 * time.Second, + MinTimeout: 3 * time.Second, + } + + outputRaw, err := stateConf.WaitForStateContext(ctx) + if v, ok := outputRaw.(*awstypes.Container); ok { + return v, err + } + + return nil, err } diff --git a/internal/service/mediastore/container_policy.go b/internal/service/mediastore/container_policy.go index bb418440275..0c1f5523587 100644 --- a/internal/service/mediastore/container_policy.go +++ b/internal/service/mediastore/container_policy.go @@ -7,14 +7,17 @@ import ( "context" "log" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/mediastore" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/mediastore" + awstypes "github.com/aws/aws-sdk-go-v2/service/mediastore/types" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" "github.com/hashicorp/terraform-provider-aws/internal/verify" ) @@ -51,7 +54,7 @@ func ResourceContainerPolicy() *schema.Resource { func resourceContainerPolicyPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) name := d.Get("container_name").(string) policy, err := structure.NormalizeJsonString(d.Get("policy").(string)) @@ -65,7 +68,7 @@ func resourceContainerPolicyPut(ctx context.Context, d *schema.ResourceData, met Policy: aws.String(policy), } - _, err = conn.PutContainerPolicyWithContext(ctx, input) + _, err = conn.PutContainerPolicy(ctx, input) if err != nil { return sdkdiag.AppendErrorf(diags, "putting MediaStore Container Policy (%s): %s", name, err) } @@ -76,30 +79,23 @@ func resourceContainerPolicyPut(ctx context.Context, d *schema.ResourceData, met func resourceContainerPolicyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) - input := &mediastore.GetContainerPolicyInput{ - ContainerName: aws.String(d.Id()), + resp, err := findContainerPolicyByContainerName(ctx, conn, d.Id()) + + if tfresource.NotFound(err) { + log.Printf("[WARN] MediaStore Container Policy (%s) not found, removing from state", d.Id()) + d.SetId("") + return diags } - resp, err := conn.GetContainerPolicyWithContext(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - log.Printf("[WARN] MediaStore Container Policy (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodePolicyNotFoundException) { - log.Printf("[WARN] MediaStore Container Policy (%s) not found, removing from state", d.Id()) - d.SetId("") - return diags - } return sdkdiag.AppendErrorf(diags, "reading MediaStore Container Policy (%s): %s", d.Id(), err) } d.Set("container_name", d.Id()) - policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.StringValue(resp.Policy)) + policyToSet, err := verify.PolicyToSet(d.Get("policy").(string), aws.ToString(resp.Policy)) if err != nil { return sdkdiag.AppendErrorf(diags, "reading MediaStore Container Policy (%s): %s", d.Id(), err) } @@ -111,25 +107,42 @@ func resourceContainerPolicyRead(ctx context.Context, d *schema.ResourceData, me func resourceContainerPolicyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics - conn := meta.(*conns.AWSClient).MediaStoreConn(ctx) + conn := meta.(*conns.AWSClient).MediaStoreClient(ctx) input := &mediastore.DeleteContainerPolicyInput{ ContainerName: aws.String(d.Id()), } - _, err := conn.DeleteContainerPolicyWithContext(ctx, input) + _, err := conn.DeleteContainerPolicy(ctx, input) + + if errs.IsA[*awstypes.ContainerNotFoundException](err) || errs.IsA[*awstypes.PolicyNotFoundException](err) { + return diags + } + if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - return diags - } - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodePolicyNotFoundException) { - return diags - } - // if isAWSErr(err, mediastore.ErrCodeContainerInUseException, "Container must be ACTIVE in order to perform this operation") { - // return nil - // } return sdkdiag.AppendErrorf(diags, "deleting MediaStore Container Policy (%s): %s", d.Id(), err) } return diags } + +func findContainerPolicyByContainerName(ctx context.Context, conn *mediastore.Client, id string) (*mediastore.GetContainerPolicyOutput, error) { + input := &mediastore.GetContainerPolicyInput{ + ContainerName: aws.String(id), + } + + output, err := conn.GetContainerPolicy(ctx, input) + + if errs.IsA[*awstypes.ContainerNotFoundException](err) || errs.IsA[*awstypes.PolicyNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if output == nil || output.Policy == nil { + return nil, tfresource.NewEmptyResultError(input) + } + + return output, nil +} diff --git a/internal/service/mediastore/container_policy_test.go b/internal/service/mediastore/container_policy_test.go index b7978fc322f..b01d1fe9cb7 100644 --- a/internal/service/mediastore/container_policy_test.go +++ b/internal/service/mediastore/container_policy_test.go @@ -9,14 +9,14 @@ import ( "strings" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/mediastore" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfmediastore "github.com/hashicorp/terraform-provider-aws/internal/service/mediastore" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccMediaStoreContainerPolicy_basic(t *testing.T) { @@ -28,7 +28,7 @@ func TestAccMediaStoreContainerPolicy_basic(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, mediastore.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.MedialStoreEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckContainerPolicyDestroy(ctx), Steps: []resource.TestStep{ @@ -57,35 +57,53 @@ func TestAccMediaStoreContainerPolicy_basic(t *testing.T) { }) } +func TestAccMediaStoreContainerPolicy_disappears(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_media_store_container_policy.test" + + rName = strings.ReplaceAll(rName, "-", "_") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.MedialStoreEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckContainerPolicyDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccContainerPolicyConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckContainerPolicyExists(ctx, resourceName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfmediastore.ResourceContainerPolicy(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckContainerPolicyDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_media_store_container_policy" { continue } - input := &mediastore.GetContainerPolicyInput{ - ContainerName: aws.String(rs.Primary.ID), + _, err := tfmediastore.FindContainerPolicyByContainerName(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } - _, err := conn.GetContainerPolicyWithContext(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - return nil - } - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodePolicyNotFoundException) { - return nil - } - if tfawserr.ErrMessageContains(err, mediastore.ErrCodeContainerInUseException, "Container must be ACTIVE in order to perform this operation") { - return nil - } return err } return fmt.Errorf("Expected MediaStore Container Policy to be destroyed, %s found", rs.Primary.ID) } + return nil } } @@ -97,15 +115,15 @@ func testAccCheckContainerPolicyExists(ctx context.Context, name string) resourc return fmt.Errorf("Not found: %s", name) } - conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreClient(ctx) - input := &mediastore.GetContainerPolicyInput{ - ContainerName: aws.String(rs.Primary.ID), - } + _, err := tfmediastore.FindContainerPolicyByContainerName(ctx, conn, rs.Primary.ID) - _, err := conn.GetContainerPolicyWithContext(ctx, input) + if err != nil { + return fmt.Errorf("retrieving MediaStore Container Policy (%s): %w", rs.Primary.ID, err) + } - return err + return nil } } diff --git a/internal/service/mediastore/container_test.go b/internal/service/mediastore/container_test.go index efed8634027..14fae80c528 100644 --- a/internal/service/mediastore/container_test.go +++ b/internal/service/mediastore/container_test.go @@ -6,30 +6,35 @@ package mediastore_test import ( "context" "fmt" + "strings" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/mediastore" - "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/aws/aws-sdk-go-v2/service/mediastore" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-aws/internal/acctest" "github.com/hashicorp/terraform-provider-aws/internal/conns" + tfmediastore "github.com/hashicorp/terraform-provider-aws/internal/service/mediastore" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" ) func TestAccMediaStoreContainer_basic(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_media_store_container.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName = strings.ReplaceAll(rName, "-", "_") + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, mediastore.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.MedialStoreEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckContainerDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccContainerConfig_basic(sdkacctest.RandString(5)), + Config: testAccContainerConfig_basic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckContainerExists(ctx, resourceName), ), @@ -45,12 +50,14 @@ func TestAccMediaStoreContainer_basic(t *testing.T) { func TestAccMediaStoreContainer_tags(t *testing.T) { ctx := acctest.Context(t) - rName := sdkacctest.RandString(5) resourceName := "aws_media_store_container.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName = strings.ReplaceAll(rName, "-", "_") + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, - ErrorCheck: acctest.ErrorCheck(t, mediastore.EndpointsID), + ErrorCheck: acctest.ErrorCheck(t, names.MedialStoreEndpointID), ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, CheckDestroy: testAccCheckContainerDestroy(ctx), Steps: []resource.TestStep{ @@ -59,7 +66,6 @@ func TestAccMediaStoreContainer_tags(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckContainerExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "3"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", fmt.Sprintf("tf_mediastore_%s", rName)), resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar"), resource.TestCheckResourceAttr(resourceName, "tags.fizz", "buzz"), ), @@ -69,7 +75,6 @@ func TestAccMediaStoreContainer_tags(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckContainerExists(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, "tags.%", "3"), - resource.TestCheckResourceAttr(resourceName, "tags.Name", fmt.Sprintf("tf_mediastore_%s", rName)), resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar2"), resource.TestCheckResourceAttr(resourceName, "tags.fizz2", "buzz2"), ), @@ -90,31 +95,53 @@ func TestAccMediaStoreContainer_tags(t *testing.T) { }) } +func TestAccMediaStoreContainer_disappears(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_media_store_container.test" + + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName = strings.ReplaceAll(rName, "-", "_") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.MedialStoreEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckContainerDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccContainerConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckContainerExists(ctx, resourceName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tfmediastore.ResourceContainer(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckContainerDestroy(ctx context.Context) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreClient(ctx) for _, rs := range s.RootModule().Resources { if rs.Type != "aws_media_store_container" { continue } - input := &mediastore.DescribeContainerInput{ - ContainerName: aws.String(rs.Primary.ID), + _, err := tfmediastore.FindContainerByName(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue } - resp, err := conn.DescribeContainerWithContext(ctx, input) if err != nil { - if tfawserr.ErrCodeEquals(err, mediastore.ErrCodeContainerNotFoundException) { - return nil - } return err } - if *resp.Container.Status != mediastore.ContainerStatusDeleting { - return fmt.Errorf("MediaStore Container (%s) not deleted", rs.Primary.ID) - } + return fmt.Errorf("container (%s) still exists", rs.Primary.ID) } + return nil } } @@ -126,24 +153,24 @@ func testAccCheckContainerExists(ctx context.Context, name string) resource.Test return fmt.Errorf("Not found: %s", name) } - conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreClient(ctx) - input := &mediastore.DescribeContainerInput{ - ContainerName: aws.String(rs.Primary.ID), - } + _, err := tfmediastore.FindContainerByName(ctx, conn, rs.Primary.ID) - _, err := conn.DescribeContainerWithContext(ctx, input) + if err != nil { + return fmt.Errorf("retrieving MediaStore Container (%s): %w", rs.Primary.ID, err) + } - return err + return nil } } func testAccPreCheck(ctx context.Context, t *testing.T) { - conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreConn(ctx) + conn := acctest.Provider.Meta().(*conns.AWSClient).MediaStoreClient(ctx) input := &mediastore.ListContainersInput{} - _, err := conn.ListContainersWithContext(ctx, input) + _, err := conn.ListContainers(ctx, input) if acctest.PreCheckSkipError(err) { t.Skipf("skipping acceptance testing: %s", err) @@ -157,7 +184,7 @@ func testAccPreCheck(ctx context.Context, t *testing.T) { func testAccContainerConfig_basic(rName string) string { return fmt.Sprintf(` resource "aws_media_store_container" "test" { - name = "tf_mediastore_%s" + name = %[1]q } `, rName) } @@ -165,10 +192,10 @@ resource "aws_media_store_container" "test" { func testAccContainerConfig_tags(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { return fmt.Sprintf(` resource "aws_media_store_container" "test" { - name = "tf_mediastore_%[1]s" + name = %[1]q tags = { - Name = "tf_mediastore_%[1]s" + Name = %[1]q %[2]s = %[3]q %[4]s = %[5]q diff --git a/internal/service/mediastore/exports_test.go b/internal/service/mediastore/exports_test.go new file mode 100644 index 00000000000..8df3834cdda --- /dev/null +++ b/internal/service/mediastore/exports_test.go @@ -0,0 +1,10 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package mediastore + +// Exports for use in tests only. +var ( + FindContainerByName = findContainerByName + FindContainerPolicyByContainerName = findContainerPolicyByContainerName +) diff --git a/internal/service/mediastore/generate.go b/internal/service/mediastore/generate.go index 55c91274d5b..4104febbaa4 100644 --- a/internal/service/mediastore/generate.go +++ b/internal/service/mediastore/generate.go @@ -1,7 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -//go:generate go run ../../generate/tags/main.go -ListTags -ListTagsInIDElem=Resource -ServiceTagsSlice -TagInIDElem=Resource -UpdateTags +//go:generate go run ../../generate/tags/main.go -AWSSDKVersion=2 -ListTags -ListTagsInIDElem=Resource -ServiceTagsSlice -TagInIDElem=Resource -UpdateTags //go:generate go run ../../generate/servicepackage/main.go // ONLY generate directives and package declaration! Do not add anything else to this file. diff --git a/internal/service/mediastore/service_endpoints_gen_test.go b/internal/service/mediastore/service_endpoints_gen_test.go index 9fc7ab99e57..312ba6fb9fa 100644 --- a/internal/service/mediastore/service_endpoints_gen_test.go +++ b/internal/service/mediastore/service_endpoints_gen_test.go @@ -4,16 +4,16 @@ package mediastore_test import ( "context" + "errors" "fmt" - "net/url" "os" "path/filepath" "reflect" "strings" "testing" - "github.com/aws/aws-sdk-go/aws/endpoints" - mediastore_sdkv1 "github.com/aws/aws-sdk-go/service/mediastore" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediastore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediastore" "github.com/aws/smithy-go/middleware" smithyhttp "github.com/aws/smithy-go/transport/http" "github.com/google/go-cmp/cmp" @@ -212,32 +212,42 @@ func TestEndpointConfiguration(t *testing.T) { //nolint:paralleltest // uses t.S } func defaultEndpoint(region string) string { - r := endpoints.DefaultResolver() + r := mediastore_sdkv2.NewDefaultEndpointResolverV2() - ep, err := r.EndpointFor(mediastore_sdkv1.EndpointsID, region) + ep, err := r.ResolveEndpoint(context.Background(), mediastore_sdkv2.EndpointParameters{ + Region: aws_sdkv2.String(region), + }) if err != nil { return err.Error() } - url, _ := url.Parse(ep.URL) - - if url.Path == "" { - url.Path = "/" + if ep.URI.Path == "" { + ep.URI.Path = "/" } - return url.String() + return ep.URI.String() } func callService(ctx context.Context, t *testing.T, meta *conns.AWSClient) string { t.Helper() - client := meta.MediaStoreConn(ctx) - - req, _ := client.ListContainersRequest(&mediastore_sdkv1.ListContainersInput{}) + var endpoint string - req.HTTPRequest.URL.Path = "/" + client := meta.MediaStoreClient(ctx) - endpoint := req.HTTPRequest.URL.String() + _, err := client.ListContainers(ctx, &mediastore_sdkv2.ListContainersInput{}, + func(opts *mediastore_sdkv2.Options) { + opts.APIOptions = append(opts.APIOptions, + addRetrieveEndpointURLMiddleware(t, &endpoint), + addCancelRequestMiddleware(), + ) + }, + ) + if err == nil { + t.Fatal("Expected an error, got none") + } else if !errors.Is(err, errCancelOperation) { + t.Fatalf("Unexpected error: %s", err) + } return endpoint } diff --git a/internal/service/mediastore/service_package_gen.go b/internal/service/mediastore/service_package_gen.go index 15af80f5a96..1302d1f2628 100644 --- a/internal/service/mediastore/service_package_gen.go +++ b/internal/service/mediastore/service_package_gen.go @@ -5,9 +5,8 @@ package mediastore import ( "context" - aws_sdkv1 "github.com/aws/aws-sdk-go/aws" - session_sdkv1 "github.com/aws/aws-sdk-go/aws/session" - mediastore_sdkv1 "github.com/aws/aws-sdk-go/service/mediastore" + aws_sdkv2 "github.com/aws/aws-sdk-go-v2/aws" + mediastore_sdkv2 "github.com/aws/aws-sdk-go-v2/service/mediastore" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/names" @@ -48,11 +47,15 @@ func (p *servicePackage) ServicePackageName() string { return names.MediaStore } -// NewConn returns a new AWS SDK for Go v1 client for this service package's AWS API. -func (p *servicePackage) NewConn(ctx context.Context, config map[string]any) (*mediastore_sdkv1.MediaStore, error) { - sess := config["session"].(*session_sdkv1.Session) +// NewClient returns a new AWS SDK for Go v2 client for this service package's AWS API. +func (p *servicePackage) NewClient(ctx context.Context, config map[string]any) (*mediastore_sdkv2.Client, error) { + cfg := *(config["aws_sdkv2_config"].(*aws_sdkv2.Config)) - return mediastore_sdkv1.New(sess.Copy(&aws_sdkv1.Config{Endpoint: aws_sdkv1.String(config["endpoint"].(string))})), nil + return mediastore_sdkv2.NewFromConfig(cfg, func(o *mediastore_sdkv2.Options) { + if endpoint := config["endpoint"].(string); endpoint != "" { + o.BaseEndpoint = aws_sdkv2.String(endpoint) + } + }), nil } func ServicePackage(ctx context.Context) conns.ServicePackage { diff --git a/internal/service/mediastore/tags_gen.go b/internal/service/mediastore/tags_gen.go index b7095fc02ab..302c07ff86f 100644 --- a/internal/service/mediastore/tags_gen.go +++ b/internal/service/mediastore/tags_gen.go @@ -5,9 +5,9 @@ import ( "context" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/mediastore" - "github.com/aws/aws-sdk-go/service/mediastore/mediastoreiface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/mediastore" + awstypes "github.com/aws/aws-sdk-go-v2/service/mediastore/types" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-aws/internal/conns" "github.com/hashicorp/terraform-provider-aws/internal/logging" @@ -19,12 +19,12 @@ import ( // listTags lists mediastore service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func listTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identifier string) (tftags.KeyValueTags, error) { +func listTags(ctx context.Context, conn *mediastore.Client, identifier string, optFns ...func(*mediastore.Options)) (tftags.KeyValueTags, error) { input := &mediastore.ListTagsForResourceInput{ Resource: aws.String(identifier), } - output, err := conn.ListTagsForResourceWithContext(ctx, input) + output, err := conn.ListTagsForResource(ctx, input, optFns...) if err != nil { return tftags.New(ctx, nil), err @@ -36,7 +36,7 @@ func listTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identifie // ListTags lists mediastore service tags and set them in Context. // It is called from outside this package. func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier string) error { - tags, err := listTags(ctx, meta.(*conns.AWSClient).MediaStoreConn(ctx), identifier) + tags, err := listTags(ctx, meta.(*conns.AWSClient).MediaStoreClient(ctx), identifier) if err != nil { return err @@ -52,11 +52,11 @@ func (p *servicePackage) ListTags(ctx context.Context, meta any, identifier stri // []*SERVICE.Tag handling // Tags returns mediastore service tags. -func Tags(tags tftags.KeyValueTags) []*mediastore.Tag { - result := make([]*mediastore.Tag, 0, len(tags)) +func Tags(tags tftags.KeyValueTags) []awstypes.Tag { + result := make([]awstypes.Tag, 0, len(tags)) for k, v := range tags.Map() { - tag := &mediastore.Tag{ + tag := awstypes.Tag{ Key: aws.String(k), Value: aws.String(v), } @@ -68,11 +68,11 @@ func Tags(tags tftags.KeyValueTags) []*mediastore.Tag { } // KeyValueTags creates tftags.KeyValueTags from mediastore service tags. -func KeyValueTags(ctx context.Context, tags []*mediastore.Tag) tftags.KeyValueTags { +func KeyValueTags(ctx context.Context, tags []awstypes.Tag) tftags.KeyValueTags { m := make(map[string]*string, len(tags)) for _, tag := range tags { - m[aws.StringValue(tag.Key)] = tag.Value + m[aws.ToString(tag.Key)] = tag.Value } return tftags.New(ctx, m) @@ -80,7 +80,7 @@ func KeyValueTags(ctx context.Context, tags []*mediastore.Tag) tftags.KeyValueTa // getTagsIn returns mediastore service tags from Context. // nil is returned if there are no input tags. -func getTagsIn(ctx context.Context) []*mediastore.Tag { +func getTagsIn(ctx context.Context) []awstypes.Tag { if inContext, ok := tftags.FromContext(ctx); ok { if tags := Tags(inContext.TagsIn.UnwrapOrDefault()); len(tags) > 0 { return tags @@ -91,7 +91,7 @@ func getTagsIn(ctx context.Context) []*mediastore.Tag { } // setTagsOut sets mediastore service tags in Context. -func setTagsOut(ctx context.Context, tags []*mediastore.Tag) { +func setTagsOut(ctx context.Context, tags []awstypes.Tag) { if inContext, ok := tftags.FromContext(ctx); ok { inContext.TagsOut = option.Some(KeyValueTags(ctx, tags)) } @@ -100,7 +100,7 @@ func setTagsOut(ctx context.Context, tags []*mediastore.Tag) { // updateTags updates mediastore service tags. // The identifier is typically the Amazon Resource Name (ARN), although // it may also be a different identifier depending on the service. -func updateTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identifier string, oldTagsMap, newTagsMap any) error { +func updateTags(ctx context.Context, conn *mediastore.Client, identifier string, oldTagsMap, newTagsMap any, optFns ...func(*mediastore.Options)) error { oldTags := tftags.New(ctx, oldTagsMap) newTags := tftags.New(ctx, newTagsMap) @@ -111,10 +111,10 @@ func updateTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identif if len(removedTags) > 0 { input := &mediastore.UntagResourceInput{ Resource: aws.String(identifier), - TagKeys: aws.StringSlice(removedTags.Keys()), + TagKeys: removedTags.Keys(), } - _, err := conn.UntagResourceWithContext(ctx, input) + _, err := conn.UntagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("untagging resource (%s): %w", identifier, err) @@ -129,7 +129,7 @@ func updateTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identif Tags: Tags(updatedTags), } - _, err := conn.TagResourceWithContext(ctx, input) + _, err := conn.TagResource(ctx, input, optFns...) if err != nil { return fmt.Errorf("tagging resource (%s): %w", identifier, err) @@ -142,5 +142,5 @@ func updateTags(ctx context.Context, conn mediastoreiface.MediaStoreAPI, identif // UpdateTags updates mediastore service tags. // It is called from outside this package. func (p *servicePackage) UpdateTags(ctx context.Context, meta any, identifier string, oldTags, newTags any) error { - return updateTags(ctx, meta.(*conns.AWSClient).MediaStoreConn(ctx), identifier, oldTags, newTags) + return updateTags(ctx, meta.(*conns.AWSClient).MediaStoreClient(ctx), identifier, oldTags, newTags) } diff --git a/names/data/names_data.csv b/names/data/names_data.csv index 3bd84a6d767..a36837ea586 100644 --- a/names/data/names_data.csv +++ b/names/data/names_data.csv @@ -146,7 +146,7 @@ mediaconvert,mediaconvert,mediaconvert,mediaconvert,,mediaconvert,,,MediaConvert medialive,medialive,medialive,medialive,,medialive,,,MediaLive,MediaLive,,,2,,aws_medialive_,,medialive_,Elemental MediaLive,AWS,,,,,,,MediaLive,ListOfferings,, mediapackage,mediapackage,mediapackage,mediapackage,,mediapackage,,,MediaPackage,MediaPackage,,,2,aws_media_package_,aws_mediapackage_,,media_package_,Elemental MediaPackage,AWS,,,,,,,MediaPackage,ListChannels,, mediapackage-vod,mediapackagevod,mediapackagevod,mediapackagevod,,mediapackagevod,,,MediaPackageVOD,MediaPackageVod,,1,,,aws_mediapackagevod_,,mediapackagevod_,Elemental MediaPackage VOD,AWS,,x,,,,,MediaPackage Vod,,, -mediastore,mediastore,mediastore,mediastore,,mediastore,,,MediaStore,MediaStore,,1,,aws_media_store_,aws_mediastore_,,media_store_,Elemental MediaStore,AWS,,,,,,,MediaStore,ListContainers,, +mediastore,mediastore,mediastore,mediastore,,mediastore,,,MediaStore,MediaStore,,,2,aws_media_store_,aws_mediastore_,,media_store_,Elemental MediaStore,AWS,,,,,,,MediaStore,ListContainers,, mediastore-data,mediastoredata,mediastoredata,mediastoredata,,mediastoredata,,,MediaStoreData,MediaStoreData,,1,,,aws_mediastoredata_,,mediastoredata_,Elemental MediaStore Data,AWS,,x,,,,,MediaStore Data,,, mediatailor,mediatailor,mediatailor,mediatailor,,mediatailor,,,MediaTailor,MediaTailor,,1,,,aws_mediatailor_,,media_tailor_,Elemental MediaTailor,AWS,,x,,,,,MediaTailor,,, ,,,,,,,,,,,,,,,,,Elemental On-Premises,AWS,x,,,,,,,,,No SDK support diff --git a/names/names.go b/names/names.go index 543b3aeab02..67fe17e7932 100644 --- a/names/names.go +++ b/names/names.go @@ -73,6 +73,7 @@ const ( LexV2ModelsEndpointID = "models-v2-lex" MediaConvertEndpointID = "mediaconvert" MediaLiveEndpointID = "medialive" + MedialStoreEndpointID = "mediastore" MQEndpointID = "mq" ObservabilityAccessManagerEndpointID = "oam" OpenSearchServerlessEndpointID = "aoss"