Skip to content

Commit

Permalink
S3 Object Lambda Support (#1183)
Browse files Browse the repository at this point in the history
  • Loading branch information
skmcgrail authored Mar 18, 2021
1 parent b9a0b1a commit 847874e
Show file tree
Hide file tree
Showing 220 changed files with 12,235 additions and 3,418 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ID": "feature.s3.manager-feature-1616093328620827000",
"SchemaVersion": 1,
"Module": "feature/s3/manager",
"Type": "feature",
"Description": "Updates for S3 Object Lambda feature",
"MinVersion": "",
"AffectedModules": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ID": "service.internal.s3shared-feature-1616093429190725000",
"SchemaVersion": 1,
"Module": "service/internal/s3shared",
"Type": "feature",
"Description": "Support for S3 Object Lambda",
"MinVersion": "",
"AffectedModules": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ID": "service.s3-feature-1616093381239174000",
"SchemaVersion": 1,
"Module": "service/s3",
"Type": "feature",
"Description": "S3 Object Lambda is a new S3 feature that enables users to apply their own custom code to process the output of a standard S3 GET request by automatically invoking a Lambda function with a GET request",
"MinVersion": "",
"AffectedModules": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ID": "service.s3control-feature-1616093391667799000",
"SchemaVersion": 1,
"Module": "service/s3control",
"Type": "feature",
"Description": "S3 Object Lambda is a new S3 feature that enables users to apply their own custom code to process the output of a standard S3 GET request by automatically invoking a Lambda function with a GET request",
"MinVersion": "",
"AffectedModules": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"ID": "service.wildcard-bugfix-1616093590156551000",
"SchemaVersion": 1,
"Module": "service/...",
"Type": "bugfix",
"Description": "Updated presign URLs to no longer include the X-Amz-User-Agent header",
"MinVersion": "",
"AffectedModules": [
"service/docdb",
"service/ec2",
"service/neptune",
"service/rds",
"service/s3",
"service/sts"
]
}
775 changes: 546 additions & 229 deletions codegen/sdk-codegen/aws-models/s3.2006-03-01.json

Large diffs are not rendered by default.

915 changes: 847 additions & 68 deletions codegen/sdk-codegen/aws-models/s3control.2018-08-20.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ private void writeConvertToPresignMiddleware(
writer.write("stack.Finalize.Clear()");
writer.write("stack.Deserialize.Clear()");
writer.write("stack.Build.Remove(($P)(nil).ID())", requestInvocationID);
writer.write("stack.Build.Remove($S)", "UserAgent");

Symbol middlewareOptionsSymbol = SymbolUtils.createValueSymbolBuilder(
"PresignHTTPRequestMiddlewareOptions", AwsGoDependency.AWS_SIGNER_V4).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;
import software.amazon.smithy.aws.go.codegen.AwsGoDependency;
import software.amazon.smithy.aws.traits.auth.UnsignedPayloadTrait;
import software.amazon.smithy.go.codegen.SymbolUtils;
import software.amazon.smithy.go.codegen.integration.GoIntegration;
import software.amazon.smithy.go.codegen.integration.MiddlewareRegistrar;
Expand All @@ -26,8 +27,15 @@ public byte getOrder() {
public List<RuntimeClientPlugin> getClientPlugins() {
return ListUtils.of(
RuntimeClientPlugin.builder()
.servicePredicate((model, service) -> S3ModelUtils.isServiceS3(model, service)
|| S3ModelUtils.isServiceS3Control(model, service))
// Only add the middleware if UnsignedPayloadTrait is not specified, as this middleware
// will have already been added.
.operationPredicate((model, service, operation) -> {
if (!(S3ModelUtils.isServiceS3(model, service)
|| S3ModelUtils.isServiceS3Control(model, service))) {
return false;
}
return !operation.hasTrait(UnsignedPayloadTrait.class);
})
.registerMiddleware(MiddlewareRegistrar.builder()
.resolvedFunction(SymbolUtils.createValueSymbolBuilder(
"AddContentSHA256HeaderMiddleware",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ private static class S3 {
"ListBuckets", "CreateBucket", "DeleteBucket"
);

private final Set<String> TARGET_OBJECT_LAMBDAS = SetUtils.of("WriteGetObjectResponse");

private S3(ServiceShape service) {
this.service = service;
}
Expand Down Expand Up @@ -285,14 +287,17 @@ private void writeMiddlewareHelper(
addMiddlewareFuncName(symbolProvider.toSymbol(operationShape).getName(),
UPDATE_ENDPOINT_INTERNAL_ADDER), () -> {
writer.write("return $T(stack, $T{ \n"
+ "Accessor : $T{\n "
+ "GetBucketFromInput: $L,\n}, \n"
+ "UsePathStyle: options.$L,\n "
+ "UseAccelerate: options.$L,\n "
+ "SupportsAccelerate: $L,\n "
+ "EndpointResolver: options.EndpointResolver,\n "
+ "Accessor : $T{\n"
+ "GetBucketFromInput: $L,\n},\n"
+ "UsePathStyle: options.$L,\n"
+ "UseAccelerate: options.$L,\n"
+ "SupportsAccelerate: $L,\n"
+ "TargetS3ObjectLambda: $L,\n"
+ "EndpointResolver: options.EndpointResolver,\n"
+ "EndpointResolverOptions: options.EndpointOptions,\n"
+ "UseDualstack: options.$L, \n UseARNRegion: options.$L, \n })",
+ "UseDualstack: options.$L,\n"
+ "UseARNRegion: options.$L,\n"
+ "})",
SymbolUtils.createValueSymbolBuilder(UPDATE_ENDPOINT_INTERNAL_ADDER,
AwsCustomGoDependency.S3_CUSTOMIZATION).build(),
SymbolUtils.createValueSymbolBuilder(UPDATE_ENDPOINT_INTERNAL_OPTIONS,
Expand All @@ -304,6 +309,7 @@ private void writeMiddlewareHelper(
USE_PATH_STYLE_OPTION,
USE_ACCELERATE_OPTION,
!NOT_SUPPORT_ACCELERATE.contains(operationName),
TARGET_OBJECT_LAMBDAS.contains(operationName),
USE_DUALSTACK_OPTION,
USE_ARNREGION_OPTION
);
Expand Down
1 change: 0 additions & 1 deletion config/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/credentials v1.1.2
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2
github.com/aws/smithy-go v1.2.0
Expand Down
1 change: 0 additions & 1 deletion credentials/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.15
require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2
github.com/aws/smithy-go v1.2.0
Expand Down
8 changes: 0 additions & 8 deletions example/service/s3/listObjects/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@ module github.com/aws/aws-sdk-go-v2/example/service/s3/listObjects
go 1.15

require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/config v1.1.2
github.com/aws/aws-sdk-go-v2/credentials v1.1.2
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.2.1
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2
)

replace github.com/aws/aws-sdk-go-v2/config => ../../../../config/
Expand Down
7 changes: 0 additions & 7 deletions example/service/s3/usingPrivateLink/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,8 @@ go 1.15
require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/config v1.1.2
github.com/aws/aws-sdk-go-v2/credentials v1.1.2
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.2.1
github.com/aws/aws-sdk-go-v2/service/s3control v1.2.1
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2
)

replace github.com/aws/aws-sdk-go-v2/config => ../../../../config/
Expand Down
1 change: 0 additions & 1 deletion feature/dynamodb/attributevalue/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.1.2
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.1.2
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2
github.com/google/go-cmp v0.5.4
)

Expand Down
2 changes: 0 additions & 2 deletions feature/dynamodb/expression/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.0.3
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.1.2
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.1.2
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2 // indirect
)

replace (
Expand Down
1 change: 0 additions & 1 deletion feature/dynamodbstreams/attributevalue/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.1.2
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.1.2
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2
github.com/google/go-cmp v0.5.4
)

Expand Down
23 changes: 23 additions & 0 deletions feature/s3/manager/arn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package manager

import (
"fmt"
"github.com/aws/aws-sdk-go-v2/aws/arn"
)

func validateSupportedARNType(bucket string) error {
if !arn.IsARN(bucket) {
return nil
}

parsedARN, err := arn.Parse(bucket)
if err != nil {
return err
}

if parsedARN.Service == "s3-object-lambda" {
return fmt.Errorf("manager does not support s3-object-lambda service ARNs")
}

return nil
}
4 changes: 4 additions & 0 deletions feature/s3/manager/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ func NewDownloader(c DownloadAPIClient, options ...func(*Downloader)) *Downloade
// to perform a single GetObjectInput request for that object's range. This will
// caused the part size, and concurrency configurations to be ignored.
func (d Downloader) Download(ctx context.Context, w io.WriterAt, input *s3.GetObjectInput, options ...func(*Downloader)) (n int64, err error) {
if err := validateSupportedARNType(aws.ToString(input.Bucket)); err != nil {
return 0, err
}

impl := downloader{w: w, in: input, cfg: d, ctx: ctx}

// Copy ClientOptions
Expand Down
47 changes: 47 additions & 0 deletions feature/s3/manager/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,53 @@ func TestDownloadBufferStrategy_Errors(t *testing.T) {
}
}

func TestDownloaderValidARN(t *testing.T) {
cases := map[string]struct {
input s3.GetObjectInput
wantErr bool
}{
"standard bucket": {
input: s3.GetObjectInput{
Bucket: aws.String("test-bucket"),
Key: aws.String("test-key"),
},
},
"accesspoint": {
input: s3.GetObjectInput{
Bucket: aws.String("arn:aws:s3:us-west-2:123456789012:accesspoint/myap"),
Key: aws.String("test-key"),
},
},
"outpost accesspoint": {
input: s3.GetObjectInput{
Bucket: aws.String("arn:aws:s3-outposts:us-west-2:012345678901:outpost/op-1234567890123456/accesspoint/myaccesspoint"),
Key: aws.String("test-key"),
},
},
"s3-object-lambda accesspoint": {
input: s3.GetObjectInput{
Bucket: aws.String("arn:aws:s3-object-lambda:us-west-2:123456789012:accesspoint/myap"),
},
wantErr: true,
},
}

for name, tt := range cases {
t.Run(name, func(t *testing.T) {
client, _ := newDownloadNonRangeClient(buf2MB)

downloader := manager.NewDownloader(client, func(downloader *manager.Downloader) {
downloader.Concurrency = 1
})

_, err := downloader.Download(context.Background(), &awstesting.DiscardAt{}, &tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("err: %v, wantErr: %v", err, tt.wantErr)
}
})
}
}

type recordedWriterReadFromProvider struct {
callbacksVended uint32
callbacksExecuted uint32
Expand Down
7 changes: 0 additions & 7 deletions feature/s3/manager/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@ go 1.15
require (
github.com/aws/aws-sdk-go-v2 v1.2.1
github.com/aws/aws-sdk-go-v2/config v1.1.2
github.com/aws/aws-sdk-go-v2/credentials v1.1.2
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.3
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.2.1
github.com/aws/aws-sdk-go-v2/service/sso v1.1.2
github.com/aws/aws-sdk-go-v2/service/sts v1.1.2
github.com/aws/smithy-go v1.2.0
github.com/google/go-cmp v0.5.4
)
Expand Down
5 changes: 5 additions & 0 deletions feature/s3/manager/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"io"
"net/http"
"sort"
Expand Down Expand Up @@ -275,6 +276,10 @@ func (u *uploader) upload() (*UploadOutput, error) {

// init will initialize all default options.
func (u *uploader) init() error {
if err := validateSupportedARNType(aws.ToString(u.in.Bucket)); err != nil {
return err
}

if u.cfg.Concurrency == 0 {
u.cfg.Concurrency = DefaultUploadConcurrency
}
Expand Down
51 changes: 51 additions & 0 deletions feature/s3/manager/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,57 @@ func TestUploadBufferStrategy(t *testing.T) {
}
}

func TestUploaderValidARN(t *testing.T) {
cases := map[string]struct {
input s3.PutObjectInput
wantErr bool
}{
"standard bucket": {
input: s3.PutObjectInput{
Bucket: aws.String("test-bucket"),
Key: aws.String("test-key"),
Body: bytes.NewReader([]byte("test body content")),
},
},
"accesspoint": {
input: s3.PutObjectInput{
Bucket: aws.String("arn:aws:s3:us-west-2:123456789012:accesspoint/myap"),
Key: aws.String("test-key"),
Body: bytes.NewReader([]byte("test body content")),
},
},
"outpost accesspoint": {
input: s3.PutObjectInput{
Bucket: aws.String("arn:aws:s3-outposts:us-west-2:012345678901:outpost/op-1234567890123456/accesspoint/myaccesspoint"),
Key: aws.String("test-key"),
Body: bytes.NewReader([]byte("test body content")),
},
},
"s3-object-lambda accesspoint": {
input: s3.PutObjectInput{
Bucket: aws.String("arn:aws:s3-object-lambda:us-west-2:123456789012:accesspoint/myap"),
Key: aws.String("test-key"),
Body: bytes.NewReader([]byte("test body content")),
},
wantErr: true,
},
}

for name, tt := range cases {
t.Run(name, func(t *testing.T) {
client, _, _ := s3testing.NewUploadLoggingClient(nil)
client.ConsumeBody = true

uploader := manager.NewUploader(client)

_, err := uploader.Upload(context.Background(), &tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("err: %v, wantErr: %v", err, tt.wantErr)
}
})
}
}

type mockS3UploadServer struct {
*http.ServeMux

Expand Down
1 change: 1 addition & 0 deletions service/acm/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
Loading

0 comments on commit 847874e

Please sign in to comment.