Skip to main content

canic_host/installed_fleet/
mod.rs

1use crate::{
2    fleet_catalog::{FleetCatalogEntryV1, FleetCatalogError, read_fleet_catalog_entry_from_root},
3    icp::IcpCommandError,
4    registry::{RegistryEntry, RegistryParseError},
5    replica_query::ReplicaQueryError,
6};
7use std::{collections::BTreeMap, path::Path};
8use thiserror::Error as ThisError;
9
10///
11/// InstalledFleetRequest
12///
13
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct InstalledFleetRequest {
16    pub fleet: String,
17    pub environment: String,
18    pub icp: String,
19    pub detect_lost_local_root: bool,
20}
21
22///
23/// InstalledFleetResolution
24///
25
26#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct InstalledFleetResolution {
28    pub source: InstalledFleetSource,
29    pub fleet: FleetCatalogEntryV1,
30    pub registry: InstalledFleetRegistry,
31    pub topology: ResolvedFleetTopology,
32}
33
34///
35/// InstalledFleetSource
36///
37
38#[derive(Clone, Copy, Debug, Eq, PartialEq)]
39pub enum InstalledFleetSource {
40    LocalReplica,
41    IcpCli,
42}
43
44///
45/// InstalledFleetRegistry
46///
47
48#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct InstalledFleetRegistry {
50    pub root_canister_id: String,
51    pub entries: Vec<RegistryEntry>,
52}
53
54///
55/// ResolvedFleetTopology
56///
57
58#[derive(Clone, Debug, Eq, PartialEq)]
59pub struct ResolvedFleetTopology {
60    pub root_canister_id: String,
61    pub children_by_parent: BTreeMap<Option<String>, Vec<String>>,
62    pub roles_by_canister: BTreeMap<String, String>,
63}
64
65///
66/// InstalledFleetError
67///
68
69#[derive(Debug, ThisError)]
70pub enum InstalledFleetError {
71    #[error("Fleet {fleet} is not installed on environment {environment}")]
72    NoInstalledFleet { environment: String, fleet: String },
73
74    #[error("failed to read the canonical-network Fleet catalog: {0}")]
75    FleetCatalog(#[from] FleetCatalogError),
76
77    #[error("local replica query failed: {0}")]
78    ReplicaQuery(#[source] ReplicaQueryError),
79
80    #[error(transparent)]
81    Icp(#[from] IcpCommandError),
82
83    #[error(
84        "Fleet {fleet} points to root {root}, but that canister is not present on environment {environment}"
85    )]
86    LostLocalFleet {
87        fleet: String,
88        environment: String,
89        root: String,
90    },
91
92    #[error(
93        "Fleet {fleet} is Coordinator-anchored at {coordinator}; the removed single-root topology resolver cannot serve this operation"
94    )]
95    CoordinatorAnchoredTopologyUnavailable { fleet: String, coordinator: String },
96
97    #[error(transparent)]
98    Registry(#[from] RegistryParseError),
99
100    #[error(transparent)]
101    Io(#[from] std::io::Error),
102}
103
104pub fn resolve_installed_fleet_from_root(
105    request: &InstalledFleetRequest,
106    icp_root: &Path,
107) -> Result<InstalledFleetResolution, InstalledFleetError> {
108    let fleet = read_installed_fleet_from_root(&request.environment, &request.fleet, icp_root)?;
109    Err(
110        InstalledFleetError::CoordinatorAnchoredTopologyUnavailable {
111            fleet: fleet.fleet_name.to_string(),
112            coordinator: fleet.coordinator_principal,
113        },
114    )
115}
116
117pub fn read_installed_fleet_from_root(
118    environment: &str,
119    fleet: &str,
120    icp_root: &Path,
121) -> Result<FleetCatalogEntryV1, InstalledFleetError> {
122    read_fleet_catalog_entry_from_root(icp_root, environment, fleet)
123        .map_err(InstalledFleetError::FleetCatalog)?
124        .ok_or_else(|| InstalledFleetError::NoInstalledFleet {
125            environment: environment.to_string(),
126            fleet: fleet.to_string(),
127        })
128}
129
130#[cfg(test)]
131mod tests;