@@ -0,0 +1,259 @@
1+use rand::{
2+ distributions::{Alphanumeric, Distribution},
3+ thread_rng,
4+};
5+use std::convert::TryFrom;
6+use std::env;
7+use std::fs;
8+use std::path::Path;
9+use std::path::PathBuf;
10+use std::process::Output;
11+
12+const APP_CHART_NAME: &str = "b2b-dm-staging";
13+const INFRA_CHART_NAME: &str = "b2b-infra-dm-staging";
14+
15+pub fn tmp_dir() -> String {
16+ const LENGTH: usize = 10;
17+
18+ let rng = thread_rng();
19+ let random_string: String = Alphanumeric.sample_iter(rng).take(LENGTH).collect();
20+ format!("dm-{}", random_string)
21+}
22+
23+pub struct TmpDirGuard(PathBuf);
24+
25+impl TmpDirGuard {
26+ pub fn new(tmp_dir: &PathBuf) -> Self {
27+ TmpDirGuard(tmp_dir.clone())
28+ }
29+}
30+
31+impl Drop for TmpDirGuard {
32+ fn drop(&mut self) {
33+ match fs::remove_dir_all(&self.0) {
34+ Ok(_) => (),
35+ Err(err) => eprintln!("remove_dir_all error: {:?}", err),
36+ };
37+ }
38+}
39+
40+pub fn whereis(cmd: &str) -> Option<String> {
41+ env::var("PATH")
42+ .expect("get PATH")
43+ .split(':')
44+ .fold(None, |acc, path| {
45+ if acc.is_some() {
46+ acc
47+ } else {
48+ let full_path = Path::new(path).join(cmd);
49+ if full_path.is_file() {
50+ full_path.to_str().map(ToString::to_string)
51+ } else {
52+ None
53+ }
54+ }
55+ })
56+}
57+
58+pub fn print_command_result(output: Output) {
59+ println!("status: {}", output.status);
60+ println!(
61+ "{}",
62+ String::from_utf8(output.stdout).expect("valid stdout")
63+ );
64+ eprintln!(
65+ "{}",
66+ String::from_utf8(output.stderr).expect("valid stderr")
67+ );
68+}
69+
70+#[derive(Debug)]
71+pub struct EnvPair {
72+ pub key: String,
73+ pub value: String,
74+}
75+
76+impl TryFrom<&str> for EnvPair {
77+ type Error = &'static str;
78+ fn try_from(s: &str) -> Result<Self, Self::Error> {
79+ let parts = s.split('=').collect::<Vec<_>>();
80+ if parts.len() == 2 {
81+ Ok(EnvPair {
82+ key: parts[0].to_string(),
83+ value: parts[1].to_string(),
84+ })
85+ } else {
86+ Err("Malformed environment key-value pair, should be similar to FOO=bar")
87+ }
88+ }
89+}
90+
91+impl ToString for EnvPair {
92+ fn to_string(&self) -> String {
93+ format!("{}={}", self.key, self.value)
94+ }
95+}
96+
97+pub fn create_infra_atrs(domain: &str, namespace: &str, name: &str) -> Vec<String> {
98+ let chart = INFRA_CHART_NAME;
99+ let rn = release_name(chart, name);
100+ let db = rn.replace("-", "_");
101+ let es = "elasticsearch";
102+
103+ vec![
104+ "-d",
105+ "deploy",
106+ "--release-name",
107+ &rn,
108+ "--set",
109+ &format!("b2b-kafka-int.zk={}-zk-0.{}-zk.{}/int", rn, rn, namespace),
110+ "--set",
111+ &format!(
112+ "b2b-{}.cluster_hosts={}-{}-0.{}-{}.{}",
113+ es, rn, es, rn, es, namespace
114+ ),
115+ "--set",
116+ &format!("b2b-postgres.postgres_db={}", db),
117+ "--set",
118+ &format!("global.staging_name={}", name),
119+ "--set",
120+ &format!(
121+ "b2b-kibana.elasic_hosts=http://{}-{}-{}-0.{}-{}-{}.{}:9200",
122+ chart, name, es, chart, name, es, namespace
123+ ),
124+ "--set",
125+ &format!("b2b-kibana.domain=kibana.{}.{}", name, domain),
126+ chart,
127+ ]
128+ .iter()
129+ .map(ToString::to_string)
130+ .collect::<Vec<_>>()
131+}
132+
133+pub fn create_app_atrs(
134+ domain: &str,
135+ namespace: &str,
136+ name: &str,
137+ tag: &str,
138+ envs: Vec<EnvPair>,
139+) -> Vec<String> {
140+ let rn = release_name(APP_CHART_NAME, name);
141+ let rni = release_name(INFRA_CHART_NAME, name);
142+ let es = "elasticsearch";
143+
144+ let mut atrs = vec![
145+ "-d",
146+ "deploy",
147+ "--release-name",
148+ &rn,
149+ "--set",
150+ "b2b-app.api_enabled=true",
151+ "--set",
152+ &format!("b2b-app.email_domain={}.{}", name, domain),
153+ "--set",
154+ &format!("b2b-app.domain={}.{}", name, domain),
155+ "--set",
156+ &format!(
157+ "b2b-app.connections.pg_instance=avia:avia@{}-postgres-0.{}-postgres.{}:5432",
158+ rni, rni, namespace
159+ ),
160+ "--set",
161+ &format!(
162+ "b2b-app.connections.elastic=http://{}-{}.{}:9200",
163+ rni, es, namespace
164+ ),
165+ "--set",
166+ &format!(
167+ "b2b-app.connections.elasic_hosts=http://{}-{}-0.{}-{}.{}:9200",
168+ rni, es, rni, es, namespace
169+ ),
170+ "--set",
171+ &format!(
172+ "b2b-app.connections.redis={}-redis-0.{}-redis.{}:6379",
173+ rni, rni, namespace
174+ ),
175+ "--set",
176+ &format!(
177+ "b2b-app.connections.kafka_ext={}-kafka-int-0.{}-kafka-int:9092",
178+ rni, rni
179+ ),
180+ "--set",
181+ &format!(
182+ "b2b-app.connections.kafka_int={}-kafka-int-0.{}-kafka-int:9092",
183+ rni, rni
184+ ),
185+ "--set",
186+ &format!("global.staging_name={}", name),
187+ ]
188+ .iter()
189+ .map(ToString::to_string)
190+ .collect::<Vec<_>>();
191+
192+ let mut env_atrs = envs
193+ .into_iter()
194+ .map(|e| {
195+ vec![
196+ "--set".to_string(),
197+ format!("b2b-app.env.{}", e.to_string()),
198+ ]
199+ })
200+ .flatten()
201+ .collect::<Vec<_>>();
202+ let mut tagged_release_name = vec![tagged_release(APP_CHART_NAME, tag)];
203+
204+ atrs.append(&mut env_atrs);
205+ atrs.append(&mut tagged_release_name);
206+
207+ atrs
208+}
209+
210+pub fn delete_infra_atrs(name: &str) -> Vec<String> {
211+ vec!["delete", &release_name(INFRA_CHART_NAME, name), "--purge"]
212+ .iter()
213+ .map(ToString::to_string)
214+ .collect::<Vec<_>>()
215+}
216+
217+pub fn delete_app_atrs(name: &str) -> Vec<String> {
218+ vec!["delete", &release_name(APP_CHART_NAME, name), "--purge"]
219+ .iter()
220+ .map(ToString::to_string)
221+ .collect::<Vec<_>>()
222+}
223+
224+pub fn delete_pvcs_atrs(namespace: &str, name: &str) -> Vec<String> {
225+ vec![
226+ "delete",
227+ "pvc",
228+ "-n",
229+ namespace,
230+ "-l",
231+ &format!("staging={}", name),
232+ ]
233+ .iter()
234+ .map(ToString::to_string)
235+ .collect::<Vec<_>>()
236+}
237+
238+pub fn delete_cert_atrs(namespace: &str, name: &str) -> Vec<String> {
239+ vec![
240+ "delete",
241+ "certificate",
242+ "-n",
243+ namespace,
244+ &format!("b2b-dm-staging-{}-tls", name),
245+ &format!("b2b-dm-staging-{}-tls-tasker", name),
246+ &format!("b2b-infra-dm-staging-{}-kibana-tls", name),
247+ ]
248+ .iter()
249+ .map(ToString::to_string)
250+ .collect::<Vec<_>>()
251+}
252+
253+fn release_name(chart_name: &str, name: &str) -> String {
254+ format!("{}-{}", chart_name, name)
255+}
256+
257+fn tagged_release(chart_name: &str, tag: &str) -> String {
258+ format!("{}:{}", chart_name, tag)
259+}