diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d2b53a..a08f468 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,9 @@ jobs: - name: Install Linux packages run: sudo apt install -y --no-install-recommends pandoc + - name: Install and start DynamoDB + uses: rrainn/dynamodb-action@v2.0.1 + - name: Install Go uses: actions/setup-go@v5 with: diff --git a/go.mod b/go.mod index a7f3ba8..00661c9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,10 @@ module github.com/nyaruka/gocommon go 1.22 require ( - github.com/aws/aws-sdk-go v1.55.3 + github.com/aws/aws-sdk-go-v2 v1.30.4 + github.com/aws/aws-sdk-go-v2/config v1.27.28 + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 + github.com/aws/aws-sdk-go-v2/service/s3 v1.60.0 github.com/gabriel-vasile/mimetype v1.4.5 github.com/go-chi/chi/v5 v5.1.0 github.com/go-playground/validator/v10 v10.22.0 @@ -24,10 +27,23 @@ require ( ) require ( + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.25.0 // indirect diff --git a/go.sum b/go.sum index fc5c79c..ffc44e9 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,41 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/aws/aws-sdk-go v1.55.3 h1:0B5hOX+mIx7I5XPOrjrHlKSDQV/+ypFZpIHOx5LOk3E= -github.com/aws/aws-sdk-go v1.55.3/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4 h1:70PVAiL15/aBMh5LThwgXdSQorVr91L127ttckI9QQU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.4/go.mod h1:/MQxMqci8tlqDH+pjmoLu1i0tbWCUP1hhyMRuFxpQCw= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16 h1:mimdLQkIX1zr8GIPY1ZtALdBQGxcASiBd2MOp8m/dMc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.16/go.mod h1:YHk6owoSwrIsok+cAH9PENCOGoH5PU2EllX4vLtSrsY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18 h1:GckUnpm4EJOAio1c8o25a+b3lVfwVzC9gnSBqiiNmZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.18/go.mod h1:Br6+bxfG33Dk3ynmkhsW2Z/t9D4+lRqdLDNCKi85w0U= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16 h1:jg16PhLPUiHIj8zYIW6bqzeQSuHVEiWnGA0Brz5Xv2I= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.16/go.mod h1:Uyk1zE1VVdsHSU7096h/rwnXDzOzYQVl+FNPhPw7ShY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.60.0 h1:2QXGJvG19QwqXUvgcdoCOZPyLuvZf8LiXPCN4P53TdI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.60.0/go.mod h1:BSPI0EfnYUuNHPS0uqIo5VrRwzie+Fp+YhQOUs16sKI= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= @@ -27,10 +60,6 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE= github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -49,7 +78,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -70,7 +98,5 @@ google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6h google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/s3x/service.go b/s3x/service.go index 91effa6..f63bf10 100644 --- a/s3x/service.go +++ b/s3x/service.go @@ -8,30 +8,30 @@ import ( "sync" "time" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go-v2/service/s3/types" ) // Service is simple abstraction layer to work with a S3-compatible storage service type Service struct { - Client *s3.S3 + Client *s3.Client urler ObjectURLer } // NewService creates a new S3 service with the given credentials and configuration func NewService(accessKey, secretKey, region, endpoint string, minio bool) (*Service, error) { - cfg := &aws.Config{ - Region: aws.String(region), - Endpoint: aws.String(endpoint), - S3ForcePathStyle: aws.Bool(minio), // urls as endpoint/bucket/key instead of bucket.endpoint/key - MaxRetries: aws.Int(3), - } - if accessKey != "" || secretKey != "" { - cfg.Credentials = credentials.NewStaticCredentials(accessKey, secretKey, "") + opts := []func(*config.LoadOptions) error{config.WithRegion(region)} + + if accessKey != "" && secretKey != "" { + opts = append(opts, config.WithCredentialsProvider(credentials.StaticCredentialsProvider{Value: aws.Credentials{ + AccessKeyID: accessKey, SecretAccessKey: secretKey, + }})) } - s, err := session.NewSession(cfg) + + cfg, err := config.LoadDefaultConfig(context.TODO(), opts...) if err != nil { return nil, err } @@ -43,7 +43,15 @@ func NewService(accessKey, secretKey, region, endpoint string, minio bool) (*Ser urler = AWSURLer(region) } - return &Service{Client: s3.New(s), urler: urler}, nil + client := s3.NewFromConfig(cfg, func(o *s3.Options) { + o.UsePathStyle = minio // urls as endpoint/bucket/key instead of bucket.endpoint/key + + if endpoint != "" { + o.BaseEndpoint = aws.String(endpoint) + } + }) + + return &Service{Client: client, urler: urler}, nil } // ObjectURL returns the publicly accessible URL for the given object @@ -53,13 +61,13 @@ func (s *Service) ObjectURL(bucket, key string) string { // Test is a convenience method to HEAD a bucket to test if it exists and we can access it func (s *Service) Test(ctx context.Context, bucket string) error { - _, err := s.Client.HeadBucket(&s3.HeadBucketInput{Bucket: aws.String(bucket)}) + _, err := s.Client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucket)}) return err } // GetObject is a convenience method to get an object from S3 and read its contents into a byte slice func (s *Service) GetObject(ctx context.Context, bucket, key string) (string, []byte, error) { - out, err := s.Client.GetObjectWithContext(ctx, &s3.GetObjectInput{ + out, err := s.Client.GetObject(ctx, &s3.GetObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), }) @@ -72,17 +80,17 @@ func (s *Service) GetObject(ctx context.Context, bucket, key string) (string, [] return "", nil, fmt.Errorf("error reading S3 object: %w", err) } - return aws.StringValue(out.ContentType), body, nil + return aws.ToString(out.ContentType), body, nil } // PutObject is a convenience method to put the given object and return its publicly accessible URL -func (s *Service) PutObject(ctx context.Context, bucket, key string, contentType string, body []byte, acl string) (string, error) { - _, err := s.Client.PutObjectWithContext(ctx, &s3.PutObjectInput{ +func (s *Service) PutObject(ctx context.Context, bucket, key string, contentType string, body []byte, acl types.ObjectCannedACL) (string, error) { + _, err := s.Client.PutObject(ctx, &s3.PutObjectInput{ Bucket: aws.String(bucket), Body: bytes.NewReader(body), Key: aws.String(key), ContentType: aws.String(contentType), - ACL: aws.String(acl), + ACL: acl, }) if err != nil { return "", fmt.Errorf("error putting S3 object: %w", err) @@ -96,7 +104,7 @@ type Upload struct { Key string ContentType string Body []byte - ACL string + ACL types.ObjectCannedACL // set by BatchPut URL string @@ -154,12 +162,12 @@ func (s *Service) batchWorker(ctx context.Context, uploads chan *Upload, errors uctx, cancel := context.WithTimeout(ctx, time.Second*15) defer cancel() - _, err = s.Client.PutObjectWithContext(uctx, &s3.PutObjectInput{ + _, err = s.Client.PutObject(uctx, &s3.PutObjectInput{ Bucket: aws.String(u.Bucket), Body: bytes.NewReader(u.Body), Key: aws.String(u.Key), ContentType: aws.String(u.ContentType), - ACL: aws.String(u.ACL), + ACL: u.ACL, }) if err == nil { @@ -186,19 +194,19 @@ func (s *Service) EmptyBucket(ctx context.Context, bucket string) error { request := &s3.ListObjectsV2Input{Bucket: aws.String(bucket)} for { - response, err := s.Client.ListObjectsV2WithContext(ctx, request) + response, err := s.Client.ListObjectsV2(ctx, request) if err != nil { return fmt.Errorf("error listing S3 objects: %w", err) } if len(response.Contents) > 0 { - del := &s3.Delete{} + del := &types.Delete{} for _, obj := range response.Contents { - del.Objects = append(del.Objects, &s3.ObjectIdentifier{Key: obj.Key}) + del.Objects = append(del.Objects, types.ObjectIdentifier{Key: obj.Key}) } - _, err = s.Client.DeleteObjectsWithContext(ctx, &s3.DeleteObjectsInput{Bucket: aws.String(bucket), Delete: del}) + _, err = s.Client.DeleteObjects(ctx, &s3.DeleteObjectsInput{Bucket: aws.String(bucket), Delete: del}) if err != nil { return fmt.Errorf("error deleting S3 objects: %w", err) } @@ -206,7 +214,7 @@ func (s *Service) EmptyBucket(ctx context.Context, bucket string) error { request.ContinuationToken = response.NextContinuationToken - if !aws.BoolValue(response.IsTruncated) { + if !aws.ToBool(response.IsTruncated) { break } } diff --git a/s3x/service_test.go b/s3x/service_test.go index 8794b4b..d997e2c 100644 --- a/s3x/service_test.go +++ b/s3x/service_test.go @@ -4,8 +4,9 @@ import ( "context" "testing" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/nyaruka/gocommon/s3x" "github.com/stretchr/testify/assert" ) @@ -17,15 +18,15 @@ func TestService(t *testing.T) { assert.NoError(t, err) err = svc.Test(ctx, "gocommon-tests") - assert.ErrorContains(t, err, "NotFound: Not Found\n\tstatus code: 404") + assert.ErrorContains(t, err, "NotFound") - _, err = svc.Client.CreateBucket(&s3.CreateBucketInput{Bucket: aws.String("gocommon-tests")}) + _, err = svc.Client.CreateBucket(ctx, &s3.CreateBucketInput{Bucket: aws.String("gocommon-tests")}) assert.NoError(t, err) err = svc.Test(ctx, "gocommon-tests") assert.NoError(t, err) - url, err := svc.PutObject(ctx, "gocommon-tests", "1/hello world.txt", "text/plain", []byte("hello world"), s3.BucketCannedACLPublicRead) + url, err := svc.PutObject(ctx, "gocommon-tests", "1/hello world.txt", "text/plain", []byte("hello world"), types.ObjectCannedACLPublicRead) assert.NoError(t, err) assert.Equal(t, "http://localhost:9000/gocommon-tests/1/hello+world.txt", url) @@ -41,14 +42,14 @@ func TestService(t *testing.T) { Key: "foo/thing1", Body: []byte(`HELLOWORLD`), ContentType: "text/plain", - ACL: s3.BucketCannedACLPublicRead, + ACL: types.ObjectCannedACLPublicRead, }, { Bucket: "gocommon-tests", Key: "foo/thing2", Body: []byte(`HELLOWORLD2`), ContentType: "text/plain", - ACL: s3.BucketCannedACLPublicRead, + ACL: types.ObjectCannedACLPublicRead, }, } @@ -68,7 +69,7 @@ func TestService(t *testing.T) { assert.NoError(t, err) // test deleting a bucket - _, err = svc.Client.DeleteBucket(&s3.DeleteBucketInput{Bucket: aws.String("gocommon-tests")}) + _, err = svc.Client.DeleteBucket(ctx, &s3.DeleteBucketInput{Bucket: aws.String("gocommon-tests")}) assert.NoError(t, err) err = svc.Test(ctx, "gocommon-tests")