git.delta.rocks / jrsonnet / refs/commits / 5be15053c173

difftreelog

source

src/host.rs2.9 KiBsourcehistory
1use std::{2	env::current_dir,3	ffi::{OsStr, OsString},4	ops::Deref,5	path::PathBuf,6	process::Command,7	sync::Arc,8};910use anyhow::Result;11use clap::Clap;1213use crate::command::CommandExt;1415pub struct FleetConfigInternals {16	pub directory: PathBuf,17	pub opts: FleetOpts,18}1920#[derive(Clone)]21pub struct FleetConfig(Arc<FleetConfigInternals>);2223impl Deref for FleetConfig {24	type Target = FleetConfigInternals;2526	fn deref(&self) -> &Self::Target {27		&self.028	}29}3031impl FleetConfig {32	pub fn data_dir(&self) -> PathBuf {33		let mut out = self.directory.clone();34		out.push(".fleet");35		out36	}3738	pub fn full_attr_name(&self, attr_name: &str) -> OsString {39		let mut str = self.directory.as_os_str().to_owned();40		str.push("#");41		str.push(attr_name);42		str43	}4445	pub fn list_host_names(&self) -> Result<Vec<String>> {46		Ok(Command::new("nix")47			.arg("eval")48			.arg(self.full_attr_name("fleetConfigurations.default.configuredHosts"))49			.args(&["--apply", "builtins.attrNames", "--json"])50			.inherit_stdio()51			.run_json()?)52	}5354	pub fn list_hosts(&self) -> Result<Vec<Host>> {55		Ok(self56			.list_host_names()?57			.into_iter()58			.map(|hostname| Host {59				fleet_config: self.clone(),60				hostname,61			})62			.collect())63	}64}6566pub struct Host {67	pub fleet_config: FleetConfig,6869	pub hostname: String,70}7172impl Host {73	pub fn skip(&self) -> bool {74		self.fleet_config.0.opts.should_skip(&self.hostname)75	}76	pub fn is_local(&self) -> bool {77		self.fleet_config.0.opts.is_local(&self.hostname)78	}79	pub fn command_on(&self, cmd: impl AsRef<OsStr>, sudo: bool) -> Command {80		if !self.is_local() {81			let mut out = Command::new("ssh");82			out.arg(&self.hostname).arg("--");83			if sudo {84				out.arg("sudo");85			}86			out.arg(cmd);87			out88		} else if sudo {89			let mut out = Command::new("sudo");90			out.arg(cmd);91			out92		} else {93			Command::new(cmd)94		}95	}96}9798#[derive(Clap, Clone)]99#[clap(group = clap::ArgGroup::new("target_hosts"))]100pub struct FleetOpts {101	/// All hosts except those would be skipped102	#[clap(long, number_of_values = 1, group = "target_hosts")]103	only: Vec<String>,104105	/// Hosts to skip106	#[clap(long, number_of_values = 1, group = "target_hosts")]107	skip: Vec<String>,108109	/// Host, which should be threaten as current machine110	#[clap(long)]111	pub localhost: Option<String>,112}113114impl FleetOpts {115	pub fn should_skip(&self, host: &str) -> bool {116		if self.skip.len() > 0 {117			self.skip.iter().find(|h| h as &str == host).is_some()118		} else if self.only.len() > 0 {119			self.only.iter().find(|h| h as &str == host).is_none()120		} else {121			false122		}123	}124	pub fn is_local(&self, host: &str) -> bool {125		self.localhost.as_ref().map(|s| &s as &str) == Some(host)126	}127	pub fn build(mut self) -> Result<FleetConfig> {128		if self.localhost.is_none() {129			self.localhost130				.replace(hostname::get().unwrap().to_str().unwrap().to_owned());131		}132		let directory = current_dir()?;133		Ok(FleetConfig(Arc::new(FleetConfigInternals {134			opts: self,135			directory,136		})))137	}138}