diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-03-04 10:14:15 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-03-04 10:14:24 +0200 |
commit | 4eded18d1cffe2bcbc432e4c14e4712b0c1ab4cb (patch) | |
tree | 903be1d7643439007ef4e39ef3d566171913f0ee /src/spec.rs | |
parent | 5141d3a654e3abc8064a6ba252220426701a5f89 (diff) | |
download | vmadm-4eded18d1cffe2bcbc432e4c14e4712b0c1ab4cb.tar.gz |
feat! allow specification files to have any number of machines
Diffstat (limited to 'src/spec.rs')
-rw-r--r-- | src/spec.rs | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/src/spec.rs b/src/spec.rs index 8325d98..c99da6b 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -2,14 +2,13 @@ use crate::config::Configuration; use log::debug; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::fs; use std::path::{Path, PathBuf}; #[derive(Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -struct InputSpecification { - pub name: String, - +struct OneVmInputSpecification { #[serde(default)] pub ssh_key_files: Vec<PathBuf>, @@ -51,8 +50,8 @@ pub struct Specification { #[derive(Debug, thiserror::Error)] pub enum SpecificationError { - #[error("No base image or default base image specified: {0}")] - NoBaseImage(PathBuf), + #[error("No base image or default base image specified in {0} for {1}")] + NoBaseImage(PathBuf, String), #[error("No image filename and no image directory specified in configuration")] NoImage, @@ -74,39 +73,58 @@ impl Specification { pub fn from_file( config: &Configuration, filename: &Path, - ) -> Result<Specification, SpecificationError> { + ) -> Result<Vec<Specification>, SpecificationError> { debug!("reading specification from {}", filename.display()); let spec = fs::read(filename)?; - let input: InputSpecification = serde_yaml::from_slice(&spec)?; + let input: HashMap<String, OneVmInputSpecification> = serde_yaml::from_slice(&spec)?; debug!("specification as read from file: {:#?}", input); - let base = if let Some(base) = input.base { + let mut machines = vec![]; + for (name, machine) in input.iter() { + let spec = Specification::one_machine(config, &filename, &name, &machine)?; + debug!("machine with defaults applied: {:#?}", spec); + machines.push(spec); + } + + Ok(machines) + } + + fn one_machine( + config: &Configuration, + filename: &Path, + name: &str, + input: &OneVmInputSpecification, + ) -> Result<Specification, SpecificationError> { + let base = if let Some(base) = &input.base { base.to_path_buf() } else if let Some(ref base) = config.default_base_image { base.to_path_buf() } else { - return Err(SpecificationError::NoBaseImage(filename.to_path_buf())); + return Err(SpecificationError::NoBaseImage( + filename.to_path_buf(), + name.to_string(), + )); }; - let image = if let Some(image) = input.image { + let image = if let Some(image) = &input.image { image.to_path_buf() } else if let Some(dirname) = &config.image_directory { - dirname.join(format!("{}.qcow2", input.name)) + dirname.join(format!("{}.qcow2", name)) } else { return Err(SpecificationError::NoImage.into()); }; let spec = Specification { - name: input.name.clone(), + name: name.to_string(), ssh_keys: ssh_keys(&input.ssh_key_files)?, - rsa_host_key: input.rsa_host_key, - rsa_host_cert: input.rsa_host_cert, - dsa_host_key: input.dsa_host_key, - dsa_host_cert: input.dsa_host_cert, - ecdsa_host_key: input.ecdsa_host_key, - ecdsa_host_cert: input.ecdsa_host_cert, - ed25519_host_key: input.ed25519_host_key, - ed25519_host_cert: input.ed25519_host_cert, + rsa_host_key: input.rsa_host_key.clone(), + rsa_host_cert: input.rsa_host_cert.clone(), + dsa_host_key: input.dsa_host_key.clone(), + dsa_host_cert: input.dsa_host_cert.clone(), + ecdsa_host_key: input.ecdsa_host_key.clone(), + 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, image, image_size_gib: input.image_size_gib, |