git.delta.rocks / jrsonnet / refs/commits / 81e3c77f96ff

difftreelog

source

cmds/fleet/src/host.rs3.7 KiBsourcehistory
1use std::{2	cell::{Ref, RefCell, RefMut},3	env::current_dir,4	ffi::{OsStr, OsString},5	ops::Deref,6	path::PathBuf,7	sync::Arc,8};910use anyhow::Result;11use serde::de::DeserializeOwned;12use structopt::clap::ArgGroup;13use structopt::StructOpt;14use tokio::process::Command;1516use crate::{command::CommandExt, fleetdata::FleetData};1718pub struct FleetConfigInternals {19	pub local_system: String,20	pub directory: PathBuf,21	pub opts: FleetOpts,22	pub data: RefCell<FleetData>,23}2425#[derive(Clone)]26pub struct Config(Arc<FleetConfigInternals>);2728impl Deref for Config {29	type Target = FleetConfigInternals;3031	fn deref(&self) -> &Self::Target {32		&self.033	}34}3536impl Config {37	pub fn should_skip(&self, host: &str) -> bool {38		if !self.opts.skip.is_empty() {39			self.opts.skip.iter().any(|h| h as &str == host)40		} else if !self.opts.only.is_empty() {41			!self.opts.only.iter().any(|h| h as &str == host)42		} else {43			false44		}45	}46	pub fn is_local(&self, host: &str) -> bool {47		self.opts.localhost.as_ref().map(|s| s as &str) == Some(host)48	}4950	pub fn command_on(&self, host: &str, program: impl AsRef<OsStr>, sudo: bool) -> Command {51		if self.is_local(host) {52			if sudo {53				let mut cmd = Command::new("sudo");54				cmd.arg(program);55				cmd56			} else {57				Command::new(program)58			}59		} else {60			let mut cmd = Command::new("ssh");61			cmd.arg(host).arg("--");62			if sudo {63				cmd.arg("sudo");64			}65			cmd.arg(program);66			cmd67		}68	}6970	pub fn configuration_attr_name(&self, name: &str) -> OsString {71		let mut str = self.directory.as_os_str().to_owned();72		str.push("#");73		str.push(&format!(74			"fleetConfigurations.default.{}.{}",75			self.local_system,76			name77		));78		str79	}8081	pub async fn list_hosts(&self) -> Result<Vec<String>> {82		Command::new("nix")83			.arg("eval")84			.arg(self.configuration_attr_name("configuredHosts"))85			.args(&["--apply", "builtins.attrNames", "--json", "--show-trace"])86			.run_nix_json()87			.await88	}89	pub async fn config_attr<T: DeserializeOwned>(&self, host: &str, attr: &str) -> Result<T> {90		Command::new("nix")91			.arg("eval")92			.arg(self.configuration_attr_name(&format!("configuredSystems.{}.config.{}", host, attr)))93			.args(&["--json", "--show-trace"])94			.run_nix_json()95			.await96	}9798	pub fn data(&self) -> Ref<FleetData> {99		self.data.borrow()100	}101	pub fn data_mut(&self) -> RefMut<FleetData> {102		self.data.borrow_mut()103	}104105	pub fn save(&self) -> Result<()> {106		let mut fleet_data_path = self.directory.clone();107		fleet_data_path.push("fleet.nix");108		let data = nixlike::serialize(&self.data() as &FleetData)?;109		std::fs::write(110			fleet_data_path,111			format!(112				"# This file contains fleet state and shouldn't be edited by hand\n\n{}\n",113				data114			),115		)?;116		Ok(())117	}118}119120#[derive(StructOpt, Clone)]121#[structopt(group = ArgGroup::with_name("target_hosts"))]122pub struct FleetOpts {123	/// All hosts except those would be skipped124	#[structopt(long, number_of_values = 1, group = "target_hosts")]125	only: Vec<String>,126127	/// Hosts to skip128	#[structopt(long, number_of_values = 1, group = "target_hosts")]129	skip: Vec<String>,130131	/// Host, which should be threaten as current machine132	#[structopt(long)]133	pub localhost: Option<String>,134135	#[structopt(long, default_value = "x86_64-linux")]136	pub local_system: String,137}138139impl FleetOpts {140	pub fn build(mut self) -> Result<Config> {141		let local_system = self.local_system.clone();142		if self.localhost.is_none() {143			self.localhost144				.replace(hostname::get().unwrap().to_str().unwrap().to_owned());145		}146		let directory = current_dir()?;147148		let mut fleet_data_path = directory.clone();149		fleet_data_path.push("fleet.nix");150		let bytes = std::fs::read_to_string(fleet_data_path)?;151		let data = nixlike::parse_str(&bytes)?;152153		Ok(Config(Arc::new(FleetConfigInternals {154			opts: self,155			directory,156			data,157			local_system,158		})))159	}160}