diff --git a/aws/middleware/user_agent.go b/aws/middleware/user_agent.go index ff0bc921f1b..67aaa02265d 100644 --- a/aws/middleware/user_agent.go +++ b/aws/middleware/user_agent.go @@ -85,6 +85,7 @@ const ( UserAgentFeatureS3ExpressBucket = "J" UserAgentFeatureS3AccessGrants = "K" // not yet implemented UserAgentFeatureGZIPRequestCompression = "L" + UserAgentFeatureProtocolRPCV2CBOR = "M" ) // RequestUserAgent is a build middleware that set the User-Agent for the request. diff --git a/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/BasicUserAgentFeatures.java b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/BasicUserAgentFeatures.java new file mode 100644 index 00000000000..9149ef86cfa --- /dev/null +++ b/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/BasicUserAgentFeatures.java @@ -0,0 +1,88 @@ +package software.amazon.smithy.aws.go.codegen.customization; + +import static software.amazon.smithy.go.codegen.GoWriter.goTemplate; +import static software.amazon.smithy.go.codegen.SymbolUtils.buildPackageSymbol; + +import java.util.List; +import java.util.Map; +import java.util.function.BiPredicate; +import software.amazon.smithy.aws.go.codegen.AwsGoDependency; +import software.amazon.smithy.codegen.core.Symbol; +import software.amazon.smithy.go.codegen.GoCodegenContext; +import software.amazon.smithy.go.codegen.GoWriter; +import software.amazon.smithy.go.codegen.SmithyGoTypes; +import software.amazon.smithy.go.codegen.integration.GoIntegration; +import software.amazon.smithy.go.codegen.integration.MiddlewareRegistrar; +import software.amazon.smithy.go.codegen.integration.RuntimeClientPlugin; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.protocol.traits.Rpcv2CborTrait; + +/** + * Adds user agent tracking for basic features - i.e. simple model-based ones that do not require any additional in-code + * checks, such as a particular protocol. + */ +public class BasicUserAgentFeatures implements GoIntegration { + private static final List FEATURES = List.of( + new Feature("ProtocolRPCV2CBOR", (model, service) -> service.hasTrait(Rpcv2CborTrait.class)) + ); + + @Override + public List getClientPlugins() { + return FEATURES.stream().map(Feature::getPlugin).toList(); + } + + @Override + public void writeAdditionalFiles(GoCodegenContext ctx) { + var model = ctx.model(); + var service = ctx.settings().getService(model); + ctx.writerDelegator().useFileWriter("api_client.go", ctx.settings().getModuleName(), + GoWriter.ChainWritable.of( + FEATURES.stream() + .filter(it -> it.servicePredicate.test(model, service)) + .map(Feature::getAddMiddleware) + .toList() + ).compose()); + } + + private static final class Feature { + public final Symbol featureId; + public final BiPredicate servicePredicate; + + public Feature(String id, BiPredicate servicePredicate) { + this.featureId = AwsGoDependency.AWS_MIDDLEWARE.constSymbol("UserAgentFeature" + id); + this.servicePredicate = servicePredicate; + } + + public RuntimeClientPlugin getPlugin() { + return RuntimeClientPlugin.builder() + .servicePredicate(servicePredicate) + .registerMiddleware( + MiddlewareRegistrar.builder() + .resolvedFunction(buildPackageSymbol("add" + featureId.getName())) + .useClientOptions() + .build() + ) + .build(); + } + + public GoWriter.Writable getAddMiddleware() { + return goTemplate(""" + func add$featureName:L(stack $stack:P, options Options) error { + ua, err := getOrAddRequestUserAgent(stack) + if err != nil { + return err + } + + ua.AddUserAgentFeature($featureEnum:T) + return nil + } + """, + Map.of( + "stack", SmithyGoTypes.Middleware.Stack, + "featureName", featureId.getName(), + "featureEnum", featureId + )); + } + } +} diff --git a/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration b/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration index b4f24f9552b..7c2810d24f8 100644 --- a/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration +++ b/codegen/smithy-aws-go-codegen/src/main/resources/META-INF/services/software.amazon.smithy.go.codegen.integration.GoIntegration @@ -86,3 +86,4 @@ software.amazon.smithy.aws.go.codegen.customization.RequestCompressionUserAgent software.amazon.smithy.aws.go.codegen.customization.s3.ExpressUserAgent software.amazon.smithy.aws.go.codegen.customization.BackfillRequiredTrait software.amazon.smithy.aws.go.codegen.customization.DeprecateService +software.amazon.smithy.aws.go.codegen.customization.BasicUserAgentFeatures diff --git a/internal/protocoltest/smithyrpcv2cbor/api_client.go b/internal/protocoltest/smithyrpcv2cbor/api_client.go index 4fed3a1fada..758bc631e0f 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_client.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_client.go @@ -702,6 +702,16 @@ func addUserAgentRetryMode(stack *middleware.Stack, options Options) error { return nil } +func addUserAgentFeatureProtocolRPCV2CBOR(stack *middleware.Stack, options Options) error { + ua, err := getOrAddRequestUserAgent(stack) + if err != nil { + return err + } + + ua.AddUserAgentFeature(awsmiddleware.UserAgentFeatureProtocolRPCV2CBOR) + return nil +} + func resolveTracerProvider(options *Options) { if options.TracerProvider == nil { options.TracerProvider = &tracing.NopTracerProvider{} diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_EmptyInputOutput.go b/internal/protocoltest/smithyrpcv2cbor/api_op_EmptyInputOutput.go index 681643fd53c..3c4ef76db27 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_EmptyInputOutput.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_EmptyInputOutput.go @@ -97,6 +97,9 @@ func (c *Client) addOperationEmptyInputOutputMiddlewares(stack *middleware.Stack if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opEmptyInputOutput(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_Float16.go b/internal/protocoltest/smithyrpcv2cbor/api_op_Float16.go index 0b2858586bf..306dbddb820 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_Float16.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_Float16.go @@ -99,6 +99,9 @@ func (c *Client) addOperationFloat16Middlewares(stack *middleware.Stack, options if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opFloat16(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_FractionalSeconds.go b/internal/protocoltest/smithyrpcv2cbor/api_op_FractionalSeconds.go index bb98c547d92..0e83b326edf 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_FractionalSeconds.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_FractionalSeconds.go @@ -100,6 +100,9 @@ func (c *Client) addOperationFractionalSecondsMiddlewares(stack *middleware.Stac if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opFractionalSeconds(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_GreetingWithErrors.go b/internal/protocoltest/smithyrpcv2cbor/api_op_GreetingWithErrors.go index 44616bcf4cf..0b9133781c2 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_GreetingWithErrors.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_GreetingWithErrors.go @@ -107,6 +107,9 @@ func (c *Client) addOperationGreetingWithErrorsMiddlewares(stack *middleware.Sta if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opGreetingWithErrors(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_NoInputOutput.go b/internal/protocoltest/smithyrpcv2cbor/api_op_NoInputOutput.go index 76f6cb453ce..db6bc35c62a 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_NoInputOutput.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_NoInputOutput.go @@ -97,6 +97,9 @@ func (c *Client) addOperationNoInputOutputMiddlewares(stack *middleware.Stack, o if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opNoInputOutput(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_OperationWithDefaults.go b/internal/protocoltest/smithyrpcv2cbor/api_op_OperationWithDefaults.go index 661ab41329d..ecbc832a280 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_OperationWithDefaults.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_OperationWithDefaults.go @@ -153,6 +153,9 @@ func (c *Client) addOperationOperationWithDefaultsMiddlewares(stack *middleware. if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOperationWithDefaults(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_OptionalInputOutput.go b/internal/protocoltest/smithyrpcv2cbor/api_op_OptionalInputOutput.go index 0158b5182c5..ff2cdee67de 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_OptionalInputOutput.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_OptionalInputOutput.go @@ -101,6 +101,9 @@ func (c *Client) addOperationOptionalInputOutputMiddlewares(stack *middleware.St if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opOptionalInputOutput(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_RecursiveShapes.go b/internal/protocoltest/smithyrpcv2cbor/api_op_RecursiveShapes.go index 106052f543f..d61c01d67ca 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_RecursiveShapes.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_RecursiveShapes.go @@ -102,6 +102,9 @@ func (c *Client) addOperationRecursiveShapesMiddlewares(stack *middleware.Stack, if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRecursiveShapes(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborDenseMaps.go b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborDenseMaps.go index f5b92e10d35..559f20931b8 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborDenseMaps.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborDenseMaps.go @@ -119,6 +119,9 @@ func (c *Client) addOperationRpcV2CborDenseMapsMiddlewares(stack *middleware.Sta if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRpcV2CborDenseMaps(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborLists.go b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborLists.go index 59d48cdb802..d18906aac9c 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborLists.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborLists.go @@ -148,6 +148,9 @@ func (c *Client) addOperationRpcV2CborListsMiddlewares(stack *middleware.Stack, if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRpcV2CborLists(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborSparseMaps.go b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborSparseMaps.go index 260147ec12f..72e4937bb53 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborSparseMaps.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_RpcV2CborSparseMaps.go @@ -118,6 +118,9 @@ func (c *Client) addOperationRpcV2CborSparseMapsMiddlewares(stack *middleware.St if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opRpcV2CborSparseMaps(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_SimpleScalarProperties.go b/internal/protocoltest/smithyrpcv2cbor/api_op_SimpleScalarProperties.go index a65a41e1535..00a9cd0734f 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_SimpleScalarProperties.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_SimpleScalarProperties.go @@ -137,6 +137,9 @@ func (c *Client) addOperationSimpleScalarPropertiesMiddlewares(stack *middleware if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSimpleScalarProperties(options.Region), middleware.Before); err != nil { return err } diff --git a/internal/protocoltest/smithyrpcv2cbor/api_op_SparseNullsOperation.go b/internal/protocoltest/smithyrpcv2cbor/api_op_SparseNullsOperation.go index 94ce7bd6c39..3d4c4ba4cf2 100644 --- a/internal/protocoltest/smithyrpcv2cbor/api_op_SparseNullsOperation.go +++ b/internal/protocoltest/smithyrpcv2cbor/api_op_SparseNullsOperation.go @@ -105,6 +105,9 @@ func (c *Client) addOperationSparseNullsOperationMiddlewares(stack *middleware.S if err = addUserAgentRetryMode(stack, options); err != nil { return err } + if err = addUserAgentFeatureProtocolRPCV2CBOR(stack, options); err != nil { + return err + } if err = stack.Initialize.Add(newServiceMetadataMiddleware_opSparseNullsOperation(options.Region), middleware.Before); err != nil { return err }