Skip to main content

ic_query/nns/
mod.rs

1#[cfg(feature = "host")]
2#[macro_use]
3mod macros;
4pub mod data_center;
5#[cfg(feature = "host")]
6mod leaf;
7pub mod node;
8pub mod node_operator;
9pub mod node_provider;
10pub mod proposals;
11pub mod registry;
12pub mod render;
13#[cfg(feature = "cli")]
14mod subnet;
15pub mod topology;
16
17#[cfg(all(test, feature = "cli"))]
18mod tests;
19
20#[cfg(feature = "cli")]
21use crate::{
22    cli::{
23        clap::{
24            parse_matches_or_usage, parse_required_subcommand_or_usage, passthrough_subcommand,
25            render_help,
26        },
27        common::{CurrentUnixSecsError, OutputFormat, current_unix_secs, write_text_or_json},
28        help::collect_args_or_print_help_or_version,
29    },
30    nns::{
31        data_center::report::NnsDataCenterHostError, node::report::NnsNodeHostError,
32        node_operator::report::NnsNodeOperatorHostError,
33        node_provider::report::NnsNodeProviderHostError, proposals::NnsProposalHostError,
34        registry::report::NnsRegistryHostError, topology::report::NnsTopologyHostError,
35    },
36    project::icp_root as project_icp_root,
37    subnet_catalog::SubnetCatalogHostError,
38    version_text,
39};
40#[cfg(feature = "cli")]
41use clap::{ArgMatches, Command as ClapCommand};
42#[cfg(feature = "cli")]
43use std::{ffi::OsString, io, path::PathBuf};
44#[cfg(feature = "cli")]
45use thiserror::Error as ThisError;
46
47///
48/// NnsCommandError
49///
50#[cfg(feature = "cli")]
51#[derive(Debug, ThisError)]
52pub enum NnsCommandError {
53    #[error("{0}")]
54    Usage(String),
55
56    #[error(transparent)]
57    SubnetHost(#[from] SubnetCatalogHostError),
58
59    #[error(transparent)]
60    DataCenterHost(#[from] NnsDataCenterHostError),
61
62    #[error(transparent)]
63    NodeHost(#[from] NnsNodeHostError),
64
65    #[error(transparent)]
66    NodeProviderHost(#[from] NnsNodeProviderHostError),
67
68    #[error(transparent)]
69    NodeOperatorHost(#[from] NnsNodeOperatorHostError),
70
71    #[error(transparent)]
72    ProposalHost(#[from] NnsProposalHostError),
73
74    #[error(transparent)]
75    RegistryHost(#[from] NnsRegistryHostError),
76
77    #[error(transparent)]
78    TopologyHost(#[from] NnsTopologyHostError),
79
80    #[error(transparent)]
81    Clock(#[from] CurrentUnixSecsError),
82
83    #[error(transparent)]
84    Io(#[from] io::Error),
85
86    #[error(transparent)]
87    Json(#[from] serde_json::Error),
88}
89
90#[cfg(feature = "cli")]
91pub fn run<I>(args: I) -> Result<(), NnsCommandError>
92where
93    I: IntoIterator<Item = OsString>,
94{
95    let Some(args) = command_args(args, usage) else {
96        return Ok(());
97    };
98    let (command, args) = parse_nns_required_subcommand(nns_command(), args, usage)?;
99
100    match command.as_str() {
101        "subnet" => subnet::run(args),
102        "data-center" => data_center::run(args),
103        "node" => node::run(args),
104        "node-provider" => node_provider::run(args),
105        "node-operator" => node_operator::run(args),
106        "proposal" => proposals::run(args),
107        "registry" => registry::run(args),
108        "topology" => topology::run(args),
109        _ => unreachable!("nns dispatch command only defines known commands"),
110    }
111}
112
113#[cfg(feature = "cli")]
114pub(in crate::nns) fn command_args<I>(
115    args: I,
116    usage: impl FnOnce() -> String,
117) -> Option<Vec<OsString>>
118where
119    I: IntoIterator<Item = OsString>,
120{
121    collect_args_or_print_help_or_version(args, usage, version_text())
122}
123
124#[cfg(feature = "cli")]
125pub(in crate::nns) fn parse_nns_matches<I>(
126    command: ClapCommand,
127    args: I,
128    usage: impl FnOnce() -> String,
129) -> Result<ArgMatches, NnsCommandError>
130where
131    I: IntoIterator<Item = OsString>,
132{
133    parse_matches_or_usage(command, args, usage).map_err(NnsCommandError::Usage)
134}
135
136#[cfg(feature = "cli")]
137pub(in crate::nns) fn parse_nns_required_subcommand<I>(
138    command: ClapCommand,
139    args: I,
140    usage: impl FnOnce() -> String,
141) -> Result<(String, Vec<OsString>), NnsCommandError>
142where
143    I: IntoIterator<Item = OsString>,
144{
145    parse_required_subcommand_or_usage(command, args, usage).map_err(NnsCommandError::Usage)
146}
147
148#[cfg(feature = "cli")]
149fn now_unix_secs() -> Result<u64, NnsCommandError> {
150    Ok(current_unix_secs()?)
151}
152
153#[cfg(feature = "cli")]
154fn command_icp_root() -> Result<PathBuf, NnsCommandError> {
155    project_icp_root().map_err(|err| NnsCommandError::Usage(err.to_string()))
156}
157
158#[cfg(feature = "cli")]
159fn nns_command() -> ClapCommand {
160    ClapCommand::new("nns")
161        .bin_name("icq nns")
162        .about("Inspect NNS metadata")
163        .disable_help_flag(true)
164        .subcommand(passthrough_subcommand(
165            ClapCommand::new("subnet").about("Inspect and refresh NNS subnet metadata"),
166        ))
167        .subcommand(passthrough_subcommand(
168            ClapCommand::new("data-center").about("Inspect NNS data-center metadata"),
169        ))
170        .subcommand(passthrough_subcommand(
171            ClapCommand::new("node").about("Inspect NNS node metadata"),
172        ))
173        .subcommand(passthrough_subcommand(
174            ClapCommand::new("node-provider").about("Inspect NNS node-provider metadata"),
175        ))
176        .subcommand(passthrough_subcommand(
177            ClapCommand::new("node-operator").about("Inspect NNS node-operator metadata"),
178        ))
179        .subcommand(passthrough_subcommand(
180            ClapCommand::new("proposal").about("Inspect NNS governance proposals"),
181        ))
182        .subcommand(passthrough_subcommand(
183            ClapCommand::new("registry").about("Inspect NNS registry metadata"),
184        ))
185        .subcommand(passthrough_subcommand(
186            ClapCommand::new("topology").about("Summarize joined NNS topology metadata"),
187        ))
188}
189
190#[cfg(feature = "cli")]
191fn usage() -> String {
192    render_help(nns_command())
193}