Skip to content

Commit

Permalink
add new method to connect to CFS sessino target ansible container to …
Browse files Browse the repository at this point in the history
…build an image
  • Loading branch information
Manuel Sopena Ballesteros committed Aug 20, 2023
1 parent 96fc745 commit 3f65a5c
Show file tree
Hide file tree
Showing 2 changed files with 314 additions and 4 deletions.
161 changes: 158 additions & 3 deletions src/manta/console.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use core::time;
use std::thread;

use k8s_openapi::api::core::v1::Pod;
use kube::{
api::{AttachParams, AttachedProcess},
Expand All @@ -9,18 +12,17 @@ use tokio_util::io::ReaderStream;

use crate::{
common::vault::http_client::fetch_shasta_k8s_secrets,
shasta::kubernetes::get_k8s_client_programmatically,
shasta::kubernetes::{self, get_k8s_client_programmatically},
};

pub async fn get_container_attachment(
pub async fn get_container_attachment_to_conman(
xname: &String,
vault_base_url: &str,
vault_secret_path: &str,
vault_role_id: &str,
k8s_api_url: &str,
) -> AttachedProcess {
log::info!("xname: {}", xname);

let shasta_k8s_secrets =
fetch_shasta_k8s_secrets(vault_base_url, vault_secret_path, vault_role_id).await;

Expand Down Expand Up @@ -94,3 +96,156 @@ pub async fn get_container_attachment(
std::process::exit(1);
}
}

pub async fn get_container_attachment_to_cfs_session_image_target(
cfs_session_name: &str,
vault_base_url: &str,
vault_secret_path: &str,
vault_role_id: &str,
k8s_api_url: &str,
) -> AttachedProcess {
let shasta_k8s_secrets =
fetch_shasta_k8s_secrets(vault_base_url, vault_secret_path, vault_role_id).await;

let client = get_k8s_client_programmatically(k8s_api_url, shasta_k8s_secrets)
.await
.unwrap();

let pods_fabric: Api<Pod> = Api::namespaced(client.clone(), "services");

let params = kube::api::ListParams::default()
.limit(1)
.labels(format!("cfsession={}", cfs_session_name).as_str());

let mut pods = pods_fabric.list(&params).await.unwrap();

let mut i = 0;
let max = 300;

// Waiting for pod to start
while pods.items.is_empty() && i <= max {
format!(
"\nPod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}\n",
cfs_session_name,
i + 1,
max
);
i += 1;
thread::sleep(time::Duration::from_secs(2));
pods = pods_fabric.list(&params).await.unwrap();
}

if pods.items.is_empty() {
eprintln!(
"Pod for cfs session {} not ready. Aborting operation",
cfs_session_name
);
std::process::exit(1);
}

let console_operator_pod = &pods.items[0].clone();

let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();

log::info!("Ansible pod name: {}", console_operator_pod_name);

let attached = pods_fabric
.exec(
&console_operator_pod_name,
vec![
"sh",
"-c",
"cat /inventory/hosts/01-cfs-generated.yaml | grep cray-ims- | head -n 1",
],
&AttachParams::default().container("ansible").stderr(false),
)
.await
.unwrap();

let mut output = kubernetes::get_output(attached).await;
log::info!("{output}");

output = output.trim().to_string();

log::info!("{output}");

output = output.strip_prefix("ansible_host: ").unwrap().to_string();

output = output
.strip_suffix("-service.ims.svc.cluster.local")
.unwrap()
.to_string();

log::info!("{output}");

let ansible_target_container_label = output + "-customize";

log::info!("{ansible_target_container_label}");

// Find ansible target container

let pods_fabric: Api<Pod> = Api::namespaced(client, "ims");

let params = kube::api::ListParams::default()
.limit(1)
.labels(format!("job-name={}", ansible_target_container_label).as_str());

let mut pods = pods_fabric.list(&params).await.unwrap();

let mut i = 0;
let max = 300;

// Waiting for pod to start
while pods.items.is_empty() && i <= max {
format!(
"\nPod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}\n",
cfs_session_name,
i + 1,
max
);
i += 1;
thread::sleep(time::Duration::from_secs(2));
pods = pods_fabric.list(&params).await.unwrap();
}

if pods.items.is_empty() {
eprintln!(
"Pod for cfs session {} not ready. Aborting operation",
cfs_session_name
);
std::process::exit(1);
}

let console_operator_pod = &pods.items[0].clone();

log::info!("Connecting to console ansible target container");

let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();

let command = vec!["bash"]; // Enter the container and open conman to access node's console
// let command = vec!["bash"]; // Enter the container and open bash to start an interactive
// terminal session

let attachment_rslt = pods_fabric
.exec(
&console_operator_pod_name,
command,
&AttachParams::default()
.container("sshd")
.stdin(true)
.stdout(true)
.stderr(false) // Note to self: tty and stderr cannot both be true
.tty(true),
)
.await;

if attachment_rslt.is_ok() {
attachment_rslt.unwrap()
} else {
eprintln!(
"Error attaching to container, check 'kubectl -n services exec -it {} -c sshd'. Exit",
console_operator_pod_name
);
std::process::exit(1);
}
}
157 changes: 156 additions & 1 deletion src/shasta/kubernetes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use hyper::Uri;
use hyper_socks2::SocksConnector;
use k8s_openapi::api::core::v1::{Container, Pod};
use kube::{
api::ListParams,
api::{AttachParams, AttachedProcess, ListParams},
client::ConfigExt,
config::{
AuthInfo, Cluster, Context, KubeConfigOptions, Kubeconfig, NamedAuthInfo, NamedCluster,
Expand All @@ -15,6 +15,8 @@ use kube::{
Api,
};

use futures::StreamExt;

use secrecy::SecretString;
use serde_json::Value;

Expand Down Expand Up @@ -438,6 +440,159 @@ fn get_container_state(
}
}

pub async fn attach_cfs_session_container_target_k8s_service_name(
client: kube::Client,
cfs_session_name: &str,
) -> AttachedProcess {
let pods_fabric: Api<Pod> = Api::namespaced(client.clone(), "services");

let params = kube::api::ListParams::default()
.limit(1)
.labels(format!("cfsession={}", cfs_session_name).as_str());

let mut pods = pods_fabric.list(&params).await.unwrap();

let mut i = 0;
let max = 300;

// Waiting for pod to start
while pods.items.is_empty() && i <= max {
format!(
"\nPod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}\n",
cfs_session_name,
i + 1,
max
);
i += 1;
thread::sleep(time::Duration::from_secs(2));
pods = pods_fabric.list(&params).await.unwrap();
}

if pods.items.is_empty() {
eprintln!(
"Pod for cfs session {} not ready. Aborting operation",
cfs_session_name
);
std::process::exit(1);
}

let console_operator_pod = &pods.items[0].clone();

let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();

let attached = pods_fabric
.exec(
&console_operator_pod_name,
vec![
"sh",
"-c",
"cat /inventory/hosts/01-cfs-generated.yaml | grep cray-ims- | head -n 1",
],
&AttachParams::default()
.container("cray-console-operator")
.stderr(false),
)
.await
.unwrap();

let mut output = get_output(attached).await;
log::info!("{output}");

output = output.trim().to_string();

println!("{output}");

output
.strip_prefix("ansible_host: ")
.unwrap()
.strip_suffix("-service.ims.svc.cluster.local")
.unwrap();

println!("{output}");

let ansible_target_container_label = output + "-customize";

println!("{ansible_target_container_label}");

// Find ansible target container

let pods_fabric: Api<Pod> = Api::namespaced(client, "ims");

let params = kube::api::ListParams::default()
.limit(1)
.labels(format!("job-name={}", ansible_target_container_label).as_str());

let mut pods = pods_fabric.list(&params).await.unwrap();

let mut i = 0;
let max = 300;

// Waiting for pod to start
while pods.items.is_empty() && i <= max {
format!(
"\nPod for cfs session {} not ready. Trying again in 2 secs. Attempt {} of {}\n",
cfs_session_name,
i + 1,
max
);
i += 1;
thread::sleep(time::Duration::from_secs(2));
pods = pods_fabric.list(&params).await.unwrap();
}

if pods.items.is_empty() {
eprintln!(
"Pod for cfs session {} not ready. Aborting operation",
cfs_session_name
);
std::process::exit(1);
}

let console_operator_pod = &pods.items[0].clone();

log::info!("Connecting to console ansible target container");

let console_operator_pod_name = console_operator_pod.metadata.name.clone().unwrap();

let command = vec!["bash"]; // Enter the container and open conman to access node's console
// let command = vec!["bash"]; // Enter the container and open bash to start an interactive
// terminal session

let attachment_rslt = pods_fabric
.exec(
&console_operator_pod_name,
command,
&AttachParams::default()
.container("sshd")
.stdin(true)
.stdout(true)
.stderr(false) // Note to self: tty and stderr cannot both be true
.tty(true),
)
.await;

if attachment_rslt.is_ok() {
attachment_rslt.unwrap()
} else {
eprintln!(
"Error attaching to container, check 'kubectl -n services exec -it {} -c sshd'. Exit",
console_operator_pod_name
);
std::process::exit(1);
}
}

pub async fn get_output(mut attached: AttachedProcess) -> String {
let stdout = tokio_util::io::ReaderStream::new(attached.stdout().unwrap());
let out = stdout
.filter_map(|r| async { r.ok().and_then(|v| String::from_utf8(v.to_vec()).ok()) })
.collect::<Vec<_>>()
.await
.join("");
attached.join().await.unwrap();
out
}

#[cfg(test)]
mod test {

Expand Down

0 comments on commit 3f65a5c

Please sign in to comment.