From 56cf12d23923b42f1ad0ee6a3cc735d993d9e017 Mon Sep 17 00:00:00 2001 From: Angad Misra Date: Fri, 16 May 2025 12:14:26 -0700 Subject: [PATCH 1/5] chore: add Spotless and Prettier action, format files --- .github/ISSUE_TEMPLATE/bug_report.md | 8 +- .github/ISSUE_TEMPLATE/feature_request.md | 7 +- .github/PULL_REQUEST_TEMPLATE.md | 5 +- .github/workflows/codeql-analysis.yml | 61 +++--- .github/workflows/maven.yml | 46 +++-- CODE_OF_CONDUCT.md | 5 +- CONTRIBUTING.md | 45 +++-- README.md | 11 +- pom.xml | 16 +- .../secretsmanager/caching/SecretCache.java | 25 ++- .../caching/SecretCacheConfiguration.java | 14 +- .../caching/SecretCacheHook.java | 4 +- .../caching/cache/LRUCache.java | 3 +- .../caching/cache/SecretCacheItem.java | 45 +++-- .../caching/cache/SecretCacheObject.java | 31 +-- .../caching/cache/SecretCacheVersion.java | 24 +-- .../caching/cache/internal/VersionInfo.java | 9 +- .../caching/SecretCacheTest.java | 177 ++++++++++-------- .../caching/cache/LRUCacheTest.java | 4 +- .../caching/internal/VersionInfoTest.java | 4 +- 20 files changed, 300 insertions(+), 244 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 98ad086..20fd77d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,17 +1,17 @@ --- name: Bug report about: Create a report to help us improve -title: '' +title: "" labels: bug -assignees: '' - +assignees: "" --- **Describe the bug** **To Reproduce** Steps to reproduce: -1. + +1. **Expected behavior** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 809b7b0..60f49e9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,10 +1,7 @@ --- name: Feature request about: Suggest an idea for this project -title: '' +title: "" labels: enhancement -assignees: '' - +assignees: "" --- - - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ab40d21..3bfff59 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,5 @@ -*Issue #, if available:* - -*Description of changes:* +_Issue #, if available:_ +_Description of changes:_ By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5726a28..a006bf7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,12 +13,12 @@ name: "CodeQL" on: push: - branches: [ "master", "v2" ] + branches: ["master", "v2"] pull_request: # The branches below must be a subset of the branches above - branches: [ "master", "v2" ] + branches: ["master", "v2"] schedule: - - cron: '17 12 * * 1' + - cron: "17 12 * * 1" jobs: analyze: @@ -30,41 +30,40 @@ jobs: strategy: fail-fast: true matrix: - language: [ 'java' ] + language: ["java"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9c6bb8e..85aa099 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,27 +4,39 @@ name: Java CI with Maven on: - push: - branches: [ "master", "v2" ] pull_request: - branches: [ "master", "v2" ] + branches: [master, v2] jobs: build: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'corretto' - cache: maven - - name: Maven version - run: mvn --version - - name: Build with Maven - run: mvn clean package - - name: Codecov - uses: codecov/codecov-action@v5.4.0 + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: corretto + cache: mave + + - name: Prettier + uses: rutajdash/prettier-cli-action@v1.0.2 + with: + file_pattern: "**/*.{md,yml}" + + - name: Check formatting + run: mvn spotless:check + + - name: Maven version + run: mvn --version + + - name: Build with Maven + run: mvn clean package + + - name: Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 3b64466..ec98f2b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,5 @@ ## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact + +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com with any additional questions or comments. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 560cb61..962b701 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,29 +1,28 @@ # Contributing Guidelines -Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional +Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from our community. -Please read through this document before submitting any issues or pull requests to ensure we have all the necessary +Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. - ## Reporting Bugs/Feature Requests We welcome you to use the GitHub issue tracker to report bugs or suggest features. -When filing an issue, please check [existing open](https://github.com/aws/aws-secretsmanager-caching-java/issues), or [recently closed](https://github.com/aws/aws-secretsmanager-caching-java/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already +When filing an issue, please check [existing open](https://github.com/aws/aws-secretsmanager-caching-java/issues), or [recently closed](https://github.com/aws/aws-secretsmanager-caching-java/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: -* A reproducible test case or series of steps -* The version of our code being used -* Any modifications you've made relevant to the bug -* Anything unusual about your environment or deployment - +- A reproducible test case or series of steps +- The version of our code being used +- Any modifications you've made relevant to the bug +- Anything unusual about your environment or deployment ## Contributing via Pull Requests + Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: -1. You are working against the latest source on the *master* branch. +1. You are working against the latest source on the _master_ branch. 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. @@ -31,28 +30,34 @@ To send us a pull request, please: 1. Fork the repository. 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -3. Ensure local tests pass. -4. Commit to your fork using clear commit messages. -5. Send us a pull request, answering any default questions in the pull request interface. -6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. +3. Use Spotless to ensure consistent formatting for `.java` files, and Prettier for `.md` and `.yml` files (see [Formatting instructions](#formatting-instructions)). +4. Ensure local tests pass. +5. Commit to your fork using clear commit messages. +6. Send us a pull request, answering any default questions in the pull request interface. +7. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. -GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). +# Formatting instructions + +- Install [Prettier](https://prettier.io/docs/install). + - If using VS Code, install the VS Code extension for the above. +- Run `mvn spotless:apply` and `prettier --write **/*.{md,yml}`. ## Finding contributions to work on -Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/aws-secretsmanager-caching-java/labels/help%20wanted) issues is a great place to start. +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/aws-secretsmanager-caching-java/labels/help%20wanted) issues is a great place to start. ## Code of Conduct -This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). -For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact -opensource-codeofconduct@amazon.com with any additional questions or comments. +This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). +For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact +opensource-codeofconduct@amazon.com with any additional questions or comments. ## Security issue notifications -If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. +If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. ## Licensing diff --git a/README.md b/README.md index 03745d9..b74f66c 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,20 @@ The AWS Secrets Manager Java caching client enables in-process caching of secret ## Getting Started ### Required Prerequisites + To use this client you must have: -* **A Java 8 development environment** +- **A Java 8 development environment** If you do not have one, go to [Java SE Downloads](https://www.oracle.com/technetwork/java/javase/downloads/index.html) on the Oracle website, then download and install the Java SE Development Kit (JDK). Java 8 or higher is recommended. An Amazon Web Services (AWS) account to access secrets stored in AWS Secrets Manager and use AWS SDK for Java. -* **To create an AWS account**, go to [Sign In or Create an AWS Account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) and then choose **I am a new user.** Follow the instructions to create an AWS account. +- **To create an AWS account**, go to [Sign In or Create an AWS Account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) and then choose **I am a new user.** Follow the instructions to create an AWS account. -* **To create a secret in AWS Secrets Manager**, go to [Creating Secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html) and follow the instructions on that page. +- **To create a secret in AWS Secrets Manager**, go to [Creating Secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html) and follow the instructions on that page. -* **To download and install the AWS SDK for Java**, go to [Installing the AWS SDK for Java](https://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-install-sdk.html) in the AWS SDK for Java documentation and then follow the instructions on that page. +- **To download and install the AWS SDK for Java**, go to [Installing the AWS SDK for Java](https://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/java-dg-install-sdk.html) in the AWS SDK for Java documentation and then follow the instructions on that page. ### Download @@ -90,4 +91,4 @@ public class SampleClass implements RequestHandler { ## License -This library is licensed under the Apache 2.0 License. +This library is licensed under the Apache 2.0 License. diff --git a/pom.xml b/pom.xml index d6479d9..47dcdf5 100644 --- a/pom.xml +++ b/pom.xml @@ -189,6 +189,20 @@ @{argLine} -javaagent:${org.mockito:mockito-core:jar} + + com.diffplug.spotless + spotless-maven-plugin + 2.44.4 + + + + + 2.39.0 + + + + + @@ -224,4 +238,4 @@ - \ No newline at end of file + diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java index d0c2672..e9c5c15 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCache.java @@ -12,12 +12,10 @@ */ package com.amazonaws.secretsmanager.caching; -import java.nio.ByteBuffer; - import com.amazonaws.secretsmanager.caching.cache.LRUCache; import com.amazonaws.secretsmanager.caching.cache.SecretCacheItem; import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; - +import java.nio.ByteBuffer; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; @@ -70,12 +68,11 @@ public SecretCache() { * client. */ public SecretCache(SecretsManagerClientBuilder builder) { - this(new SecretCacheConfiguration().withClient(builder - .overrideConfiguration( - builder.overrideConfiguration().toBuilder() + this(new SecretCacheConfiguration() + .withClient(builder.overrideConfiguration(builder.overrideConfiguration().toBuilder() .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, VersionInfo.USER_AGENT) .build()) - .build())); + .build())); } /** @@ -100,9 +97,13 @@ public SecretCache(SecretCacheConfiguration config) { this.cache = new LRUCache(config.getMaxCacheSize()); this.config = config; ClientOverrideConfiguration defaultOverride = ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, VersionInfo.USER_AGENT).build(); - this.client = config.getClient() != null ? config.getClient() - : SecretsManagerClient.builder().overrideConfiguration(defaultOverride).build(); + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, VersionInfo.USER_AGENT) + .build(); + this.client = config.getClient() != null + ? config.getClient() + : SecretsManagerClient.builder() + .overrideConfiguration(defaultOverride) + .build(); } /** @@ -114,8 +115,7 @@ public SecretCache(SecretCacheConfiguration config) { private SecretCacheItem getCachedSecret(final String secretId) { SecretCacheItem secret = this.cache.get(secretId); if (null == secret) { - this.cache.putIfAbsent(secretId, - new SecretCacheItem(secretId, this.client, this.config)); + this.cache.putIfAbsent(secretId, new SecretCacheItem(secretId, this.client, this.config)); secret = this.cache.get(secretId); } return secret; @@ -171,5 +171,4 @@ public boolean refreshNow(final String secretId) throws InterruptedException { public void close() { this.cache.clear(); } - } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java index 744ebbd..c0833ac 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java @@ -13,12 +13,10 @@ package com.amazonaws.secretsmanager.caching; -import java.util.concurrent.TimeUnit; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.concurrent.TimeUnit; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; - /** * Cache configuration options such as max cache size, ttl for cached items, etc. * @@ -34,7 +32,7 @@ public class SecretCacheConfiguration { /** The default version stage to use when retrieving secret values. */ public static final String DEFAULT_VERSION_STAGE = "AWSCURRENT"; - /** + /** * The default maximum jitter value in milliseconds to use when forcing a refresh. * This prevents continuous refreshNow() calls by adding a random sleep. */ @@ -77,8 +75,7 @@ public class SecretCacheConfiguration { * Default constructor for the SecretCacheConfiguration object. * */ - public SecretCacheConfiguration() { - } + public SecretCacheConfiguration() {} /** * Returns the AWS Secrets Manager client that is used for requesting secret values. @@ -90,7 +87,6 @@ public SecretsManagerClient getClient() { return client; } - /** * Sets the AWS Secrets Manager client that should be used by the cache for requesting * secrets. @@ -116,7 +112,6 @@ public SecretCacheConfiguration withClient(SecretsManagerClient client) { return this; } - /** * Returns the interface used to hook in-memory cache updates. * @@ -127,7 +122,6 @@ public SecretCacheHook getCacheHook() { return cacheHook; } - /** * Sets the interface used to hook the in-memory cache. * @@ -139,7 +133,6 @@ public void setCacheHook(SecretCacheHook cacheHook) { this.cacheHook = cacheHook; } - /** * Sets the interface used to hook the in-memory cache. * @@ -152,7 +145,6 @@ public SecretCacheConfiguration withCacheHook(SecretCacheHook cacheHook) { return this; } - /** * Returns the max cache size that should be used for creating the cache. * diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheHook.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheHook.java index e347e1d..85e6ed0 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheHook.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheHook.java @@ -19,7 +19,7 @@ * cache. One example would be encrypting/decrypting items stored in the * in-memory cache. */ -public interface SecretCacheHook{ +public interface SecretCacheHook { /** * Prepare the object for storing in the cache * @@ -35,4 +35,4 @@ public interface SecretCacheHook{ * @return The object that should be returned from the cache */ Object get(final Object cachedObject); -} \ No newline at end of file +} diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/LRUCache.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/LRUCache.java index 2102a42..ef8856b 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/LRUCache.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/LRUCache.java @@ -13,8 +13,8 @@ package com.amazonaws.secretsmanager.caching.cache; -import java.util.Map; import java.util.LinkedHashMap; +import java.util.Map; /** * An LRU cache based on the Java LinkedHashMap. @@ -201,5 +201,4 @@ public void clear() { map.clear(); } } - } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java index 9c0ed78..2594722 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheItem.java @@ -13,12 +13,10 @@ package com.amazonaws.secretsmanager.caching.cache; +import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; - -import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; - import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest; import software.amazon.awssdk.services.secretsmanager.model.DescribeSecretResponse; @@ -52,16 +50,15 @@ public class SecretCacheItem extends SecretCacheObject { * @param config * Cache configuration. */ - public SecretCacheItem(final String secretId, - final SecretsManagerClient client, - final SecretCacheConfiguration config) { + public SecretCacheItem( + final String secretId, final SecretsManagerClient client, final SecretCacheConfiguration config) { super(secretId, client, config); } @Override public boolean equals(Object obj) { if (obj instanceof SecretCacheItem) { - return Objects.equals(this.secretId, ((SecretCacheItem)obj).secretId); + return Objects.equals(this.secretId, ((SecretCacheItem) obj).secretId); } return false; } @@ -85,8 +82,12 @@ public String toString() { */ @Override protected boolean isRefreshNeeded() { - if (super.isRefreshNeeded()) { return true; } - if (null != this.exception) { return false; } + if (super.isRefreshNeeded()) { + return true; + } + if (null != this.exception) { + return false; + } if (System.currentTimeMillis() >= this.nextRefreshTime) { return true; } @@ -100,10 +101,11 @@ protected boolean isRefreshNeeded() { */ @Override protected DescribeSecretResponse executeRefresh() { - DescribeSecretResponse describeSecretResponse = client.describeSecret(DescribeSecretRequest.builder().secretId(this.secretId).build()); + DescribeSecretResponse describeSecretResponse = client.describeSecret( + DescribeSecretRequest.builder().secretId(this.secretId).build()); long ttl = this.config.getCacheItemTTL(); - this.nextRefreshTime = System.currentTimeMillis() + - ThreadLocalRandom.current().nextLong(ttl / 2,ttl + 1) ; + this.nextRefreshTime = + System.currentTimeMillis() + ThreadLocalRandom.current().nextLong(ttl / 2, ttl + 1); return describeSecretResponse; } @@ -116,10 +118,13 @@ protected DescribeSecretResponse executeRefresh() { * @return The cached secret version. */ private SecretCacheVersion getVersion(DescribeSecretResponse describeResponse) { - if (null == describeResponse) { return null; } - if (null == describeResponse.versionIdsToStages()) { return null; } - Optional currentVersionId = describeResponse.versionIdsToStages().entrySet() - .stream() + if (null == describeResponse) { + return null; + } + if (null == describeResponse.versionIdsToStages()) { + return null; + } + Optional currentVersionId = describeResponse.versionIdsToStages().entrySet().stream() .filter(Objects::nonNull) .filter(x -> x.getValue() != null) .filter(x -> x.getValue().contains(this.config.getVersionStage())) @@ -128,7 +133,8 @@ private SecretCacheVersion getVersion(DescribeSecretResponse describeResponse) { if (currentVersionId.isPresent()) { SecretCacheVersion version = versions.get(currentVersionId.get()); if (null == version) { - versions.putIfAbsent(currentVersionId.get(), + versions.putIfAbsent( + currentVersionId.get(), new SecretCacheVersion(this.secretId, currentVersionId.get(), this.client, this.config)); version = versions.get(currentVersionId.get()); } @@ -147,8 +153,9 @@ private SecretCacheVersion getVersion(DescribeSecretResponse describeResponse) { @Override protected GetSecretValueResponse getSecretValue(DescribeSecretResponse describeResponse) { SecretCacheVersion version = getVersion(describeResponse); - if (null == version) { return null; } + if (null == version) { + return null; + } return version.getSecretValue(); } - } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java index 3d626c4..181f384 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java @@ -13,10 +13,9 @@ package com.amazonaws.secretsmanager.caching.cache; -import java.util.concurrent.ThreadLocalRandom; - import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.concurrent.ThreadLocalRandom; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; @@ -86,9 +85,8 @@ public abstract class SecretCacheObject { * The secret cache configuration. */ @SuppressFBWarnings(value = "EI_EXPOSE_REP2") - public SecretCacheObject(final String secretId, - final SecretsManagerClient client, - final SecretCacheConfiguration config) { + public SecretCacheObject( + final String secretId, final SecretsManagerClient client, final SecretCacheConfiguration config) { this.secretId = secretId; this.client = client; this.config = config; @@ -112,7 +110,9 @@ public SecretCacheObject(final String secretId, protected abstract GetSecretValueResponse getSecretValue(T result); public abstract boolean equals(Object obj); + public abstract int hashCode(); + public abstract String toString(); /** @@ -123,9 +123,9 @@ public SecretCacheObject(final String secretId, @SuppressWarnings("unchecked") private T getResult() { if (null != this.config.getCacheHook()) { - return (T)this.config.getCacheHook().get(this.data); + return (T) this.config.getCacheHook().get(this.data); } - return (T)this.data; + return (T) this.data; } /** @@ -145,7 +145,9 @@ private void setResult(T result) { * @return True if the secret item should be refreshed. */ protected boolean isRefreshNeeded() { - if (this.refreshNeeded) { return true; } + if (this.refreshNeeded) { + return true; + } if (null != this.exception) { // If we encountered an exception on the last attempt // we do not want to keep retrying without a pause between @@ -167,7 +169,9 @@ protected boolean isRefreshNeeded() { * Refresh the cached secret state only when needed. */ private void refresh() { - if (!this.isRefreshNeeded()) { return; } + if (!this.isRefreshNeeded()) { + return; + } this.refreshNeeded = false; try { this.setResult(this.executeRefresh()); @@ -179,13 +183,13 @@ private void refresh() { // factor and default backoff duration. Long growth = 1L; if (this.exceptionBackoffPower > 0) { - growth = (long)Math.pow(EXCEPTION_BACKOFF_GROWTH_FACTOR, this.exceptionBackoffPower); + growth = (long) Math.pow(EXCEPTION_BACKOFF_GROWTH_FACTOR, this.exceptionBackoffPower); } growth *= EXCEPTION_BACKOFF; // Add in EXCEPTION_BACKOFF time to make sure the random jitter will not reduce // the wait time too low. Long retryWait = Math.min(EXCEPTION_BACKOFF + growth, BACKOFF_PLATEAU); - if ( retryWait < BACKOFF_PLATEAU ) { + if (retryWait < BACKOFF_PLATEAU) { // Only increase the backoff power if we haven't hit the backoff plateau yet. this.exceptionBackoffPower += 1; } @@ -239,11 +243,12 @@ public GetSecretValueResponse getSecretValue() { synchronized (lock) { refresh(); if (null == this.data) { - if (null != this.exception) { throw this.exception; } + if (null != this.exception) { + throw this.exception; + } } return this.getSecretValue(this.getResult()); } } - } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java index ec98dbf..f47fc25 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheVersion.java @@ -13,10 +13,8 @@ package com.amazonaws.secretsmanager.caching.cache; -import java.util.Objects; - import com.amazonaws.secretsmanager.caching.SecretCacheConfiguration; - +import java.util.Objects; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; @@ -47,10 +45,11 @@ public class SecretCacheVersion extends SecretCacheObject> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder() + .secretString(secret) .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); getSecretValueResponse = resBuilder.build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); @@ -130,8 +131,7 @@ public void basicSecretCacheTest() { Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); - repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), - ByteBuffer.wrap(secret.getBytes()))); + repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); sc.close(); } @@ -142,12 +142,15 @@ public void hookSecretCacheTest() { versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder() + .secretString(secret) .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); getSecretValueResponse = resBuilder.build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); class Hook implements SecretCacheHook { private HashMap map = new HashMap(); @@ -166,9 +169,8 @@ public int getCount() { } } Hook hook = new Hook(); - SecretCache sc = new SecretCache(new SecretCacheConfiguration() - .withClient(asm) - .withCacheHook(hook)); + SecretCache sc = + new SecretCache(new SecretCacheConfiguration().withClient(asm).withCacheHook(hook)); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); @@ -177,8 +179,7 @@ public int getCount() { Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); - repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), - ByteBuffer.wrap(secret.getBytes()))); + repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); Assert.assertEquals(hook.getCount(), 2); sc.close(); } @@ -189,12 +190,16 @@ public void secretCacheNullStagesTest() { Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) - .secretBinary(SdkBytes.fromByteArray(secret.getBytes())).versionStages((Collection) null); + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder() + .secretString(secret) + .secretBinary(SdkBytes.fromByteArray(secret.getBytes())) + .versionStages((Collection) null); getSecretValueResponse = resBuilder.build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result @@ -204,8 +209,7 @@ public void secretCacheNullStagesTest() { Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); Mockito.verify(asm, Mockito.times(1)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); - repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), - ByteBuffer.wrap(secret.getBytes()))); + repeat(10, n -> Assert.assertEquals(sc.getSecretBinary(""), ByteBuffer.wrap(secret.getBytes()))); sc.close(); } @@ -216,12 +220,15 @@ public void basicSecretCacheRefreshNowTest() throws Throwable { versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder().secretString(secret) + GetSecretValueResponse.Builder resBuilder = GetSecretValueResponse.builder() + .secretString(secret) .secretBinary(SdkBytes.fromByteArray(secret.getBytes())); getSecretValueResponse = resBuilder.build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result @@ -251,16 +258,22 @@ public void basicSecretCacheByteBufferTest() { versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - GetSecretValueResponse diff = GetSecretValueResponse.builder().secretBinary(SdkBytes.fromByteBuffer(buffer)) + GetSecretValueResponse diff = GetSecretValueResponse.builder() + .secretBinary(SdkBytes.fromByteBuffer(buffer)) .build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(diff); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(diff); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result - repeat(10, n -> Assert.assertEquals(StandardCharsets.UTF_8.decode(sc.getSecretBinary("")).toString(), secret)); + repeat( + 10, + n -> Assert.assertEquals( + StandardCharsets.UTF_8.decode(sc.getSecretBinary("")).toString(), secret)); // Verify that multiple requests did not call the API Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); @@ -277,31 +290,36 @@ public void basicSecretCacheMultipleTest() { Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - getSecretValueResponse = GetSecretValueResponse.builder().secretString(secretA).build(); + getSecretValueResponse = + GetSecretValueResponse.builder().secretString(secretA).build(); - GetSecretValueResponse res2 = GetSecretValueResponse.builder().secretString(secretB).build(); + GetSecretValueResponse res2 = + GetSecretValueResponse.builder().secretString(secretB).build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); Mockito.when(asm.getSecretValue(ArgumentMatchers.argThat(new ArgumentMatcher() { - @Override - public boolean matches(GetSecretValueRequest argument) { - if (argument == null) { - return false; - } - return argument.secretId().equals("SecretA"); - } - }))).thenReturn(getSecretValueResponse); + @Override + public boolean matches(GetSecretValueRequest argument) { + if (argument == null) { + return false; + } + return argument.secretId().equals("SecretA"); + } + }))) + .thenReturn(getSecretValueResponse); Mockito.when(asm.getSecretValue(ArgumentMatchers.argThat(new ArgumentMatcher() { - @Override - public boolean matches(GetSecretValueRequest argument) { - if (argument == null) { - return false; - } - return argument.secretId().equals("SecretB"); - } - }))).thenReturn(res2); + @Override + public boolean matches(GetSecretValueRequest argument) { + if (argument == null) { + return false; + } + return argument.secretId().equals("SecretB"); + } + }))) + .thenReturn(res2); SecretCache sc = new SecretCache(asm); @@ -321,14 +339,16 @@ public void basicSecretCacheRefreshTest() throws Throwable { Map> versionMap = new HashMap>(); versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + getSecretValueResponse = + GetSecretValueResponse.builder().secretString(secret).build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); - SecretCache sc = new SecretCache(new SecretCacheConfiguration() - .withClient(asm) - .withCacheItemTTL(500)); + SecretCache sc = + new SecretCache(new SecretCacheConfiguration().withClient(asm).withCacheItemTTL(500)); // Request the secret multiple times and verify the correct result repeat(10, n -> Assert.assertEquals(sc.getSecretString(""), secret)); @@ -352,13 +372,15 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { versionMap.put("versionId", Arrays.asList("AWSCURRENT")); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + getSecretValueResponse = + GetSecretValueResponse.builder().secretString(secret).build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); - SecretCache sc = new SecretCache(new SecretCacheConfiguration() - .withClient(asm) - .withCacheItemTTL(500)); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); + SecretCache sc = + new SecretCache(new SecretCacheConfiguration().withClient(asm).withCacheItemTTL(500)); // Request the secret multiple times and verify the correct result repeat(5, n -> Assert.assertEquals(sc.getSecretString(""), secret)); @@ -382,10 +404,13 @@ public void secretCacheRefreshAfterVersionChangeTest() throws Throwable { public void basicSecretCacheTestNoVersions() { final String secret = "basicSecretCacheTestNoVersion"; - getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + getSecretValueResponse = + GetSecretValueResponse.builder().secretString(secret).build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result @@ -398,9 +423,10 @@ public void basicSecretCacheTestNoVersions() { sc.close(); } - @Test(expectedExceptions = { RuntimeException.class }) + @Test(expectedExceptions = {RuntimeException.class}) public void basicSecretCacheExceptionTest() { - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); sc.getSecretString(""); sc.close(); @@ -408,7 +434,8 @@ public void basicSecretCacheExceptionTest() { @Test public void basicSecretCacheExceptionRefreshNowTest() throws Throwable { - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); Assert.assertFalse(sc.refreshNow("")); Mockito.verify(asm, Mockito.times(1)).describeSecret(Mockito.any(DescribeSecretRequest.class)); @@ -420,7 +447,8 @@ public void basicSecretCacheExceptionRefreshNowTest() throws Throwable { @Test public void basicSecretCacheExceptionRetryTest() throws Throwable { final int retryCount = 10; - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenThrow(new RuntimeException()); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenThrow(new RuntimeException()); SecretCache sc = new SecretCache(asm); for (int n = 0; n < retryCount; ++n) { try { @@ -446,7 +474,8 @@ public void basicSecretCacheExceptionRetryTest() throws Throwable { @Test public void basicSecretCacheNullTest() { - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(null); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(null); SecretCache sc = new SecretCache(asm); Assert.assertNull(sc.getSecretString("")); sc.close(); @@ -467,10 +496,13 @@ public void basicSecretCacheVersionWithNullStageTest() { versionMap.put("versionId", null); Mockito.when(describeSecretResponse.versionIdsToStages()).thenReturn(versionMap); - getSecretValueResponse = GetSecretValueResponse.builder().secretString(secret).build(); + getSecretValueResponse = + GetSecretValueResponse.builder().secretString(secret).build(); - Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))).thenReturn(describeSecretResponse); - Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))).thenReturn(getSecretValueResponse); + Mockito.when(asm.describeSecret(Mockito.any(DescribeSecretRequest.class))) + .thenReturn(describeSecretResponse); + Mockito.when(asm.getSecretValue(Mockito.any(GetSecretValueRequest.class))) + .thenReturn(getSecretValueResponse); SecretCache sc = new SecretCache(asm); // Request the secret multiple times and verify the correct result @@ -481,5 +513,4 @@ public void basicSecretCacheVersionWithNullStageTest() { Mockito.verify(asm, Mockito.times(0)).getSecretValue(Mockito.any(GetSecretValueRequest.class)); sc.close(); } - } diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/cache/LRUCacheTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/cache/LRUCacheTest.java index 4b6808b..9b352b0 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/cache/LRUCacheTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/cache/LRUCacheTest.java @@ -14,9 +14,8 @@ package com.amazonaws.secretsmanager.caching.cache; import java.util.HashMap; - -import org.testng.annotations.Test; import org.testng.Assert; +import org.testng.annotations.Test; public class LRUCacheTest { @@ -160,5 +159,4 @@ public void putAllTest() { Assert.assertEquals(cache.get(n), new Integer(n)); } } - } diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java index d28b555..9a08ffe 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/internal/VersionInfoTest.java @@ -1,12 +1,10 @@ package com.amazonaws.secretsmanager.caching.internal; +import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; import java.util.regex.Pattern; - import org.testng.Assert; import org.testng.annotations.Test; -import com.amazonaws.secretsmanager.caching.cache.internal.VersionInfo; - public class VersionInfoTest { @Test public void versionInfoIsValid() { From 1d9a40ef0beec4ca5fd695fcfe767e85e72e077d Mon Sep 17 00:00:00 2001 From: Angad Misra Date: Fri, 16 May 2025 12:16:21 -0700 Subject: [PATCH 2/5] fix: typo --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 85aa099..577ec19 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -20,7 +20,7 @@ jobs: with: java-version: 21 distribution: corretto - cache: mave + cache: maven - name: Prettier uses: rutajdash/prettier-cli-action@v1.0.2 From bbeb30b39d9dfeec26ea039ed7937bf8b0ccc497 Mon Sep 17 00:00:00 2001 From: Angad Misra Date: Fri, 16 May 2025 12:29:15 -0700 Subject: [PATCH 3/5] fix: add types trigger --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 577ec19..4c35b3d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -6,6 +6,7 @@ name: Java CI with Maven on: pull_request: branches: [master, v2] + types: [opened, synchronize, ready_for_review] jobs: build: From 52eb36b76db738728ecc173affbc55dbd44beac2 Mon Sep 17 00:00:00 2001 From: Angad Misra Date: Tue, 15 Jul 2025 15:53:23 -0700 Subject: [PATCH 4/5] chore: apply Spotless formatting --- .../caching/SecretCacheConfiguration.java | 1 - .../caching/cache/SecretCacheObject.java | 5 +---- .../secretsmanager/caching/SecretCacheTest.java | 16 +++++++++------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java index c0833ac..bfdf5d6 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/SecretCacheConfiguration.java @@ -282,5 +282,4 @@ public SecretCacheConfiguration withForceRefreshJitterMillis(long forceRefreshJi this.setForceRefreshJitterMillis(forceRefreshJitterMillis); return this; } - } diff --git a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java index 181f384..a80796f 100644 --- a/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java +++ b/src/main/java/com/amazonaws/secretsmanager/caching/cache/SecretCacheObject.java @@ -213,10 +213,7 @@ public boolean refreshNow() throws InterruptedException { // to prevent coding errors that could be calling refreshNow // in a loop. long jitter = this.config.getForceRefreshJitterMillis(); - long sleep = ThreadLocalRandom.current() - .nextLong( - jitter / 2, - jitter + 1); + long sleep = ThreadLocalRandom.current().nextLong(jitter / 2, jitter + 1); // Make sure we are not waiting for the next refresh after an // exception. If we are, sleep based on the retry delay of // the refresh to prevent a hard loop in attempting to refresh a diff --git a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java index 8161659..aadbf63 100644 --- a/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java +++ b/src/test/java/com/amazonaws/secretsmanager/caching/SecretCacheTest.java @@ -81,25 +81,27 @@ public void secretCacheConstructorTest() { } catch (Exception e) { } } - + @Test public void testForceRefreshJitterConfiguration() { // Test default value SecretCacheConfiguration config = new SecretCacheConfiguration(); - Assert.assertEquals(config.getForceRefreshJitterMillis(), SecretCacheConfiguration.DEFAULT_FORCE_REFRESH_JITTER); - + Assert.assertEquals( + config.getForceRefreshJitterMillis(), SecretCacheConfiguration.DEFAULT_FORCE_REFRESH_JITTER); + // Test setting a custom value long customJitter = 250L; config.setForceRefreshJitterMillis(customJitter); Assert.assertEquals(config.getForceRefreshJitterMillis(), customJitter); - + // Test zero is valid config.setForceRefreshJitterMillis(0); Assert.assertEquals(config.getForceRefreshJitterMillis(), 0); } - - @Test(expectedExceptions = IllegalArgumentException.class, - expectedExceptionsMessageRegExp = "Force refresh jitter must be greater than or equal to zero") + + @Test( + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = "Force refresh jitter must be greater than or equal to zero") public void testForceRefreshJitterValidation() { // Test that negative values throw an exception SecretCacheConfiguration config = new SecretCacheConfiguration(); From da377b60e49e710750806965416a90c011ade08a Mon Sep 17 00:00:00 2001 From: Angad Misra Date: Tue, 15 Jul 2025 15:55:23 -0700 Subject: [PATCH 5/5] fix: revert `push` trigger --- .github/workflows/maven.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 4c35b3d..cba7823 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,8 +4,9 @@ name: Java CI with Maven on: - pull_request: + push: branches: [master, v2] + pull_request: types: [opened, synchronize, ready_for_review] jobs: