Skip to content

Commit d59d21e

Browse files
authored
refactor: endpoint resolver exec (SRA) (#828)
1 parent 3a0f353 commit d59d21e

File tree

21 files changed

+598
-466
lines changed

21 files changed

+598
-466
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "29105f7e-0614-467e-b4bd-25162f45f94f",
3+
"type": "misc",
4+
"description": "Refactor endpoint resolution to be explicit in SdkOperationExecution and change order to match SRA."
5+
}

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/CodegenVisitor.kt

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import software.amazon.smithy.kotlin.codegen.core.*
1212
import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration
1313
import software.amazon.smithy.kotlin.codegen.model.*
1414
import software.amazon.smithy.kotlin.codegen.rendering.*
15-
import software.amazon.smithy.kotlin.codegen.rendering.endpoints.EndpointParametersGenerator
16-
import software.amazon.smithy.kotlin.codegen.rendering.endpoints.EndpointProviderGenerator
1715
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ApplicationProtocol
1816
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
1917
import software.amazon.smithy.model.Model
@@ -200,21 +198,14 @@ class CodegenVisitor(context: PluginContext) : ShapeVisitor.Default<Unit>() {
200198
// the actual default implementation and test cases will only be generated if there's an actual rule set from which to
201199
// derive them
202200
private fun ProtocolGenerator.generateEndpointsSources(ctx: ProtocolGenerator.GenerationContext) {
203-
val rules = ctx.service.getEndpointRules()
204-
val paramsSymbol = EndpointParametersGenerator.getSymbol(ctx.settings)
205-
val providerSymbol = EndpointProviderGenerator.getSymbol(ctx.settings)
206-
207-
ctx.delegator.useFileWriter(paramsSymbol) {
208-
EndpointParametersGenerator(it, rules).render()
209-
}
210-
ctx.delegator.useFileWriter(providerSymbol) {
211-
EndpointProviderGenerator(it, paramsSymbol).render()
212-
}
213-
214-
generateEndpointProviderMiddleware(ctx)
215-
if (rules != null) {
201+
with(endpointDelegator(ctx)) {
202+
val rules = ctx.service.getEndpointRules()
216203
generateEndpointProvider(ctx, rules)
217-
generateEndpointProviderTests(ctx, ctx.service.getEndpointTests(), rules)
204+
generateEndpointParameters(ctx, rules)
205+
generateEndpointResolverAdapter(ctx)
206+
if (rules != null) {
207+
generateEndpointProviderTests(ctx, ctx.service.getEndpointTests(), rules)
208+
}
218209
}
219210
}
220211

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,24 @@ object RuntimeTypes {
5050

5151
object Middleware : RuntimeTypePackage(KotlinDependency.HTTP, "middleware") {
5252
val MutateHeadersMiddleware = symbol("MutateHeaders")
53-
val RetryMiddleware = symbol("RetryMiddleware")
54-
val ResolveEndpoint = symbol("ResolveEndpoint")
55-
val setResolvedEndpoint = symbol("setResolvedEndpoint")
5653
}
5754

5855
object Operation : RuntimeTypePackage(KotlinDependency.HTTP, "operation") {
5956
val AuthSchemeResolver = symbol("AuthSchemeResolver")
6057
val context = symbol("context")
58+
val EndpointResolver = symbol("EndpointResolver")
59+
val ResolveEndpointRequest = symbol("ResolveEndpointRequest")
6160
val execute = symbol("execute")
6261
val HttpDeserialize = symbol("HttpDeserialize")
62+
val HttpOperationContext = symbol("HttpOperationContext")
6363
val HttpSerialize = symbol("HttpSerialize")
6464
val OperationAuthConfig = symbol("OperationAuthConfig")
6565
val OperationRequest = symbol("OperationRequest")
6666
val roundTrip = symbol("roundTrip")
6767
val sdkRequestId = symbol("sdkRequestId")
6868
val SdkHttpOperation = symbol("SdkHttpOperation")
6969
val SdkHttpRequest = symbol("SdkHttpRequest")
70+
val setResolvedEndpoint = symbol("setResolvedEndpoint")
7071
}
7172

7273
object Config : RuntimeTypePackage(KotlinDependency.HTTP, "config") {
@@ -287,6 +288,7 @@ object RuntimeTypes {
287288

288289
object HttpAuth: RuntimeTypePackage(KotlinDependency.HTTP_AUTH) {
289290
val AnonymousAuthScheme = symbol("AnonymousAuthScheme")
291+
val AnonymousIdentity = symbol("AnonymousIdentity")
290292
val AnonymousIdentityProvider = symbol("AnonymousIdentityProvider")
291293
val HttpAuthConfig = symbol("HttpAuthConfig")
292294
val HttpAuthScheme = symbol("HttpAuthScheme")

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/integration/KotlinIntegration.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigProperty
1515
import software.amazon.smithy.model.Model
1616
import software.amazon.smithy.model.shapes.ServiceShape
1717
import software.amazon.smithy.model.shapes.Shape
18+
import software.amazon.smithy.rulesengine.language.EndpointRuleSet
1819

1920
/**
2021
* JVM SPI for customizing Kotlin code generation, registering new protocol
@@ -152,5 +153,13 @@ interface KotlinIntegration {
152153
* Get a list of auth scheme handlers this integration is responsible for
153154
*/
154155
fun authSchemes(ctx: ProtocolGenerator.GenerationContext): List<AuthSchemeHandler> = emptyList()
156+
157+
/**
158+
* Render binding of endpoint ruleset builtin parameters
159+
* @param ctx The codegen generation context
160+
* @param rules The endpoint rules
161+
* @param writer The writer to render to
162+
*/
163+
fun renderBindEndpointBuiltins(ctx: ProtocolGenerator.GenerationContext, rules: EndpointRuleSet, writer: KotlinWriter) {}
155164
}
156165

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.kotlin.codegen.model.knowledge
7+
8+
import software.amazon.smithy.kotlin.codegen.model.getTrait
9+
import software.amazon.smithy.kotlin.codegen.utils.getOrNull
10+
import software.amazon.smithy.model.Model
11+
import software.amazon.smithy.model.knowledge.KnowledgeIndex
12+
import software.amazon.smithy.model.knowledge.OperationIndex
13+
import software.amazon.smithy.model.shapes.MemberShape
14+
import software.amazon.smithy.model.shapes.OperationShape
15+
import software.amazon.smithy.rulesengine.traits.ContextParamTrait
16+
import software.amazon.smithy.rulesengine.traits.StaticContextParamsTrait
17+
18+
19+
/**
20+
* Provides endpoint parameter binding knowledge index
21+
*/
22+
class EndpointParameterIndex private constructor(model: Model): KnowledgeIndex {
23+
private val opIndex = OperationIndex.of(model)
24+
25+
/**
26+
* Get the static context params for an operation
27+
*
28+
* @param op operation shape
29+
* @return the static context params if they exist
30+
*/
31+
fun staticContextParams(op: OperationShape): StaticContextParamsTrait? = op.getTrait<StaticContextParamsTrait>()
32+
33+
/**
34+
* Get the `inputContextParams` for an operation.
35+
*
36+
* @param op the operation shape to get context params for
37+
* @return map of parameter name to input member shape
38+
*/
39+
fun inputContextParams(op: OperationShape): Map<String, MemberShape> {
40+
// maps endpoint parameter name -> input member shape
41+
return buildMap {
42+
opIndex.getInput(op).getOrNull()?.members()?.forEach { member ->
43+
member.getTrait<ContextParamTrait>()?.let { trait ->
44+
put(trait.name, member)
45+
}
46+
}
47+
}
48+
}
49+
50+
/**
51+
* Check if there are any context parameters bound to an operation
52+
*
53+
* @param op operation to check parameters for
54+
* @return true if there are any static or input context parameters for the given operation
55+
*/
56+
fun hasContextParams(op: OperationShape): Boolean =
57+
staticContextParams(op) != null || inputContextParams(op).isNotEmpty()
58+
59+
companion object {
60+
fun of(model: Model): EndpointParameterIndex = EndpointParameterIndex(model)
61+
}
62+
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.kotlin.codegen.rendering.endpoints
7+
8+
import software.amazon.smithy.kotlin.codegen.core.useFileWriter
9+
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
10+
import software.amazon.smithy.rulesengine.language.EndpointRuleSet
11+
import software.amazon.smithy.rulesengine.traits.EndpointTestCase
12+
13+
/**
14+
* Responsible for providing various endpoint related generation components
15+
*/
16+
interface EndpointDelegator {
17+
companion object {
18+
/**
19+
* Get the default endpoint delegator
20+
*/
21+
val Default: EndpointDelegator = object : EndpointDelegator {}
22+
}
23+
/**
24+
* Generate a default implementation for the modeled endpoint provider.
25+
* Will only be invoked when a model's service shape has the necessary endpoint rule set trait, however, the base
26+
* interface and parameter type will always be generated (the expectation being that the caller supplies their own
27+
* at runtime).
28+
*/
29+
fun generateEndpointProvider(ctx: ProtocolGenerator.GenerationContext, rules: EndpointRuleSet?) {
30+
val paramsSymbol = EndpointParametersGenerator.getSymbol(ctx.settings)
31+
val providerSymbol = EndpointProviderGenerator.getSymbol(ctx.settings)
32+
val defaultProviderSymbol = DefaultEndpointProviderGenerator.getSymbol(ctx.settings)
33+
34+
ctx.delegator.useFileWriter(providerSymbol) {
35+
EndpointProviderGenerator(it, paramsSymbol).render()
36+
}
37+
38+
if (rules != null) {
39+
ctx.delegator.useFileWriter(defaultProviderSymbol) {
40+
DefaultEndpointProviderGenerator(it, rules, providerSymbol, paramsSymbol).render()
41+
}
42+
}
43+
}
44+
45+
/**
46+
* Generate the input parameter type for the generated endpoint provider implementation.
47+
*/
48+
fun generateEndpointParameters(ctx: ProtocolGenerator.GenerationContext, rules: EndpointRuleSet?) {
49+
val paramsSymbol = EndpointParametersGenerator.getSymbol(ctx.settings)
50+
ctx.delegator.useFileWriter(paramsSymbol) {
51+
EndpointParametersGenerator(it, rules).render()
52+
}
53+
}
54+
55+
/**
56+
* Generate unit tests for the modeled endpoint rules test cases.
57+
* Will only be invoked when a model's service shape has both the rule set and test case traits for endpoints.
58+
*/
59+
fun generateEndpointProviderTests(ctx: ProtocolGenerator.GenerationContext, tests: List<EndpointTestCase>, rules: EndpointRuleSet) {
60+
val paramsSymbol = EndpointParametersGenerator.getSymbol(ctx.settings)
61+
val defaultProviderSymbol = DefaultEndpointProviderGenerator.getSymbol(ctx.settings)
62+
val testSymbol = DefaultEndpointProviderTestGenerator.getSymbol(ctx.settings)
63+
64+
ctx.delegator.useTestFileWriter("${testSymbol.name}.kt", testSymbol.namespace) {
65+
DefaultEndpointProviderTestGenerator(it, rules, tests, defaultProviderSymbol, paramsSymbol).render()
66+
}
67+
}
68+
69+
/**
70+
* Generate the operation adapter for going from the type agnostic HTTP endpoint resolver to the generated
71+
* endpoint provider.
72+
*/
73+
fun generateEndpointResolverAdapter(ctx: ProtocolGenerator.GenerationContext) {
74+
ctx.delegator.useFileWriter(EndpointResolverAdapterGenerator.getSymbol(ctx.settings)) {
75+
EndpointResolverAdapterGenerator(ctx, it).render()
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)