Skip to content

Commit

Permalink
chore(codegen): refactor S3 customizations to own class (#1656)
Browse files Browse the repository at this point in the history
  • Loading branch information
AllanZhengYP authored Nov 3, 2020
1 parent 9c1c245 commit 1f46eac
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 77 deletions.
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");
}
}

0 comments on commit 1f46eac

Please sign in to comment.