Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiLang AWS SDK v1 to v2 #1

Merged
merged 16 commits into from
Sep 4, 2024
Merged

Conversation

ethkatnic
Copy link
Owner

No description provided.

@ethkatnic ethkatnic changed the title Aws sdk v1 to v2 MultiLang AWS SDK v1 to v2 Aug 21, 2024
return constructor.construct();
} catch (InstantiationException e) {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sloppy and needs a second look. The issue here is that we relied on this provider constructor to create any provider class that is passed to this function.

However, in our tests, we use software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider. This used to be invoked like new DefaultCredentialsProvider but now is constructed with DefaultCredentialsProvider.create() - https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-client-credentials.html

I tried to generalize this to work with both, but its quite sloppy.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we just want v2 support now and the v2 credential providers are either created using create or builder do we still need this check?

Copy link
Owner Author

@ethkatnic ethkatnic Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users can still create classes that implement the v2 AwsCredentialsProvider that use a default constructor clazz::newInstance instead of a builder/create.

For instance, we create a basic AwsCredentialsProvider that relies on a default constructor in our testing.

Since this is still a valid way to create v2 providers, I think this code should support both a .create() method and a constructor method of instantiating providers.

Copy link
Owner Author

@ethkatnic ethkatnic Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing to consider is that we currently support passing args to default constructors through the config like ConstructorCredentialsProvider|arg1|arg2 . This eventually calls a constructor like provider = ConstructorCredentialsProvider(arg1, arg2), allowing the user to pass in a provider string with constructor args. This still works as expected for classes with public static constructors.

I don't think this is possible for the providers that require builders, though. For instance, if a user wanted to create a DefaultCredentialsProvider with profileName = "test-profile" like DefaultCredentialsProvider.builder().profileName("Test").build(), the code currently doesn't support this.

In this version of the code DefaultCredentialsProvider|test-profile, we would try and fail to call a new instance like DefaultCredentialsProvider("test-profile"), and so it would invoke DefaultCredentialsProvider.create() to create a default instance of the class.

So currently, that .create() block is just to create a default builder instance if there's no basic constructor.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should come up with a way that's easy for customer to use the default credential providers without having to peek into the multilang code or documentation to pick the providers. Let's iterate on this

@ethkatnic ethkatnic self-assigned this Aug 22, 2024
Comment on lines 102 to 109
provider = constructProvider(
providerName,
() -> {
Class<?>[] argTypes = new Class<?>[nameAndArgs.length - 1];
Arrays.fill(argTypes, String.class);
return clazz.getConstructor(argTypes).newInstance(varargs);
},
clazz);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new V2 providers are constructed using builders correct? Are they able use the same constructing logic as v1?

Copy link
Owner Author

@ethkatnic ethkatnic Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New providers are constructed with builders / a create() call to build a generic instance, old providers were created with simple constructors.
Screenshot 2024-08-27 at 9 17 00 AM
Screenshot 2024-08-27 at 9 17 07 AM

To build the old providers generically, we used clazz::newInstance. This will fail for the v2 versions and throw a InstantiationException. To build the new providers generically, my only idea was to catch this InstantiationException and try something like

Method createMethod = clazz.getDeclaredMethod("create");
Object provider = createMethod.invoke(null);

This makes things a bit complicated, as we are trying to generically build these classes in 2 different ways in one function.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified this a bit. Now added an additional attempt to construct create() without touching constructProvider().

@ethkatnic ethkatnic changed the base branch from master to 3.0 August 28, 2024 18:13
return constructor.construct();
} catch (InstantiationException e) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we just want v2 support now and the v2 credential providers are either created using create or builder do we still need this check?

import software.amazon.kinesis.multilang.NestedPropertyKey;
import software.amazon.kinesis.multilang.NestedPropertyProcessor;

public class KclStsAssumeRoleCredentialsProvider implements AwsCredentialsProvider, NestedPropertyProcessor {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker for this PR - This class is an extension of the StsProvider. I feel like the users should not have to pick between the normal stsProvider and KCLstsProvider if they want to add extra fields like externalId etc... We can direct all construction of stsProvider to this class internally so users can use all of its feature by declaring the generic stsProvider in the property file.

I think this is especially important for sdk v2 because credential providers don't provide constructors anymore and this stsProvider doesn't have a create() method either meaning that we will need to rely on this class to build stsProvider

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agreed. The old docs described creating an STSAssumeRoleSessionCredentialsProvider from the config, which relied on a deprecated constructor for the STSAssumeRoleSessionCredentialsProvider.

As you said, this is no longer possible because the v2 StsAssumeRoleCredentialsProvider requires a builder, so we can't use a simple constructor. In that way, we are forcing users to use the KclStsAssumeRoleCredentialsProvider as I mentioned in the documentation changes.

@@ -113,6 +117,20 @@ private static List<AWSCredentialsProvider> getValidCredentialsProviders(List<St
provider = constructProvider(providerName, clazz::newInstance);
}

if (provider == null) {
// if still not found, try empty create() method

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could try passing in all the args that are in the property file to the create() method? This provides more flexibility and It might not create the expected credential provider if not taking the extra args anyway. But let's see what solution we decide to use for builder based credential providers and we can iterate on it

return constructor.construct();
} catch (InstantiationException e) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should come up with a way that's easy for customer to use the default credential providers without having to peek into the multilang code or documentation to pick the providers. Let's iterate on this

@ethkatnic ethkatnic marked this pull request as ready for review August 30, 2024 18:21
@ethkatnic ethkatnic merged commit 42a7768 into multilang-sdk-upgrade Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants