protected open fun constructAwsClient()

in plugins/core/core/src/migration/software/aws/toolkits/core/ToolkitClientManager.kt [148:258]


    protected open fun <T : SdkClient> constructAwsClient(
        sdkClass: KClass<T>,
        credProvider: AwsCredentialsProvider? = null,
        tokenProvider: SdkTokenProvider? = null,
        region: Region,
        endpointOverride: String? = null,
        clientCustomizer: ToolkitClientCustomizer? = null,
    ): T {
        checkNotNull(credProvider ?: tokenProvider) { "Either a credential provider or a bearer token provider must be provided" }

        val builderMethod = sdkClass.java.methods.find {
            it.name == "builder" && Modifier.isStatic(it.modifiers) && Modifier.isPublic(it.modifiers)
        } ?: throw IllegalArgumentException("Expected service interface to have a public static `builder()` method.")

        val builder = builderMethod.invoke(null) as AwsDefaultClientBuilder<*, *>

        @Suppress("UNCHECKED_CAST")
        return builder
            .region(region)
            .apply {
                if (this is SdkSyncClientBuilder<*, *>) {
                    // async clients use CRT, and keeps trying to shut down our apache client even though it doesn't respect our client settings
                    // so only set this for sync clients
                    httpClient(sdkHttpClient())
                }

                val clientOverrideConfig = ClientOverrideConfiguration.builder()

                if (credProvider != null) {
                    credentialsProvider(credProvider)
                }

                if (tokenProvider != null) {
                    val tokenMethod = builderMethod.returnType.methods.find {
                        it.name == "tokenProvider" &&
                            it.parameterCount == 1 &&
                            it.parameters[0].type.name == "software.amazon.awssdk.auth.token.credentials.SdkTokenProvider"
                    }

                    if (tokenMethod == null) {
                        LOG.warn { "Ignoring bearer provider parameter for ${sdkClass.qualifiedName} since it's not a supported client attribute" }
                    } else {
                        tokenMethod.invoke(this, tokenProvider)
                        clientOverrideConfig.nullDefaultProfileFile()
                        // TODO: why do we need this?
                        clientOverrideConfig.putAdvancedOption(SdkAdvancedClientOption.SIGNER, BearerTokenSigner())
                    }
                }

                clientOverrideConfig.addExecutionInterceptor(object : ExecutionInterceptor {
                    override fun modifyRequest(
                        context: Context.ModifyRequest,
                        executionAttributes: ExecutionAttributes,
                    ): SdkRequest {
                        val request = context.request()
                        if (request !is AwsRequest) {
                            return request
                        }

                        val clientType = executionAttributes.getAttribute(AwsExecutionAttribute.CLIENT_TYPE)
                        val sdkClient = executionAttributes.getAttribute(SdkInternalExecutionAttribute.SDK_CLIENT)
                        val serviceClientConfiguration = sdkClient.serviceClientConfiguration()
                        val retryMode = serviceClientConfiguration.overrideConfiguration().retryMode().orElse(RetryMode.defaultRetryMode())
                        val toolkitUserAgent = userAgent()

                        val requestUserAgent = ApplyUserAgentStage.resolveClientUserAgent(
                            toolkitUserAgent,
                            null,
                            clientType,
                            null,
                            null,
                            retryMode.toString().lowercase()
                        )

                        val overrideConfiguration = request.overrideConfiguration()
                            .map { config ->
                                config.toBuilder()
                                    .putHeader(HEADER_USER_AGENT, requestUserAgent)
                                    .build()
                            }
                            .orElseGet {
                                AwsRequestOverrideConfiguration.builder()
                                    .putHeader(HEADER_USER_AGENT, requestUserAgent)
                                    .build()
                            }

                        return request.toBuilder()
                            .overrideConfiguration(overrideConfiguration)
                            .build()
                    }
                })

                clientOverrideConfig.let { configuration ->
                    configuration.retryStrategy(RetryMode.STANDARD)
                }

                endpointOverride?.let {
                    endpointOverride(URI.create(it))
                }

                globalClientCustomizer(credProvider, tokenProvider, region.id(), this, clientOverrideConfig)

                clientCustomizer?.let {
                    it.customize(credProvider, tokenProvider, region.id(), this, clientOverrideConfig)
                }

                // TODO: ban overrideConfiguration outside of here
                overrideConfiguration(clientOverrideConfig.build())
            }
            .build() as T
    }