diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-03-25 11:18:33 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-03-25 11:18:33 +0000 |
commit | 228758b795b3c27d5fd146e380774b29db73432f (patch) | |
tree | 20df497a743e8442f9725c2f5ab552747363a9d1 | |
parent | a45450a42e4cdcd7f2d5671984c9c7f3945131fd (diff) | |
parent | 00dc4a7a85b32c4337dd3672adec2cbfe3597bfe (diff) | |
download | vmadm-228758b795b3c27d5fd146e380774b29db73432f.tar.gz |
Merge branch 'tilde' into 'main'
test: don't hide clippy output if it's successful
See merge request larswirzenius/vmadm!30
-rwxr-xr-x | check | 2 | ||||
-rw-r--r-- | src/config.rs | 12 | ||||
-rw-r--r-- | src/install.rs | 2 | ||||
-rw-r--r-- | src/libvirt.rs | 15 | ||||
-rw-r--r-- | src/spec.rs | 10 | ||||
-rw-r--r-- | src/sshkeys.rs | 8 | ||||
-rw-r--r-- | src/util.rs | 34 | ||||
-rw-r--r-- | vmadm.md | 12 |
8 files changed, 72 insertions, 23 deletions
@@ -21,7 +21,7 @@ got_cargo_cmd() } $hideok cargo build --all-targets -got_cargo_cmd clippy && $hideok cargo clippy +got_cargo_cmd clippy && cargo clippy -q got_cargo_cmd fmt && $hideok cargo fmt -- --check $hideok cargo test 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/install.rs b/src/install.rs index e74e6ba..94c703c 100644 --- a/src/install.rs +++ b/src/install.rs @@ -116,7 +116,7 @@ pub fn virt_install(args: &VirtInstallArgs, iso: &Path) -> Result<PathBuf, VirtI .arg("--noautoconsole") .arg("--quiet") .output() - .map_err(|err| VirtInstallError::Run(err))?; + .map_err(VirtInstallError::Run)?; if !r.status.success() { let stderr = String::from_utf8(r.stderr)?; return Err(VirtInstallError::VirtInstallFailed(stderr)); diff --git a/src/libvirt.rs b/src/libvirt.rs index e65ea1e..4bf8590 100644 --- a/src/libvirt.rs +++ b/src/libvirt.rs @@ -66,16 +66,13 @@ pub struct Libvirt { impl Libvirt { pub fn connect(url: &str) -> Result<Self, VirtError> { debug!("connecting to libvirtd {}", url); - let conn = Connect::open(url).map_err(|err| VirtError::Connect(err))?; + let conn = Connect::open(url).map_err(VirtError::Connect)?; Ok(Self { conn }) } fn get_domains(&self) -> Result<Vec<Domain>, VirtError> { debug!("listing all domains"); - Ok(self - .conn - .list_all_domains(0) - .map_err(|err| VirtError::Domains(err))?) + Ok(self.conn.list_all_domains(0).map_err(VirtError::Domains)?) } fn get_domain(&self, name: &str) -> Result<Option<Domain>, VirtError> { @@ -119,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.len() > 0 { + if !disk.is_empty() { domain .detach_device_flags(&disk, flags) .map_err(|err| VirtError::DetachIso(name.to_string(), err))?; @@ -141,7 +138,7 @@ impl Libvirt { } pub fn start(&self, name: &str) -> Result<(), VirtError> { - if let Some(_) = self.get_domain(name)? { + if self.get_domain(name)?.is_some() { self.trigger_start(name)?; wait_for_ssh(name); } @@ -196,7 +193,7 @@ impl Libvirt { } fn get_name(domain: &Domain) -> Result<String, VirtError> { - let name = domain.get_name().map_err(|err| VirtError::GetName(err))?; + let name = domain.get_name().map_err(VirtError::GetName)?; Ok(name) } @@ -260,7 +257,7 @@ fn find_iso_xml(xml: &str) -> String { } let end = end.unwrap(); let disk = &xml[..end + 7]; - if let Some(_) = disk.find(".iso") { + if disk.contains(".iso") { return disk.to_string(); } xml = &xml[end..]; 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<Vec<String>, 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/sshkeys.rs b/src/sshkeys.rs index 349cabe..b6a5dd9 100644 --- a/src/sshkeys.rs +++ b/src/sshkeys.rs @@ -110,7 +110,7 @@ impl KeyPair { /// Generate a new key pair of the desired kind. pub fn generate(kind: KeyKind) -> Result<Self, KeyError> { - let dirname = tempdir().map_err(|err| KeyError::TempDir(err))?; + let dirname = tempdir().map_err(KeyError::TempDir)?; let private_key = dirname.path().join("key"); let output = Command::new("ssh-keygen") .arg("-f") @@ -122,7 +122,7 @@ impl KeyPair { .arg("-N") .arg("") .output() - .map_err(|err| KeyError::Run(err))?; + .map_err(KeyError::Run)?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); @@ -178,7 +178,7 @@ impl CaKey { /// /// Return as a string. pub fn certify_host(&self, host_key: &KeyPair, hostname: &str) -> Result<String, KeyError> { - let dirname = tempdir().map_err(|err| KeyError::TempDir(err))?; + let dirname = tempdir().map_err(KeyError::TempDir)?; let ca_key = dirname.path().join("ca"); let host_key_pub = dirname.path().join("host.pub"); let cert = dirname.path().join("host-cert.pub"); @@ -196,7 +196,7 @@ impl CaKey { .arg(format!("host key for {}", hostname)) .arg(&host_key_pub) .output() - .map_err(|err| KeyError::Run(err))?; + .map_err(KeyError::Run)?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); 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<PathBuf>) { + if let Some(path) = maybe_path { + *maybe_path = Some(expand_tilde(path)); + } +} + +pub fn expand_optional_pathbufs(maybe_paths: &mut Option<Vec<PathBuf>>) { + if let Some(paths) = maybe_paths { + let mut expanded = vec![]; + for path in paths { + expanded.push(expand_tilde(&path)); + } + *maybe_paths = Some(expanded); + } +} @@ -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} |