-
Notifications
You must be signed in to change notification settings - Fork 914
Merge credentials reloading feature branch to mainline #3712
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
Conversation
…les change (#3487) * ProfileFile can update if disk changed, reload as new instance * ProfileCredentialsProvider reloads credentials if profile file has changes * Created class ProfileFileRefresher * Created ReloadingProfileCredentialsProvider; moved new logic in ProfileFile to ProfileFileRefresher * Fix ReloadingProfileCredentialsBehavior when missing ProfileFile Supplier or Predicate, and dealing with defaults * Consolidated ReloadingProfileCredentialsProvider functionality into ProfileCredentialsProvider * Fix behavior when dealing with defaults * Created ProfileFileSupplier interface; refactored * Misc fixes * Created package-private ProfileFileSupplierBuilder; ProfileFileSupplier now extends Supplier; Fixed Javadoc * Fixed unit tests for default credentials file * Removed ProfileFileSupplier.Builder interface * Code cleanup
* Added methods for aggregating ProfileFile objects * Removed redundant logic, changelog entry * Removed redundant methods * Use compare and set to make thread safe
* Misc fixes * Reload credentials by DefaultCredentialsProvider; pass supplier to InstanceProfileCredentialsProvider * Fix code alignment
* Updated ProfileTokenProvider * Updated tests, do not explicitly swallow exceptions * ProfileTokenProviderLoader can use Supplier<Profilefile> internally * Simplified ProfileTokenProviderLoader API; implemented synchronized block
* S3 support classes take Supplier<ProfileFile> * Review comments
* Presigners, other Support classes take Supplier<ProfileFile> * Split new ProfileFile tests from existing parameterized tests * Improved tests readability
#3692) * Leverage SdkClientOption and SdkExecutionAttributes; fallback to simple ProfileFile * Addressed review comments
if (profileFile instanceof SdkAutoCloseable) { | ||
((SdkAutoCloseable) profileFile).close(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a red flag to me: closing something we didn't necessarily create. What if this is being used by someone else and we just closed it/broke it?
My bigger question is: why are profile file suppliers closeable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A problem indeed. I even brought this up during a discussion, so I'm not sure why I didn't remove it.
Re: closeable suppliers--it's only because the specific implementation with reloadWhenModified
uses ProfileFileRefresher
internally, which in turn uses CachedSupplier
being AutoCloseable
.
This is also something you did touch upon in another comment.
= ProfileFileLocation.configurationFileLocation() | ||
.map(path -> reloadWhenModified(path, ProfileFile.Type.CONFIGURATION)); | ||
|
||
ProfileFileSupplier supplier = () -> null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we return an empty file instead of null? Or do we handle null everywhere that we handle profile files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty file indeed. Changed.
aggregator.addFile(supplier.get()); | ||
} | ||
|
||
return refreshAndGetCurrentAggregate(aggregator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to re-aggregate with every profile file get()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that if an aggregate file is made up of N subfiles, then whenever we call get() we need to look at the new contents of the individual files. The need to reaggregate is to determine if the new contents are different from the current aggregate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, yeah if we can avoid re-aggregating when the files haven't changed that's a good fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reimplemented previous code that was looking at whether the individual files had changes. With this new version, we should not re-aggregate if not needed.
import software.amazon.awssdk.profiles.internal.ProfileFileRefresher; | ||
|
||
@SdkInternalApi | ||
final class ProfileFileSupplierBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anything use this class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only a test class. Mainly for the clock()
method making it easier to setup tests involving timing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, I searched this CR to see if things were using it and I must have missed something using it.
|
||
@Override | ||
public void close() { | ||
profileFileCache.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only need to close the cached supplier when it is async. I think it's fine to exclude this close for now so that we don't have to deal with managing the lifecycle of a profile file supplier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
this.profileFileCache = CachedSupplier.builder(this::refreshResult) | ||
.clock(this.clock) | ||
.build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like we're actually using the cached supplier here for any of its caching functionality, just as a proxy for calling refreshResult. Do we actually need it, or can we rewrite this to not require it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. We can probably discuss this offline, but yes, the original intent of CachedSupplier
was to abstract away managing individually the profile files. I may have chipped too much off and now it doesn't really make sense to use it.
One benefit of still using the cached supplier, if I understand correctly is to avoid refreshing a value when the request occurs within a timeframe (jitter time), which in this case means not hitting the disk excessively in a short amount of time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I didn't think of that benefit. I think excluding jittering for local resources isn't a major risk. The failure mode is pretty different than a remote resource where jittering becomes important.
Instant now = clock.instant(); | ||
Instant staleTime = now; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have two variables for the same value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was being too verbose. Remove this and other instance.
} catch (RuntimeException exception) { | ||
Instant now = Instant.now(); | ||
Instant staleTime = now; | ||
ProfileFile exceptionProfileFile = exceptionHandler.apply(exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we not just throw the exception? What's the purpose of an exception profile file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was copying CachedTokenRefresher
. I guess we could recover from an exception and provide a fallback profile file, maybe the default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I was thinking the intuitive behavior would just be to throw the exception (failing whatever profile file refresh is happening) and then let the next get() call try again. Essentially, push the failure handling upstream.
Trying to do something more intelligent might be confusing for the user to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed this may be too complex. Removed.
60e3eae
to
adac974
Compare
SonarCloud Quality Gate failed.
|
…59e84a727 Pull request: release <- staging/0065af7f-0a1b-4ce9-b143-81d59e84a727
Motivation and Context
Add support for reloading credentials provided by
ProfileCredentialsProvider
if file changes on disk.In addition, propagate changes to other classes with similar behavior: such as
DefaultCredentialsProvider
,InstanceProfileCredentialsProvider
andProfileTokenProvider
.Finally, some service classes also implemented this functionality so that configuration options might be changed on the fly.
Modifications
Multiple PRs
Testing
Added new test cases
Will run integ tests
Screenshots (if appropriate)
Types of changes
Checklist
mvn install
succeedsscripts/new-change
script and following the instructions. Commit the new file created by the script in.changes/next-release
with your changes.License