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..cba7823 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,26 +5,40 @@ name: Java CI with Maven on: push: - branches: [ "master", "v2" ] + branches: [master, v2] pull_request: - branches: [ "master", "v2" ] + types: [opened, synchronize, ready_for_review] 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: maven + + - 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..bfdf5d6 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. * @@ -290,5 +282,4 @@ public SecretCacheConfiguration withForceRefreshJitterMillis(long forceRefreshJi this.setForceRefreshJitterMillis(forceRefreshJitterMillis); return this; } - } 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..a80796f 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; } @@ -209,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 @@ -239,11 +240,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 +133,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 +144,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 +171,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 +181,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 +192,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 +211,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 +222,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 +260,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 +292,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 +341,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 +374,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 +406,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 +425,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 +436,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 +449,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 +476,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 +498,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 +515,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() {