use std::{
collections::{BTreeMap, BTreeSet},
fs,
path::{Path, PathBuf},
};
mod model;
mod mutation;
mod projection;
pub use model::{
AttachedFleetRole, ConfiguredPoolExpectation, ConfiguredRoleLifecycle, DeclaredFleetRole,
LOCAL_ROOT_MIN_READY_CYCLES, RenamedFleetRole,
};
pub(super) use mutation::{
attach_fleet_role_source, declare_fleet_role_source, rename_fleet_role_source,
};
pub(super) use projection::{
configured_bootstrap_roles_from_source, configured_controllers_from_source,
configured_deployable_roles_from_source, configured_fleet_name_from_source,
configured_local_root_create_cycles_from_source, configured_pool_expectations_from_source,
configured_release_roles_from_source, configured_role_auto_create_from_source,
configured_role_capabilities_from_source, configured_role_details_from_source,
configured_role_kinds_from_source, configured_role_lifecycle_from_source,
configured_role_metrics_profiles_from_source, configured_role_topups_from_source,
};
pub fn configured_release_roles(
config_path: &Path,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_release_roles_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_deployable_roles(
config_path: &Path,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_deployable_roles_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_bootstrap_roles(
config_path: &Path,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_bootstrap_roles_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_install_targets(
config_path: &Path,
root_canister: &str,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let mut targets = vec![root_canister.to_string()];
targets.extend(configured_release_roles(config_path)?);
Ok(targets)
}
pub fn configured_local_root_create_cycles(
config_path: &Path,
) -> Result<u128, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_local_root_create_cycles_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_fleet_name(config_path: &Path) -> Result<String, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_fleet_name_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_controllers(
config_path: &Path,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_controllers_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_pool_expectations(
config_path: &Path,
) -> Result<Vec<ConfiguredPoolExpectation>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_pool_expectations_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_lifecycle(
config_path: &Path,
) -> Result<Vec<ConfiguredRoleLifecycle>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_lifecycle_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn declare_fleet_role(
config_path: &Path,
expected_fleet: &str,
role: &str,
package: &str,
) -> Result<DeclaredFleetRole, Box<dyn std::error::Error>> {
let source = fs::read_to_string(config_path)?;
let updated = declare_fleet_role_source(&source, expected_fleet, role, package)
.map_err(|err| format!("invalid {}: {err}", config_path.display()))?;
fs::write(config_path, updated.source)?;
Ok(updated.role)
}
pub fn attach_fleet_role(
config_path: &Path,
expected_fleet: &str,
role: &str,
subnet: &str,
kind: &str,
) -> Result<AttachedFleetRole, Box<dyn std::error::Error>> {
let source = fs::read_to_string(config_path)?;
let updated = attach_fleet_role_source(&source, expected_fleet, role, subnet, kind)
.map_err(|err| format!("invalid {}: {err}", config_path.display()))?;
fs::write(config_path, updated.source)?;
Ok(updated.role)
}
pub fn rename_fleet_role(
config_path: &Path,
expected_fleet: &str,
old_role: &str,
new_role: &str,
) -> Result<RenamedFleetRole, Box<dyn std::error::Error>> {
let source = fs::read_to_string(config_path)?;
let updated =
rename_fleet_role_source(&source, config_path, expected_fleet, old_role, new_role)
.map_err(|err| format!("invalid {}: {err}", config_path.display()))?;
fs::write(config_path, updated.source)?;
if let (Some(path), Some(source)) = (&updated.package_manifest, &updated.package_source) {
fs::write(path, source)?;
}
Ok(updated.role)
}
#[must_use]
pub fn matching_fleet_config_paths(choices: &[PathBuf], fleet: &str) -> Vec<PathBuf> {
choices
.iter()
.filter_map(|path| match configured_fleet_name(path) {
Ok(name) if name == fleet => Some(path.clone()),
Ok(_) | Err(_) => None,
})
.collect()
}
pub fn configured_role_kinds(
config_path: &Path,
) -> Result<BTreeMap<String, String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_kinds_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_capabilities(
config_path: &Path,
) -> Result<BTreeMap<String, Vec<String>>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_capabilities_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_auto_create(
config_path: &Path,
) -> Result<BTreeSet<String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_auto_create_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_topups(
config_path: &Path,
) -> Result<BTreeMap<String, String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_topups_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_metrics_profiles(
config_path: &Path,
) -> Result<BTreeMap<String, String>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_metrics_profiles_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}
pub fn configured_role_details(
config_path: &Path,
) -> Result<BTreeMap<String, Vec<String>>, Box<dyn std::error::Error>> {
let config_source = fs::read_to_string(config_path)?;
configured_role_details_from_source(&config_source)
.map_err(|err| format!("invalid {}: {err}", config_path.display()).into())
}