Skip to content

Commit

Permalink
refactor(dre): replacing boiler plate enum calls with a procedural ma…
Browse files Browse the repository at this point in the history
…cro (#702)
  • Loading branch information
NikolaMilosa authored Aug 9, 2024
1 parent 6c934f8 commit 4aec5fc
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 384 deletions.
39 changes: 7 additions & 32 deletions rs/cli/src/commands/api_boundary_nodes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use add::Add;
use clap::{Args, Subcommand};
use clap::Args;
use remove::Remove;
use update::Update;

use super::{ExecutableCommand, IcAdminRequirement};
use super::{impl_executable_command_for_enums, ExecutableCommand, IcAdminRequirement};

mod add;
mod remove;
Expand All @@ -12,46 +12,21 @@ mod update;
#[derive(Args, Debug)]
pub struct ApiBoundaryNodes {
#[clap(subcommand)]
pub subcommand: ApiBoundaryNodesSubcommands,
pub subcommand: Subcommands,
}

#[derive(Subcommand, Debug)]
pub enum ApiBoundaryNodesSubcommands {
/// Turn a set of unassigned nodes into API BNs
Add(Add),

#[clap(about = r#"Update specified set of nodes to the provided version.
The provided "version" must be already elected.
The "nodes" list must contain the node IDs where the version
should be rolled out."#)]
Update(Update),

/// Decommission a set of API BNs and turn them again in unassigned nodes
Remove(Remove),
}
impl_executable_command_for_enums! { Add, Update, Remove }

impl ExecutableCommand for ApiBoundaryNodes {
fn require_ic_admin(&self) -> IcAdminRequirement {
match &self.subcommand {
ApiBoundaryNodesSubcommands::Add(a) => a.require_ic_admin(),
ApiBoundaryNodesSubcommands::Update(u) => u.require_ic_admin(),
ApiBoundaryNodesSubcommands::Remove(r) => r.require_ic_admin(),
}
self.subcommand.require_ic_admin()
}

async fn execute(&self, ctx: crate::ctx::DreContext) -> anyhow::Result<()> {
match &self.subcommand {
ApiBoundaryNodesSubcommands::Add(a) => a.execute(ctx).await,
ApiBoundaryNodesSubcommands::Update(u) => u.execute(ctx).await,
ApiBoundaryNodesSubcommands::Remove(r) => r.execute(ctx).await,
}
self.subcommand.execute(ctx).await
}

fn validate(&self, cmd: &mut clap::Command) {
match &self.subcommand {
ApiBoundaryNodesSubcommands::Add(a) => a.validate(cmd),
ApiBoundaryNodesSubcommands::Update(u) => u.validate(cmd),
ApiBoundaryNodesSubcommands::Remove(r) => r.validate(cmd),
}
self.subcommand.validate(cmd)
}
}
37 changes: 8 additions & 29 deletions rs/cli/src/commands/hostos/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use clap::{Args, Subcommand};
use clap::Args;
use rollout::Rollout;
use rollout_from_node_group::RolloutFromNodeGroup;

Expand All @@ -8,44 +8,23 @@ mod rollout;
pub mod rollout_from_node_group;

#[derive(Args, Debug)]
pub struct HostOsCmd {
pub struct HostOs {
#[clap(subcommand)]
pub subcommand: HostOsSubcommands,
pub subcommand: Subcommands,
}

#[derive(Subcommand, Debug)]
pub enum HostOsSubcommands {
#[clap(about = r#"Roll out an elected HostOS version to the specified list of nodes.
The provided "version" must be already elected. The "nodes" list must
contain the node IDs where the version should be rolled out."#)]
Rollout(Rollout),
super::impl_executable_command_for_enums! { Rollout, RolloutFromNodeGroup }

#[clap(about = r#"Smarter roll out of the elected HostOS version to groups of nodes.
The groups of nodes are created based on assignment to subnets, and on
the owner of the nodes: DFINITY/other. The provided "version" must be
already elected."#)]
RolloutFromNodeGroup(RolloutFromNodeGroup),
}

impl ExecutableCommand for HostOsCmd {
impl ExecutableCommand for HostOs {
fn require_ic_admin(&self) -> IcAdminRequirement {
match &self.subcommand {
HostOsSubcommands::Rollout(r) => r.require_ic_admin(),
HostOsSubcommands::RolloutFromNodeGroup(r) => r.require_ic_admin(),
}
self.subcommand.require_ic_admin()
}

async fn execute(&self, ctx: crate::ctx::DreContext) -> anyhow::Result<()> {
match &self.subcommand {
HostOsSubcommands::Rollout(r) => r.execute(ctx).await,
HostOsSubcommands::RolloutFromNodeGroup(r) => r.execute(ctx).await,
}
self.subcommand.execute(ctx).await
}

fn validate(&self, cmd: &mut clap::Command) {
match &self.subcommand {
HostOsSubcommands::Rollout(r) => r.validate(cmd),
HostOsSubcommands::RolloutFromNodeGroup(r) => r.validate(cmd),
}
self.subcommand.validate(cmd)
}
}
160 changes: 38 additions & 122 deletions rs/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
use std::{collections::BTreeMap, path::PathBuf, str::FromStr};

use crate::commands::subnet::Subnet;
use api_boundary_nodes::ApiBoundaryNodes;
use clap::{error::ErrorKind, Command, Parser, Subcommand};
use clap::{error::ErrorKind, Parser};
use clap_num::maybe_hex;
use completions::Completions;
use der_to_principal::DerToPrincipal;
use firewall::Firewall;
use get::Get;
use heal::Heal;
use hostos::HostOsCmd;
use hostos::HostOs;
use ic_management_types::{MinNakamotoCoefficients, Network, NodeFeature};
use node_metrics::NodeMetrics;
use nodes::Nodes;
use proposals::Proposals;
use propose::Propose;
use qualify::QualifyCmd;
use qualify::Qualify;
use registry::Registry;
use update_authorized_subnets::UpdateAuthorizedSubnets;
use update_unassigned_nodes::UpdateUnassignedNodes;
use upgrade::Upgrade;
use url::Url;
use version::VersionCmd;
use version::Version;
use vote::Vote;

use crate::{auth::Neuron, ctx::DreContext};
use crate::auth::Neuron;

mod api_boundary_nodes;
mod completions;
Expand Down Expand Up @@ -110,65 +111,40 @@ The argument is mandatory for testnets, and is optional for mainnet and staging"
pub no_sync: bool,
}

#[derive(Subcommand, Debug)]
pub enum Subcommands {
/// Convert a DER file to a Principal
DerToPrincipal(DerToPrincipal),
macro_rules! impl_executable_command_for_enums {
($($var:ident),*) => {
use crate::ctx::DreContext;
use clap::{Subcommand, Command};

/// Heal subnets
Heal(Heal),
#[derive(Subcommand, Debug)]
pub enum Subcommands { $(
$var($var),
)*}

/// Manage subnets
Subnet(subnet::SubnetCommand),

/// Get a value using ic-admin CLI
Get(Get),

/// Place a proposal using the ic-admin CLI
Propose(Propose),

/// Place a proposal for updating unassigned nodes
UpdateUnassignedNodes(UpdateUnassignedNodes),

/// Manage versions
Version(VersionCmd),

/// Fetch node metrics stats
NodeMetrics(NodeMetrics),

/// Manage hostos versions
HostOs(HostOsCmd),

/// Manage nodes
Nodes(Nodes),

/// Manage api boundary nodes
ApiBoundaryNodes(ApiBoundaryNodes),

/// Vote on our proposals
Vote(Vote),

/// Registry inspection (dump) operations
Registry(Registry),

/// Firewall rules
Firewall(Firewall),

/// Upgrade
Upgrade(Upgrade),

/// Proposals
Proposals(Proposals),

/// Completions
Completions(Completions),
impl ExecutableCommand for Subcommands {
fn require_ic_admin(&self) -> IcAdminRequirement {
match &self {
$(Subcommands::$var(variant) => variant.require_ic_admin(),)*
}
}

/// Qualification
Qualify(QualifyCmd),
async fn execute(&self, ctx: DreContext) -> anyhow::Result<()> {
match &self {
$(Subcommands::$var(variant) => variant.execute(ctx).await,)*
}
}

/// Manage authorized subnets
UpdateAuthorizedSubnets(UpdateAuthorizedSubnets),
fn validate(&self, cmd: &mut Command) {
match &self {
$(Subcommands::$var(variant) => variant.validate(cmd),)*
}
}
}
}
}
pub(crate) use impl_executable_command_for_enums;

impl_executable_command_for_enums! { DerToPrincipal, Heal, Subnet, Get, Propose, UpdateUnassignedNodes, Version, NodeMetrics, HostOs, Nodes, ApiBoundaryNodes, Vote, Registry, Firewall, Upgrade, Proposals, Completions, Qualify, UpdateAuthorizedSubnets }

pub trait ExecutableCommand {
fn require_ic_admin(&self) -> IcAdminRequirement;
Expand Down Expand Up @@ -255,74 +231,14 @@ pub enum IcAdminRequirement {

impl ExecutableCommand for Args {
fn require_ic_admin(&self) -> IcAdminRequirement {
match &self.subcommands {
Subcommands::DerToPrincipal(c) => c.require_ic_admin(),
Subcommands::Heal(c) => c.require_ic_admin(),
Subcommands::Subnet(c) => c.require_ic_admin(),
Subcommands::Get(c) => c.require_ic_admin(),
Subcommands::Propose(c) => c.require_ic_admin(),
Subcommands::UpdateUnassignedNodes(c) => c.require_ic_admin(),
Subcommands::Version(c) => c.require_ic_admin(),
Subcommands::HostOs(c) => c.require_ic_admin(),
Subcommands::Nodes(c) => c.require_ic_admin(),
Subcommands::ApiBoundaryNodes(c) => c.require_ic_admin(),
Subcommands::Vote(c) => c.require_ic_admin(),
Subcommands::Registry(c) => c.require_ic_admin(),
Subcommands::Firewall(c) => c.require_ic_admin(),
Subcommands::Upgrade(c) => c.require_ic_admin(),
Subcommands::Proposals(c) => c.require_ic_admin(),
Subcommands::Completions(c) => c.require_ic_admin(),
Subcommands::Qualify(c) => c.require_ic_admin(),
Subcommands::NodeMetrics(c) => c.require_ic_admin(),
Subcommands::UpdateAuthorizedSubnets(c) => c.require_ic_admin(),
}
self.subcommands.require_ic_admin()
}

async fn execute(&self, ctx: DreContext) -> anyhow::Result<()> {
match &self.subcommands {
Subcommands::DerToPrincipal(c) => c.execute(ctx).await,
Subcommands::Heal(c) => c.execute(ctx).await,
Subcommands::Subnet(c) => c.execute(ctx).await,
Subcommands::Get(c) => c.execute(ctx).await,
Subcommands::Propose(c) => c.execute(ctx).await,
Subcommands::UpdateUnassignedNodes(c) => c.execute(ctx).await,
Subcommands::Version(c) => c.execute(ctx).await,
Subcommands::HostOs(c) => c.execute(ctx).await,
Subcommands::Nodes(c) => c.execute(ctx).await,
Subcommands::ApiBoundaryNodes(c) => c.execute(ctx).await,
Subcommands::Vote(c) => c.execute(ctx).await,
Subcommands::Registry(c) => c.execute(ctx).await,
Subcommands::Firewall(c) => c.execute(ctx).await,
Subcommands::Upgrade(c) => c.execute(ctx).await,
Subcommands::Proposals(c) => c.execute(ctx).await,
Subcommands::Completions(c) => c.execute(ctx).await,
Subcommands::Qualify(c) => c.execute(ctx).await,
Subcommands::NodeMetrics(c) => c.execute(ctx).await,
Subcommands::UpdateAuthorizedSubnets(c) => c.execute(ctx).await,
}
self.subcommands.execute(ctx).await
}

fn validate(&self, cmd: &mut Command) {
match &self.subcommands {
Subcommands::DerToPrincipal(c) => c.validate(cmd),
Subcommands::Heal(c) => c.validate(cmd),
Subcommands::Subnet(c) => c.validate(cmd),
Subcommands::Get(c) => c.validate(cmd),
Subcommands::Propose(c) => c.validate(cmd),
Subcommands::UpdateUnassignedNodes(c) => c.validate(cmd),
Subcommands::Version(c) => c.validate(cmd),
Subcommands::HostOs(c) => c.validate(cmd),
Subcommands::Nodes(c) => c.validate(cmd),
Subcommands::ApiBoundaryNodes(c) => c.validate(cmd),
Subcommands::Vote(c) => c.validate(cmd),
Subcommands::Registry(c) => c.validate(cmd),
Subcommands::Firewall(c) => c.validate(cmd),
Subcommands::Upgrade(c) => c.validate(cmd),
Subcommands::Proposals(c) => c.validate(cmd),
Subcommands::Completions(c) => c.validate(cmd),
Subcommands::Qualify(c) => c.validate(cmd),
Subcommands::NodeMetrics(c) => c.validate(cmd),
Subcommands::UpdateAuthorizedSubnets(c) => c.validate(cmd),
}
self.subcommands.validate(cmd)
}
}
25 changes: 7 additions & 18 deletions rs/cli/src/commands/nodes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
use clap::{Args, Subcommand};
use clap::Args;
use remove::Remove;

use super::{ExecutableCommand, IcAdminRequirement};
use super::{impl_executable_command_for_enums, ExecutableCommand, IcAdminRequirement};

mod remove;

#[derive(Args, Debug)]
pub struct Nodes {
#[clap(subcommand)]
pub subcommand: NodesSubcommands,
}

#[derive(Subcommand, Debug)]
pub enum NodesSubcommands {
/// Remove nodes from the network
Remove(Remove),
pub subcommand: Subcommands,
}
impl_executable_command_for_enums! { Remove }

impl ExecutableCommand for Nodes {
fn require_ic_admin(&self) -> IcAdminRequirement {
match &self.subcommand {
NodesSubcommands::Remove(r) => r.require_ic_admin(),
}
self.subcommand.require_ic_admin()
}

async fn execute(&self, ctx: crate::ctx::DreContext) -> anyhow::Result<()> {
match &self.subcommand {
NodesSubcommands::Remove(r) => r.execute(ctx).await,
}
self.subcommand.execute(ctx).await
}

fn validate(&self, cmd: &mut clap::Command) {
match &self.subcommand {
NodesSubcommands::Remove(r) => r.validate(cmd),
}
self.subcommand.validate(cmd)
}
}
Loading

0 comments on commit 4aec5fc

Please sign in to comment.