Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Migrate S3 on Outposts resource to AWS SDK v2 #38816

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.9.16 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 // indirect
github.com/aws/aws-sdk-go-v2/service/s3outposts v1.26.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3 h1:hT8ZAZRIfqBqHbzKTII+CIiY8G2oC
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.3/go.mod h1:Lcxzg5rojyVPU/0eFwLtcyTaek/6Mtic5B1gJo7e/zE=
github.com/aws/aws-sdk-go-v2/service/s3control v1.46.3 h1:3De8/YQpup0mLNKh0G9JHWJLEkWNdghd5z84vw4v+yw=
github.com/aws/aws-sdk-go-v2/service/s3control v1.46.3/go.mod h1:sUA7DOI2fdRHQQUpvRVfYKTo9P0+UAsWYBHvyqFHcC0=
github.com/aws/aws-sdk-go-v2/service/s3outposts v1.26.3 h1:Hg1FVxD9pelFS8j3ilHJDUe6J/Q/VVwzWaNtN8vyNUQ=
github.com/aws/aws-sdk-go-v2/service/s3outposts v1.26.3/go.mod h1:GVq0lM4BUD3GyiLzlNWXUq9U/H5t+2eytsEDirQSAn4=
github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.3 h1:gmpU7E0ntMzXr+yQQIXbiiueOewf/1BQ9WgeaXo6BcQ=
github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.3/go.mod h1:jnQp5kPPvEgPmVPm0h/XZPmlx7DQ0pqUiISRO4s6U3s=
github.com/aws/aws-sdk-go-v2/service/schemas v1.26.3 h1:ZJW2OQNpkR8P7URtISmF8twpvz2V0tUN/OgMenlxkao=
Expand Down
6 changes: 3 additions & 3 deletions internal/conns/awsclient_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 50 additions & 55 deletions internal/service/s3outposts/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,24 @@ import (
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/s3outposts"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/arn"
"github.com/aws/aws-sdk-go-v2/service/s3outposts"
awstypes "github.com/aws/aws-sdk-go-v2/service/s3outposts/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"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @SDKResource("aws_s3outposts_endpoint")
func ResourceEndpoint() *schema.Resource {
// @SDKResource("aws_s3outposts_endpoint", name="Endpoint")
func resourceEndpoint() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceEndpointCreate,
ReadWithoutTimeout: resourceEndpointRead,
Expand All @@ -36,11 +39,11 @@ func ResourceEndpoint() *schema.Resource {

Schema: map[string]*schema.Schema{
"access_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(s3outposts.EndpointAccessType_Values(), false),
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateDiagFunc: enum.Validate[awstypes.EndpointAccessType](),
},
names.AttrARN: {
Type: schema.TypeString,
Expand Down Expand Up @@ -96,7 +99,7 @@ func ResourceEndpoint() *schema.Resource {

func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).S3OutpostsConn(ctx)
conn := meta.(*conns.AWSClient).S3OutpostsClient(ctx)

input := &s3outposts.CreateEndpointInput{
OutpostId: aws.String(d.Get("outpost_id").(string)),
Expand All @@ -105,20 +108,20 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta in
}

if v, ok := d.GetOk("access_type"); ok {
input.AccessType = aws.String(v.(string))
input.AccessType = awstypes.EndpointAccessType(v.(string))
}

if v, ok := d.GetOk("customer_owned_ipv4_pool"); ok {
input.CustomerOwnedIpv4Pool = aws.String(v.(string))
}

output, err := conn.CreateEndpointWithContext(ctx, input)
output, err := conn.CreateEndpoint(ctx, input)

if err != nil {
return sdkdiag.AppendErrorf(diags, "creating S3 Outposts Endpoint: %s", err)
}

d.SetId(aws.StringValue(output.EndpointArn))
d.SetId(aws.ToString(output.EndpointArn))

if _, err := waitEndpointStatusCreated(ctx, conn, d.Id()); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for S3 Outposts Endpoint (%s) create: %s", d.Id(), err)
Expand All @@ -129,9 +132,9 @@ func resourceEndpointCreate(ctx context.Context, d *schema.ResourceData, meta in

func resourceEndpointRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).S3OutpostsConn(ctx)
conn := meta.(*conns.AWSClient).S3OutpostsClient(ctx)

endpoint, err := FindEndpointByARN(ctx, conn, d.Id())
endpoint, err := findEndpointByARN(ctx, conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] S3 Outposts Endpoint %s not found, removing from state", d.Id())
Expand All @@ -147,7 +150,7 @@ func resourceEndpointRead(ctx context.Context, d *schema.ResourceData, meta inte
d.Set(names.AttrARN, endpoint.EndpointArn)
d.Set(names.AttrCIDRBlock, endpoint.CidrBlock)
if endpoint.CreationTime != nil {
d.Set(names.AttrCreationTime, aws.TimeValue(endpoint.CreationTime).Format(time.RFC3339))
d.Set(names.AttrCreationTime, aws.ToTime(endpoint.CreationTime).Format(time.RFC3339))
}
d.Set("customer_owned_ipv4_pool", endpoint.CustomerOwnedIpv4Pool)
if err := d.Set("network_interfaces", flattenNetworkInterfaces(endpoint.NetworkInterfaces)); err != nil {
Expand All @@ -160,7 +163,7 @@ func resourceEndpointRead(ctx context.Context, d *schema.ResourceData, meta inte

func resourceEndpointDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).S3OutpostsConn(ctx)
conn := meta.(*conns.AWSClient).S3OutpostsClient(ctx)

parsedArn, err := arn.Parse(d.Id())

Expand All @@ -176,7 +179,7 @@ func resourceEndpointDelete(ctx context.Context, d *schema.ResourceData, meta in
}

log.Printf("[DEBUG] Deleting S3 Outposts Endpoint: %s", d.Id())
_, err = conn.DeleteEndpointWithContext(ctx, &s3outposts.DeleteEndpointInput{
_, err = conn.DeleteEndpoint(ctx, &s3outposts.DeleteEndpointInput{
EndpointId: aws.String(arnResourceParts[3]),
OutpostId: aws.String(arnResourceParts[1]),
})
Expand Down Expand Up @@ -206,7 +209,7 @@ func resourceEndpointImportState(ctx context.Context, d *schema.ResourceData, me
return []*schema.ResourceData{d}, nil
}

func FindEndpointByARN(ctx context.Context, conn *s3outposts.S3Outposts, arn string) (*s3outposts.Endpoint, error) {
func findEndpointByARN(ctx context.Context, conn *s3outposts.Client, arn string) (*awstypes.Endpoint, error) {
input := &s3outposts.ListEndpointsInput{}

output, err := findEndpoints(ctx, conn, input)
Expand All @@ -216,41 +219,41 @@ func FindEndpointByARN(ctx context.Context, conn *s3outposts.S3Outposts, arn str
}

for _, v := range output {
if aws.StringValue(v.EndpointArn) == arn && aws.StringValue(v.Status) != s3outposts.EndpointStatusDeleting && aws.StringValue(v.Status) != s3outposts.EndpointStatusDeleteFailed {
return v, nil
if aws.ToString(v.EndpointArn) == arn && v.Status != awstypes.EndpointStatusDeleting && v.Status != awstypes.EndpointStatusDeleteFailed {
return &v, nil
}
}

return nil, &retry.NotFoundError{}
return nil, tfresource.NewEmptyResultError(input)
}

func findEndpoints(ctx context.Context, conn *s3outposts.S3Outposts, input *s3outposts.ListEndpointsInput) ([]*s3outposts.Endpoint, error) {
var output []*s3outposts.Endpoint
func findEndpoints(ctx context.Context, conn *s3outposts.Client, input *s3outposts.ListEndpointsInput) ([]awstypes.Endpoint, error) {
var output []awstypes.Endpoint

err := conn.ListEndpointsPagesWithContext(ctx, input, func(page *s3outposts.ListEndpointsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}
pages := s3outposts.NewListEndpointsPaginator(conn, input)
for pages.HasMorePages() {
page, err := pages.NextPage(ctx)

for _, v := range page.Endpoints {
if v != nil {
output = append(output, v)
if errs.IsA[*awstypes.ResourceNotFoundException](err) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

return !lastPage
})
if err != nil {
return nil, err
}

if err != nil {
return nil, err
output = append(output, page.Endpoints...)
}

return output, nil
}

func statusEndpoint(ctx context.Context, conn *s3outposts.S3Outposts, arn string) retry.StateRefreshFunc {
func statusEndpoint(ctx context.Context, conn *s3outposts.Client, arn string) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindEndpointByARN(ctx, conn, arn)
output, err := findEndpointByARN(ctx, conn, arn)

if tfresource.NotFound(err) {
return nil, "", nil
Expand All @@ -260,26 +263,26 @@ func statusEndpoint(ctx context.Context, conn *s3outposts.S3Outposts, arn string
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
return output, string(output.Status), nil
}
}

func waitEndpointStatusCreated(ctx context.Context, conn *s3outposts.S3Outposts, arn string) (*s3outposts.Endpoint, error) {
func waitEndpointStatusCreated(ctx context.Context, conn *s3outposts.Client, arn string) (*awstypes.Endpoint, error) {
const (
timeout = 20 * time.Minute
)
stateConf := &retry.StateChangeConf{
Pending: []string{s3outposts.EndpointStatusPending},
Target: []string{s3outposts.EndpointStatusAvailable},
Pending: enum.Slice(awstypes.EndpointStatusPending),
Target: enum.Slice(awstypes.EndpointStatusAvailable),
Refresh: statusEndpoint(ctx, conn, arn),
Timeout: timeout,
}

outputRaw, err := stateConf.WaitForStateContext(ctx)

if output, ok := outputRaw.(*s3outposts.Endpoint); ok {
if output, ok := outputRaw.(*awstypes.Endpoint); ok {
if failedReason := output.FailedReason; failedReason != nil {
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.StringValue(failedReason.ErrorCode), aws.StringValue(failedReason.Message)))
tfresource.SetLastError(err, fmt.Errorf("%s: %s", aws.ToString(failedReason.ErrorCode), aws.ToString(failedReason.Message)))
}

return output, err
Expand All @@ -288,29 +291,21 @@ func waitEndpointStatusCreated(ctx context.Context, conn *s3outposts.S3Outposts,
return nil, err
}

func flattenNetworkInterfaces(apiObjects []*s3outposts.NetworkInterface) []interface{} {
func flattenNetworkInterfaces(apiObjects []awstypes.NetworkInterface) []interface{} {
var tfList []interface{}

for _, apiObject := range apiObjects {
if apiObject == nil {
continue
}

tfList = append(tfList, flattenNetworkInterface(apiObject))
}

return tfList
}

func flattenNetworkInterface(apiObject *s3outposts.NetworkInterface) map[string]interface{} {
if apiObject == nil {
return nil
}

func flattenNetworkInterface(apiObject awstypes.NetworkInterface) map[string]interface{} {
tfMap := map[string]interface{}{}

if v := apiObject.NetworkInterfaceId; v != nil {
tfMap[names.AttrNetworkInterfaceID] = aws.StringValue(v)
tfMap[names.AttrNetworkInterfaceID] = aws.ToString(v)
}

return tfMap
Expand Down
4 changes: 2 additions & 2 deletions internal/service/s3outposts/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func TestAccS3OutpostsEndpoint_disappears(t *testing.T) {

func testAccCheckEndpointDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).S3OutpostsConn(ctx)
conn := acctest.Provider.Meta().(*conns.AWSClient).S3OutpostsClient(ctx)

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_s3outposts_endpoint" {
Expand Down Expand Up @@ -188,7 +188,7 @@ func testAccCheckEndpointExists(ctx context.Context, n string) resource.TestChec
return fmt.Errorf("No S3 Outposts Endpoint ID is set")
}

conn := acctest.Provider.Meta().(*conns.AWSClient).S3OutpostsConn(ctx)
conn := acctest.Provider.Meta().(*conns.AWSClient).S3OutpostsClient(ctx)

_, err := tfs3outposts.FindEndpointByARN(ctx, conn, rs.Primary.ID)

Expand Down
11 changes: 11 additions & 0 deletions internal/service/s3outposts/exports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package s3outposts

// Exports for use in tests only.
var (
FindEndpointByARN = findEndpointByARN

ResourceEndpoint = resourceEndpoint
)
Loading
Loading