diff --git a/linkup-cli/src/background_booting.rs b/linkup-cli/src/background_booting.rs index f46931f..4ef03c4 100644 --- a/linkup-cli/src/background_booting.rs +++ b/linkup-cli/src/background_booting.rs @@ -1,6 +1,3 @@ -use std::fs::{self, OpenOptions}; -use std::io::Write; -use std::path::{Path, PathBuf}; use std::thread; use std::time::{Duration, Instant}; @@ -17,8 +14,8 @@ use crate::background_tunnel::start_tunnel; use crate::local_config::{LocalState, ServiceTarget}; use crate::start::save_state; use crate::status::print_session_names; +use crate::LINKUP_LOCALSERVER_PORT; use crate::{start::get_state, CliError}; -use crate::{LINKUP_ENV_SEPARATOR, LINKUP_LOCALSERVER_PORT}; pub fn boot_background_services() -> Result<(), CliError> { let mut state = get_state()?; @@ -43,13 +40,6 @@ pub fn boot_background_services() -> Result<(), CliError> { println!("Cloudflare tunnel was already running.. Try stopping linkup first if you have problems."); } - for service in &state.services { - match &service.directory { - Some(d) => set_service_env(d.clone(), state.linkup.config_path.clone())?, - None => {} - } - } - let (local_server_conf, remote_server_conf) = server_config_from_state(&state); let server_session_name = load_config( @@ -195,88 +185,3 @@ pub fn wait_till_ok(url: String) -> Result<(), CliError> { thread::sleep(Duration::from_millis(2000)); } } - -fn set_service_env(directory: String, config_path: String) -> Result<(), CliError> { - let config_dir = Path::new(&config_path).parent().ok_or_else(|| { - CliError::SetServiceEnv( - directory.clone(), - "config_path does not have a parent directory".to_string(), - ) - })?; - - let service_path = PathBuf::from(config_dir).join(&directory); - - let dev_env_files_result = fs::read_dir(&service_path); - let dev_env_files: Vec<_> = match dev_env_files_result { - Ok(entries) => entries - .filter_map(Result::ok) - .filter(|entry| { - entry.file_name().to_string_lossy().ends_with(".linkup") - && entry.file_name().to_string_lossy().starts_with(".env.") - }) - .collect(), - Err(e) => { - return Err(CliError::SetServiceEnv( - directory.clone(), - format!("Failed to read directory: {}", e), - )) - } - }; - - if dev_env_files.is_empty() { - return Err(CliError::NoDevEnv(directory)); - } - - for dev_env_file in dev_env_files { - let dev_env_path = dev_env_file.path(); - let env_path = - PathBuf::from(dev_env_path.parent().unwrap()).join(dev_env_path.file_stem().unwrap()); - - if let Ok(env_content) = fs::read_to_string(&env_path) { - if env_content.contains(LINKUP_ENV_SEPARATOR) { - continue; - } - } - - let dev_env_content = fs::read_to_string(&dev_env_path).map_err(|e| { - CliError::SetServiceEnv( - directory.clone(), - format!("could not read dev env file: {}", e), - ) - })?; - - let mut env_file = OpenOptions::new() - .create(true) - .append(true) - .open(&env_path) - .map_err(|e| { - CliError::SetServiceEnv( - directory.clone(), - format!("Failed to open .env file: {}", e), - ) - })?; - - writeln!(env_file, "{}", LINKUP_ENV_SEPARATOR).map_err(|e| { - CliError::SetServiceEnv( - directory.clone(), - format!("could not write to env file: {}", e), - ) - })?; - - writeln!(env_file, "{}", dev_env_content).map_err(|e| { - CliError::SetServiceEnv( - directory.clone(), - format!("could not write to env file: {}", e), - ) - })?; - - writeln!(env_file, "{}", LINKUP_ENV_SEPARATOR).map_err(|e| { - CliError::SetServiceEnv( - directory.clone(), - format!("could not write to env file: {}", e), - ) - })?; - } - - Ok(()) -} diff --git a/linkup-cli/src/main.rs b/linkup-cli/src/main.rs index 83312c9..134519e 100644 --- a/linkup-cli/src/main.rs +++ b/linkup-cli/src/main.rs @@ -127,15 +127,7 @@ enum Commands { #[clap(about = "Stop a running linkup session")] Stop {}, #[clap(about = "Reset a linkup session")] - Reset { - #[arg( - short, - long, - value_name = "CONFIG", - help = "Path to config file, overriding environment variable." - )] - config: Option, - }, + Reset {}, #[clap(about = "Route session traffic to a local service")] Local { service_names: Vec }, #[clap(about = "Route session traffic to a remote service")] @@ -163,7 +155,7 @@ fn main() -> Result<(), CliError> { match &cli.command { Commands::Start { config } => start(config.clone()), Commands::Stop {} => stop(), - Commands::Reset { config } => reset(config.clone()), + Commands::Reset {} => reset(), Commands::Local { service_names } => local(service_names.clone()), Commands::Remote { service_names } => remote(service_names.clone()), Commands::Status { json, all } => status(*json, *all), diff --git a/linkup-cli/src/reset.rs b/linkup-cli/src/reset.rs index 2ba8237..4b2d13a 100644 --- a/linkup-cli/src/reset.rs +++ b/linkup-cli/src/reset.rs @@ -1,6 +1,11 @@ -use crate::{start, stop, CliError}; +use crate::{ + background_booting::boot_background_services, start::get_state, stop::shutdown, CliError, +}; -pub fn reset(config_arg: Option) -> Result<(), CliError> { - stop()?; - start(config_arg) +pub fn reset() -> Result<(), CliError> { + // Ensure there is some kind of state from before, otherwise reset doesn't make sense + get_state()?; + + shutdown()?; + boot_background_services() } diff --git a/linkup-cli/src/start.rs b/linkup-cli/src/start.rs index 2c69863..0932e10 100644 --- a/linkup-cli/src/start.rs +++ b/linkup-cli/src/start.rs @@ -1,6 +1,8 @@ +use std::io::Write; use std::{ env, - fs::{self, File}, + fs::{self, File, OpenOptions}, + path::{Path, PathBuf}, }; use crate::{ @@ -8,7 +10,7 @@ use crate::{ linkup_file_path, local_config::{config_to_state, LocalState, YamlLocalConfig}, status::{server_status, ServerStatus}, - CliError, LINKUP_CONFIG_ENV, LINKUP_STATE_FILE, + CliError, LINKUP_CONFIG_ENV, LINKUP_ENV_SEPARATOR, LINKUP_STATE_FILE, }; pub fn start(config_arg: Option) -> Result<(), CliError> { @@ -27,7 +29,15 @@ pub fn start(config_arg: Option) -> Result<(), CliError> { state.linkup.tunnel = ps.linkup.tunnel; } - save_state(state)?; + save_state(state.clone())?; + + // Set env vars to linkup + for service in &state.services { + match &service.directory { + Some(d) => set_service_env(d.clone(), state.linkup.config_path.clone())?, + None => {} + } + } boot_background_services()?; @@ -118,6 +128,91 @@ pub fn save_state(state: LocalState) -> Result<(), CliError> { Ok(()) } +fn set_service_env(directory: String, config_path: String) -> Result<(), CliError> { + let config_dir = Path::new(&config_path).parent().ok_or_else(|| { + CliError::SetServiceEnv( + directory.clone(), + "config_path does not have a parent directory".to_string(), + ) + })?; + + let service_path = PathBuf::from(config_dir).join(&directory); + + let dev_env_files_result = fs::read_dir(&service_path); + let dev_env_files: Vec<_> = match dev_env_files_result { + Ok(entries) => entries + .filter_map(Result::ok) + .filter(|entry| { + entry.file_name().to_string_lossy().ends_with(".linkup") + && entry.file_name().to_string_lossy().starts_with(".env.") + }) + .collect(), + Err(e) => { + return Err(CliError::SetServiceEnv( + directory.clone(), + format!("Failed to read directory: {}", e), + )) + } + }; + + if dev_env_files.is_empty() { + return Err(CliError::NoDevEnv(directory)); + } + + for dev_env_file in dev_env_files { + let dev_env_path = dev_env_file.path(); + let env_path = + PathBuf::from(dev_env_path.parent().unwrap()).join(dev_env_path.file_stem().unwrap()); + + if let Ok(env_content) = fs::read_to_string(&env_path) { + if env_content.contains(LINKUP_ENV_SEPARATOR) { + continue; + } + } + + let dev_env_content = fs::read_to_string(&dev_env_path).map_err(|e| { + CliError::SetServiceEnv( + directory.clone(), + format!("could not read dev env file: {}", e), + ) + })?; + + let mut env_file = OpenOptions::new() + .create(true) + .append(true) + .open(&env_path) + .map_err(|e| { + CliError::SetServiceEnv( + directory.clone(), + format!("Failed to open .env file: {}", e), + ) + })?; + + writeln!(env_file, "{}", LINKUP_ENV_SEPARATOR).map_err(|e| { + CliError::SetServiceEnv( + directory.clone(), + format!("could not write to env file: {}", e), + ) + })?; + + writeln!(env_file, "{}", dev_env_content).map_err(|e| { + CliError::SetServiceEnv( + directory.clone(), + format!("could not write to env file: {}", e), + ) + })?; + + writeln!(env_file, "{}", LINKUP_ENV_SEPARATOR).map_err(|e| { + CliError::SetServiceEnv( + directory.clone(), + format!("could not write to env file: {}", e), + ) + })?; + } + + Ok(()) +} + fn check_local_not_started() -> Result<(), CliError> { let state = get_state()?; for service in state.services { diff --git a/linkup-cli/src/stop.rs b/linkup-cli/src/stop.rs index 8689a2a..0194104 100644 --- a/linkup-cli/src/stop.rs +++ b/linkup-cli/src/stop.rs @@ -10,15 +10,7 @@ use crate::{ }; pub fn stop() -> Result<(), CliError> { - let local_stopped = stop_pid_file(LINKUP_LOCALSERVER_PID_FILE); - if local_stopped.is_ok() { - let _ = std::fs::remove_file(linkup_file_path(LINKUP_LOCALSERVER_PID_FILE)); - } - let tunnel_stopped = stop_pid_file(LINKUP_CLOUDFLARED_PID); - if tunnel_stopped.is_ok() { - let _ = std::fs::remove_file(linkup_file_path(LINKUP_CLOUDFLARED_PID)); - } - + // Reset env vars back to what they were before let state = get_state()?; for service in &state.services { let remove_res = match &service.directory { @@ -31,6 +23,19 @@ pub fn stop() -> Result<(), CliError> { } } + shutdown() +} + +pub fn shutdown() -> Result<(), CliError> { + let local_stopped = stop_pid_file(LINKUP_LOCALSERVER_PID_FILE); + if local_stopped.is_ok() { + let _ = std::fs::remove_file(linkup_file_path(LINKUP_LOCALSERVER_PID_FILE)); + } + let tunnel_stopped = stop_pid_file(LINKUP_CLOUDFLARED_PID); + if tunnel_stopped.is_ok() { + let _ = std::fs::remove_file(linkup_file_path(LINKUP_CLOUDFLARED_PID)); + } + match (local_stopped, tunnel_stopped) { (Ok(_), Ok(_)) => { println!("Stopped linkup");