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

chore(codegen): refactor S3 customizations to own class #1656

Merged
merged 1 commit into from
Nov 3, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 6 additions & 6 deletions clients/client-s3/S3Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,8 @@ export type S3ClientConfig = Partial<__SmithyConfiguration<__HttpHandlerOptions>
AwsAuthInputConfig &
RetryInputConfig &
UserAgentInputConfig &
BucketEndpointInputConfig &
HostHeaderInputConfig &
BucketEndpointInputConfig &
EventStreamSerdeInputConfig;

export type S3ClientResolvedConfig = __SmithyResolvedConfiguration<__HttpHandlerOptions> &
Expand All @@ -604,8 +604,8 @@ export type S3ClientResolvedConfig = __SmithyResolvedConfiguration<__HttpHandler
AwsAuthResolvedConfig &
RetryResolvedConfig &
UserAgentResolvedConfig &
BucketEndpointResolvedConfig &
HostHeaderResolvedConfig &
BucketEndpointResolvedConfig &
EventStreamSerdeResolvedConfig;

/**
Expand All @@ -629,20 +629,20 @@ export class S3Client extends __Client<
let _config_3 = resolveAwsAuthConfig(_config_2);
let _config_4 = resolveRetryConfig(_config_3);
let _config_5 = resolveUserAgentConfig(_config_4);
let _config_6 = resolveBucketEndpointConfig(_config_5);
let _config_7 = resolveHostHeaderConfig(_config_6);
let _config_6 = resolveHostHeaderConfig(_config_5);
let _config_7 = resolveBucketEndpointConfig(_config_6);
let _config_8 = resolveEventStreamSerdeConfig(_config_7);
super(_config_8);
this.config = _config_8;
this.middlewareStack.use(getAwsAuthPlugin(this.config));
this.middlewareStack.use(getRetryPlugin(this.config));
this.middlewareStack.use(getUserAgentPlugin(this.config));
this.middlewareStack.use(getContentLengthPlugin(this.config));
this.middlewareStack.use(getHostHeaderPlugin(this.config));
this.middlewareStack.use(getLoggerPlugin(this.config));
this.middlewareStack.use(getValidateBucketNamePlugin(this.config));
this.middlewareStack.use(getUseRegionalEndpointPlugin(this.config));
this.middlewareStack.use(getAddExpectContinuePlugin(this.config));
this.middlewareStack.use(getHostHeaderPlugin(this.config));
this.middlewareStack.use(getLoggerPlugin(this.config));
}

destroy(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
*/
public class AddBuiltinPlugins implements TypeScriptIntegration {

private static final Set<String> SSEC_OPERATIONS = SetUtils.of("SSECustomerKey", "CopySourceSSECustomerKey");

private static final Set<String> ROUTE_53_ID_MEMBERS = SetUtils.of("DelegationSetId", "HostedZoneId", "Id");

private static final Set<String> RDS_PRESIGNED_URL_OPERATIONS = SetUtils.of(
Expand All @@ -51,22 +49,6 @@ public class AddBuiltinPlugins implements TypeScriptIntegration {
"CopyDBClusterSnapshot"
);

private static final Set<String> S3_MD5_OPERATIONS = SetUtils.of(
"DeleteObjects",
"PutBucketCors",
"PutBucketLifecycle",
"PutBucketLifecycleConfiguration",
"PutBucketPolicy",
"PutBucketTagging",
"PutBucketReplication"
);

private static final Set<String> NON_BUCKET_ENDPOINT_OPERATIONS = SetUtils.of(
"CreateBucket",
"DeleteBucket",
"ListBuckets"
);

@Override
public List<RuntimeClientPlugin> getClientPlugins() {
// Note that order is significant because configurations might
Expand Down Expand Up @@ -102,21 +84,6 @@ public List<RuntimeClientPlugin> getClientPlugins() {
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s, "API Gateway"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.S3_MIDDLEWARE.dependency, "ValidateBucketName",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.S3_MIDDLEWARE.dependency, "UseRegionalEndpoint",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.ADD_EXPECT_CONTINUE.dependency, "AddExpectContinue",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.GLACIER_MIDDLEWARE.dependency,
"Glacier", HAS_MIDDLEWARE)
Expand All @@ -128,44 +95,12 @@ public List<RuntimeClientPlugin> getClientPlugins() {
.operationPredicate((m, s, o) -> o.getId().getName().equals("CopySnapshot")
&& testServiceId(s, "EC2"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.SSEC_MIDDLEWARE.dependency, "Ssec", HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> testInputContainsMember(m, o, SSEC_OPERATIONS)
&& testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.LOCATION_CONSTRAINT.dependency, "LocationConstraint",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> o.getId().getName().equals("CreateBucket")
&& testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.MACHINELEARNING_MIDDLEWARE.dependency, "PredictEndpoint",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> o.getId().getName().equals("Predict")
&& testServiceId(s, "Machine Learning"))
.build(),
/**
* BUCKET_ENDPOINT_MIDDLEWARE needs two separate plugins. The first resolves the config in the client.
* The second applies the middleware to bucket endpoint operations.
*/
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BUCKET_ENDPOINT_MIDDLEWARE.dependency, "BucketEndpoint",
HAS_CONFIG)
.servicePredicate((m, s) -> testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BUCKET_ENDPOINT_MIDDLEWARE.dependency, "BucketEndpoint",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> !NON_BUCKET_ENDPOINT_OPERATIONS.contains(o.getId().getName())
&& testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BODY_CHECKSUM.dependency, "ApplyMd5BodyChecksum",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> S3_MD5_OPERATIONS.contains(o.getId().getName())
&& testServiceId(s, "S3"))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.ROUTE53_MIDDLEWARE.dependency,
"ChangeResourceRecordSets", HAS_MIDDLEWARE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,58 @@

package software.amazon.smithy.aws.typescript.codegen;

import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_CONFIG;
import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import software.amazon.smithy.aws.traits.ServiceTrait;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.knowledge.OperationIndex;
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin;
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
import software.amazon.smithy.utils.ListUtils;
import software.amazon.smithy.utils.MapUtils;
import software.amazon.smithy.utils.SetUtils;

/**
* AWS S3 client configuration.
*/
public final class AddS3Config implements TypeScriptIntegration {

private static final Set<String> S3_MD5_OPERATIONS = SetUtils.of(
"DeleteObjects",
"PutBucketCors",
"PutBucketLifecycle",
"PutBucketLifecycleConfiguration",
"PutBucketPolicy",
"PutBucketTagging",
"PutBucketReplication"
);

private static final Set<String> SSEC_OPERATIONS = SetUtils.of("SSECustomerKey", "CopySourceSSECustomerKey");

private static final Set<String> NON_BUCKET_ENDPOINT_OPERATIONS = SetUtils.of(
"CreateBucket",
"DeleteBucket",
"ListBuckets"
);

@Override
public void addConfigInterfaceFields(TypeScriptSettings settings, Model model, SymbolProvider symbolProvider,
TypeScriptWriter writer) {
if (!needsS3Config(settings.getService(model))) {
if (!testServiceId(settings.getService(model))) {
return;
}
writer.writeDocs("Whether to escape request path when signing the request.")
Expand All @@ -53,7 +81,7 @@ public void addConfigInterfaceFields(TypeScriptSettings settings, Model model, S
@Override
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(TypeScriptSettings settings, Model model,
SymbolProvider symbolProvider, LanguageTarget target) {
if (!needsS3Config(settings.getService(model))) {
if (!testServiceId(settings.getService(model))) {
return Collections.emptyMap();
}
switch (target) {
Expand All @@ -77,8 +105,71 @@ public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(TypeScrip
}
}

private static boolean needsS3Config(ServiceShape service) {
String serviceId = service.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("");
return serviceId.equals("S3");
@Override
public List<RuntimeClientPlugin> getClientPlugins() {
return ListUtils.of(
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.S3_MIDDLEWARE.dependency, "ValidateBucketName",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.S3_MIDDLEWARE.dependency, "UseRegionalEndpoint",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.ADD_EXPECT_CONTINUE.dependency, "AddExpectContinue",
HAS_MIDDLEWARE)
.servicePredicate((m, s) -> testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.SSEC_MIDDLEWARE.dependency, "Ssec", HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> testInputContainsMember(m, o, SSEC_OPERATIONS)
&& testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.LOCATION_CONSTRAINT.dependency, "LocationConstraint",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> o.getId().getName().equals("CreateBucket")
&& testServiceId(s))
.build(),
/**
* BUCKET_ENDPOINT_MIDDLEWARE needs two separate plugins. The first resolves the config in the client.
* The second applies the middleware to bucket endpoint operations.
*/
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BUCKET_ENDPOINT_MIDDLEWARE.dependency, "BucketEndpoint",
HAS_CONFIG)
.servicePredicate((m, s) -> testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BUCKET_ENDPOINT_MIDDLEWARE.dependency, "BucketEndpoint",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> !NON_BUCKET_ENDPOINT_OPERATIONS.contains(o.getId().getName())
&& testServiceId(s))
.build(),
RuntimeClientPlugin.builder()
.withConventions(AwsDependency.BODY_CHECKSUM.dependency, "ApplyMd5BodyChecksum",
HAS_MIDDLEWARE)
.operationPredicate((m, s, o) -> S3_MD5_OPERATIONS.contains(o.getId().getName())
&& testServiceId(s))
.build()
);
}

private static boolean testInputContainsMember(
Model model,
OperationShape operationShape,
Set<String> expectedMemberNames
) {
OperationIndex operationIndex = OperationIndex.of(model);
return operationIndex.getInput(operationShape)
.filter(input -> input.getMemberNames().stream().anyMatch(expectedMemberNames::contains))
.isPresent();
}

private static boolean testServiceId(Shape serviceShape) {
return serviceShape.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("").equals("S3");
}
}