Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changes/28e51fe7-a4d8-4c99-a257-886ad89b7d02.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "28e51fe7-a4d8-4c99-a257-886ad89b7d02",
"type": "bugfix",
"description": "improve retry policies for ECS and IMDS credentials to handle common network errors",
"issues": [
"awslabs/aws-sdk-kotlin#1626"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ import aws.smithy.kotlin.runtime.io.closeIfCloseable
import aws.smithy.kotlin.runtime.net.*
import aws.smithy.kotlin.runtime.net.url.Url
import aws.smithy.kotlin.runtime.operation.ExecutionContext
import aws.smithy.kotlin.runtime.retries.policy.RetryDirective
import aws.smithy.kotlin.runtime.retries.policy.RetryErrorType
import aws.smithy.kotlin.runtime.retries.policy.RetryPolicy
import aws.smithy.kotlin.runtime.serde.json.JsonDeserializer
import aws.smithy.kotlin.runtime.telemetry.logging.logger
import aws.smithy.kotlin.runtime.time.TimestampFormat
Expand Down Expand Up @@ -97,8 +94,6 @@ public class EcsCredentialsProvider(
execution.endpointResolver = EndpointResolver { Endpoint(url) }
}

op.execution.retryPolicy = EcsCredentialsRetryPolicy()

logger.debug { "retrieving container credentials" }
val client = SdkHttpClient(httpClient)
val creds = try {
Expand Down Expand Up @@ -260,22 +255,6 @@ private class EcsCredentialsSerializer(
}
}

internal class EcsCredentialsRetryPolicy : RetryPolicy<Any?> {
override fun evaluate(result: Result<Any?>): RetryDirective = when {
result.isSuccess -> RetryDirective.TerminateAndSucceed
else -> evaluate(result.exceptionOrNull()!!)
}

private fun evaluate(throwable: Throwable): RetryDirective = when (throwable) {
is CredentialsProviderException -> when {
throwable.sdkErrorMetadata.isThrottling -> RetryDirective.RetryError(RetryErrorType.Throttling)
throwable.sdkErrorMetadata.isRetryable -> RetryDirective.RetryError(RetryErrorType.ServerSide)
else -> RetryDirective.TerminateAndFail
}
else -> RetryDirective.TerminateAndFail
}
}

private val ecsV4Addr = IpV4Addr(169u, 254u, 170u, 2u)

private val eksV4Addr = IpV4Addr(169u, 254u, 170u, 23u)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,25 @@ import aws.smithy.kotlin.runtime.http.HttpStatusCode
import aws.smithy.kotlin.runtime.http.category
import aws.smithy.kotlin.runtime.retries.policy.RetryDirective
import aws.smithy.kotlin.runtime.retries.policy.RetryErrorType
import aws.smithy.kotlin.runtime.retries.policy.RetryPolicy
import aws.smithy.kotlin.runtime.retries.policy.StandardRetryPolicy
import aws.smithy.kotlin.runtime.telemetry.logging.logger
import kotlin.coroutines.CoroutineContext

internal class ImdsRetryPolicy(
private val callContext: CoroutineContext,
) : RetryPolicy<Any?> {
override fun evaluate(result: Result<Any?>): RetryDirective = when {
result.isSuccess -> RetryDirective.TerminateAndSucceed
else -> evaluate(result.exceptionOrNull()!!)
}

private fun evaluate(throwable: Throwable): RetryDirective = when (throwable) {
internal class ImdsRetryPolicy(private val callContext: CoroutineContext) : StandardRetryPolicy() {
override fun evaluateSpecificExceptions(ex: Throwable) = when (ex) {
is EC2MetadataError -> {
val status = throwable.status
val status = ex.status
when {
status.category() == HttpStatusCode.Category.SERVER_ERROR -> RetryDirective.RetryError(RetryErrorType.ServerSide)
// 401 indicates the token has expired, this is retryable
status == HttpStatusCode.Unauthorized -> RetryDirective.RetryError(RetryErrorType.ServerSide)
else -> {
val logger = callContext.logger<ImdsRetryPolicy>()
logger.debug { "Non retryable IMDS error: statusCode=$status; ${throwable.message}" }
RetryDirective.TerminateAndFail
logger.debug { "IMDS error: statusCode=$status; ${ex.message}" }
null
}
}
}
else -> RetryDirective.TerminateAndFail
else -> null
}
}
Loading