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