From 89b13a940e3a7ff8535be8f374c40543e702d208 Mon Sep 17 00:00:00 2001 From: b5 Date: Sun, 23 Oct 2022 10:26:00 -0400 Subject: [PATCH 1/2] start/stop accept arguments, start defaults to [store,gateway] --- iroh/src/doc.rs | 63 +++++++++++++++++++++++++++----------------- iroh/src/run.rs | 20 ++++++++------ iroh/src/services.rs | 32 +++++++++++++++++----- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/iroh/src/doc.rs b/iroh/src/doc.rs index 34d495e825..7a8eb5e800 100644 --- a/iroh/src/doc.rs +++ b/iroh/src/doc.rs @@ -12,36 +12,51 @@ For more info see https://iroh.computer/docs"; pub const START_LONG_DESCRIPTION: &str = " Iroh start kicks off 'daemons' on your local machine: long-running processes that make iroh work. Iroh requires a running daemon to do anything meaningful -like add or get content, and `iroh start` is the fastest way to get iroh up & -running locally. Once running, stop iroh with `iroh stop`. +like get or add content, and `iroh start` is the fastest way to get iroh up & +running locally Use the start, stop, and status commands to monitor iroh on your local machine, -and control it's uptime. - -Daemons provide 'services' like storage, peer-2-peer networking, and a gateway -to bridge IPFS to HTTP. Services work together to fullfill API requests. In this -v0.1.0 release iroh is hard-coded to start three deamons: iroh-gateway, -iroh-p2p, and iroh-store. Each daemon provides gateway, p2p, and store services, -respectively. To learn more about each service, see: - https://iroh.computer/docs/services - -Iroh start is a simple command, under the hood it just kicks off daemons to run -in the background. On startup each deamon writes its process identifier (PID) to -a lock file, which iroh stop uses to lookup and terminate. Iroh start is by no -means the only way to get iroh up & running. Long running local deployments -should be scheduled by your operating systems daemon supervisior, and cloud -deployments should invoke daemon binaries directly. Regardless of how iroh is -started, you can always use `iroh status` to monitor service health. +and control it's uptime. start runs daemons in the background, so there's no +need to keep your terminal open after running start. Once running, stop iroh +with `iroh stop`. + +Daemons provide 'services'. Services work together to fullfill requests. +There are three services: + + storage - a database of IPFS content + p2p - peer-2-peer networking functionality + gateway - bridge the IPFS network to HTTP + +By default iroh start spins up storage & gateway services. Start the p2p service +with `iroh start p2p`. To learn more about each service, see: +https://iroh.computer/docs/services + +Iroh start is by no means the only way to get iroh up & running. Long running +local deployments should be scheduled by your operating systems daemon +supervisior, and cloud deployments should invoke daemon binaries directly. +Regardless of how iroh is started, you can always use `iroh status` to monitor +service health. "; pub const STOP_LONG_DESCRIPTION: &str = " -stop turns local iroh services off by killing daemon processes. When a deamon -starts it creates a lockfile and writes it's process identifier (PID) to the -lock. Iroh stop uses this lock to lookup the process & send an interrupt signal -to the daemon, which halts the service. +stop turns local iroh services off by killing daemon processes. There are three +iroh services, each backed by a daemon: -iroh stop will also try to clean up any stray lock files in the even that a -program crash fails to remove the lockfile from the file system. + storage - a database of IPFS content + p2p - peer-2-peer networking functionality + gateway - bridge the IPFS network to HTTP + +By default `iroh stop` attempts to stop all three services. To stop specific +services, provide service names as arguments, eg: `iroh stop p2p`. + +When a deamon starts it creates a lockfile and writes it's process identifier +(PID) to the lock. Iroh stop uses this lock to lookup the process & send an +interrupt signal to the daemon, which halts the service. Stop will also try to +clean up any stray lock files in the even that a program crash fails to remove +the lockfile from the file system. + +Stop only works for local processes, and cannot be used to interact with remote +services. "; pub const STATUS_LONG_DESCRIPTION: &str = " diff --git a/iroh/src/run.rs b/iroh/src/run.rs index 470cf06ee5..8245c51d6c 100644 --- a/iroh/src/run.rs +++ b/iroh/src/run.rs @@ -57,9 +57,11 @@ enum Commands { /// filesystem path to write to. Optional and defaults to $CID output: Option, }, - #[clap(about = "Start iroh services locally")] + #[clap(about = "Start local iroh services")] #[clap(after_help = doc::START_LONG_DESCRIPTION )] - Start {}, + Start { + service: Vec, + }, /// status checks the health of the different processes #[clap(about = "Check the health of the different iroh services")] #[clap(after_help = doc::STATUS_LONG_DESCRIPTION)] @@ -68,9 +70,11 @@ enum Commands { /// when true, updates the status table whenever a change in a process's status occurs watch: bool, }, - #[clap(about = "Stop all local iroh services")] + #[clap(about = "Stop local iroh services")] #[clap(after_help = doc::STOP_LONG_DESCRIPTION )] - Stop {}, + Stop { + service: Vec, + }, } impl Cli { @@ -127,14 +131,14 @@ impl Cli { println!("Saving file(s) to {}", root_path.to_str().unwrap()); } Commands::P2p(p2p) => run_p2p_command(&api.p2p()?, p2p).await?, - Commands::Start {} => { - crate::services::start(api).await?; + Commands::Start { service } => { + crate::services::start(api, service).await?; } Commands::Status { watch } => { crate::services::status(api, *watch).await?; } - Commands::Stop {} => { - crate::services::stop(api).await?; + Commands::Stop { service } => { + crate::services::stop(api, service).await?; } }; diff --git a/iroh/src/services.rs b/iroh/src/services.rs index 33ecec4bef..e77afbee37 100644 --- a/iroh/src/services.rs +++ b/iroh/src/services.rs @@ -15,8 +15,18 @@ const SERVICE_START_TIMEOUT_SECONDS: u64 = 15; /// start any of {iroh-gateway,iroh-store,iroh-p2p} that aren't currently /// running. -pub async fn start(api: &impl Api) -> Result<()> { - start_services(api, HashSet::from(["store", "p2p", "gateway"])).await +pub async fn start(api: &impl Api, services: &Vec) -> Result<()> { + let services = match services.is_empty() { + true => HashSet::from(["gateway", "store"]), + false => { + let mut hs: HashSet<&str> = HashSet::new(); + for s in services { + hs.insert(s.as_str()); + } + hs + } + }; + start_services(api, services).await } // TODO(b5) - should check for configuration mismatch between iroh CLI configuration @@ -98,8 +108,18 @@ async fn start_services(api: &impl Api, services: HashSet<&str>) -> Result<()> { /// stop the default set of services by sending SIGINT to any active daemons /// identified by lockfiles -pub async fn stop(api: &impl Api) -> Result<()> { - stop_services(api, HashSet::from(["gateway", "p2p", "store"])).await +pub async fn stop(api: &impl Api, services: &Vec) -> Result<()> { + let services = match services.is_empty() { + true => HashSet::from(["store", "p2p", "gateway"]), + false => { + let mut hs: HashSet<&str> = HashSet::new(); + for s in services { + hs.insert(s.as_str()); + } + hs + } + }; + stop_services(api, services).await } pub async fn stop_services(api: &impl Api, services: HashSet<&str>) -> Result<()> { @@ -134,7 +154,7 @@ pub async fn stop_services(api: &impl Api, services: HashSet<&str>) -> Result<() } Err(e) => match e { LockError::NoLock(_) => { - eprintln!("{}", format!("{} is already stopped", daemon_name).red()); + eprintln!("{}", format!("{} is already stopped", daemon_name).white()); } LockError::ZombieLock(_) => { lock.destroy_without_checking().unwrap(); @@ -222,7 +242,7 @@ where .queue(style::Print("\tThe service has been interupted"))?; } code => { - w.queue(style::PrintStyledContent("Down".red()))? + w.queue(style::PrintStyledContent("Down".grey()))? .queue(style::Print(format!("\t{}", code)))?; } }, From 7ed9aee7cb137733ae702de4ff52136ff48935fd Mon Sep 17 00:00:00 2001 From: b5 Date: Sun, 23 Oct 2022 12:37:17 -0400 Subject: [PATCH 2/2] change 'Down' color from red -> grey --- iroh/src/services.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iroh/src/services.rs b/iroh/src/services.rs index e77afbee37..7231f3d746 100644 --- a/iroh/src/services.rs +++ b/iroh/src/services.rs @@ -286,7 +286,7 @@ mod tests { #[test] fn status_table_queue() { - let expect = format!("{}gateway\t\t\t1/1\t{}\np2p\t\t\t1/1\t{}\nstore\t\t\t1/1\t{}\tThe service is currently unavailable\n", "Process\t\t\tNumber\tStatus\n".bold(), "Unknown".dark_yellow(), "Serving".green(), "Down".red()); + let expect = format!("{}gateway\t\t\t1/1\t{}\np2p\t\t\t1/1\t{}\nstore\t\t\t1/1\t{}\tThe service is currently unavailable\n", "Process\t\t\tNumber\tStatus\n".bold(), "Unknown".dark_yellow(), "Serving".green(), "Down".grey()); let table = StatusTable::new( Some(StatusRow::new("gateway", 1, ServiceStatus::Unknown)), Some(StatusRow::new("p2p", 1, ServiceStatus::Serving)), @@ -350,7 +350,7 @@ mod tests { ), output: format!( "test\t\t\t1/1\t{}\tThe service is currently unavailable\n", - "Down".red() + "Down".grey() ), }, ];