canic_core/ops/
config.rs

1use crate::{
2    Error,
3    config::{
4        Config,
5        schema::{CanisterConfig, SubnetConfig},
6    },
7    ids::{CanisterRole, SubnetRole},
8    ops::{
9        OpsError,
10        storage::env::{EnvOps, EnvOpsError},
11    },
12};
13use thiserror::Error as ThisError;
14
15///
16/// ConfigOpsError
17///
18
19#[derive(Debug, ThisError)]
20pub enum ConfigOpsError {
21    #[error("subnet {0} not found in configuration")]
22    SubnetNotFound(String),
23
24    #[error("canister {0} not defined in subnet {1}")]
25    CanisterNotFound(String, String),
26
27    #[error(transparent)]
28    EnvOpsError(#[from] EnvOpsError),
29}
30
31impl From<ConfigOpsError> for Error {
32    fn from(err: ConfigOpsError) -> Self {
33        OpsError::from(err).into()
34    }
35}
36
37///
38/// ConfigOps
39///
40/// Ops-layer façade for configuration access.
41///
42/// Responsibilities:
43/// - Provide fallible lookups over the config *model* (`try_get_subnet`,
44///   `try_get_canister`).
45/// - Provide "current context" helpers (`cfg_current_subnet`,
46///   `cfg_current_canister`) that combine `EnvOps` (who am I?) with the
47///   static configuration model.
48///
49
50pub struct ConfigOps;
51
52impl ConfigOps {
53    /// Fetch a subnet configuration by type.
54    pub fn try_get_subnet(role: &SubnetRole) -> Result<SubnetConfig, Error> {
55        let cfg = Config::try_get()
56            .ok_or_else(|| Error::custom("config must be initialized before use"))?;
57
58        let subnet_cfg = cfg
59            .get_subnet(role)
60            .ok_or_else(|| ConfigOpsError::SubnetNotFound(role.to_string()))?;
61
62        Ok(subnet_cfg)
63    }
64
65    /// Get a canister configuration inside a specific subnet.
66    pub fn try_get_canister(
67        subnet_role: &SubnetRole,
68        canister_role: &CanisterRole,
69    ) -> Result<CanisterConfig, Error> {
70        let subnet_cfg = Self::try_get_subnet(subnet_role)?;
71
72        let canister_cfg = subnet_cfg.get_canister(canister_role).ok_or_else(|| {
73            ConfigOpsError::CanisterNotFound(canister_role.to_string(), subnet_role.to_string())
74        })?;
75
76        Ok(canister_cfg)
77    }
78
79    /// Fetch the configuration record for the *current* subnet.
80    pub fn current_subnet() -> Result<SubnetConfig, Error> {
81        let subnet_role = EnvOps::try_get_subnet_role()?;
82
83        // delegate lookup to ConfigOps
84        let subnet_cfg = Self::try_get_subnet(&subnet_role)?;
85
86        Ok(subnet_cfg)
87    }
88
89    pub fn current_canister() -> Result<CanisterConfig, Error> {
90        let subnet_role = EnvOps::try_get_subnet_role()?;
91        let canister_role = EnvOps::try_get_canister_role()?;
92
93        // delegate lookup to ConfigOps or use subnet_cfg (either is fine)
94        let canister_cfg = Self::try_get_canister(&subnet_role, &canister_role)?;
95
96        Ok(canister_cfg)
97    }
98
99    pub fn current_subnet_canister(canister_role: &CanisterRole) -> Result<CanisterConfig, Error> {
100        let subnet_role = EnvOps::try_get_subnet_role()?;
101
102        // delegate lookup to ConfigOps or use subnet_cfg (either is fine)
103        let canister_cfg = Self::try_get_canister(&subnet_role, canister_role)?;
104
105        Ok(canister_cfg)
106    }
107}