opensearch_testcontainer/
lib.rs

1use std::collections::HashMap;
2
3use testcontainers::{core::WaitFor, Image};
4
5const NAME: &str = "opensearchproject/opensearch";
6const TAG: &str = "2.11.1";
7
8#[derive(Debug, Clone)]
9pub struct OpenSearch {
10  image_name: String,
11  env_vars: HashMap<String, String>,
12  tag: String,
13  username: String,
14  password: String,
15}
16
17impl OpenSearch {
18  pub fn with_name(mut self, name: &str) -> Self {
19    self.image_name = name.to_owned();
20    self
21  }
22
23  pub fn with_tag(mut self, tag: &str) -> Self {
24    self.tag = tag.to_owned();
25    self
26  }
27
28  pub fn with_cluster_name(mut self, name: &str) -> Self {
29    self.env_vars.insert("cluster.name".to_owned(), name.to_owned());
30    self
31  }
32
33  pub fn with_env_var(mut self, key: &str, value: &str) -> Self {
34    self.env_vars.insert(key.to_owned(), value.to_owned());
35    self
36  }
37
38  pub fn username(&self) -> String {
39    self.username.to_owned()
40  }
41
42  pub fn password(&self) -> String {
43    self.password.to_owned()
44  }
45}
46
47impl Default for OpenSearch {
48  fn default() -> Self {
49    let mut env_vars = HashMap::new();
50    env_vars.insert("discovery.type".to_owned(), "single-node".to_owned());
51    OpenSearch {
52      image_name: NAME.to_owned(),
53      env_vars,
54      tag: TAG.to_owned(),
55      username: "admin".to_owned(),
56      password: "admin".to_owned(),
57    }
58  }
59}
60
61impl Image for OpenSearch {
62  type Args = ();
63
64  fn name(&self) -> String {
65    self.image_name.to_owned()
66  }
67
68  fn tag(&self) -> String {
69    self.tag.to_owned()
70  }
71
72  fn ready_conditions(&self) -> Vec<WaitFor> {
73    vec![
74      WaitFor::message_on_stdout("[YELLOW] to [GREEN]"),
75      WaitFor::message_on_stdout("ML configuration initialized successfully"),
76    ]
77  }
78
79  fn env_vars(&self) -> Box<dyn Iterator<Item = (&String, &String)> + '_> {
80    Box::new(self.env_vars.iter())
81  }
82
83  fn expose_ports(&self) -> Vec<u16> {
84    vec![9200, 9300, 9600]
85  }
86}
87
88#[cfg(test)]
89mod tests {
90  use testcontainers::clients;
91
92  use crate::OpenSearch as OpenSearchImage;
93
94  #[test]
95  fn opensearch_default() {
96    let docker = clients::Cli::default();
97    let os_image = OpenSearchImage::default();
98    let node: testcontainers::Container<'_, OpenSearchImage> = docker.run(os_image.clone());
99    let host_port = node.get_host_port_ipv4(9200);
100
101    let client = reqwest::blocking::Client::builder()
102      .danger_accept_invalid_certs(true)
103      .build()
104      .unwrap();
105
106    let response = client
107      .get(format!("https://127.0.0.1:{host_port}"))
108      .header("content-type", "application/json")
109      .basic_auth(os_image.username(), Some(os_image.password()))
110      .send()
111      .unwrap();
112
113    let response = response.text().unwrap();
114    println!("response: {}", response);
115    let response: serde_json::Value = serde_json::from_str(&response).unwrap();
116
117    assert_eq!(response["version"]["number"], "2.11.1");
118  }
119}