Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: more consistent cli #263

Merged
merged 3 commits into from
Jan 7, 2025
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
73 changes: 25 additions & 48 deletions zfctl/src/daemon_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ use crate::{

#[derive(Subcommand)]
pub(crate) enum DaemonCommand {
/// List all the Zenoh-Flow daemons reachable on the Zenoh network.
List,
/// Launch a Zenoh-Flow Daemon.
#[command(verbatim_doc_comment)]
#[command(group(
Expand All @@ -52,48 +54,38 @@ pub(crate) enum DaemonCommand {
name: Option<String>,
/// The path of the configuration of the Zenoh-Flow Daemon.
///
/// This configuration allows setting extensions supported by the Runtime
/// This configuration allows setting extensions supported by the Daemon
/// and its name.
#[arg(short, long, verbatim_doc_comment)]
configuration: Option<PathBuf>,
/// The path to a Zenoh configuration to manage the connection to the Zenoh
/// network.
///
/// If no configuration is provided, `zfctl` will default to connecting as
/// a peer with multicast scouting enabled.
#[arg(short = 'z', long, verbatim_doc_comment)]
zenoh_configuration: Option<PathBuf>,
},
/// List all the Zenoh-Flow runtimes reachable on the Zenoh network.
List,
/// Returns the status of the provided Zenoh-Flow runtime.
/// Returns the status of the provided Zenoh-Flow daemon.
///
/// The status consists of general information regarding the runtime and the
/// The status consists of general information regarding the daemon and the
/// machine it runs on:
/// - the name associated with the Zenoh-Flow runtime,
/// - the number of CPUs the machine running the Zenoh-Flow runtime has,
/// - the total amount of RAM the machine running the Zenoh-Flow runtime has,
/// - for each data flow the Zenoh-Flow runtime manages (partially or not):
/// - the name associated with the Zenoh-Flow daemon,
/// - the number of CPUs the machine running the Zenoh-Flow daemon has,
/// - the total amount of RAM the machine running the Zenoh-Flow daemon has,
/// - for each data flow the Zenoh-Flow daemon manages (partially or not):
/// - its unique identifier,
/// - its name,
/// - its status.
#[command(verbatim_doc_comment)]
#[command(group(
ArgGroup::new("exclusive")
.args(&["runtime_id", "runtime_name"])
.args(&["daemon_id", "daemon_name"])
.required(true)
.multiple(false)
))]
Status {
/// The unique identifier of the Zenoh-Flow runtime to contact.
#[arg(short = 'i', long = "id")]
runtime_id: Option<RuntimeId>,
/// The name of the Zenoh-Flow runtime to contact.
/// The name of the Zenoh-Flow daemon to contact.
///
/// Note that if several runtimes share the same name, the first to
/// Note that if several daemons share the same name, the first to
/// answer will be selected.
#[arg(short = 'n', long = "name")]
runtime_name: Option<String>,
daemon_name: Option<String>,
/// The unique identifier of the Zenoh-Flow daemon to contact.
#[arg(short = 'i', long = "id")]
daemon_id: Option<RuntimeId>,
},
}

Expand All @@ -103,22 +95,7 @@ impl DaemonCommand {
DaemonCommand::Start {
name,
configuration,
zenoh_configuration,
} => {
let zenoh_config = match zenoh_configuration {
Some(path) => zenoh::Config::from_file(path.clone()).unwrap_or_else(|e| {
panic!(
"Failed to parse the Zenoh configuration from < {} >:\n{e:?}",
path.display()
)
}),
None => zenoh::Config::default(),
};

let zenoh_session = zenoh::open(zenoh_config)
.await
.unwrap_or_else(|e| panic!("Failed to open Zenoh session:\n{e:?}"));

let daemon = match configuration {
Some(path) => {
let (zenoh_flow_configuration, _) =
Expand All @@ -131,13 +108,13 @@ impl DaemonCommand {
)
});

Daemon::spawn_from_config(zenoh_session, zenoh_flow_configuration)
Daemon::spawn_from_config(session, zenoh_flow_configuration)
.await
.expect("Failed to spawn the Zenoh-Flow Daemon")
}
None => Daemon::spawn(
Runtime::builder(name.unwrap())
.session(zenoh_session)
.session(session)
.build()
.await
.expect("Failed to build the Zenoh-Flow Runtime"),
Expand Down Expand Up @@ -179,10 +156,10 @@ impl DaemonCommand {
println!("{table}");
}
DaemonCommand::Status {
runtime_id,
runtime_name,
daemon_id,
daemon_name,
} => {
let runtime_id = match (runtime_id, runtime_name) {
let runtime_id = match (daemon_id, daemon_name) {
(Some(id), _) => id,
(None, Some(name)) => get_runtime_by_name(&session, &name).await,
(None, None) => {
Expand All @@ -191,9 +168,9 @@ impl DaemonCommand {
// any group.
// (2) The `group` macro has `multiple = false` which indicates that only a single entry for
// any group is accepted.
// (3) The `runtime_id` and `runtime_name` fields belong to the same group "runtime".
// (3) The `daemon_id` and `daemon_name` fields belong to the same group "exclusive".
//
// => A single entry for the group "runtime" is required (and mandatory).
// => A single entry for the group "exclusive" is required (and mandatory).
unreachable!()
}
};
Expand All @@ -215,7 +192,7 @@ impl DaemonCommand {
.await
.map_err(|e| {
anyhow!(
"Failed to query Zenoh-Flow runtime < {} >: {:?}",
"Failed to query Zenoh-Flow daemon < {} >: {:?}",
runtime_id,
e
)
Expand Down Expand Up @@ -272,7 +249,7 @@ impl DaemonCommand {
}
}

Err(e) => tracing::error!("Reply to runtime status failed with: {:?}", e),
Err(e) => tracing::error!("Reply to daemon status failed with: {:?}", e),
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions zfctl/src/instance_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ pub(crate) enum InstanceCommand {
/// zfctl instance status <uuid>
///
/// - This call will **not** start the data flow instance, only load on all
/// the involved runtimes the nodes composing the data flow.
/// the involved daemons the nodes composing the data flow.
///
/// - If Zenoh-Flow runtimes are specified in the data flow descriptor,
/// - If Zenoh-Flow daemons are specified in the data flow descriptor,
/// there is no need to contact them separately or even to make the
/// `create` query on any of them. The Zenoh-Flow runtime orchestrating
/// the creation will query the appropriate Zenoh-Flow runtimes.
/// `create` query on any of them. The Zenoh-Flow daemon orchestrating
/// the creation will query the appropriate Zenoh-Flow daemons.
#[command(verbatim_doc_comment)]
Create {
/// The path, on your machine, of the data flow descriptor.
Expand All @@ -64,11 +64,11 @@ pub(crate) enum InstanceCommand {
Delete { instance_id: Uuid },
/// Obtain the status of the data flow instance.
Status { instance_id: Uuid },
/// List all the data flow instances on the contacted Zenoh-Flow runtime
/// List all the data flow instances on the contacted Zenoh-Flow daemon
List,
/// Start the data flow instance, on all the involved Zenoh-Flow runtimes.
/// Start the data flow instance, on all the involved Zenoh-Flow daemons.
Start { instance_id: Uuid },
/// Abort the data flow instance, on all the involved Zenoh-Flow runtimes.
/// Abort the data flow instance, on all the involved Zenoh-Flow daemons.
Abort { instance_id: Uuid },
}

Expand Down
66 changes: 24 additions & 42 deletions zfctl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ use instance_command::InstanceCommand;
mod daemon_command;
use daemon_command::DaemonCommand;

mod run_local;
mod run_local_command;
use run_local_command::RunLocalCommand;

mod utils;
use std::path::PathBuf;

use anyhow::anyhow;
use clap::{Parser, Subcommand};
use clap::{ArgGroup, Parser, Subcommand};
use utils::{get_random_runtime, get_runtime_by_name};
use zenoh_flow_commons::{parse_vars, Result, RuntimeId};
use zenoh_flow_commons::{Result, RuntimeId};

const ZENOH_FLOW_INTERNAL_ERROR: &str = r#"
`zfctl` encountered a fatal internal error.
Expand Down Expand Up @@ -55,6 +56,7 @@ struct Zfctl {
/// a peer with multicast scouting enabled.
#[arg(short = 'z', long, verbatim_doc_comment)]
zenoh_configuration: Option<PathBuf>,

#[command(subcommand)]
command: Command,
}
Expand All @@ -63,21 +65,26 @@ struct Zfctl {
enum Command {
/// To manage a data flow instance.
///
/// This command accepts an optional `name` or `id` of a Zenoh-Flow Runtime
/// This command accepts an optional `name` or `id` of a Zenoh-Flow Daemon
/// to contact. If no name or id is provided, one is randomly selected.
#[group(required = false, multiple = false)]
#[command(group(
ArgGroup::new("exclusive")
.args(&["daemon_id", "daemon_name"])
.required(false)
.multiple(false)
))]
Instance {
#[command(subcommand)]
command: InstanceCommand,
/// The unique identifier of the Zenoh-Flow runtime to contact.
#[arg(short = 'i', long = "id", verbatim_doc_comment, group = "runtime")]
runtime_id: Option<RuntimeId>,
/// The name of the Zenoh-Flow runtime to contact.
/// The unique identifier of the Zenoh-Flow daemon to contact.
#[arg(short = 'i', long = "id", verbatim_doc_comment)]
daemon_id: Option<RuntimeId>,
/// The name of the Zenoh-Flow daemon to contact.
///
/// If several runtimes share the same name, `zfctl` will abort
/// If several daemons share the same name, `zfctl` will abort
/// its execution asking you to instead use their `id`.
#[arg(short = 'n', long = "name", verbatim_doc_comment, group = "runtime")]
runtime_name: Option<String>,
#[arg(short = 'n', long = "name", verbatim_doc_comment)]
daemon_name: Option<String>,
},

/// To interact with a Zenoh-Flow daemon.
Expand All @@ -86,27 +93,7 @@ enum Command {

/// Run a dataflow locally.
#[command(verbatim_doc_comment)]
RunLocal {
/// The data flow to execute.
flow: PathBuf,
/// The path to a Zenoh configuration to manage the connection to the Zenoh
/// network.
///
/// If no configuration is provided, `zfctl` will default to connecting as
/// a peer with multicast scouting enabled.
#[arg(short = 'z', long, verbatim_doc_comment)]
zenoh_configuration: Option<PathBuf>,
/// The, optional, location of the configuration to load nodes implemented not in Rust.
#[arg(short, long, value_name = "path")]
extensions: Option<PathBuf>,
/// Variables to add / overwrite in the `vars` section of your data
/// flow, with the form `KEY=VALUE`. Can be repeated multiple times.
///
/// Example:
/// --vars HOME_DIR=/home/zenoh-flow --vars BUILD=debug
#[arg(long, value_parser = parse_vars::<String, String>, verbatim_doc_comment)]
vars: Option<Vec<(String, String)>>,
},
RunLocal(RunLocalCommand),
}

#[async_std::main]
Expand Down Expand Up @@ -136,10 +123,10 @@ async fn main() -> Result<()> {
match zfctl.command {
Command::Instance {
command,
runtime_id,
runtime_name,
daemon_id,
daemon_name,
} => {
let orchestrator_id = match (runtime_id, runtime_name) {
let orchestrator_id = match (daemon_id, daemon_name) {
(Some(id), _) => id,
(None, Some(name)) => get_runtime_by_name(&session, &name).await,
(None, None) => get_random_runtime(&session).await,
Expand All @@ -148,11 +135,6 @@ async fn main() -> Result<()> {
command.run(session, orchestrator_id).await
}
Command::Daemon(command) => command.run(session).await,
Command::RunLocal {
flow,
zenoh_configuration,
extensions,
vars,
} => run_local::run_locally(flow, zenoh_configuration, extensions, vars).await,
Command::RunLocal(command) => command.run(session).await,
}
}
Loading
Loading