Skip to content

Commit

Permalink
Add customization to retry STS IDPCommunicationErrorException (#1718)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdisanti authored Sep 10, 2022
1 parent 054d922 commit 56f4be3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,9 @@ message = "Smithy IDL v2 mixins are now supported"
references = ["smithy-rs#1680"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all"}
author = "ogudavid"

[[aws-sdk-rust]]
message = "The AWS STS SDK now automatically retries `IDPCommunicationError` when calling `AssumeRoleWithWebIdentity`"
references = ["smithy-rs#966", "smithy-rs#1718"]
meta = { "breaking" = false, "tada" = false, "bug" = true }
author = "jdisanti"
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import software.amazon.smithy.rustsdk.customize.ec2.Ec2Decorator
import software.amazon.smithy.rustsdk.customize.glacier.GlacierDecorator
import software.amazon.smithy.rustsdk.customize.route53.Route53Decorator
import software.amazon.smithy.rustsdk.customize.s3.S3Decorator
import software.amazon.smithy.rustsdk.customize.sts.STSDecorator

val DECORATORS = listOf(
// General AWS Decorators
Expand All @@ -35,12 +36,13 @@ val DECORATORS = listOf(
AwsReadmeDecorator(),

// Service specific decorators
DisabledAuthDecorator(),
ApiGatewayDecorator(),
S3Decorator(),
DisabledAuthDecorator(),
Ec2Decorator(),
GlacierDecorator(),
Route53Decorator(),
S3Decorator(),
STSDecorator(),

// Only build docs-rs for linux to reduce load on docs.rs
DocsRsMetadataDecorator(DocsRsMetadataSettings(targets = listOf("x86_64-unknown-linux-gnu"), allFeatures = true)),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package software.amazon.smithy.rustsdk.customize.sts

import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.ServiceShape
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.model.traits.ErrorTrait
import software.amazon.smithy.model.traits.RetryableTrait
import software.amazon.smithy.model.transform.ModelTransformer
import software.amazon.smithy.rust.codegen.client.smithy.ClientCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.CoreCodegenContext
import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator
import software.amazon.smithy.rust.codegen.client.smithy.letIf
import software.amazon.smithy.rust.codegen.client.util.hasTrait
import java.util.logging.Logger

class STSDecorator : RustCodegenDecorator<ClientCodegenContext> {
override val name: String = "STS"
override val order: Byte = 0
private val logger: Logger = Logger.getLogger(javaClass.name)

private fun applies(serviceId: ShapeId) =
serviceId == ShapeId.from("com.amazonaws.sts#AWSSecurityTokenServiceV20110615")

private fun isIdpCommunicationError(shape: Shape): Boolean =
shape is StructureShape && shape.hasTrait<ErrorTrait>() &&
shape.id.namespace == "com.amazonaws.sts" && shape.id.name == "IDPCommunicationErrorException"

override fun transformModel(service: ServiceShape, model: Model): Model {
return model.letIf(applies(service.id)) {
ModelTransformer.create().mapShapes(model) { shape ->
shape.letIf(isIdpCommunicationError(shape)) {
logger.info("Adding @retryable trait to $shape and setting its error type to 'server'")
(shape as StructureShape).toBuilder()
.removeTrait(ErrorTrait.ID)
.addTrait(ErrorTrait("server"))
.addTrait(RetryableTrait.builder().build()).build()
}
}
}
}

override fun supportsCodegenContext(clazz: Class<out CoreCodegenContext>): Boolean =
clazz.isAssignableFrom(ClientCodegenContext::class.java)
}
1 change: 1 addition & 0 deletions aws/sdk/integration-tests/sts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ edition = "2021"
aws-sdk-sts = { path = "../../build/aws-sdk/sdk/sts" }
aws-smithy-client = { path = "../../build/aws-sdk/sdk/aws-smithy-client", features = ["test-util", "rustls"] }
aws-smithy-http = { path = "../../build/aws-sdk/sdk/aws-smithy-http" }
aws-smithy-types = { path = "../../build/aws-sdk/sdk/aws-smithy-types" }
tokio = { version = "1.8.4", features = ["full", "test-util"] }
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
32 changes: 32 additions & 0 deletions aws/sdk/integration-tests/sts/tests/retry_idp_comms_err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use aws_sdk_sts as sts;
use aws_smithy_types::error::Error as ErrorMeta;
use aws_smithy_types::retry::{ErrorKind, ProvideErrorKind};
use sts::error::{
AssumeRoleWithWebIdentityError, AssumeRoleWithWebIdentityErrorKind,
IdpCommunicationErrorException,
};

#[tokio::test]
async fn idp_comms_err_retryable() {
let error = AssumeRoleWithWebIdentityError::new(
AssumeRoleWithWebIdentityErrorKind::IdpCommunicationErrorException(
IdpCommunicationErrorException::builder()
.message("test")
.build(),
),
ErrorMeta::builder()
.code("IDPCommunicationError")
.message("test")
.build(),
);
assert_eq!(
Some(ErrorKind::ServerError),
error.retryable_error_kind(),
"IdpCommunicationErrorException should be a retryable server error"
);
}

0 comments on commit 56f4be3

Please sign in to comment.