Skip to main content

ic_query/nns/
mod.rs

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