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