use crate::{
cfs,
error::Error,
hsm::{
self,
group::{
hacks::{filter_roles_and_subroles, filter_system_hsm_group_names},
types::Group,
},
},
};
use std::io::{self, Write};
use super::http_client::v2::types::CfsSessionGetResponse;
pub fn check_cfs_session_against_groups_available(
cfs_session: &CfsSessionGetResponse,
group_available: Vec<Group>,
) -> bool {
group_available.iter().any(|group| {
cfs_session
.get_target_hsm()
.is_some_and(|group_vec| group_vec.contains(&group.label))
|| cfs_session
.get_target_xname()
.is_some_and(|session_xname_vec| {
session_xname_vec
.iter()
.all(|xname| group.get_members().contains(xname))
})
})
}
pub fn is_session_image_generic(cfs_session: &CfsSessionGetResponse) -> bool {
let target_group_vec_opt = cfs_session.get_target_hsm();
let is_image = cfs_session.is_target_def_image();
if let (Some(mut target_group_vec), true) = (target_group_vec_opt, is_image) {
target_group_vec = filter_roles_and_subroles(target_group_vec);
target_group_vec = filter_system_hsm_group_names(target_group_vec);
log::debug!(
"CFS session {} is generic: {}",
cfs_session.name.as_ref().unwrap(),
target_group_vec.is_empty()
);
target_group_vec.is_empty()
} else {
false
}
}
pub async fn filter_by_hsm(
shasta_token: &str,
shasta_base_url: &str,
shasta_root_cert: &[u8],
cfs_session_vec: &mut Vec<CfsSessionGetResponse>,
hsm_group_name_vec: &[String],
limit_number_opt: Option<&u8>,
keep_generic_sessions: bool,
) -> Result<(), Error> {
log::info!("Filter CFS sessions by groups");
let xname_vec: Vec<String> =
hsm::group::utils::get_member_vec_from_hsm_name_vec(
shasta_token,
shasta_base_url,
shasta_root_cert,
&hsm_group_name_vec,
)
.await?;
filter(
cfs_session_vec,
hsm_group_name_vec.to_vec(),
xname_vec,
limit_number_opt,
keep_generic_sessions,
)
}
pub async fn filter_by_xname(
shasta_token: &str,
shasta_base_url: &str,
shasta_root_cert: &[u8],
cfs_session_vec: &mut Vec<CfsSessionGetResponse>,
xname_vec: &[&str],
limit_number_opt: Option<&u8>,
keep_generic_sessions: bool,
) -> Result<(), Error> {
log::info!("Filter CFS sessions by xnames");
let hsm_group_name_from_xnames_vec: Vec<String> =
hsm::group::utils::get_hsm_group_name_vec_from_xname_vec(
shasta_token,
shasta_base_url,
shasta_root_cert,
xname_vec,
)
.await;
log::info!(
"HSM groups that belongs to xnames {:?} are: {:?}",
xname_vec,
hsm_group_name_from_xnames_vec
);
filter(
cfs_session_vec,
Vec::new(),
xname_vec
.iter()
.map(|xname| xname.to_string())
.collect::<Vec<String>>(),
limit_number_opt,
keep_generic_sessions,
)
}
pub fn filter(
cfs_session_vec: &mut Vec<CfsSessionGetResponse>,
hsm_group_name_available_vec: Vec<String>,
xname_available_vec: Vec<String>,
limit_number_opt: Option<&u8>,
keep_generic_sessions: bool,
) -> Result<(), Error> {
log::info!("Filter CFS sessions by groups");
cfs_session_vec.retain(|cfs_session| {
cfs_session.get_target_hsm().is_some_and(|target_hsm_vec| {
(keep_generic_sessions && is_session_image_generic(cfs_session))
|| target_hsm_vec.iter().any(|target_hsm| {
hsm_group_name_available_vec
.iter()
.any(|hsm_group_name| hsm_group_name.contains(target_hsm))
})
}) || cfs_session
.get_target_xname()
.is_some_and(|target_xname_vec| {
target_xname_vec
.iter()
.any(|target_xname| xname_available_vec.contains(target_xname))
})
});
cfs_session_vec.sort_by(|a, b| {
a.get_start_time()
.unwrap()
.cmp(&b.get_start_time().unwrap())
});
if let Some(limit_number) = limit_number_opt {
*cfs_session_vec = cfs_session_vec
[cfs_session_vec.len().saturating_sub(*limit_number as usize)..]
.to_vec();
}
Ok(())
}
pub fn filter_by_cofiguration(
cfs_session_vec: &mut Vec<CfsSessionGetResponse>,
cfs_configuration_name: &str,
) {
log::info!(
"Filter CFS sessions by configuration name '{}'",
cfs_configuration_name
);
cfs_session_vec.retain(|cfs_session| {
cfs_session.configuration_namen().as_deref() == Some(cfs_configuration_name)
});
}
pub fn find_cfs_session_related_to_image_id(
cfs_session_vec: &[CfsSessionGetResponse],
image_id: &str,
) -> Option<CfsSessionGetResponse> {
cfs_session_vec
.iter()
.find(|cfs_session| {
cfs_session
.get_first_result_id()
.is_some_and(|result_id| result_id == image_id)
})
.cloned()
}
pub fn get_cfs_configuration_name(
cfs_session: &CfsSessionGetResponse,
) -> Option<String> {
cfs_session
.configuration
.as_ref()
.unwrap()
.name
.as_ref()
.cloned()
}
pub fn get_image_id_cfs_configuration_target_tuple_vec(
cfs_session_vec: Vec<CfsSessionGetResponse>,
) -> Vec<(String, String, Vec<String>)> {
let mut image_id_cfs_configuration_target_from_cfs_session: Vec<(
String,
String,
Vec<String>,
)> = Vec::new();
cfs_session_vec.iter().for_each(|cfs_session| {
let result_id: &str = cfs_session.first_result_id().unwrap_or_default();
let target: Vec<String> = cfs_session
.get_target_hsm()
.or_else(|| cfs_session.get_target_xname())
.unwrap_or_default();
let cfs_configuration = cfs_session.configuration_namen().unwrap();
image_id_cfs_configuration_target_from_cfs_session.push((
result_id.to_string(),
cfs_configuration.to_string(),
target,
));
});
image_id_cfs_configuration_target_from_cfs_session
}
pub fn get_image_id_cfs_configuration_target_for_existing_images_tuple_vec(
cfs_session_vec: &[CfsSessionGetResponse],
) -> Vec<(String, String, Vec<String>)> {
let mut image_id_cfs_configuration_target_from_cfs_session: Vec<(
String,
String,
Vec<String>,
)> = Vec::new();
cfs_session_vec.iter().for_each(|cfs_session| {
if let Some(result_id) = cfs_session.get_first_result_id() {
let target: Vec<String> = cfs_session
.get_target_hsm()
.or_else(|| cfs_session.get_target_xname())
.unwrap_or_default();
let cfs_configuration = cfs_session.configuration_namen().unwrap();
image_id_cfs_configuration_target_from_cfs_session.push((
result_id.to_string(),
cfs_configuration.to_string(),
target,
));
} else {
image_id_cfs_configuration_target_from_cfs_session.push((
"".to_string(),
"".to_string(),
vec![],
));
}
});
image_id_cfs_configuration_target_from_cfs_session
}
#[deprecated(note = "Use `images_id_from_cfs_session` instead")]
pub fn get_image_id_from_cfs_session_vec(
cfs_session_vec: &[CfsSessionGetResponse],
) -> Vec<String> {
let mut image_id_vec: Vec<String> = cfs_session_vec
.iter()
.flat_map(|cfs_session| cfs_session.get_result_id_vec())
.collect();
image_id_vec.sort();
image_id_vec.dedup();
image_id_vec
}
pub fn images_id_from_cfs_session(
cfs_session_vec: &[CfsSessionGetResponse],
) -> impl Iterator<Item = &str> {
let mut image_id_vec: Vec<&str> = cfs_session_vec
.iter()
.flat_map(|cfs_session| cfs_session.results_id())
.collect();
image_id_vec.sort();
image_id_vec.dedup();
image_id_vec.into_iter()
}
pub async fn wait_cfs_session_to_finish(
shasta_token: &str,
shasta_base_url: &str,
shasta_root_cert: &[u8],
cfs_session_id: &str,
) -> Result<(), Error> {
let mut i = 0;
let max = 3000; loop {
let cfs_session_vec = cfs::session::get_and_sort(
shasta_token,
shasta_base_url,
shasta_root_cert,
None,
None,
None,
Some(&cfs_session_id.to_string()),
None,
)
.await?;
let cfs_session = if cfs_session_vec.is_empty() {
return Err(Error::Message(format!(
"ERROR - CFS session '{}' missing. Exit",
cfs_session_id
)));
} else {
cfs_session_vec.first().unwrap().clone()
};
log::debug!("CFS session details:\n{:#?}", cfs_session);
let cfs_session_status =
cfs_session.status.unwrap().session.unwrap().status.unwrap();
if cfs_session_status != "complete" && i < max {
print!("\x1B[2K"); io::stdout().flush().unwrap();
println!(
"Waiting CFS session '{}' with status '{}'. Checking again in 2 secs. Attempt {} of {}.",
cfs_session_id, cfs_session_status, i, max
);
io::stdout().flush().unwrap();
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
i += 1;
} else {
println!(
"CFS session '{}' finished with status '{}'",
cfs_session_id, cfs_session_status
);
break Ok(());
}
}
}
pub async fn get_list_xnames_related_to_session(
group_available_vec: Vec<Group>,
cfs_session: CfsSessionGetResponse,
) -> Result<Vec<String>, Error> {
let target_group_xname_vec: Vec<String> = if let Some(target_hsm_vec) =
cfs_session.get_target_hsm()
{
group_available_vec
.into_iter()
.filter(|group_available| target_hsm_vec.contains(&group_available.label))
.flat_map(|group_available| group_available.get_members())
.collect()
} else {
vec![]
};
let target_xname_vec =
if let Some(target_xname) = cfs_session.get_target_xname() {
target_xname
} else {
vec![]
};
Ok([target_xname_vec, target_group_xname_vec].concat())
}