Skip to content

Commit

Permalink
Add Endpoint Resolver Implementation
Browse files Browse the repository at this point in the history
This commit adds `EndpointDecorator`, standard libary + tests that can be used to add endpoints 2.0 to the AWS SDK.

It _does not_ actually wire these things up. We'll follow up with a PR that actually integrates everything.
  • Loading branch information
rcoh committed Nov 28, 2022
1 parent ec9588b commit 3e8af14
Show file tree
Hide file tree
Showing 49 changed files with 2,050 additions and 185 deletions.
2 changes: 1 addition & 1 deletion aws/rust-runtime/aws-endpoint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl ResolveEndpoint<Params> for EndpointShim {
.ok_or_else(|| ResolveEndpointError::message("no region in params"))?,
)
.map_err(|err| {
ResolveEndpointError::message("failure resolving endpoint").with_source(err)
ResolveEndpointError::message("failure resolving endpoint").with_source(Some(err))
})?;
let uri = aws_endpoint.endpoint().uri();
let mut auth_scheme =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.rustsdk

import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.node.ObjectNode
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.CustomRuntimeFunction
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointCustomization
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.rulesgen.awsStandardLib
import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.ClientProtocolGenerator
import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext
import kotlin.io.path.readText

/**
* Standard library functions for AWS-specific endpoint standard library functions.
*
* This decorator uses partitions.json to source a default partition map for the partition resolver (when used).
*
* For test purposes, [awsStandardLib] can be used directly with a manually supplied partitions.json
*/
class AwsEndpointsStdLib() : RustCodegenDecorator<ClientProtocolGenerator, ClientCodegenContext> {
private var partitionsCache: ObjectNode? = null
override val name: String = "AwsEndpointsStdLib"
override val order: Byte = 0

override fun supportsCodegenContext(clazz: Class<out CodegenContext>): Boolean {
return clazz.isAssignableFrom(ClientCodegenContext::class.java)
}

private fun partitionsDotjson(sdkSettings: SdkSettings): ObjectNode {
if (partitionsCache == null) {
val partitionsJson = when (val path = sdkSettings.partitionsDotJson) {
null -> (
javaClass.getResource("/default-partitions.json")
?: throw IllegalStateException("Failed to find default-default-partitions.json in the JAR")
).readText()

else -> path.readText()
}
partitionsCache = Node.parse(partitionsJson).expectObjectNode()
}
return partitionsCache!!
}

override fun endpointCustomizations(codegenContext: ClientCodegenContext): List<EndpointCustomization> {
return listOf<EndpointCustomization>(
object : EndpointCustomization {
override fun customRuntimeFunctions(codegenContext: ClientCodegenContext): List<CustomRuntimeFunction> {
val sdkSettings = SdkSettings.from(codegenContext.settings)
return awsStandardLib(codegenContext.runtimeConfig, partitionsDotjson(sdkSettings))
}
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import software.amazon.smithy.rulesengine.language.syntax.parameters.Builtins
import software.amazon.smithy.rulesengine.language.syntax.parameters.Parameter
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.RulesEngineBuiltInResolver
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.CustomRuntimeFunction
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ServiceConfig
import software.amazon.smithy.rust.codegen.client.smithy.generators.protocol.ClientProtocolGenerator
Expand Down Expand Up @@ -100,18 +101,18 @@ class RegionDecorator : RustCodegenDecorator<ClientProtocolGenerator, ClientCode
return baseCustomizations + PubUseRegion(codegenContext.runtimeConfig)
}

override fun builtInResolvers(codegenContext: ClientCodegenContext): List<RulesEngineBuiltInResolver> {
override fun endpointCustomizations(codegenContext: ClientCodegenContext): List<EndpointCustomization> {
return listOf(
object : RulesEngineBuiltInResolver {
override fun defaultFor(
parameter: Parameter,
configRef: String,
): Writable? {
object : EndpointCustomization {
override fun builtInDefaultValue(parameter: Parameter, configRef: String): Writable? {
return when (parameter) {
Builtins.REGION -> writable { rust("$configRef.region.as_ref().map(|r|r.as_ref())") }
Builtins.REGION -> writable { rust("$configRef.region.as_ref().map(|r|r.as_ref().to_owned())") }
else -> null
}
}

override fun customRuntimeFunctions(codegenContext: ClientCodegenContext): List<CustomRuntimeFunction> =
listOf()
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ class SdkSettings private constructor(private val awsSdk: ObjectNode?) {
get() =
awsSdk?.getStringMember("endpointsConfigPath")?.orNull()?.value?.let { Paths.get(it) }

/** Path to the `default-partitions.json` configuration */
val partitionsDotJson: Path?
get() =
awsSdk?.getStringMember("partitionsConfigPath")?.orNull()?.value?.let { Paths.get(it) }

/** Path to AWS SDK integration tests */
val integrationTestPath: String
get() =
Expand Down
105 changes: 105 additions & 0 deletions aws/sdk-codegen/src/main/resources/default-partitions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"version": "1.1",
"partitions": [
{
"id": "aws",
"regionRegex": "^(us|eu|ap|sa|ca|me|af)-\\w+-\\d+$",
"regions": {
"af-south-1": {},
"ap-east-1": {},
"ap-northeast-1": {},
"ap-northeast-2": {},
"ap-northeast-3": {},
"ap-south-1": {},
"ap-southeast-1": {},
"ap-southeast-2": {},
"ap-southeast-3": {},
"ca-central-1": {},
"eu-central-1": {},
"eu-north-1": {},
"eu-south-1": {},
"eu-west-1": {},
"eu-west-2": {},
"eu-west-3": {},
"me-central-1": {},
"me-south-1": {},
"sa-east-1": {},
"us-east-1": {},
"us-east-2": {},
"us-west-1": {},
"us-west-2": {},
"aws-global": {}
},
"outputs": {
"name": "aws",
"dnsSuffix": "amazonaws.com",
"dualStackDnsSuffix": "api.aws",
"supportsFIPS": true,
"supportsDualStack": true
}
},
{
"id": "aws-us-gov",
"regionRegex": "^us\\-gov\\-\\w+\\-\\d+$",
"regions": {
"us-gov-west-1": {},
"us-gov-east-1": {},
"aws-us-gov-global": {}
},
"outputs": {
"name": "aws-us-gov",
"dnsSuffix": "amazonaws.com",
"dualStackDnsSuffix": "api.aws",
"supportsFIPS": true,
"supportsDualStack": true
}
},
{
"id": "aws-cn",
"regionRegex": "^cn\\-\\w+\\-\\d+$",
"regions": {
"cn-north-1": {},
"cn-northwest-1": {},
"aws-cn-global": {}
},
"outputs": {
"name": "aws-cn",
"dnsSuffix": "amazonaws.com.cn",
"dualStackDnsSuffix": "api.amazonwebservices.com.cn",
"supportsFIPS": true,
"supportsDualStack": true
}
},
{
"id": "aws-iso",
"regionRegex": "^us\\-iso\\-\\w+\\-\\d+$",
"outputs": {
"name": "aws-iso",
"dnsSuffix": "c2s.ic.gov",
"supportsFIPS": true,
"supportsDualStack": false,
"dualStackDnsSuffix": "c2s.ic.gov"
},
"regions": {
"us-iso-east-1": {},
"us-iso-west-1": {},
"aws-iso-global": {}
}
},
{
"id": "aws-iso-b",
"regionRegex": "^us\\-isob\\-\\w+\\-\\d+$",
"outputs": {
"name": "aws-iso-b",
"dnsSuffix": "sc2s.sgov.gov",
"supportsFIPS": true,
"supportsDualStack": false,
"dualStackDnsSuffix": "sc2s.sgov.gov"
},
"regions": {
"us-isob-east-1": {},
"aws-iso-b-global": {}
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ val AllowedClippyLints = listOf(
"should_implement_trait",

// Protocol tests use silly names like `baz`, don't flag that.
// TODO(msrv_upgrade): switch
"blacklisted_name",
// "disallowed_names",

// Forcing use of `vec![]` can make codegen harder in some cases.
"vec_init_then_push",
Expand All @@ -42,6 +44,14 @@ val AllowedClippyLints = listOf(

// Determining if the expression is the last one (to remove return) can make codegen harder in some cases.
"needless_return",

// For backwards compatibility, we often don't derive Eq
// TODO(msrv_upgrade): enable
// "derive_partial_eq_without_eq",

// Keeping errors small in a backwards compatible way is challenging
// TODO(msrv_upgrade): enable
// "result_large_err",
)

val AllowedRustdocLints = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.RulesEngineBuiltInResolver
import software.amazon.smithy.rust.codegen.client.smithy.endpoint.EndpointCustomization
import software.amazon.smithy.rust.codegen.client.smithy.generators.config.ConfigCustomization
import software.amazon.smithy.rust.codegen.core.smithy.CodegenContext
import software.amazon.smithy.rust.codegen.core.smithy.RustCrate
Expand Down Expand Up @@ -70,7 +70,7 @@ interface RustCodegenDecorator<T, C : CodegenContext> {

fun transformModel(service: ServiceShape, model: Model): Model = model

fun builtInResolvers(codegenContext: C): List<RulesEngineBuiltInResolver> = listOf()
fun endpointCustomizations(codegenContext: C): List<EndpointCustomization> = listOf()

fun supportsCodegenContext(clazz: Class<out CodegenContext>): Boolean
}
Expand Down Expand Up @@ -144,8 +144,8 @@ open class CombinedCodegenDecorator<T, C : CodegenContext>(decorators: List<Rust
}
}

override fun builtInResolvers(codegenContext: C): List<RulesEngineBuiltInResolver> {
return orderedDecorators.flatMap { it.builtInResolvers(codegenContext) }
override fun endpointCustomizations(codegenContext: C): List<EndpointCustomization> {
return orderedDecorators.flatMap { it.endpointCustomizations(codegenContext) }
}

override fun supportsCodegenContext(clazz: Class<out CodegenContext>): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import software.amazon.smithy.rust.codegen.core.util.toSnakeCase
/**
* This decorator adds `ClientContextParams` to the service config.
*
* This handles injecting parameters like `s3::Accelerate` or `s3::ForcePathStyle`
* This handles injecting parameters like `s3::Accelerate` or `s3::ForcePathStyle`. The resulting parameters become
* setters on the config builder object.
*/
class ClientContextDecorator(ctx: CodegenContext) : ConfigCustomization() {
internal class ClientContextDecorator(ctx: CodegenContext) : ConfigCustomization() {
private val contextParams = ctx.serviceShape.getTrait<ClientContextParamsTrait>()?.parameters.orEmpty().toList()
.map { (key, value) -> ContextParam.fromClientParam(key, value, ctx.symbolProvider) }

Expand Down
Loading

0 comments on commit 3e8af14

Please sign in to comment.