Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for dynamodb-local #3557

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/modules/databases/awsdynamodb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# AWS DynamoDb Module

Testcontainers module for [AWS DynamoDb](https://hub.docker.com/r/amazon/dynamodb-local) official
Docker image.

## Usage example

Running the container as a stand-in for DynamoDB in a test:

```java
public class SomeTest {

@Rule
public DynamoDbContainer dynamoDB = new DynamoDbContainer();

@Test
public void someTestMethod() {
// getClient() returns a preconfigured DynamoDB client that is connected to the container
final DynamoDbClient client = dynamoDB.getClient();

... interact with client as if using DynamoDB normally
```

## Adding this module to your project dependencies

Add the following dependency to your `pom.xml`/`build.gradle` file:

```groovy tab='Gradle'
testCompile "org.testcontainers:aws-dynamodb:{{latest_version}}"
```

```xml tab='Maven'
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>aws-dynamodb</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```

!!! hint
Adding this Testcontainers library JAR will not automatically add an AWS SDK JAR to your project. You should ensure that your project also has a suitable AWS SDK JAR as a dependency.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ nav:
- modules/databases/index.md
- modules/databases/jdbc.md
- modules/databases/r2dbc.md
- modules/databases/awsdynamodb.md
- modules/databases/cassandra.md
- modules/databases/cockroachdb.md
- modules/databases/couchbase.md
Expand Down
8 changes: 8 additions & 0 deletions modules/aws-dynamodb/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
description = "Testcontainers :: AWS DynamoDb"

dependencies {
compile project(':testcontainers')

compileOnly 'software.amazon.awssdk:dynamodb:2.15.39'
testCompile 'software.amazon.awssdk:dynamodb:2.15.39'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.testcontainers.dynamodb;

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;

import java.net.URI;
import java.net.URISyntaxException;

/**
* Container for official AWS DynamoDB.
*/
public class DynamoDbContainer extends GenericContainer<DynamoDbContainer> {

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("amazon/dynamodb-local");
private static final String DEFAULT_TAG = "1.13.5";
private static final int MAPPED_PORT = 8000;

/**
* @deprecated use {@link DynamoDbContainer (DockerImageName)} instead
*/
@Deprecated
public DynamoDbContainer() {
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need this constructor? can it be removed?

Copy link
Author

Choose a reason for hiding this comment

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

Nope, we don't. Fixed!

this(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG));
}

public DynamoDbContainer(String dockerImageName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This constructor isn't needed. Can you remove it?

Copy link
Author

Choose a reason for hiding this comment

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

You're right this contractor is not needed. I added only because I found it in most of the other modules. Is there any convention suggesting I should keep it?

this(DockerImageName.parse(dockerImageName));
}

public DynamoDbContainer(final DockerImageName dockerImageName) {
super(dockerImageName);

dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

withExposedPorts(MAPPED_PORT);
}


/**
* Gets a preconfigured {@link DynamoDbClient} client object for connecting to this
* container.
*
* @return preconfigured client
*/
public DynamoDbClient getClient() {
return DynamoDbClient.builder()
.region(Region.AWS_GLOBAL)
.credentialsProvider(getCredentials())
.endpointOverride(getEndpointURI())
.build();
}

/**
* Gets {@link URI} that may be used to connect to this container.
*
* @return endpoint configuration
*/
public URI getEndpointURI() {
try {
return new URI("http://" +
this.getHost() + ":" +
this.getMappedPort(MAPPED_PORT));
} catch (URISyntaxException exc) {
throw new IllegalStateException("URI cannot be generated", exc);
}
}

/**
* Gets an {@link StaticCredentialsProvider} that may be used to connect to this container.
*
* @return dummy AWS credentials
*/
public StaticCredentialsProvider getCredentials() {
return StaticCredentialsProvider.create(
AwsBasicCredentials.create("dummy", "dummy"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.testcontainers.dynamodb;

import org.junit.Rule;
import org.junit.Test;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.TableDescription;

import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals;
import static org.rnorth.visibleassertions.VisibleAssertions.assertNotNull;

public class DynamoDbContainerTest {

private static final DockerImageName AWS_DYNAMODB_IMAGE = DockerImageName.parse(
"amazon/dynamodb-local:1.13.5");

@Rule
public DynamoDbContainer dynamoDB = new DynamoDbContainer(AWS_DYNAMODB_IMAGE);

@Test
public void simpleTestWithManualClientCreation() {
final DynamoDbClient client = DynamoDbClient.builder()
.region(Region.AWS_GLOBAL)
.credentialsProvider(dynamoDB.getCredentials())
.endpointOverride(dynamoDB.getEndpointURI())
.build();

runTest(client);
}

@Test
public void simpleTestWithProvidedClient() {
final DynamoDbClient client = dynamoDB.getClient();

runTest(client);
}

private void runTest(DynamoDbClient client) {
CreateTableRequest request = CreateTableRequest.builder()
.tableName("foo")
.billingMode(BillingMode.PROVISIONED)
.keySchema(
KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("Name").build())
.attributeDefinitions(
AttributeDefinition.builder()
.attributeName("Name")
.attributeType(ScalarAttributeType.S)
.build())
.provisionedThroughput(
ProvisionedThroughput.builder()
.readCapacityUnits(10L)
.writeCapacityUnits(10L)
.build())
.build();

client.createTable(request);

final TableDescription tableDescription = client.describeTable(
DescribeTableRequest.builder().tableName("foo").build())
.table();

assertNotNull("the description is not null", tableDescription);
assertEquals("the table has the right name",
"foo", tableDescription.tableName());
assertEquals("the name has the right primary key",
"Name", tableDescription.keySchema().get(0).attributeName());
}
}
16 changes: 16 additions & 0 deletions modules/aws-dynamodb/src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>

<logger name="org.testcontainers" level="DEBUG"/>
</configuration>