Simplify decoder logic for empty create constructor. Update documentation.
This commit is contained in:
parent
444a4ddf9a
commit
921781b9f9
3 changed files with 60 additions and 67 deletions
|
|
@ -99,27 +99,34 @@ class AwsCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode
|
|||
final String[] varargs = Arrays.copyOfRange(nameAndArgs, 1, nameAndArgs.length);
|
||||
|
||||
// attempt to invoke an explicit N-arg constructor of FooClass(String, String, ...)
|
||||
provider = constructProvider(
|
||||
providerName,
|
||||
() -> {
|
||||
Class<?>[] argTypes = new Class<?>[nameAndArgs.length - 1];
|
||||
Arrays.fill(argTypes, String.class);
|
||||
return clazz.getConstructor(argTypes).newInstance(varargs);
|
||||
},
|
||||
clazz);
|
||||
provider = constructProvider(providerName, () -> {
|
||||
Class<?>[] argTypes = new Class<?>[nameAndArgs.length - 1];
|
||||
Arrays.fill(argTypes, String.class);
|
||||
return clazz.getConstructor(argTypes).newInstance(varargs);
|
||||
});
|
||||
|
||||
if (provider == null) {
|
||||
// attempt to invoke a public varargs/array constructor of FooClass(String[])
|
||||
provider = constructProvider(
|
||||
providerName,
|
||||
() -> clazz.getConstructor(String[].class).newInstance((Object) varargs),
|
||||
clazz);
|
||||
provider = constructProvider(providerName, () -> clazz.getConstructor(String[].class)
|
||||
.newInstance((Object) varargs));
|
||||
}
|
||||
}
|
||||
|
||||
if (provider == null) {
|
||||
// regardless of parameters, fallback to invoke a public no-arg constructor
|
||||
provider = constructProvider(providerName, clazz::newInstance, clazz);
|
||||
// fallback to invoke a public no-arg constructor
|
||||
provider = constructProvider(providerName, clazz::newInstance);
|
||||
}
|
||||
|
||||
if (provider == null) {
|
||||
// if still not found, try empty create() method
|
||||
try {
|
||||
Method createMethod = clazz.getDeclaredMethod("create");
|
||||
if (Modifier.isStatic(createMethod.getModifiers())) {
|
||||
provider = constructProvider(providerName, () -> clazz.cast(createMethod.invoke(null)));
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
// No create() method found for class
|
||||
}
|
||||
}
|
||||
|
||||
if (provider != null) {
|
||||
|
|
@ -145,17 +152,18 @@ class AwsCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode
|
|||
|
||||
private static List<String> getPossibleFullClassNames(final String provider) {
|
||||
return Stream.of(
|
||||
// Customer provides a short name of common providers in com.amazonaws.auth package
|
||||
// (e.g., any classes implementing the AWSCredentialsProvider interface)
|
||||
// @see
|
||||
// http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/AWSCredentialsProvider.html
|
||||
"com.amazonaws.auth.",
|
||||
|
||||
// Customer provides a short name of a provider offered by this multi-lang package
|
||||
"software.amazon.kinesis.multilang.auth.",
|
||||
// Customer provides a short name of common providers in software.amazon.awssdk.auth.credentials
|
||||
// package (e.g., any classes implementing the AWSCredentialsProvider interface)
|
||||
// @see
|
||||
// https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/AwsCredentialsProvider.html
|
||||
"software.amazon.awssdk.auth.credentials.",
|
||||
// Customer provides a fully-qualified provider name, or a custom credentials provider
|
||||
// (e.g., com.amazonaws.auth.ClasspathFileCredentialsProvider, org.mycompany.FooProvider)
|
||||
// (e.g., software.amazon.awssdk.auth.credentials.AwsCredentialsProvider)
|
||||
|
||||
// Sts auth provider
|
||||
"software.amazon.awssdk.services.sts.auth.",
|
||||
"")
|
||||
.map(prefix -> prefix + provider)
|
||||
.collect(Collectors.toList());
|
||||
|
|
@ -173,39 +181,18 @@ class AwsCredentialsProviderPropertyValueDecoder implements IPropertyValueDecode
|
|||
* @param providerName Raw, unmodified provider name. Should there be an
|
||||
* Exception during construction, this parameter will be logged.
|
||||
* @param constructor supplier-like function that will perform the construction
|
||||
* @param clazz the class to attempt to construct
|
||||
* @return the constructed provider, if successful; otherwise, null
|
||||
*
|
||||
* @param <T> type of the CredentialsProvider to construct
|
||||
*/
|
||||
private static <T extends AwsCredentialsProvider> T constructProvider(
|
||||
final String providerName,
|
||||
final CredentialsProviderConstructor<T> constructor,
|
||||
Class<? extends AwsCredentialsProvider> clazz) {
|
||||
final String providerName, final CredentialsProviderConstructor<T> constructor) {
|
||||
try {
|
||||
// Try to create an instance using the given constructor
|
||||
return constructor.construct();
|
||||
} catch (InstantiationException e) {
|
||||
try {
|
||||
// Try to create an instance using .create()
|
||||
Method createMethod = clazz.getDeclaredMethod("create");
|
||||
if (Modifier.isStatic(createMethod.getModifiers())) {
|
||||
Object provider = createMethod.invoke(null);
|
||||
if (provider instanceof AwsCredentialsProvider) {
|
||||
return (T) provider;
|
||||
} else {
|
||||
log.warn("Returned provider is not an instance of {}", AwsCredentialsProvider.class.getName());
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
log.warn("Found non-static create() method in {}", providerName);
|
||||
}
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e1) {
|
||||
log.warn("Exception thrown by create() method in {}", providerName, e1.getCause());
|
||||
}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
// ignore
|
||||
} catch (IllegalAccessException | InvocationTargetException | RuntimeException e) {
|
||||
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | RuntimeException e) {
|
||||
log.warn("Failed to construct {}", providerName, e);
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ applicationName = MultiLangTest
|
|||
# Users can change the credentials provider the KCL will use to retrieve credentials.
|
||||
# The DefaultAWSCredentialsProviderChain checks several other providers, which is
|
||||
# described here:
|
||||
# http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html
|
||||
# https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html
|
||||
AWSCredentialsProvider = DefaultCredentialsProvider
|
||||
|
||||
# Appended to the user agent of the KCL. Does not impact the functionality of the
|
||||
|
|
|
|||
|
|
@ -7,21 +7,22 @@ However, KCL now provides better extensibility to handle, and be enhanced to han
|
|||
This document should help multilang customers configure a suitable `CredentialProvider` (or contribute changes to support a new use case!).
|
||||
|
||||
## Sample Provider Configuration
|
||||
DEPRECATED: StsAssumeRoleCredentialsProvider can no longer be constructed in this way:
|
||||
```
|
||||
AWSCredentialsProvider = StsAssumeRoleCredentialsProvider|<arn>|<sessionName>`
|
||||
```
|
||||
|
||||
In a Properties file, an `AWSCredentialsProperty` configuration might look like:
|
||||
```
|
||||
AWSCredentialsProvider = STSAssumeRoleSessionCredentialsProvider|<arn>|<sessionName>
|
||||
```
|
||||
This basic configuration creates an [STSAssumeRoleSessionCredentialsProvider][sts-assume-provider] with an ARN and session name.
|
||||
While functional, this configuration is limited.
|
||||
For example, this configuration cannot set a regional endpoint (e.g., VPC use case).
|
||||
To create a [StsAssumeRoleCredentialsProvider][sts-assume-provider], see KclStsAssumeRoleCredentialsProvider below.
|
||||
|
||||
Leveraging nested properties, an `AWSCredentialsProperty` value might change to:
|
||||
You can create a default [DefaultCredentialsProvider][default-credentials-provider] or [AnonymousCredentialsProvider][anonymous-credentials-provider]
|
||||
by passing it in the config like:
|
||||
```
|
||||
AWSCredentialsProvider = KclSTSAssumeRoleSessionCredentialsProvider|<arn>|<sessionName>\
|
||||
|endpointRegion=us-east-1|externalId=spartacus
|
||||
AWSCredentialsProvider = DefaultCredentialsProvider
|
||||
```
|
||||
N.B. Backslash (`\`) is for multi-line legibility and is not required.
|
||||
|
||||
If you wish to customize properties on an AWS SDK provider that uses a builder, like the StsASsumeRoleCredentialsProvider,
|
||||
you will need to wrap this provider class, provide a constructor, and manage the build of the provider.
|
||||
See implementation of [KclStsAssumeRoleCredentialsProvider][kcl-sts-provider]
|
||||
|
||||
## Nested Properties
|
||||
|
||||
|
|
@ -36,9 +37,6 @@ The [Backus-Naur form][bnf] of the value:
|
|||
<nested-value ::= <string> # this depends on the nested key
|
||||
```
|
||||
|
||||
In general, required parameters are passed directly to the class' constructor
|
||||
(e.g., [STSAssumeRoleSessionCredentialsProvider(String, String)][sts-assume-provider-constructor]).
|
||||
|
||||
Nested properties are a custom mapping provided by KCL multilang, and do not exist in the AWS SDK.
|
||||
See [NestedPropertyKey][nested-property-key] for the supported keys, and details on their expected values.
|
||||
|
||||
|
|
@ -54,18 +52,26 @@ A backwards-compatible addition might look like:
|
|||
}
|
||||
```
|
||||
|
||||
### KclSTSAssumeRoleSessionCredentialsProvider
|
||||
|
||||
KCL multilang includes a [custom nested property processor for `STSAssumeRole`][kcl-sts-provider].
|
||||
Multilang configurations that use `STSAssumeRoleSessionCredentialsProvider` need only prefix `Kcl` to exercise this new provider:
|
||||
Leveraging nested properties, an `AWSCredentialsProperty` value might look like:
|
||||
```
|
||||
AWSCredentialsProvider = KclSTSAssumeRoleSessionCredentialsProvider|<arn>|<sessionName>
|
||||
AWSCredentialsProvider = KclSTSAssumeRoleSessionCredentialsProvider|<arn>|<sessionName>\
|
||||
|endpointRegion=us-east-1|externalId=spartacus
|
||||
```
|
||||
|
||||
N.B. Backslash (`\`) is for multi-line legibility and is not required.
|
||||
### KclStsAssumeRoleCredentialsProvider
|
||||
|
||||
KCL multilang includes a [custom nested property processor for `StsAssumeRole`][kcl-sts-provider].
|
||||
Multilang configurations that use `StsAssumeRoleSessionCredentialsProvider` need only prefix `Kcl` to exercise this new provider:
|
||||
```
|
||||
AWSCredentialsProvider = KclStsAssumeRoleCredentialsProvider|<arn>|<sessionName>
|
||||
```
|
||||
|
||||
[aws-credentials-provider]: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/AwsCredentialsProvider.html
|
||||
[bnf]: https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form
|
||||
[kcl-sts-provider]: /amazon-kinesis-client-multilang/src/main/java/software/amazon/kinesis/multilang/auth/KclSTSAssumeRoleSessionCredentialsProvider.java
|
||||
[kcl-sts-provider]: /amazon-kinesis-client-multilang/src/main/java/software/amazon/kinesis/multilang/auth/KclStsAssumeRoleCredentialsProvider.java
|
||||
[nested-property-key]: /amazon-kinesis-client-multilang/src/main/java/software/amazon/kinesis/multilang/NestedPropertyKey.java
|
||||
[nested-property-processor]: /amazon-kinesis-client-multilang/src/main/java/software/amazon/kinesis/multilang/NestedPropertyProcessor.java
|
||||
[sts-assume-provider]: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/STSAssumeRoleSessionCredentialsProvider.html
|
||||
[sts-assume-provider-constructor]: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/STSAssumeRoleSessionCredentialsProvider.html#STSAssumeRoleSessionCredentialsProvider-java.lang.String-java.lang.String-
|
||||
[sts-assume-provider]: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sts/auth/StsAssumeRoleCredentialsProvider.html
|
||||
[default-credentials-provider]: https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html
|
||||
[anonymous-credentials-provider]: https://sdk.amazonaws.com/java/api/2.0.0-preview-11/software/amazon/awssdk/auth/credentials/AnonymousCredentialsProvider.html
|
||||
|
|
|
|||
Loading…
Reference in a new issue