use crate::{
InternalError,
config::{
Config, ConfigError, ConfigModel,
schema::{
AppInitMode, CanisterConfig, DelegatedTokenConfig, DelegationProofCacheProfile,
DirectoryConfig, LogConfig, RoleAttestationConfig, ScalingConfig, SubnetConfig,
},
},
ids::{CanisterRole, SubnetRole},
ops::{OpsError, prelude::*, runtime::env::EnvOps},
storage::stable::state::app::AppMode,
};
use std::sync::Arc;
use thiserror::Error as ThisError;
#[derive(Debug, ThisError)]
pub enum ConfigOpsError {
#[error(transparent)]
Config(#[from] ConfigError),
#[error("subnet {0} not found in configuration")]
SubnetNotFound(String),
#[error("canister {0} not defined in subnet {1}")]
CanisterNotFound(String, String),
}
impl From<ConfigOpsError> for InternalError {
fn from(err: ConfigOpsError) -> Self {
OpsError::from(err).into()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DelegationProofCachePolicy {
pub profile: DelegationProofCacheProfile,
pub capacity: usize,
pub active_window_secs: u64,
}
pub struct ConfigOps;
impl ConfigOps {
pub fn export_toml() -> Result<String, InternalError> {
let toml = Config::to_toml()?;
Ok(toml)
}
pub(crate) fn try_get_subnet(role: &SubnetRole) -> Result<SubnetConfig, InternalError> {
let cfg = Config::get()?;
cfg.get_subnet(role)
.ok_or_else(|| ConfigOpsError::SubnetNotFound(role.to_string()).into())
}
pub(crate) fn try_get_canister(
subnet_role: &SubnetRole,
canister_role: &CanisterRole,
) -> Result<CanisterConfig, InternalError> {
let subnet_cfg = Self::try_get_subnet(subnet_role)?;
subnet_cfg.get_canister(canister_role).ok_or_else(|| {
ConfigOpsError::CanisterNotFound(canister_role.to_string(), subnet_role.to_string())
.into()
})
}
pub(crate) fn get() -> Result<Arc<ConfigModel>, InternalError> {
let cfg = Config::get()?;
Ok(cfg)
}
pub(crate) fn controllers() -> Result<Vec<Principal>, InternalError> {
Ok(Config::get()?.controllers.clone())
}
pub(crate) fn log_config() -> Result<LogConfig, InternalError> {
Ok(Config::get()?.log.clone())
}
pub(crate) fn delegated_tokens_config() -> Result<DelegatedTokenConfig, InternalError> {
Ok(Config::get()?.auth.delegated_tokens.clone())
}
pub(crate) fn delegation_proof_cache_policy()
-> Result<DelegationProofCachePolicy, InternalError> {
let cfg = Self::delegated_tokens_config()?;
let profile = cfg.proof_cache.resolved_profile();
Ok(DelegationProofCachePolicy {
profile,
capacity: cfg.proof_cache.resolved_capacity(),
active_window_secs: u64::from(cfg.proof_cache.active_window_secs),
})
}
pub(crate) fn role_attestation_config() -> Result<RoleAttestationConfig, InternalError> {
Ok(Config::get()?.auth.role_attestation.clone())
}
pub(crate) fn app_init_mode() -> Result<AppMode, InternalError> {
let mode = match Config::get()?.app.init_mode {
AppInitMode::Enabled => AppMode::Enabled,
AppInitMode::Readonly => AppMode::Readonly,
AppInitMode::Disabled => AppMode::Disabled,
};
Ok(mode)
}
pub fn current_subnet() -> Result<SubnetConfig, InternalError> {
let subnet_role = EnvOps::subnet_role()?;
Self::try_get_subnet(&subnet_role)
}
pub(crate) fn current_canister() -> Result<CanisterConfig, InternalError> {
let subnet_role = EnvOps::subnet_role()?;
let canister_role = EnvOps::canister_role()?;
Self::try_get_canister(&subnet_role, &canister_role)
}
pub(crate) fn current_scaling_config() -> Result<Option<ScalingConfig>, InternalError> {
Ok(Self::current_canister()?.scaling)
}
pub(crate) fn current_directory_config() -> Result<Option<DirectoryConfig>, InternalError> {
Ok(Self::current_canister()?.directory)
}
pub(crate) fn current_subnet_canister(
canister_role: &CanisterRole,
) -> Result<CanisterConfig, InternalError> {
let subnet_role = EnvOps::subnet_role()?;
Self::try_get_canister(&subnet_role, canister_role)
}
}