Skip to content

Commit

Permalink
feat: add consul module (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruslansennov authored Mar 22, 2024
1 parent 0963b03 commit 6453ac7
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = []
consul = []
dynamodb = []
elastic_search = []
elasticmq = []
Expand Down
114 changes: 114 additions & 0 deletions src/consul/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::collections::BTreeMap;

use testcontainers::core::WaitFor;
use testcontainers::Image;

const DEFAULT_IMAGE_NAME: &str = "hashicorp/consul";
const DEFAULT_IMAGE_TAG: &str = "1.16.1";
const CONSUL_LOCAL_CONFIG: &str = "CONSUL_LOCAL_CONFIG";

/// Module to work with [`Consul`] inside of tests.
///
/// This module is based on the official [`Consul docker image`].
///
/// # Example
/// ```
/// use testcontainers::clients;
/// use testcontainers_modules::consul;
///
/// let docker = clients::Cli::default();
/// let consul = docker.run(consul::Consul::default());
///
/// let http_port = consul.get_host_port_ipv4(8500);
///
/// // do something with the started consul instance..
/// ```
///
/// [`Consul`]: https://www.consul.io/
/// [`Consul docker image`]: https://hub.docker.com/r/hashicorp/consul
#[derive(Debug)]
pub struct Consul {
name: String,
tag: String,
env_vars: BTreeMap<String, String>,
}

impl Default for Consul {
fn default() -> Self {
Consul::new(
DEFAULT_IMAGE_NAME.to_string(),
DEFAULT_IMAGE_TAG.to_string(),
)
}
}

impl Consul {
fn new(name: String, tag: String) -> Self {
Consul {
name,
tag,
env_vars: Default::default(),
}
}

pub fn with_local_config(self, config: String) -> Self {
let mut env_vars = self.env_vars;
env_vars.insert(CONSUL_LOCAL_CONFIG.to_owned(), config);
Self { env_vars, ..self }
}
}

impl Image for Consul {
type Args = ();

fn name(&self) -> String {
self.name.clone()
}

fn tag(&self) -> String {
self.tag.clone()
}

fn ready_conditions(&self) -> Vec<WaitFor> {
vec![WaitFor::message_on_stdout("agent: Consul agent running!")]
}

fn env_vars(&self) -> Box<dyn Iterator<Item = (&String, &String)> + '_> {
Box::new(self.env_vars.iter())
}
}

#[cfg(test)]
mod tests {
use serde_json::Value;
use testcontainers::clients;

use crate::consul::Consul;

#[tokio::test]
async fn consul_container() {
let docker = clients::Cli::default();

let consul = Consul::default().with_local_config("{\"datacenter\":\"dc-rust\"}".to_owned());
let node = docker.run(consul);
let port = node.get_host_port_ipv4(8500);

let response = reqwest::Client::new()
.get(format!("http://localhost:{}/v1/agent/self", port))
.send()
.await
.unwrap()
.json::<Value>()
.await
.unwrap();
let config = response.as_object().unwrap().get("Config").unwrap();
let dc = config
.as_object()
.unwrap()
.get("Datacenter")
.unwrap()
.as_str()
.unwrap();
assert_eq!("dc-rust", dc)
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#![doc = include_str!("../README.md")]
//! Please have a look at the documentation of the separate modules for examples on how to use the module.

#[cfg(feature = "consul")]
#[cfg_attr(docsrs, doc(cfg(feature = "consul")))]
pub mod consul;
#[cfg(feature = "dynamodb")]
#[cfg_attr(docsrs, doc(cfg(feature = "dynamodb")))]
pub mod dynamodb_local;
Expand Down

0 comments on commit 6453ac7

Please sign in to comment.