Skip to main content

ic_query/cloud_engine/
mod.rs

1//! CloudEngine control-plane and official Dashboard report models, adapters, and renderers.
2
3#[cfg(feature = "cloud-engine-host")]
4mod build;
5#[cfg(all(feature = "cloud-engine-host", feature = "subnet-catalog-host"))]
6mod list;
7mod model;
8mod provider;
9#[cfg(feature = "cloud-engine-host")]
10mod source;
11mod text;
12#[cfg(feature = "cloud-engine-host")]
13mod wire;
14
15#[cfg(feature = "cloud-engine-host")]
16use crate::runtime::RuntimeError;
17#[cfg(feature = "cloud-engine-host")]
18use thiserror::Error as ThisError;
19
20#[cfg(feature = "cloud-engine-host")]
21pub use build::{
22    build_cloud_engine_operator_report, build_cloud_engine_operator_report_with_source,
23    build_cloud_engine_prices_report, build_cloud_engine_prices_report_with_source,
24};
25#[cfg(all(feature = "cloud-engine-host", feature = "subnet-catalog-host"))]
26pub use list::{build_cloud_engine_list_report, build_cloud_engine_list_report_with_sources};
27#[cfg(all(feature = "cloud-engine-host", feature = "subnet-catalog-host"))]
28pub use model::{CloudEngineListReport, CloudEngineListRow, CloudEngineOperatorLookupStatus};
29pub use model::{
30    CloudEngineNodeType, CloudEngineOperatorReport, CloudEnginePriceRow, CloudEnginePricesReport,
31    CloudEngineReportContext,
32};
33#[cfg(feature = "cloud-engine-host")]
34pub use model::{
35    CloudEngineOperatorBindingSourceData, CloudEngineOperatorSourceData,
36    CloudEnginePricesSourceData,
37};
38pub use provider::{
39    CloudEngineProviderInfoReport, CloudEngineProviderInfoRequest, CloudEngineProviderListReport,
40    CloudEngineProviderListRequest, CloudEngineProviderLocation, CloudEngineProviderRow,
41    DEFAULT_CLOUD_ENGINE_PROVIDER_SOURCE_ENDPOINT, MAX_CLOUD_ENGINE_PROVIDER_LOCATIONS,
42    MAX_CLOUD_ENGINE_PROVIDER_SOURCE_ROWS, cloud_engine_provider_info_report_text,
43    cloud_engine_provider_list_report_text,
44};
45#[cfg(feature = "dashboard-host")]
46pub use provider::{
47    CloudEngineProviderInfoSourceData, CloudEngineProviderListSourceData,
48    CloudEngineProviderSource, build_cloud_engine_provider_info_report,
49    build_cloud_engine_provider_info_report_with_source, build_cloud_engine_provider_list_report,
50    build_cloud_engine_provider_list_report_with_source,
51};
52#[cfg(feature = "cloud-engine-host")]
53pub use source::{
54    CloudEngineOperatorBindingSource, CloudEngineSource, CloudEngineSourceRequest,
55    LiveCloudEngineSource,
56};
57#[cfg(all(feature = "cloud-engine-host", feature = "subnet-catalog-host"))]
58pub use text::cloud_engine_list_report_text;
59pub use text::{cloud_engine_operator_report_text, cloud_engine_prices_report_text};
60
61/// Mainnet CloudEngine control-plane registry canister principal.
62pub const MAINNET_CLOUD_ENGINE_CANISTER_ID: &str = "q6cfj-fyaaa-aaaar-qb77q-cai";
63
64/// Default replica endpoint used for live CloudEngine control-plane queries.
65pub const DEFAULT_CLOUD_ENGINE_SOURCE_ENDPOINT: &str = "https://icp-api.io";
66
67/// Maximum marketplace rows accepted from one live response.
68pub const MAX_CLOUD_ENGINE_PRICE_ROWS: usize = 1_000;
69
70/// Maximum Registry CloudEngine Subnets followed by one list invocation.
71pub const MAX_CLOUD_ENGINE_LIST_ROWS: usize = 100;
72
73/// Maximum claimed domains accepted from one engine operator.
74pub const MAX_CLOUD_ENGINE_DOMAINS: usize = 100;
75
76/// Maximum decimal digits accepted for one marketplace cycle amount.
77pub const MAX_CLOUD_ENGINE_CYCLE_DECIMAL_DIGITS: usize = 256;
78
79#[cfg(feature = "cloud-engine-host")]
80const CLOUD_ENGINE_REPORT_SCHEMA_VERSION: u32 = 1;
81#[cfg(feature = "cloud-engine-host")]
82const CLOUD_ENGINE_AUTHORITY: &str = "cloud_engine_control_plane_canister";
83
84///
85/// CloudEngineHostError
86///
87/// Failure while collecting or validating one live CloudEngine report.
88///
89
90#[cfg(feature = "cloud-engine-host")]
91#[derive(Debug, ThisError)]
92pub enum CloudEngineHostError {
93    /// The requested network is not the supported mainnet identity.
94    #[error(
95        "`icq cloud-engine` supports only the mainnet `ic` network\n\nThese reports query the mainnet CloudEngine control-plane canister.\n\nTry:\n  icq --network ic cloud-engine prices"
96    )]
97    UnsupportedNetwork {
98        /// Rejected network identity.
99        network: String,
100    },
101
102    /// A requested principal is invalid.
103    #[error("invalid {field}: {reason}")]
104    InvalidPrincipal {
105        /// Principal field being parsed.
106        field: &'static str,
107        /// Principal parsing failure.
108        reason: String,
109    },
110
111    /// The IC agent could not be constructed for the requested endpoint.
112    #[error("failed to build IC agent for {endpoint}: {reason}")]
113    AgentBuild {
114        /// Endpoint used to build the agent.
115        endpoint: String,
116        /// Agent construction failure.
117        reason: String,
118    },
119
120    /// The built-in CloudEngine control-plane principal could not be parsed.
121    #[error("invalid built-in CloudEngine canister principal: {reason}")]
122    CanisterId {
123        /// Principal parsing failure.
124        reason: String,
125    },
126
127    /// A CloudEngine control-plane query failed.
128    #[error("CloudEngine agent call {method} failed: {reason}")]
129    AgentCall {
130        /// Canister method being queried.
131        method: &'static str,
132        /// Agent call failure.
133        reason: String,
134    },
135
136    /// A CloudEngine query argument could not be Candid encoded.
137    #[error("failed to encode Candid {message}: {reason}")]
138    CandidEncode {
139        /// Candid request type.
140        message: &'static str,
141        /// Encoding failure.
142        reason: String,
143    },
144
145    /// A CloudEngine response could not be Candid decoded.
146    #[error("failed to decode Candid {message}: {reason}")]
147    CandidDecode {
148        /// Candid response type.
149        message: &'static str,
150        /// Decoding failure.
151        reason: String,
152    },
153
154    /// A custom CloudEngine source returned inconsistent or excessive data.
155    #[error("invalid CloudEngine source data: {reason}")]
156    InvalidSourceData {
157        /// Deterministic source-contract failure.
158        reason: String,
159    },
160
161    /// The Registry-backed Subnet Catalog could not supply the list inventory.
162    #[cfg(feature = "subnet-catalog-host")]
163    #[error(transparent)]
164    SubnetCatalog(#[from] crate::subnet_catalog::SubnetCatalogHostError),
165
166    /// The synchronous host runtime could not execute the live query.
167    #[error(transparent)]
168    Runtime(#[from] RuntimeError),
169}
170
171#[cfg(feature = "cloud-engine-host")]
172fn enforce_mainnet_network(network: &str) -> Result<(), CloudEngineHostError> {
173    crate::network::enforce_mainnet_network_with(network, |network| {
174        CloudEngineHostError::UnsupportedNetwork { network }
175    })
176}
177
178#[cfg(all(test, feature = "cloud-engine-host"))]
179mod tests;