use std::collections::HashMap;
use manta_backend_dispatcher::error::Error;
use manta_backend_dispatcher::interfaces::hsm::group::GroupTrait;
use crate::server::common::app_context::InfraContext;
use crate::service::authorization::validate_user_group_members_access;
use crate::service::node_ops;
#[derive(serde::Serialize, utoipa::ToSchema)]
pub struct NodeMigrationResult {
pub target_hsm_name: String,
pub parent_hsm_name: String,
pub target_members: Vec<String>,
pub parent_members: Vec<String>,
}
pub async fn migrate_nodes(
infra: &InfraContext<'_>,
token: &str,
target_group_name_vec: &[String],
parent_group_name_vec: &[String],
hosts_expression: &str,
dry_run: bool,
create_group: bool,
) -> Result<(Vec<String>, Vec<NodeMigrationResult>), Error> {
let xname_to_move_vec = node_ops::from_user_hosts_expression_to_xname_vec(
infra,
token,
hosts_expression,
false,
)
.await?;
if xname_to_move_vec.is_empty() {
return Err(Error::BadRequest(
"The list of nodes to operate is empty. Nothing to do".to_string(),
));
}
validate_user_group_members_access(infra, token, &xname_to_move_vec).await?;
let mut group_summary: HashMap<String, Vec<String>> =
node_ops::get_curated_group_from_xname_hostlist(
infra,
token,
&xname_to_move_vec,
)
.await?;
group_summary.retain(|hsm_name, _| parent_group_name_vec.contains(hsm_name));
tracing::debug!("xnames to move: {:?}", xname_to_move_vec);
let mut results = Vec::new();
for target_name in target_group_name_vec {
if infra.backend.get_group(token, target_name).await.is_ok() {
tracing::debug!("The group '{target_name}' exists, good.");
} else if create_group {
tracing::info!(
"The group {} does not exist, it will be created",
target_name
);
if dry_run {
return Err(Error::BadRequest(format!(
"Dry-run selected, the group '{target_name}' created"
)));
}
} else {
return Err(Error::NotFound(format!(
"The group '{target_name}' does not exist and the option \
to create the group was not specified"
)));
}
for (parent_group_name, xnames) in &group_summary {
let xnames_ref: Vec<&str> = xnames.iter().map(String::as_str).collect();
let (mut target_members, mut parent_members) = infra
.backend
.migrate_group_members(
token,
target_name,
parent_group_name,
&xnames_ref,
dry_run,
)
.await?;
target_members.sort();
parent_members.sort();
results.push(NodeMigrationResult {
target_hsm_name: target_name.clone(),
parent_hsm_name: parent_group_name.clone(),
target_members,
parent_members,
});
}
}
Ok((xname_to_move_vec, results))
}