summaryrefslogtreecommitdiff
path: root/src/spec.rs
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-03-04 10:14:15 +0200
committerLars Wirzenius <liw@liw.fi>2021-03-04 10:14:24 +0200
commit4eded18d1cffe2bcbc432e4c14e4712b0c1ab4cb (patch)
tree903be1d7643439007ef4e39ef3d566171913f0ee /src/spec.rs
parent5141d3a654e3abc8064a6ba252220426701a5f89 (diff)
downloadvmadm-4eded18d1cffe2bcbc432e4c14e4712b0c1ab4cb.tar.gz
feat! allow specification files to have any number of machines
Diffstat (limited to 'src/spec.rs')
-rw-r--r--src/spec.rs58
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,