1use core::time;
2
3use k8s_openapi::api::core::v1::Pod;
4use kube::{
5 api::{AttachParams, AttachedProcess},
6 Api,
7};
8use serde_json::Value;
9use tokio_stream::StreamExt;
10use tokio_util::io::ReaderStream;
11
12use crate::common::{
13 kubernetes::{self, get_k8s_client_programmatically},
14 vault::http_client::fetch_shasta_k8s_secrets,
15};
16
17pub async fn get_container_attachment_to_conman(
18 xname: &String,
19 vault_base_url: &str,
20 vault_secret_path: &str,
21 vault_role_id: &str,
22 k8s_api_url: &str,
23) -> AttachedProcess {
24 log::info!("xname: {}", xname);
25 let shasta_k8s_secrets =
26 fetch_shasta_k8s_secrets(vault_base_url, vault_secret_path, vault_role_id).await;
27
28 let client = get_k8s_client_programmatically(k8s_api_url, shasta_k8s_secrets)
29 .await
30 .unwrap();
31
32 let pods_fabric: Api<Pod> = Api::namespaced(client, "services");
33
34 let params = kube::api::ListParams::default()
35 .limit(1)
36 .labels("app.kubernetes.io/name=cray-console-operator");
37
38 let pods_objects = pods_fabric.list(¶ms).await.unwrap();
39
40 let console_operator_pod = &pods_objects.items[0];
41 let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();
42
43 log::info!("Console operator pod name '{}'", console_operator_pod_name);
44
45 let mut attached = pods_fabric
46 .exec(
47 &console_operator_pod_name,
48 vec!["sh", "-c", &format!("/app/get-node {}", xname)],
49 &AttachParams::default()
50 .container("cray-console-operator")
51 .stderr(false),
52 )
53 .await
54 .unwrap();
55
56 let mut stdout_stream = ReaderStream::new(attached.stdout().unwrap());
57 let next_stdout = stdout_stream.next().await.unwrap().unwrap();
58 let stdout_str = std::str::from_utf8(&next_stdout).unwrap();
59 let output_json: Value = serde_json::from_str(stdout_str).unwrap();
60
61 let console_pod_name = output_json["podname"].as_str().unwrap();
62
63 let command = vec!["conman", "-j", xname]; log::info!("Console pod name: {}", console_pod_name,);
68
69 log::info!("Connecting to console {}", xname);
70
71 let attachment_rslt = pods_fabric
72 .exec(
73 console_pod_name,
74 command,
75 &AttachParams::default()
76 .container("cray-console-node")
77 .stdin(true)
78 .stdout(true)
79 .stderr(false) .tty(true),
81 )
82 .await;
83
84 if let Ok(attachment) = attachment_rslt {
85 attachment
86 } else {
87 eprintln!(
88 "Error attaching to container 'cray-console-node' in pod '{}'. Exit",
89 console_pod_name
90 );
91 std::process::exit(1);
92 }
93}
94
95pub async fn get_container_attachment_to_cfs_session_image_target(
96 cfs_session_name: &str,
97 vault_base_url: &str,
98 vault_secret_path: &str,
99 vault_role_id: &str,
100 k8s_api_url: &str,
101) -> AttachedProcess {
102 let shasta_k8s_secrets =
103 fetch_shasta_k8s_secrets(vault_base_url, vault_secret_path, vault_role_id).await;
104
105 let client = get_k8s_client_programmatically(k8s_api_url, shasta_k8s_secrets)
106 .await
107 .unwrap();
108
109 let pods_fabric: Api<Pod> = Api::namespaced(client.clone(), "services");
110
111 let params = kube::api::ListParams::default()
112 .limit(1)
113 .labels(format!("cfsession={}", cfs_session_name).as_str());
114
115 let mut pods = pods_fabric.list(¶ms).await.unwrap();
116
117 let mut i = 0;
118 let max = 30;
119
120 while pods.items.is_empty() && i <= max {
122 println!(
123 "Pod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}",
124 cfs_session_name,
125 i + 1,
126 max
127 );
128 i += 1;
129 tokio::time::sleep(time::Duration::from_secs(2)).await;
130 pods = pods_fabric.list(¶ms).await.unwrap();
131 }
132
133 if pods.items.is_empty() {
134 eprintln!(
135 "Pod for cfs session {} not ready. Aborting operation",
136 cfs_session_name
137 );
138 std::process::exit(1);
139 }
140
141 let console_operator_pod = &pods.items[0].clone();
142
143 let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();
144
145 log::info!("Ansible pod name: {}", console_operator_pod_name);
146
147 let attached = pods_fabric
148 .exec(
149 &console_operator_pod_name,
150 vec![
151 "sh",
152 "-c",
153 "cat /inventory/hosts/01-cfs-generated.yaml | grep cray-ims- | head -n 1",
154 ],
155 &AttachParams::default().container("ansible").stderr(false),
156 )
157 .await
158 .unwrap();
159
160 let mut output = kubernetes::get_output(attached).await;
161 log::info!("{output}");
162
163 output = output.trim().to_string();
164
165 log::info!("{output}");
166
167 output = output.strip_prefix("ansible_host: ").unwrap().to_string();
168
169 output = output
170 .strip_suffix("-service.ims.svc.cluster.local")
171 .unwrap()
172 .to_string();
173
174 log::info!("{output}");
175
176 let ansible_target_container_label = output + "-customize";
177
178 log::info!("{ansible_target_container_label}");
179
180 let pods_fabric: Api<Pod> = Api::namespaced(client, "ims");
183
184 let params = kube::api::ListParams::default()
185 .limit(1)
186 .labels(format!("job-name={}", ansible_target_container_label).as_str());
187
188 let mut pods = pods_fabric.list(¶ms).await.unwrap();
189
190 let mut i = 0;
191 let max = 30;
192
193 while pods.items.is_empty() && i <= max {
195 println!(
196 "Pod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}",
197 cfs_session_name,
198 i + 1,
199 max
200 );
201 i += 1;
202 tokio::time::sleep(time::Duration::from_secs(2)).await;
203 pods = pods_fabric.list(¶ms).await.unwrap();
204 }
205
206 if pods.items.is_empty() {
207 eprintln!(
208 "Pod for cfs session {} not ready. Aborting operation",
209 cfs_session_name
210 );
211 std::process::exit(1);
212 }
213
214 let console_operator_pod = &pods.items[0].clone();
215
216 log::info!("Connecting to console ansible target container");
217
218 let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();
219
220 let command = vec!["bash"]; let attachment_rslt = pods_fabric
225 .exec(
226 &console_operator_pod_name,
227 command,
228 &AttachParams::default()
229 .container("sshd")
230 .stdin(true)
231 .stdout(true)
232 .stderr(false) .tty(true),
234 )
235 .await;
236
237 if let Ok(attachment) = attachment_rslt {
238 attachment
239 } else {
240 eprintln!(
241 "Error attaching to container 'sshd' in pod '{}'. Exit",
242 console_operator_pod_name
243 );
244 std::process::exit(1);
245 }
246}