From 00dc4a7a85b32c4337dd3672adec2cbfe3597bfe Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Thu, 25 Mar 2021 12:29:44 +0200 Subject: feat: allow ~/ in config, specification files --- src/config.rs | 12 +++++++++++- src/libvirt.rs | 2 +- src/spec.rs | 10 ++++++---- src/util.rs | 34 ++++++++++++++++++++++++++++++++++ vmadm.md | 12 +++++++++--- 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/config.rs b/src/config.rs index 1866971..3f1b341 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ //! Tool configuration. +use crate::util::{expand_optional_pathbuf, expand_optional_pathbufs}; use log::debug; use serde::Deserialize; use std::default::Default; @@ -57,11 +58,20 @@ impl Configuration { debug!("reading configuration file {}", filename.display()); let config = fs::read(filename) .map_err(|err| ConfigurationError::ReadError(filename.to_path_buf(), err))?; - let config: Configuration = serde_yaml::from_slice(&config)?; + let mut config: Configuration = serde_yaml::from_slice(&config)?; + config.expand_tildes(); debug!("config: {:#?}", config); Ok(config) } else { Ok(Self::default()) } } + + fn expand_tildes(&mut self) { + expand_optional_pathbuf(&mut self.default_base_image); + expand_optional_pathbuf(&mut self.image_directory); + expand_optional_pathbuf(&mut self.image_directory); + expand_optional_pathbuf(&mut self.ca_key); + expand_optional_pathbufs(&mut self.authorized_keys) + } } diff --git a/src/libvirt.rs b/src/libvirt.rs index b144d11..4bf8590 100644 --- a/src/libvirt.rs +++ b/src/libvirt.rs @@ -116,7 +116,7 @@ impl Libvirt { let disk = find_iso_xml(&xml); let flags = VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_CURRENT | VIR_DOMAIN_AFFECT_LIVE; - if disk.is_empty() { + if !disk.is_empty() { domain .detach_device_flags(&disk, flags) .map_err(|err| VirtError::DetachIso(name.to_string(), err))?; diff --git a/src/spec.rs b/src/spec.rs index a1d1c2f..a00a5e8 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -1,6 +1,7 @@ //! Virtual machine specification. use crate::config::Configuration; +use crate::util::expand_tilde; use log::debug; use serde::{Deserialize, Serialize}; @@ -293,8 +294,8 @@ impl Specification { ecdsa_host_cert: input.ecdsa_host_cert.clone(), ed25519_host_key: input.ed25519_host_key.clone(), ed25519_host_cert: input.ed25519_host_cert.clone(), - base: input.base_image(config, name)?, - image: input.image(config, name)?, + base: expand_tilde(&input.base_image(config, name)?), + image: expand_tilde(&input.image(config, name)?), image_size_gib: input.image_size_gib(config, name)?, memory_mib: input.memory_mib(config, name)?, cpus: input.cpus(config, name)?, @@ -311,8 +312,9 @@ impl Specification { fn ssh_keys(filenames: &[PathBuf]) -> Result, SpecificationError> { let mut keys = vec![]; for filename in filenames { - let key = std::fs::read(filename) - .map_err(|e| SpecificationError::SshKeyRead(filename.to_path_buf(), e))?; + let filename = expand_tilde(filename); + let key = + std::fs::read(&filename).map_err(|e| SpecificationError::SshKeyRead(filename, e))?; let key = String::from_utf8(key)?; let key = key.strip_suffix("\n").or(Some(&key)).unwrap(); keys.push(key.to_string()); diff --git a/src/util.rs b/src/util.rs index f3e104b..c641ea6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,6 +2,7 @@ use log::debug; use std::net::TcpStream; +use std::path::{Path, PathBuf}; const SSH_PORT: i32 = 22; @@ -15,3 +16,36 @@ pub fn wait_for_ssh(name: &str) { } } } + +/// Expand a ~/ at the beginning of a Path to refer to the home directory. +pub fn expand_tilde(path: &Path) -> PathBuf { + if path.starts_with("~/") { + if let Some(home) = std::env::var_os("HOME") { + let mut expanded = PathBuf::from(home); + for comp in path.components().skip(1) { + expanded.push(comp); + } + expanded + } else { + path.to_path_buf() + } + } else { + path.to_path_buf() + } +} + +pub fn expand_optional_pathbuf(maybe_path: &mut Option) { + if let Some(path) = maybe_path { + *maybe_path = Some(expand_tilde(path)); + } +} + +pub fn expand_optional_pathbufs(maybe_paths: &mut Option>) { + if let Some(paths) = maybe_paths { + let mut expanded = vec![]; + for path in paths { + expanded.push(expand_tilde(&path)); + } + *maybe_paths = Some(expanded); + } +} diff --git a/vmadm.md b/vmadm.md index 24ffe5c..2d97876 100644 --- a/vmadm.md +++ b/vmadm.md @@ -36,9 +36,15 @@ V4cecTlFJGBtUOUAAAAMbGl3QGV4b2xvYmUxAQIDBAUGBw== -----END OPENSSH PRIVATE KEY----- ~~~ +Note that we use *tilde expansion* in filenames to indicate they go +into the home directory. The Subplot test runner sets the `HOME` +environment variable to a suitable directory, so that the files don't +go into the actual home directory of the person running the generated +test program + ~~~{#config.yaml .file .yaml} -image_directory: images -default_base_image: base.qcow2 +image_directory: ~/images +default_base_image: ~/base.qcow2 default_image_gib: 5 default_memory_mib: 2048 default_cpus: 1 @@ -46,7 +52,7 @@ default_generate_host_certificate: true default_autostart: true ca_key: ca_key authorized_keys: - - .ssh/id_rsa.pub + - ~/.ssh/id_rsa.pub ~~~ ~~~{#ssh_key_pub .file} -- cgit v1.2.1