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, collect_args_or_print_help_or_version_flag},
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 command_flag_args<I>(
126    args: I,
127    usage: impl FnOnce() -> String,
128) -> Option<Vec<OsString>>
129where
130    I: IntoIterator<Item = OsString>,
131{
132    collect_args_or_print_help_or_version_flag(args, usage, version_text())
133}
134
135#[cfg(feature = "cli")]
136pub(in crate::nns) fn parse_nns_matches<I>(
137    command: ClapCommand,
138    args: I,
139    usage: impl FnOnce() -> String,
140) -> Result<ArgMatches, NnsCommandError>
141where
142    I: IntoIterator<Item = OsString>,
143{
144    parse_matches_or_usage(command, args, usage).map_err(NnsCommandError::Usage)
145}
146
147#[cfg(feature = "cli")]
148pub(in crate::nns) fn parse_nns_required_subcommand<I>(
149    command: ClapCommand,
150    args: I,
151    usage: impl FnOnce() -> String,
152) -> Result<(String, Vec<OsString>), NnsCommandError>
153where
154    I: IntoIterator<Item = OsString>,
155{
156    parse_required_subcommand_or_usage(command, args, usage).map_err(NnsCommandError::Usage)
157}
158
159#[cfg(feature = "cli")]
160fn now_unix_secs() -> Result<u64, NnsCommandError> {
161    Ok(current_unix_secs()?)
162}
163
164#[cfg(feature = "cli")]
165fn command_icp_root() -> Result<PathBuf, NnsCommandError> {
166    project_icp_root().map_err(|err| NnsCommandError::Usage(err.to_string()))
167}
168
169#[cfg(feature = "cli")]
170fn nns_command() -> ClapCommand {
171    ClapCommand::new("nns")
172        .bin_name("icq nns")
173        .about("Inspect NNS metadata")
174        .disable_help_flag(true)
175        .subcommand(passthrough_subcommand(
176            ClapCommand::new("subnet").about("Inspect and refresh NNS subnet metadata"),
177        ))
178        .subcommand(passthrough_subcommand(
179            ClapCommand::new("data-center").about("Inspect NNS data-center metadata"),
180        ))
181        .subcommand(passthrough_subcommand(
182            ClapCommand::new("node").about("Inspect NNS node metadata"),
183        ))
184        .subcommand(passthrough_subcommand(
185            ClapCommand::new("node-provider").about("Inspect NNS node-provider metadata"),
186        ))
187        .subcommand(passthrough_subcommand(
188            ClapCommand::new("node-operator").about("Inspect NNS node-operator metadata"),
189        ))
190        .subcommand(passthrough_subcommand(
191            ClapCommand::new("proposal").about("Inspect NNS governance proposals"),
192        ))
193        .subcommand(passthrough_subcommand(
194            ClapCommand::new("registry").about("Inspect NNS registry metadata"),
195        ))
196        .subcommand(passthrough_subcommand(
197            ClapCommand::new("topology").about("Summarize joined NNS topology metadata"),
198        ))
199}
200
201#[cfg(feature = "cli")]
202fn usage() -> String {
203    render_help(nns_command())
204}