Skip to content

Commit 2e05d85

Browse files
authored
Allow consumers of libfalcon to add commands (#104)
* Allow consumers of libfalcon to add commands Users of libfalcon may now add topology-specific commands, and those will be presented under a 'extra' subcommand. * pass &mut Runner so extra commands can do useful stuff! * topology-specific
1 parent 0412e97 commit 2e05d85

File tree

1 file changed

+74
-4
lines changed

1 file changed

+74
-4
lines changed

lib/src/cli.rs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use std::fs;
88
use std::process::Command;
99
use std::{
10+
future::Future,
1011
io::{stdout, Write},
1112
net::{IpAddr, Ipv4Addr, SocketAddr},
1213
os::unix::prelude::AsRawFd,
@@ -37,16 +38,16 @@ pub enum RunMode {
3738
#[derive(Parser)]
3839
#[clap(version = "0.1")]
3940
#[clap(infer_subcommands = true, styles = oxide_cli_style())]
40-
struct Opts {
41+
pub struct Opts<T: clap::Args> {
4142
#[clap(short, long, action = ArgAction::Count)]
4243
verbose: u8,
4344

4445
#[clap(subcommand)]
45-
subcmd: SubCommand,
46+
subcmd: SubCommand<T>,
4647
}
4748

4849
#[derive(Parser)]
49-
enum SubCommand {
50+
enum SubCommand<T: clap::Args> {
5051
#[clap(about = "run topology preflight")]
5152
Preflight(CmdPreflight),
5253
#[clap(about = "launch topology")]
@@ -71,6 +72,9 @@ enum SubCommand {
7172
Snapshot(CmdSnapshot),
7273
#[clap(about = "execute a command on a node")]
7374
Exec(CmdExec),
75+
/// Allow users of this library to add their own set of commands
76+
#[clap(about = "topology-specific commands")]
77+
Extra(T),
7478
}
7579

7680
#[derive(Parser)]
@@ -213,9 +217,71 @@ struct CmdExec {
213217
/// run(&mut r);
214218
/// ```
215219
pub async fn run(r: &mut Runner) -> Result<RunMode, Error> {
220+
#[derive(Parser)]
221+
struct Dummy {}
222+
run_with_extra(r, |_: &mut Runner, _: Dummy| std::future::ready(Ok(())))
223+
.await
224+
}
225+
226+
/// Entry point for a command line application. Will parse command line
227+
/// arguments (including any extra commands that users of this library add) and
228+
/// take actions accordingly.
229+
///
230+
/// # Examples
231+
/// ```no_run
232+
/// use libfalcon::{
233+
/// cli::run_with_extra,
234+
/// Runner,
235+
/// error::Error,
236+
/// };
237+
/// use clap::Parser;
238+
///
239+
/// #[derive(Parser)]
240+
/// #[command(version = "0.1")]
241+
/// struct OtherOpts {
242+
/// #[clap(subcommand)]
243+
/// subcmd: SubCommand,
244+
/// }
245+
///
246+
/// #[derive(Parser)]
247+
/// enum SubCommand {
248+
/// #[clap(about = "some topology specific command")]
249+
/// Something,
250+
/// }
251+
///
252+
/// async fn extra_stuff(r: &mut Runner, opts: OtherOpts) -> Result<(), Error> {
253+
/// match opts.subcmd {
254+
/// SubCommand::Something => {
255+
/// // some topology specific command!
256+
/// }
257+
/// }
258+
///
259+
/// Ok(())
260+
/// }
261+
///
262+
/// let mut r = Runner::new("duo");
263+
///
264+
/// // nodes
265+
/// let violin = r.node("violin", "helios-2.5", 1, 1024);
266+
/// let piano = r.node("piano", "helios-2.5", 1, 1024);
267+
///
268+
/// // links
269+
/// r.link(violin, piano);
270+
///
271+
/// run_with_extra(&mut r, extra_stuff);
272+
/// ```
273+
pub async fn run_with_extra<'a, T, F, O>(
274+
r: &'a mut Runner,
275+
extra: F,
276+
) -> Result<RunMode, Error>
277+
where
278+
T: clap::Args,
279+
F: FnOnce(&'a mut Runner, T) -> O,
280+
O: Future<Output = Result<(), Error>>,
281+
{
216282
r.persistent = true;
217283

218-
let opts: Opts = Opts::parse();
284+
let opts: Opts<T> = Opts::<T>::parse();
219285
match opts.subcmd {
220286
SubCommand::Preflight(p) => {
221287
r.falcon_dir = p.falcon_dir;
@@ -305,6 +371,10 @@ pub async fn run(r: &mut Runner) -> Result<RunMode, Error> {
305371
exec(r, &c.node, &c.command).await?;
306372
Ok(RunMode::Unspec)
307373
}
374+
SubCommand::Extra(c) => {
375+
extra(r, c).await?;
376+
Ok(RunMode::Unspec)
377+
}
308378
}
309379
}
310380

0 commit comments

Comments
 (0)