Skip to main content

ic_query/nns/
mod.rs

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