git.delta.rocks / jrsonnet / refs/commits / ec8bd188aadf

difftreelog

source

src/host.rs3.0 KiBsourcehistory
1use std::{2	cell::{Ref, RefCell, RefMut},3	env::current_dir,4	ffi::{OsStr, OsString},5	ops::Deref,6	path::PathBuf,7	process::Command,8	sync::Arc,9};1011use anyhow::Result;12use clap::Clap;1314use crate::{command::CommandExt, fleetdata::FleetData};1516pub struct FleetConfigInternals {17	pub directory: PathBuf,18	pub opts: FleetOpts,19	pub data: RefCell<FleetData>,20}2122#[derive(Clone)]23pub struct Config(Arc<FleetConfigInternals>);2425impl Deref for Config {26	type Target = FleetConfigInternals;2728	fn deref(&self) -> &Self::Target {29		&self.030	}31}3233impl Config {34	pub fn should_skip(&self, host: &str) -> bool {35		if !self.opts.skip.is_empty() {36			self.opts.skip.iter().any(|h| h as &str == host)37		} else if !self.opts.only.is_empty() {38			!self.opts.only.iter().any(|h| h as &str == host)39		} else {40			false41		}42	}43	pub fn is_local(&self, host: &str) -> bool {44		self.opts.localhost.as_ref().map(|s| s as &str) == Some(host)45	}4647	pub fn command_on(&self, host: &str, program: impl AsRef<OsStr>, sudo: bool) -> Command {48		if self.is_local(host) {49			if sudo {50				let mut cmd = Command::new("sudo");51				cmd.arg(program);52				cmd53			} else {54				Command::new(program)55			}56		} else {57			let mut cmd = Command::new("ssh");58			cmd.arg(host).arg("--");59			if sudo {60				cmd.arg("sudo");61			}62			cmd.arg(program);63			cmd64		}65	}6667	pub fn full_attr_name(&self, attr_name: &str) -> OsString {68		let mut str = self.directory.as_os_str().to_owned();69		str.push("#");70		str.push(attr_name);7172		println!("{:?}", str);73		str74	}7576	pub fn list_hosts(&self) -> Result<Vec<String>> {77		Command::new("nix")78			.arg("eval")79			.arg(self.full_attr_name("fleetConfigurations.default.configuredHosts"))80			.args(&["--apply", "builtins.attrNames", "--json", "--show-trace"])81			.inherit_stdio()82			.run_json()83	}8485	pub fn data(&self) -> Ref<FleetData> {86		self.data.borrow()87	}88	pub fn data_mut(&self) -> RefMut<FleetData> {89		self.data.borrow_mut()90	}9192	pub fn save(&self) -> Result<()> {93		let mut fleet_data_path = self.directory.clone();94		fleet_data_path.push("fleet.nix");95		let data = nixlike::serialize(&self.data() as &FleetData)?;96		std::fs::write(fleet_data_path, data)?;97		Ok(())98	}99}100101#[derive(Clap, Clone)]102#[clap(group = clap::ArgGroup::new("target_hosts"))]103pub struct FleetOpts {104	/// All hosts except those would be skipped105	#[clap(long, number_of_values = 1, group = "target_hosts")]106	only: Vec<String>,107108	/// Hosts to skip109	#[clap(long, number_of_values = 1, group = "target_hosts")]110	skip: Vec<String>,111112	/// Host, which should be threaten as current machine113	#[clap(long)]114	pub localhost: Option<String>,115}116117impl FleetOpts {118	pub fn build(mut self) -> Result<Config> {119		if self.localhost.is_none() {120			self.localhost121				.replace(hostname::get().unwrap().to_str().unwrap().to_owned());122		}123		let directory = current_dir()?;124125		let mut fleet_data_path = directory.clone();126		fleet_data_path.push("fleet.nix");127		let bytes = std::fs::read_to_string(fleet_data_path)?;128		let data = nixlike::parse_str(&bytes)?;129130		Ok(Config(Arc::new(FleetConfigInternals {131			opts: self,132			directory,133			data,134		})))135	}136}