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

Adds support for access-point and outposts for s3 / s3control client #870

Merged
merged 21 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f86df23
add arn parsing utility for s3, s3control
skotambkar Nov 9, 2020
f1e9e6c
add arn lookup middleware
skotambkar Nov 9, 2020
a2905e2
codegen update to S3 Update Endpoint runtime plugin
skotambkar Nov 9, 2020
04bc03b
add s3 customization for accesspoint and outposts
skotambkar Nov 9, 2020
eccce15
codegen s3 endpoint resolver for s3control service
skotambkar Nov 9, 2020
bd4e12a
s3-control customizations for outposts support
skotambkar Nov 9, 2020
1b16de8
register runtime plugin
skotambkar Nov 9, 2020
801a980
generated s3 endpoint resolver in s3control
skotambkar Nov 9, 2020
bc72533
s3 update endpoint register middleware fix
skotambkar Nov 9, 2020
51933e5
generated s3 and s3control clients
skotambkar Nov 9, 2020
4d3dfad
fix codegen to only apply this change to s3 and s3control service
skotambkar Nov 9, 2020
efd767e
fix concurrent-change exception and operation predicate behavior for …
skotambkar Nov 9, 2020
9f6037a
java feedback changes
skotambkar Nov 13, 2020
708ee6f
updates s3 shared errors, adds s3shared metadata for cloned key, and …
skotambkar Nov 13, 2020
8553c94
s3 control customization feedback changes, also uncomments test cases
skotambkar Nov 13, 2020
add13c6
s3 customization feedback changes
skotambkar Nov 13, 2020
b322e8c
allow s3 accesspoint test to run
skotambkar Nov 13, 2020
8cf2f51
generated s3 control and s3 client with all feedback changes
skotambkar Nov 13, 2020
88d48ab
minor feedback
skotambkar Nov 14, 2020
5cd23c9
moves supports Accelerate option out of update endpoint accessors
skotambkar Nov 16, 2020
c0b6070
regenerate s3 client
skotambkar Nov 16, 2020
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
18 changes: 15 additions & 3 deletions aws/middleware/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (s RegisterServiceMetadata) HandleInitialize(
ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
) (out middleware.InitializeOutput, metadata middleware.Metadata, err error) {
if len(s.ServiceID) > 0 {
ctx = setServiceID(ctx, s.ServiceID)
ctx = SetServiceID(ctx, s.ServiceID)
}
if len(s.SigningName) > 0 {
ctx = SetSigningName(ctx, s.SigningName)
Expand All @@ -46,6 +46,7 @@ type (
signingRegionKey struct{}
regionKey struct{}
operationNameKey struct{}
partitionIDKey struct{}
)

// GetServiceID retrieves the service id from the context.
Expand Down Expand Up @@ -78,6 +79,12 @@ func GetOperationName(ctx context.Context) (v string) {
return v
}

// GetPartitionID retrieves the endpoint partition id from the context.
func GetPartitionID(ctx context.Context) string {
v, _ := ctx.Value(partitionIDKey{}).(string)
return v
}

// SetSigningName set or modifies the signing name on the context.
func SetSigningName(ctx context.Context, value string) context.Context {
return context.WithValue(ctx, signingNameKey{}, value)
Expand All @@ -88,8 +95,8 @@ func SetSigningRegion(ctx context.Context, value string) context.Context {
return context.WithValue(ctx, signingRegionKey{}, value)
}

// setServiceID sets the service id on the context.
func setServiceID(ctx context.Context, value string) context.Context {
// SetServiceID sets the service id on the context.
func SetServiceID(ctx context.Context, value string) context.Context {
return context.WithValue(ctx, serviceIDKey{}, value)
}

Expand All @@ -102,3 +109,8 @@ func setRegion(ctx context.Context, value string) context.Context {
func setOperationName(ctx context.Context, value string) context.Context {
return context.WithValue(ctx, operationNameKey{}, value)
}

// SetPartitionID sets the partition id of a resolved region on the context
func SetPartitionID(ctx context.Context, value string) context.Context {
return context.WithValue(ctx, partitionIDKey{}, value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
* Writes out a file that resolves endpoints using endpoints.json, but the
* created resolver resolves endpoints for a single service.
*/
final class EndpointGenerator implements Runnable {
public class EndpointGenerator implements Runnable {
public static final String MIDDLEWARE_NAME = "ResolveEndpoint";
public static final String ADD_MIDDLEWARE_HELPER_NAME = String.format("add%sMiddleware", MIDDLEWARE_NAME);
public static final String RESOLVER_INTERFACE_NAME = "EndpointResolver";
Expand Down Expand Up @@ -74,18 +74,42 @@ final class EndpointGenerator implements Runnable {
private final ObjectNode endpointData;
private final String endpointPrefix;
private final Map<String, Partition> partitions = new TreeMap<>();
private final Boolean isInternalOnly;
private final String resolvedSdkID;

EndpointGenerator(
public EndpointGenerator(
GoSettings settings,
Model model,
TriConsumer<String, String, Consumer<GoWriter>> writerFactory
) {
this(
settings,
model,
writerFactory,
settings.getService(model).expectTrait(ServiceTrait.class)
.getSdkId(),
settings.getService(model).expectTrait(ServiceTrait.class)
.getArnNamespace(),
false
);
}

public EndpointGenerator(
GoSettings settings,
Model model,
TriConsumer<String, String, Consumer<GoWriter>> writerFactory,
String sdkID,
String arnNamespace,
Boolean internalOnly
) {
this.settings = settings;
this.model = model;
this.writerFactory = writerFactory;
serviceShape = settings.getService(model);
this.endpointPrefix = getEndpointPrefix(serviceShape);
this.endpointPrefix = getEndpointPrefix(sdkID, arnNamespace);
this.endpointData = Node.parse(IoUtils.readUtf8Resource(getClass(), "endpoints.json")).expectObjectNode();
this.isInternalOnly = internalOnly;
this.resolvedSdkID = sdkID;
validateVersion();
loadPartitions();
}
Expand All @@ -106,6 +130,12 @@ private String getEndpointPrefix(ServiceShape service) {
return endpointPrefixData.getStringMemberOrDefault(serviceTrait.getSdkId(), serviceTrait.getArnNamespace());
}

private String getEndpointPrefix(String sdkId, String arnNamespace) {
ObjectNode endpointPrefixData = Node.parse(IoUtils.readUtf8Resource(getClass(), "endpoint-prefix.json"))
.expectObjectNode();
return endpointPrefixData.getStringMemberOrDefault(sdkId, arnNamespace);
}

private void loadPartitions() {
List<ObjectNode> partitionObjects = endpointData
.expectArrayMember("partitions")
Expand All @@ -119,22 +149,31 @@ private void loadPartitions() {

@Override
public void run() {
writerFactory.accept("endpoints.go", settings.getModuleName(), writer -> {
generatePublicResolverTypes(writer);
generateMiddleware(writer);
generateAwsEndpointResolverWrapper(writer);
});
writerFactory.accept(INTERNAL_ENDPOINT_PACKAGE + "/endpoints.go", getInternalEndpointImportPath(), (writer) -> {
if (!this.isInternalOnly) {
writerFactory.accept("endpoints.go", settings.getModuleName(), writer -> {
generatePublicResolverTypes(writer);
generateMiddleware(writer);
generateAwsEndpointResolverWrapper(writer);
});
}

String pkgName = isInternalOnly ? INTERNAL_ENDPOINT_PACKAGE + "/" + this.endpointPrefix : INTERNAL_ENDPOINT_PACKAGE;
writerFactory.accept(pkgName + "/endpoints.go", getInternalEndpointImportPath(), (writer) -> {
generateInternalResolverImplementation(writer);
generateInternalEndpointsModel(writer);
});
writerFactory.accept(INTERNAL_ENDPOINT_PACKAGE + "/endpoints_test.go",
getInternalEndpointImportPath(), (writer) -> {
writer.addUseImports(SmithyGoDependency.TESTING);
writer.openBlock("func TestRegexCompile(t *testing.T) {", "}", () -> {
writer.write("_ = $T", getInternalEndpointsSymbol(INTERNAL_ENDPOINTS_DATA_NAME, false).build());

if (!this.isInternalOnly) {
writerFactory.accept(INTERNAL_ENDPOINT_PACKAGE + "/endpoints_test.go",
getInternalEndpointImportPath(), (writer) -> {
writer.addUseImports(SmithyGoDependency.TESTING);
writer.openBlock("func TestRegexCompile(t *testing.T) {", "}", () -> {
writer.write("_ = $T",
getInternalEndpointsSymbol(INTERNAL_ENDPOINTS_DATA_NAME, false).build());
});
});
});
}

}

private void generateAwsEndpointResolverWrapper(GoWriter writer) {
Expand Down Expand Up @@ -254,12 +293,13 @@ private void generateMiddlewareResolverBody(GoStackStepMiddlewareGenerator g, Go
});
w.write("ctx = awsmiddleware.SetSigningName(ctx, signingName)");
});
w.write("");

w.write("ctx = awsmiddleware.SetSigningRegion(ctx, endpoint.SigningRegion)");
w.write("ctx = smithyhttp.SetHostnameImmutable(ctx, endpoint.HostnameImmutable)");
w.write("");
// set signing region on context
w.write("ctx = awsmiddleware.SetSigningRegion(ctx, endpoint.SigningRegion)");
// set partition id on context
w.write("ctx = awsmiddleware.SetPartitionID(ctx, endpoint.PartitionID)");

w.insertTrailingNewline();
w.write("return next.HandleSerialize(ctx, in)");
}

Expand Down Expand Up @@ -389,8 +429,10 @@ private void generateInternalResolverImplementation(GoWriter writer) {

// Resolver
Symbol resolverImplSymbol = SymbolUtils.createPointableSymbolBuilder(INTERNAL_RESOLVER_NAME).build();


writer.writeDocs(String.format("%s %s endpoint resolver", resolverImplSymbol.getName(),
serviceShape.expectTrait(ServiceTrait.class).getSdkId()));
this.resolvedSdkID));
writer.openBlock("type $T struct {", "}", resolverImplSymbol, () -> {
writer.write("partitions $T", SymbolUtils.createValueSymbolBuilder("Partitions",
AwsGoDependency.AWS_ENDPOINTS).build());
Expand Down Expand Up @@ -505,11 +547,70 @@ private void writeEndpoint(GoWriter writer, ObjectNode node) {
});
}

private static class ResolveConfigField extends ConfigField {
skotambkar marked this conversation as resolved.
Show resolved Hide resolved
private final boolean shared;

public ResolveConfigField(Builder builder) {
super(builder);
this.shared = builder.shared;
}

public static Builder builder() {
return new Builder();
}

public boolean isShared() {
return shared;
}

private static class Builder extends ConfigField.Builder {
private boolean shared;

public Builder() {
super();
}

/**
* Set the resolver config field to be shared common parameter
*
* @param shared whether the resolver config field is shared
* @return the builder
*/
public Builder shared(boolean shared) {
this.shared = shared;
return this;
}

@Override
public ResolveConfigField build() {
return new ResolveConfigField(this);
}

@Override
public Builder name(String name) {
super.name(name);
return this;
}

@Override
public Builder type(Symbol type) {
super.type(type);
return this;
}

@Override
public Builder documentation(String documentation) {
super.documentation(documentation);
return this;
}
}
}

private final class Partition {
private final String id;
private final ObjectNode defaults;
private String dnsSuffix;
private final ObjectNode config;
private final String dnsSuffix;

private Partition(ObjectNode config, String partition) {
id = partition;
Expand Down Expand Up @@ -563,63 +664,4 @@ public ObjectNode getConfig() {
return config;
}
}

private static class ResolveConfigField extends ConfigField {
private final boolean shared;

public ResolveConfigField(Builder builder) {
super(builder);
this.shared = builder.shared;
}

public boolean isShared() {
return shared;
}

public static Builder builder() {
return new Builder();
}

private static class Builder extends ConfigField.Builder {
private boolean shared;

public Builder() {
super();
}

/**
* Set the resolver config field to be shared common parameter
*
* @param shared whether the resolver config field is shared
* @return the builder
*/
public Builder shared(boolean shared) {
this.shared = shared;
return this;
}

@Override
public ResolveConfigField build() {
return new ResolveConfigField(this);
}

@Override
public Builder name(String name) {
super.name(name);
return this;
}

@Override
public Builder type(Symbol type) {
super.type(type);
return this;
}

@Override
public Builder documentation(String documentation) {
super.documentation(documentation);
return this;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package software.amazon.smithy.aws.go.codegen.customization;

import java.util.function.Consumer;
import software.amazon.smithy.aws.go.codegen.EndpointGenerator;
import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.go.codegen.GoSettings;
import software.amazon.smithy.go.codegen.GoWriter;
import software.amazon.smithy.go.codegen.TriConsumer;
import software.amazon.smithy.go.codegen.integration.GoIntegration;
import software.amazon.smithy.model.Model;

/**
* S3ControlEndpointResolverCustomizations adds an internal endpoint resolver
* for s3 service endpoints
*/
public class S3ControlEndpointResolver implements GoIntegration {

@Override
public void writeAdditionalFiles(
GoSettings settings,
Model model,
SymbolProvider symbolProvider,
TriConsumer<String, String, Consumer<GoWriter>> writerFactory
) {
if (!settings.getService(model).expectTrait(ServiceTrait.class).getSdkId().equalsIgnoreCase(
"S3 Control")){
return;
}

// Generate S3 internal endpoint resolver for S3 Control service
new EndpointGenerator(settings, model, writerFactory,"S3","s3", true).run();
}
}
Loading