Skip to content

Commit

Permalink
Adding support for the Amazon DynamoDB local container
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Wright committed Dec 13, 2018
1 parent ae52937 commit d8f6188
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,8 @@ Temporary Items
# .nfs files are created when an open file is removed but is still being accessed
.nfs*

# Intellij IDEA files
.idea
*.iml
*.iws
*.ipr
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ members = [
"images/trufflesuite_ganachecli",
"images/coblox_bitcoincore",
"images/parity_parity",
"images/dynamodb_local"
]
13 changes: 13 additions & 0 deletions images/dynamodb_local/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "tc_dynamodb_local"
version = "0.1.0"
authors = [ "Jack Wright <[email protected]>" ]
description = "Testcontainers image for local dynamodb"
license = "MIT OR Apache-2.0"
repository = "https://github.com/coblox/testcontainers-rs"
categories = ["development-tools::testing"]
keywords = ["docker", "testcontainers", "dynamodb"]

[dependencies]
tc_core = { path = "../../core", version = "0.2" }
log = "0.4"
11 changes: 11 additions & 0 deletions images/dynamodb_local/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# DynamoDb Local

This crate provides `DynamoDB` as an `Image` for `testcontainers`.

By default the `latest` will be used for the dynamodb-local container. This can be overridden by creating the DynamoDB
instance with `DynamoDB::with_tag_args`.

The period of time waiting for the dynamodb-local image to be available can be adjusted from the default value of
2000 milliseconds by setting the environment variable DYNAMODB_ADDITIONAL_SLEEP_PERIOD (in millis).

Information on the DynamoDB local container can be found at: https://hub.docker.com/r/amazon/dynamodb-local/
85 changes: 85 additions & 0 deletions images/dynamodb_local/src/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::{env::var, thread::sleep, time::Duration};
use tc_core::{Image, Container, Docker, WaitForMessage};

const ADDITIONAL_SLEEP_PERIOD: &'static str = "DYNAMODB_ADDITIONAL_SLEEP_PERIOD";
const DEFAULT_WAIT: u64 = 2000;
const CONTAINER_IDENTIFIER: &'static str = "amazon/dynamodb-local";
const DEFAULT_TAG: &'static str = "latest";


#[derive(Debug, Default, Clone)]
pub struct DynamoDbArgs;

impl IntoIterator for DynamoDbArgs {
type Item = String;
type IntoIter = ::std::vec::IntoIter<String>;

fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
vec![].into_iter()
}
}

#[derive(Debug)]
pub struct DynamoDb {
tag: String,
arguments: DynamoDbArgs
}

impl Default for DynamoDb {
fn default() -> Self {
DynamoDb {
tag: DEFAULT_TAG.to_string(),
arguments: DynamoDbArgs {}
}
}
}

impl Image for DynamoDb {
type Args = DynamoDbArgs;

fn descriptor(&self) -> String {
format!("{}:{}", CONTAINER_IDENTIFIER, &self.tag)
}

fn wait_until_ready<D: Docker>(&self, container: &Container<D, Self>) {
container
.logs()
.stdout
.wait_for_message("Initializing DynamoDB Local with the following configuration")
.unwrap();

let additional_sleep_period = var(ADDITIONAL_SLEEP_PERIOD)
.map(|value| value.parse().unwrap_or(DEFAULT_WAIT))
.unwrap_or(DEFAULT_WAIT);

let sleep_period = Duration::from_millis(additional_sleep_period);

trace!(
"Waiting for an additional {:?} for container {}.",
sleep_period,
container.id()
);

sleep(sleep_period)
}

fn args(&self) -> <Self as Image>::Args {
self.arguments.clone()
}

fn with_args(self, arguments: <Self as Image>::Args) -> Self {
DynamoDb {
arguments, ..self
}
}

}

impl DynamoDb {
pub fn with_tag_args(self, tag_str: &str, arguments: <Self as Image>::Args) -> Self {
DynamoDb{tag: tag_str.to_string(), arguments, ..self}
}
}



8 changes: 8 additions & 0 deletions images/dynamodb_local/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![deny(missing_debug_implementations)]

#[macro_use]
extern crate log;
extern crate tc_core;

mod image;
pub use image::*;
6 changes: 6 additions & 0 deletions testcontainers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,15 @@ tc_cli_client = { path = "../cli_client", version = "0.1" }
tc_coblox_bitcoincore = { path = "../images/coblox_bitcoincore", version = "0.3" }
tc_trufflesuite_ganachecli = { path = "../images/trufflesuite_ganachecli", version = "0.3" }
tc_parity_parity = { path = "../images/parity_parity", version = "0.2" }
tc_dynamodb_local = { path = "../images/dynamodb_local", version = "0.1" }

[dev-dependencies]
bitcoin_rpc_client = "0.4"
spectral = "0.6"
web3 = "0.4"
pretty_env_logger = "0.3"

# Dynamodb client needed for dynamodb local
rusoto_core = "0.35"
rusoto_dynamodb = "0.35"
rusoto_credential = "0.14"
6 changes: 6 additions & 0 deletions testcontainers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extern crate tc_core;
extern crate tc_coblox_bitcoincore;
extern crate tc_parity_parity;
extern crate tc_trufflesuite_ganachecli;
extern crate tc_dynamodb_local;

/// All available Docker clients.
pub mod clients {
Expand All @@ -60,6 +61,11 @@ pub mod images {
pub mod trufflesuite_ganachecli {
pub use tc_trufflesuite_ganachecli::{GanacheCli, GanacheCliArgs};
}

pub mod dynamodb_local {
pub use tc_dynamodb_local::{DynamoDb, DynamoDbArgs};
}

}

pub use tc_core::*;
64 changes: 64 additions & 0 deletions testcontainers/tests/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ extern crate pretty_env_logger;
extern crate spectral;
extern crate testcontainers;
extern crate web3;
extern crate rusoto_core;
extern crate rusoto_dynamodb;
extern crate rusoto_credential;

use spectral::prelude::*;
use testcontainers::*;
Expand All @@ -11,6 +14,17 @@ use bitcoin_rpc_client::BitcoinRpcApi;
use web3::futures::Future;
use web3::transports::Http;
use web3::Web3;
use rusoto_core::Region;
use rusoto_dynamodb::{
DynamoDb,
DynamoDbClient,
CreateTableInput,
KeySchemaElement,
AttributeDefinition,
ProvisionedThroughput
};
use rusoto_credential::StaticProvider;
use rusoto_core::HttpClient;

#[test]
fn coblox_bitcoincore_getnewaddress() {
Expand Down Expand Up @@ -74,3 +88,53 @@ fn trufflesuite_ganachecli_listaccounts() {

assert_that(&accounts).is_ok();
}

#[test]
fn dynamodb_local_create_table() {
let _ = pretty_env_logger::try_init();
let docker = clients::Cli::default();
let node = docker.run(images::dynamodb_local::DynamoDb::default());
let host_port = node.get_host_port(8000).unwrap();

let mut create_tables_input = CreateTableInput::default();
create_tables_input.table_name = "books".to_string();

let mut key_schema_input = KeySchemaElement::default();
key_schema_input.key_type = "HASH".to_string();
key_schema_input.attribute_name = "title".to_string();
create_tables_input.key_schema = vec![key_schema_input];

let mut att0 = AttributeDefinition::default();
att0.attribute_name = "title".to_string();
att0.attribute_type = "S".to_string();

create_tables_input.attribute_definitions = vec![att0];

let mut provisioned_throughput = ProvisionedThroughput::default();
provisioned_throughput.read_capacity_units = 5;
provisioned_throughput.write_capacity_units = 5;
create_tables_input.provisioned_throughput = provisioned_throughput;


let dynamodb = build_dynamodb_client(host_port);
let result = dynamodb.create_table(create_tables_input).sync();
assert_that(&result).is_ok();
}

fn build_dynamodb_client(host_port: u32) -> DynamoDbClient {
let credentials_provider = StaticProvider::new(
"fakeKey".to_string(),
"fakeSecret".to_string(),
None,
None);

let dispatcher = HttpClient::new()
.expect("could not create http client");

let region = Region::Custom {
name: "dynamodb-local".to_string(),
endpoint: format!("http://localhost:{}", host_port)
};

DynamoDbClient::new_with(dispatcher, credentials_provider, region)
}

0 comments on commit d8f6188

Please sign in to comment.