use crate::config::{self, ConfigEntity};
use crate::error::{Error, Result};
use crate::output::{CreateOutput, MergeOutput, RemoveResult};
use crate::project;
use serde::{Deserialize, Serialize};
pub mod check;
pub mod exec;
pub mod status;
pub use check::{collect_check, FleetCheckSummary, FleetComponentCheck, FleetProjectCheck};
pub use exec::{collect_exec, FleetExecProjectResult, FleetExecSummary};
pub use status::{collect_status, FleetComponentStatus, FleetProjectStatus};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Fleet {
#[serde(skip_deserializing, default)]
pub id: String,
#[serde(default)]
pub project_ids: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
impl Fleet {
pub fn new(id: String, project_ids: Vec<String>) -> Self {
Self {
id,
project_ids,
description: None,
}
}
}
impl ConfigEntity for Fleet {
const ENTITY_TYPE: &'static str = "fleet";
const DIR_NAME: &'static str = "fleets";
fn id(&self) -> &str {
&self.id
}
fn set_id(&mut self, id: String) {
self.id = id;
}
fn not_found_error(id: String, suggestions: Vec<String>) -> Error {
Error::fleet_not_found(id, suggestions)
}
}
entity_crud!(Fleet; list_ids, merge);
pub fn add_project(fleet_id: &str, project_id: &str) -> Result<Fleet> {
let mut fleet = load(fleet_id)?;
if !project::exists(project_id) {
let suggestions = config::find_similar_ids::<crate::project::Project>(project_id);
return Err(Error::project_not_found(project_id, suggestions));
}
if !fleet.project_ids.contains(&project_id.to_string()) {
fleet.project_ids.push(project_id.to_string());
save(&fleet)?;
}
Ok(fleet)
}
pub fn remove_project(fleet_id: &str, project_id: &str) -> Result<Fleet> {
let mut fleet = load(fleet_id)?;
fleet.project_ids.retain(|id| id != project_id);
save(&fleet)?;
Ok(fleet)
}
pub fn get_projects(fleet_id: &str) -> Result<Vec<crate::project::Project>> {
let fleet = load(fleet_id)?;
let mut projects = Vec::new();
for project_id in &fleet.project_ids {
if let Ok(project) = project::load(project_id) {
projects.push(project);
}
}
Ok(projects)
}
pub fn component_usage(fleet_id: &str) -> Result<std::collections::HashMap<String, Vec<String>>> {
let fleet = load(fleet_id)?;
let mut usage: std::collections::HashMap<String, Vec<String>> =
std::collections::HashMap::new();
for project_id in &fleet.project_ids {
if let Ok(project) = project::load(project_id) {
for component_id in project::project_component_ids(&project) {
usage
.entry(component_id)
.or_default()
.push(project_id.clone());
}
}
}
Ok(usage)
}