diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index e2d0cb965..e8df1f8d6 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -5,8 +5,9 @@ description: Utility The parameters utility provides a way to retrieve parameter values from -[AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html) or -[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/). It also provides a base class to create your parameter provider implementation. +[AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), +[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or [Amazon DynamoDB](https://aws.amazon.com/dynamodb/). +It also provides a base class to create your parameter provider implementation. **Key features** @@ -40,11 +41,12 @@ To install this utility, add the following dependency to your project. This utility requires additional permissions to work as expected. See the table below: -Provider | Function/Method | IAM Permission -------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------- -SSM Parameter Store | `SSMProvider.get(String)` `SSMProvider.get(String, Class)` | `ssm:GetParameter` -SSM Parameter Store | `SSMProvider.getMultiple(String)` | `ssm:GetParametersByPath` -Secrets Manager | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)` | `secretsmanager:GetSecretValue` +Provider | Function/Method | IAM Permission +------------------------------------------------- |----------------------------------------------------------------------| --------------------------------------------------------------------------------- +SSM Parameter Store | `SSMProvider.get(String)` `SSMProvider.get(String, Class)` | `ssm:GetParameter` +SSM Parameter Store | `SSMProvider.getMultiple(String)` | `ssm:GetParametersByPath` +Secrets Manager | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)` | `secretsmanager:GetSecretValue` +DynamoDB | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)` | `dynamodb:GetItem` `dynamoDB:Query` ## SSM Parameter Store @@ -74,7 +76,7 @@ in order to get data from other regions or use specific credentials. } ``` -=== "SSMProvider with an explicit region" +=== "SSMProvider with a custom client" ```java hl_lines="5 7" import software.amazon.lambda.powertools.parameters.SSMProvider; @@ -149,7 +151,7 @@ in order to get data from other regions or use specific credentials. } ``` -=== "SecretsProvider with an explicit region" +=== "SecretsProvider with a custom client" ```java hl_lines="5 7" import software.amazon.lambda.powertools.parameters.SecretsProvider; @@ -166,6 +168,52 @@ in order to get data from other regions or use specific credentials. } ``` +## DynamoDB +To get secrets stored in DynamoDB, use `getDynamoDbProvider`, providing the name of the table that +contains the secrets. As with the other providers, an overloaded methods allows you to retrieve +a `DynamoDbProvider` providing a client if you need to configure it yourself. + +=== "DynamoDbProvider" + + ```java hl_lines="6 9" + import software.amazon.lambda.powertools.parameters.DynamoDbProvider; + import software.amazon.lambda.powertools.parameters.ParamManager; + + public class AppWithDynamoDbParameters implements RequestHandler { + // Get an instance of the DynamoDbProvider + DynamoDbProvider ddbProvider = ParamManager.getDynamoDbProvider("my-parameters-table"); + + // Retrieve a single parameter + String value = ddbProvider.get("my-key"); + } + ``` + +=== "DynamoDbProvider with a custom client" + + ```java hl_lines="9 10 11 12 15 18" + import software.amazon.lambda.powertools.parameters.DynamoDbProvider; + import software.amazon.lambda.powertools.parameters.ParamManager; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; + import software.amazon.awssdk.regions.Region; + + public class AppWithDynamoDbParameters implements RequestHandler { + // Get a DynamoDB Client with an explicit region + DynamoDbClient ddbClient = DynamoDbClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .region(Region.EU_CENTRAL_2) + .build(); + + // Get an instance of the DynamoDbProvider + DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table"); + + // Retrieve a single parameter + String value = ddbProvider.get("my-key"); + } + ``` + + + ## Advanced configuration ### Caching diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 66eedce1e..befb57d09 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -73,6 +73,10 @@ software.amazon.awssdk url-connection-client + + software.amazon.awssdk + dynamodb + com.fasterxml.jackson.core jackson-databind diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java new file mode 100644 index 000000000..08031e185 --- /dev/null +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java @@ -0,0 +1,191 @@ +package software.amazon.lambda.powertools.parameters; + +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.*; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Implements a {@link ParamProvider} on top of DynamoDB. The schema of the table + * is described in the Powertools documentation. + * + * @see Parameters provider documentation + * + */ +public class DynamoDbProvider extends BaseProvider { + + private final DynamoDbClient client; + private final String tableName; + + public DynamoDbProvider(CacheManager cacheManager, String tableName) { + this(cacheManager, DynamoDbClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .build(), + tableName + ); + + } + + DynamoDbProvider(CacheManager cacheManager, DynamoDbClient client, String tableName) { + super(cacheManager); + this.client = client; + this.tableName = tableName; + } + + /** + * Return a single value from the DynamoDB parameter provider. + * + * @param key key of the parameter + * @return The value, if it exists, null if it doesn't. Throws if the row exists but doesn't match the schema. + */ + @Override + protected String getValue(String key) { + GetItemResponse resp = client.getItem(GetItemRequest.builder() + .tableName(tableName) + .key(Collections.singletonMap("id", AttributeValue.fromS(key))) + .attributesToGet("value") + .build()); + + // If we have an item at the key, we should be able to get a 'val' out of it. If not it's + // exceptional. + // If we don't have an item at the key, we should return null. + if (resp.hasItem() && !resp.item().values().isEmpty()) { + if (!resp.item().containsKey("value")) { + throw new DynamoDbProviderSchemaException("Missing 'value': " + resp.item().toString()); + } + return resp.item().get("value").s(); + } + + return null; + } + + /** + * Returns multiple values from the DynamoDB parameter provider. + * + * @param path Parameter store path + * @return All values matching the given path, and an empty map if none do. Throws if any records exist that don't match the schema. + */ + @Override + protected Map getMultipleValues(String path) { + + QueryResponse resp = client.query(QueryRequest.builder() + .tableName(tableName) + .keyConditionExpression("id = :v_id") + .expressionAttributeValues(Collections.singletonMap(":v_id", AttributeValue.fromS(path))) + .build()); + + return resp + .items() + .stream() + .peek((i) -> { + if (!i.containsKey("sk")) { + throw new DynamoDbProviderSchemaException("Missing 'sk': " + i.toString()); + } + if (!i.containsKey("value")) { + throw new DynamoDbProviderSchemaException("Missing 'value': " + i.toString()); + } + }) + .collect( + Collectors.toMap( + (i) -> i.get("sk").s(), + (i) -> i.get("value").s())); + + + } + + /** + * Create a builder that can be used to configure and create a {@link DynamoDbProvider}. + * + * @return a new instance of {@link DynamoDbProvider.Builder} + */ + public static DynamoDbProvider.Builder builder() { + return new DynamoDbProvider.Builder(); + } + + static class Builder { + private DynamoDbClient client; + private String table; + private CacheManager cacheManager; + private TransformationManager transformationManager; + + /** + * Create a {@link DynamoDbProvider} instance. + * + * @return a {@link DynamoDbProvider} + */ + public DynamoDbProvider build() { + if (cacheManager == null) { + throw new IllegalStateException("No CacheManager provided; please provide one"); + } + if (table == null) { + throw new IllegalStateException("No DynamoDB table name provided; please provide one"); + } + DynamoDbProvider provider; + if (client != null) { + provider = new DynamoDbProvider(cacheManager, client, table); + } else { + provider = new DynamoDbProvider(cacheManager, table); + } + if (transformationManager != null) { + provider.setTransformationManager(transformationManager); + } + return provider; + } + + /** + * Set custom {@link DynamoDbClient} to pass to the {@link DynamoDbClient}.
+ * Use it if you want to customize the region or any other part of the client. + * + * @param client Custom client + * @return the builder to chain calls (eg.
builder.withClient().build()
) + */ + public DynamoDbProvider.Builder withClient(DynamoDbClient client) { + this.client = client; + return this; + } + + /** + * Mandatory. Provide a CacheManager to the {@link DynamoDbProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public DynamoDbProvider.Builder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + /** + * Mandatory. Provide a DynamoDB table to the {@link DynamoDbProvider} + * + * @param table the table that parameters will be retrieved from. + * @return the builder to chain calls (eg.
builder.withTable().build()
) + */ + public DynamoDbProvider.Builder withTable(String table) { + this.table = table; + return this; + } + + /** + * Provide a transformationManager to the {@link DynamoDbProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public DynamoDbProvider.Builder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } + } +} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java index 0131ae179..e4c70acb0 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java @@ -15,6 +15,7 @@ import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -36,8 +37,8 @@ public final class ParamManager { /** * Get a concrete implementation of {@link BaseProvider}.
- * You can specify {@link SecretsProvider} or {@link SSMProvider} or create your custom provider - * by extending {@link BaseProvider} if you need to integrate with a different parameter store. + * You can specify {@link SecretsProvider}, {@link SSMProvider}, {@link DynamoDbProvider}, or create your + * custom provider by extending {@link BaseProvider} if you need to integrate with a different parameter store. * @return a {@link SecretsProvider} */ public static T getProvider(Class providerClass) { @@ -65,6 +66,21 @@ public static SSMProvider getSsmProvider() { return getProvider(SSMProvider.class); } + /** + * Get a {@link DynamoDbProvider} with default {@link DynamoDbClient}
+ * If you need to customize the region, or other part of the client, use {@link ParamManager#getDynamoDbProvider(DynamoDbClient, String)} + */ + public static DynamoDbProvider getDynamoDbProvider(String tableName) { + // Because we need a DDB table name to configure our client, we can't use + // ParamManager#getProvider. This means that we need to make sure we do the same stuff - + // set transformation manager and cache manager. + return DynamoDbProvider.builder() + .withCacheManager(cacheManager) + .withTable(tableName) + .withTransformationManager(transformationManager) + .build(); + } + /** * Get a {@link SecretsProvider} with your custom {@link SecretsManagerClient}.
* Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization. @@ -91,6 +107,20 @@ public static SSMProvider getSsmProvider(SsmClient client) { .build()); } + /** + * Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.
+ * Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization. + * @return a {@link DynamoDbProvider} + */ + public static DynamoDbProvider getDynamoDbProvider(DynamoDbClient client, String table) { + return (DynamoDbProvider) providers.computeIfAbsent(DynamoDbProvider.class, (k) -> DynamoDbProvider.builder() + .withClient(client) + .withTable(table) + .withCacheManager(cacheManager) + .withTransformationManager(transformationManager) + .build()); + } + public static CacheManager getCacheManager() { return cacheManager; } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java new file mode 100644 index 000000000..b7574e81d --- /dev/null +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java @@ -0,0 +1,11 @@ +package software.amazon.lambda.powertools.parameters.exception; + +/** + * Thrown when the DynamoDbProvider comes across parameter data that + * does not meet the DynamoDB parameters schema. + */ +public class DynamoDbProviderSchemaException extends RuntimeException { + public DynamoDbProviderSchemaException(String msg) { + super(msg); + } +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java new file mode 100644 index 000000000..c9397676b --- /dev/null +++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java @@ -0,0 +1,99 @@ +package software.amazon.lambda.powertools.parameters; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * This class provides simple end-to-end style testing of the DynamoDBProvider class. + * It is ignored, for now, as it requires AWS access and that's not yet run as part + * of our unit test suite in the cloud. + * + * The test is kept here for 1/ local development and 2/ in preparation for future + * E2E tests running in the cloud CI. Once the E2E test structure is merged we + * will move this across. + */ +@Disabled +public class DynamoDbProviderE2ETest { + + final String ParamsTestTable = "ddb-params-test"; + final String MultiparamsTestTable = "ddb-multiparams-test"; + private final DynamoDbClient ddbClient; + + public DynamoDbProviderE2ETest() { + // Create a DDB client to inject test data into our test tables + ddbClient = DynamoDbClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .build(); + + + } + + @Test + public void TestGetValue() { + + // Arrange + HashMap testItem = new HashMap(); + testItem.put("id", AttributeValue.fromS("test_param")); + testItem.put("value", AttributeValue.fromS("the_value_is_hello!")); + ddbClient.putItem(PutItemRequest.builder() + .tableName(ParamsTestTable) + .item(testItem) + .build()); + + // Act + DynamoDbProvider provider = makeProvider(ParamsTestTable); + String value = provider.getValue("test_param"); + + // Assert + assertThat(value).isEqualTo("the_value_is_hello!"); + } + + @Test + public void TestGetValues() { + + // Arrange + HashMap testItem = new HashMap(); + testItem.put("id", AttributeValue.fromS("test_param")); + testItem.put("sk", AttributeValue.fromS("test_param_part_1")); + testItem.put("value", AttributeValue.fromS("the_value_is_hello!")); + ddbClient.putItem(PutItemRequest.builder() + .tableName(MultiparamsTestTable) + .item(testItem) + .build()); + + HashMap testItem2 = new HashMap(); + testItem2.put("id", AttributeValue.fromS("test_param")); + testItem2.put("sk", AttributeValue.fromS("test_param_part_2")); + testItem2.put("value", AttributeValue.fromS("the_value_is_still_hello!")); + ddbClient.putItem(PutItemRequest.builder() + .tableName(MultiparamsTestTable) + .item(testItem2) + .build()); + + // Act + DynamoDbProvider provider = makeProvider(MultiparamsTestTable); + Map values = provider.getMultipleValues("test_param"); + + // Assert + assertThat(values.size()).isEqualTo(2); + assertThat(values.get("test_param_part_1")).isEqualTo("the_value_is_hello!"); + assertThat(values.get("test_param_part_2")).isEqualTo("the_value_is_still_hello!"); + } + + private DynamoDbProvider makeProvider(String tableName) { + return new DynamoDbProvider(new CacheManager(), DynamoDbClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()).build(), + tableName); + } + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java new file mode 100644 index 000000000..0e5b734d6 --- /dev/null +++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java @@ -0,0 +1,168 @@ +package software.amazon.lambda.powertools.parameters; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.*; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.MockitoAnnotations.openMocks; + +public class DynamoDbProviderTest { + + @Mock + DynamoDbClient client; + + @Captor + ArgumentCaptor getItemValueCaptor; + + @Captor + ArgumentCaptor queryRequestCaptor; + + + private DynamoDbProvider provider; + private final String tableName = "ddb-test-table"; + + @BeforeEach + public void init() { + openMocks(this); + CacheManager cacheManager = new CacheManager(); + provider = new DynamoDbProvider(cacheManager, client, tableName); + } + + + @Test + public void getValue() { + + // Arrange + String key = "Key1"; + String expectedValue = "Value1"; + HashMap responseData = new HashMap(); + responseData.put("id", AttributeValue.fromS(key)); + responseData.put("value", AttributeValue.fromS(expectedValue)); + GetItemResponse response = GetItemResponse.builder() + .item(responseData) + .build(); + Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(response); + + // Act + String value = provider.getValue(key); + + // Assert + assertThat(value).isEqualTo(expectedValue); + assertThat(getItemValueCaptor.getValue().tableName()).isEqualTo(tableName); + assertThat(getItemValueCaptor.getValue().key().get("id").s()).isEqualTo(key); + } + + + @Test + public void getValueWithoutResultsReturnsNull() { + // Arrange + Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(GetItemResponse.builder() + .item(null) + .build()); + + // Act + String value = provider.getValue("key"); + + // Assert + assertThat(value).isEqualTo(null); + } + + @Test + public void getValueWithMalformedRowThrows() { + // Arrange + String key = "Key1"; + HashMap responseData = new HashMap(); + responseData.put("id", AttributeValue.fromS(key)); + responseData.put("not-value", AttributeValue.fromS("something")); + Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(GetItemResponse.builder() + .item(responseData) + .build()); + // Act + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { + String value = provider.getValue(key); + }); + } + + + @Test + public void getValues() { + + // Arrange + String key = "Key1"; + String subkey1 = "Subkey1"; + String val1 = "Val1"; + String subkey2 = "Subkey2"; + String val2 = "Val2"; + HashMap item1 = new HashMap(); + item1.put("id", AttributeValue.fromS(key)); + item1.put("sk", AttributeValue.fromS(subkey1)); + item1.put("value", AttributeValue.fromS(val1)); + HashMap item2 = new HashMap(); + item2.put("id", AttributeValue.fromS(key)); + item2.put("sk", AttributeValue.fromS(subkey2)); + item2.put("value", AttributeValue.fromS(val2)); + QueryResponse response = QueryResponse.builder() + .items(item1, item2) + .build(); + Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); + + // Act + Map values = provider.getMultipleValues(key); + + // Assert + assertThat(values.size()).isEqualTo(2); + assertThat(values.get(subkey1)).isEqualTo(val1); + assertThat(values.get(subkey2)).isEqualTo(val2); + assertThat(queryRequestCaptor.getValue().tableName()).isEqualTo(tableName); + assertThat(queryRequestCaptor.getValue().keyConditionExpression()).isEqualTo("id = :v_id"); + assertThat(queryRequestCaptor.getValue().expressionAttributeValues().get(":v_id").s()).isEqualTo(key); + } + + @Test + public void getValuesWithoutResultsReturnsNull() { + // Arrange + Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn( + QueryResponse.builder().items().build()); + + // Act + Map values = provider.getMultipleValues(UUID.randomUUID().toString()); + + // Assert + assertThat(values.size()).isEqualTo(0); + } + + @Test + public void getValuesWithMalformedRowThrows() { + // Arrange + String key = "Key1"; + HashMap item1 = new HashMap(); + item1.put("id", AttributeValue.fromS(key)); + item1.put("sk", AttributeValue.fromS("some-subkey")); + item1.put("not-value", AttributeValue.fromS("somevalue")); + QueryResponse response = QueryResponse.builder() + .items(item1) + .build(); + Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); + + // Assert + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { + // Act + Map values = provider.getMultipleValues(key); + }); + } + + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java index 0b4a2093f..ec1672ead 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java +++ b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java @@ -19,6 +19,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; @@ -41,6 +42,9 @@ public class ParamManagerIntegrationTest { @Mock SsmClient ssmClient; + @Mock + DynamoDbClient ddbClient; + @Captor ArgumentCaptor ssmParamCaptor; @@ -116,4 +120,16 @@ public void secretsProvider_get() { assertThat(secretsProvider.get("keys")).isEqualTo(expectedValue); // second time is from cache verify(secretsManagerClient, times(1)).getSecretValue(any(GetSecretValueRequest.class)); } + + @Test + public void getDynamoDbProvider() { + + // Act + DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table"); + + // Assert + assertThat(provider).isNotNull(); + + + } }