testcontainers_modules/consul/
mod.rs1use std::{borrow::Cow, collections::BTreeMap};
2
3use testcontainers::{core::WaitFor, Image};
4
5const DEFAULT_IMAGE_NAME: &str = "hashicorp/consul";
6const DEFAULT_IMAGE_TAG: &str = "1.16.1";
7const CONSUL_LOCAL_CONFIG: &str = "CONSUL_LOCAL_CONFIG";
8
9#[derive(Debug, Default, Clone)]
26pub struct Consul {
27 env_vars: BTreeMap<String, String>,
28}
29
30impl Consul {
31 pub fn with_local_config(self, config: impl ToString) -> Self {
51 let mut env_vars = self.env_vars;
52 env_vars.insert(CONSUL_LOCAL_CONFIG.to_owned(), config.to_string());
53 Self { env_vars }
54 }
55}
56
57impl Image for Consul {
58 fn name(&self) -> &str {
59 DEFAULT_IMAGE_NAME
60 }
61
62 fn tag(&self) -> &str {
63 DEFAULT_IMAGE_TAG
64 }
65
66 fn ready_conditions(&self) -> Vec<WaitFor> {
67 vec![WaitFor::message_on_stdout("agent: Consul agent running!")]
68 }
69
70 fn env_vars(
71 &self,
72 ) -> impl IntoIterator<Item = (impl Into<Cow<'_, str>>, impl Into<Cow<'_, str>>)> {
73 &self.env_vars
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use serde_json::Value;
80
81 use crate::{consul::Consul, testcontainers::runners::AsyncRunner};
82
83 #[tokio::test]
84 async fn consul_container() -> Result<(), Box<dyn std::error::Error + 'static>> {
85 let consul = Consul::default().with_local_config("{\"datacenter\":\"dc-rust\"}".to_owned());
86 let node = consul.start().await?;
87 let port = node.get_host_port_ipv4(8500).await?;
88
89 let response = reqwest::Client::new()
90 .get(format!("http://localhost:{}/v1/agent/self", port))
91 .send()
92 .await
93 .unwrap()
94 .json::<Value>()
95 .await
96 .unwrap();
97 let config = response.as_object().unwrap().get("Config").unwrap();
98 let dc = config
99 .as_object()
100 .unwrap()
101 .get("Datacenter")
102 .unwrap()
103 .as_str()
104 .unwrap();
105 assert_eq!("dc-rust", dc);
106 Ok(())
107 }
108}