Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file.
- Migrate `location get` to the RFC-20 conforming verb pattern as the project's reference. `GetLocationCliCommand::execute` is now `async fn`, takes `&CliContext` as its first non-self argument, and emits a `tracing::debug!` event so `-v` surfaces what the verb is doing. The verb's user-facing args, flags, table layout, and JSON schema are unchanged. The unit test consumes the shared `doublezero_cli_core::testing::cli_context_default_for_tests()` helper and continues to use the existing `MockCliCommand` (auto-generated by `#[automock]`) as the backend. Binary dispatch arms in `client/doublezero` and `controlplane/doublezero-admin` are updated to `.await` the new method; other location verbs (Create, Update, List, Delete) keep their current sync signatures and migrate opportunistically.
- Add `docs/cli-standard.md`, the contributor-facing summary of RFC-20 with the `location get` worked example and pointers to the shared validators, formatters, logging facade, and test helpers in `doublezero-cli-core`.
- Update `CLAUDE.md` with a CLI-standard section pointing at RFC-20, the contributor doc, and the reference verb so future contributors land on the standard quickly.
- Move the per-resource serviceability subcommand wrapper files (`accesspass`, `config`, `contributor`, `device`, `exchange`, `globalconfig`, `link`, `location`, `multicastgroup`, `permission`, `resource`, `tenant`, `user`) from `client/doublezero/src/cli/` into the module crate at `smartcontract/cli/src/cli/` per RFC-20 §Module contract item 2. Internal imports in the moved files switch from `doublezero_serviceability_cli::<resource>::*` to `crate::<resource>::*`. Binary import paths in `client/doublezero/src/{cli/command.rs,main.rs}` switch to `doublezero_serviceability_cli::cli::<resource>::*`. `cli/multicast.rs` stays in the binary because its `Subscribe`/`Unsubscribe`/`Publish`/`Unpublish` variants are async and depend on binary-local daemon-control infrastructure (`ServiceControllerImpl`, `crate::command::helpers::resolve_client_ip`); the binary now imports `MulticastGroupCliCommand` from the library. Binary `Command` enum and `main.rs` dispatch are unchanged; this is pure file relocation.

## [v0.24.0](https://github.com/malbeclabs/doublezero/compare/client/v0.23.0...client/v0.24.0) - 2026-05-22

Expand Down
30 changes: 18 additions & 12 deletions client/doublezero/src/cli/command.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
use super::multicast::MulticastCliCommand;
use crate::{
cli::{
accesspass::AccessPassCliCommand, config::ConfigCliCommand,
contributor::ContributorCliCommand, device::DeviceCliCommand, exchange::ExchangeCliCommand,
geolocation::GeolocationCliCommand, globalconfig::GlobalConfigCliCommand,
link::LinkCliCommand, location::LocationCliCommand, permission::PermissionCliCommand,
resource::ResourceCliCommand, tenant::TenantCliCommand, user::UserCliCommand,
},
cli::{geolocation::GeolocationCliCommand, multicast::MulticastCliCommand},
command::{
connect::ProvisioningCliCommand, disable::DisableCliCommand,
disconnect::DecommissioningCliCommand, enable::EnableCliCommand,
Expand All @@ -16,10 +9,23 @@ use crate::{
use clap::{Args, Subcommand};
use clap_complete::Shell;
use doublezero_serviceability_cli::{
account::GetAccountCliCommand, accounts::GetAccountsCliCommand, address::AddressCliCommand,
balance::BalanceCliCommand, export::ExportCliCommand,
geolocation::programconfig::init::InitProgramConfigCliCommand, init::InitCliCommand,
keygen::KeyGenCliCommand, logcommand::LogCliCommand, migrate::MigrateCliCommand,
account::GetAccountCliCommand,
accounts::GetAccountsCliCommand,
address::AddressCliCommand,
balance::BalanceCliCommand,
cli::{
accesspass::AccessPassCliCommand, config::ConfigCliCommand,
contributor::ContributorCliCommand, device::DeviceCliCommand, exchange::ExchangeCliCommand,
globalconfig::GlobalConfigCliCommand, link::LinkCliCommand, location::LocationCliCommand,
permission::PermissionCliCommand, resource::ResourceCliCommand, tenant::TenantCliCommand,
user::UserCliCommand,
},
export::ExportCliCommand,
geolocation::programconfig::init::InitProgramConfigCliCommand,
init::InitCliCommand,
keygen::KeyGenCliCommand,
logcommand::LogCliCommand,
migrate::MigrateCliCommand,
};

#[derive(Subcommand, Debug)]
Expand Down
13 changes: 0 additions & 13 deletions client/doublezero/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
pub mod accesspass;
pub mod command;
pub mod config;
pub mod contributor;
pub mod device;
pub mod exchange;
pub mod geolocation;
pub mod globalconfig;
pub mod link;
pub mod location;
pub mod multicast;
pub mod multicastgroup;
pub mod permission;
pub mod resource;
pub mod tenant;
pub mod user;
2 changes: 1 addition & 1 deletion client/doublezero/src/cli/multicast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::{Args, Subcommand};

use super::multicastgroup::MulticastGroupCliCommand;
use doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCliCommand;

#[derive(Args, Debug)]
pub struct MulticastCliCommand {
Expand Down
122 changes: 63 additions & 59 deletions client/doublezero/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,30 @@ mod requirements;
mod servicecontroller;
use crate::cli::{
command::Command,
config::ConfigCommands,
device::{DeviceCommands, InterfaceCommands},
exchange::ExchangeCommands,
geolocation::{
probe::ProbeCommands, user::UserCommands as GeoUserCommands, GeolocationCommands,
},
globalconfig::{
AirdropCommands, AuthorityCommands, FeatureFlagsCommands, FoundationAllowlistCommands,
GlobalConfigCommands, QaAllowlistCommands,
},
link::{LinkCommands, TopologyCommands},
location::LocationCommands,
user::UserCommands,
};
use doublezero_cli_core::LogLevel;
use doublezero_sdk::{geolocation::client::GeoClient, DZClient, ProgramVersion};
use doublezero_serviceability::pda::get_globalstate_pda;
use doublezero_serviceability_cli::{
checkversion::check_version, doublezerocommand::CliCommandImpl,
geoclicommand::GeoCliCommandImpl, version::VersionCliCommand,
checkversion::check_version,
cli::{
config::ConfigCommands,
device::{DeviceCommands, InterfaceCommands},
exchange::ExchangeCommands,
globalconfig::{
AirdropCommands, AuthorityCommands, FeatureFlagsCommands, FoundationAllowlistCommands,
GlobalConfigCommands, QaAllowlistCommands,
},
link::{LinkCommands, TopologyCommands},
location::LocationCommands,
user::UserCommands,
},
doublezerocommand::CliCommandImpl,
geoclicommand::GeoCliCommandImpl,
version::VersionCliCommand,
};
use servicecontroller::ServiceControllerImpl;

Expand Down Expand Up @@ -332,37 +336,37 @@ async fn main() -> eyre::Result<()> {
ExchangeCommands::Delete(args) => args.execute(&client, &mut handle),
},
Command::Contributor(command) => match command.command {
cli::contributor::ContributorCommands::Create(args) => {
doublezero_serviceability_cli::cli::contributor::ContributorCommands::Create(args) => {
args.execute(&client, &mut handle)
}
cli::contributor::ContributorCommands::Update(args) => {
doublezero_serviceability_cli::cli::contributor::ContributorCommands::Update(args) => {
args.execute(&client, &mut handle)
}
cli::contributor::ContributorCommands::List(args) => args.execute(&client, &mut handle),
cli::contributor::ContributorCommands::Get(args) => args.execute(&client, &mut handle),
cli::contributor::ContributorCommands::Delete(args) => {
doublezero_serviceability_cli::cli::contributor::ContributorCommands::List(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::contributor::ContributorCommands::Get(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::contributor::ContributorCommands::Delete(args) => {
args.execute(&client, &mut handle)
}
},
Command::Permission(command) => match command.command {
cli::permission::PermissionCommands::Set(args) => args.execute(&client, &mut handle),
cli::permission::PermissionCommands::Suspend(args) => {
doublezero_serviceability_cli::cli::permission::PermissionCommands::Set(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::permission::PermissionCommands::Suspend(args) => {
args.execute(&client, &mut handle)
}
cli::permission::PermissionCommands::Resume(args) => args.execute(&client, &mut handle),
cli::permission::PermissionCommands::Delete(args) => args.execute(&client, &mut handle),
cli::permission::PermissionCommands::Get(args) => args.execute(&client, &mut handle),
cli::permission::PermissionCommands::List(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::permission::PermissionCommands::Resume(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::permission::PermissionCommands::Delete(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::permission::PermissionCommands::Get(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::permission::PermissionCommands::List(args) => args.execute(&client, &mut handle),
},
Command::Tenant(command) => match command.command {
cli::tenant::TenantCommands::Create(args) => args.execute(&client, &mut handle),
cli::tenant::TenantCommands::Update(args) => args.execute(&client, &mut handle),
cli::tenant::TenantCommands::List(args) => args.execute(&client, &mut handle),
cli::tenant::TenantCommands::Get(args) => args.execute(&client, &mut handle),
cli::tenant::TenantCommands::Delete(args) => args.execute(&client, &mut handle),
cli::tenant::TenantCommands::Administrator(command) => match command.command {
cli::tenant::AdministratorCommands::Add(args) => args.execute(&client, &mut handle),
cli::tenant::AdministratorCommands::Remove(args) => {
doublezero_serviceability_cli::cli::tenant::TenantCommands::Create(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::TenantCommands::Update(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::TenantCommands::List(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::TenantCommands::Get(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::TenantCommands::Delete(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::TenantCommands::Administrator(command) => match command.command {
doublezero_serviceability_cli::cli::tenant::AdministratorCommands::Add(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::tenant::AdministratorCommands::Remove(args) => {
args.execute(&client, &mut handle)
}
},
Expand All @@ -384,8 +388,8 @@ async fn main() -> eyre::Result<()> {
},
Command::Link(command) => match command.command {
LinkCommands::Create(args) => match args.command {
cli::link::CreateLinkCommands::Wan(args) => args.execute(&client, &mut handle),
cli::link::CreateLinkCommands::Dzx(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::link::CreateLinkCommands::Wan(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::link::CreateLinkCommands::Dzx(args) => args.execute(&client, &mut handle),
},
LinkCommands::Accept(args) => args.execute(&client, &mut handle),
LinkCommands::Update(args) => args.execute(&client, &mut handle),
Expand All @@ -403,14 +407,14 @@ async fn main() -> eyre::Result<()> {
},
},
Command::AccessPass(command) => match command.command {
cli::accesspass::AccessPassCommands::Set(args) => args.execute(&client, &mut handle),
cli::accesspass::AccessPassCommands::Close(args) => args.execute(&client, &mut handle),
cli::accesspass::AccessPassCommands::List(args) => args.execute(&client, &mut handle),
cli::accesspass::AccessPassCommands::Get(args) => args.execute(&client, &mut handle),
cli::accesspass::AccessPassCommands::UserBalances(args) => {
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::Set(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::Close(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::List(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::Get(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::UserBalances(args) => {
args.execute(&client, &mut handle)
}
cli::accesspass::AccessPassCommands::Fund(args) => {
doublezero_serviceability_cli::cli::accesspass::AccessPassCommands::Fund(args) => {
args.execute(&client, &mut handle, &mut std::io::stdin().lock())
}
},
Expand All @@ -426,49 +430,49 @@ async fn main() -> eyre::Result<()> {
},
Command::Multicast(args) => match args.command {
cli::multicast::MulticastCommands::Group(args) => match args.command {
cli::multicastgroup::MulticastGroupCommands::Allowlist(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::Allowlist(args) => {
match args.command {
cli::multicastgroup::MulticastGroupAllowlistCommands::Publisher(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupAllowlistCommands::Publisher(args) => {
match args.command {
cli::multicastgroup::MulticastGroupPubAllowlistCommands::List(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupPubAllowlistCommands::List(
args,
) => args.execute(&client, &mut handle),
cli::multicastgroup::MulticastGroupPubAllowlistCommands::Add(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupPubAllowlistCommands::Add(
args,
) => args.execute(&client, &mut handle),
cli::multicastgroup::MulticastGroupPubAllowlistCommands::Remove(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupPubAllowlistCommands::Remove(
args,
) => args.execute(&client, &mut handle),
}
}
cli::multicastgroup::MulticastGroupAllowlistCommands::Subscriber(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupAllowlistCommands::Subscriber(args) => {
match args.command {
cli::multicastgroup::MulticastGroupSubAllowlistCommands::List(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupSubAllowlistCommands::List(
args,
) => args.execute(&client, &mut handle),
cli::multicastgroup::MulticastGroupSubAllowlistCommands::Add(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupSubAllowlistCommands::Add(
args,
) => args.execute(&client, &mut handle),
cli::multicastgroup::MulticastGroupSubAllowlistCommands::Remove(
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupSubAllowlistCommands::Remove(
args,
) => args.execute(&client, &mut handle),
}
}
}
}
cli::multicastgroup::MulticastGroupCommands::Create(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::Create(args) => {
args.execute(&client, &mut handle)
}
cli::multicastgroup::MulticastGroupCommands::Update(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::Update(args) => {
args.execute(&client, &mut handle)
}
cli::multicastgroup::MulticastGroupCommands::List(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::List(args) => {
args.execute(&client, &mut handle)
}
cli::multicastgroup::MulticastGroupCommands::Get(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::Get(args) => {
args.execute(&client, &mut handle)
}
cli::multicastgroup::MulticastGroupCommands::Delete(args) => {
doublezero_serviceability_cli::cli::multicastgroup::MulticastGroupCommands::Delete(args) => {
args.execute(&client, &mut handle)
}
},
Expand Down Expand Up @@ -511,12 +515,12 @@ async fn main() -> eyre::Result<()> {
}

Command::Resource(command) => match command.command {
cli::resource::ResourceCommands::Allocate(args) => args.execute(&client, &mut handle),
cli::resource::ResourceCommands::Create(args) => args.execute(&client, &mut handle),
cli::resource::ResourceCommands::Deallocate(args) => args.execute(&client, &mut handle),
cli::resource::ResourceCommands::Get(args) => args.execute(&client, &mut handle),
cli::resource::ResourceCommands::Close(args) => args.execute(&client, &mut handle),
cli::resource::ResourceCommands::Verify(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Allocate(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Create(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Deallocate(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Get(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Close(args) => args.execute(&client, &mut handle),
doublezero_serviceability_cli::cli::resource::ResourceCommands::Verify(args) => args.execute(&client, &mut handle),
},

Command::Export(args) => args.execute(&client, &mut handle),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use clap::{Args, Subcommand};
use doublezero_serviceability_cli::accesspass::{
use crate::accesspass::{
close::CloseAccessPassCliCommand, fund::FundAccessPassCliCommand, get::GetAccessPassCliCommand,
list::ListAccessPassCliCommand, set::SetAccessPassCliCommand,
user_balances::UserBalancesAccessPassCliCommand,
};
use clap::{Args, Subcommand};

#[derive(Args, Debug)]
pub struct AccessPassCliCommand {
Expand Down
Loading
Loading