diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-03-01 10:13:15 +0200 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-03-01 12:28:31 +0200 |
commit | a4e59f7f6363c2bc62b91298f41b5b645842385e (patch) | |
tree | 46659f0fa296fe2128d1a7bcb929008d034f51c1 /src/spec.rs | |
parent | 05dbbc46d7b3fad9e7a1b85e10469022e07e0b40 (diff) | |
download | vmadm-a4e59f7f6363c2bc62b91298f41b5b645842385e.tar.gz |
feat: change how command line interface works
Easier to use now. --config before subcommand was annoying.
Diffstat (limited to 'src/spec.rs')
-rw-r--r-- | src/spec.rs | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/src/spec.rs b/src/spec.rs index 2cb61f6..0a3d097 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -1,9 +1,13 @@ +use crate::config::Configuration; + +use log::debug; use serde::{Deserialize, Serialize}; -use std::path::PathBuf; +use std::fs; +use std::path::{Path, PathBuf}; #[derive(Debug, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -pub struct Specification { +struct InputSpecification { pub name: String, #[serde(default)] @@ -18,6 +22,26 @@ pub struct Specification { pub ed25519_host_key: Option<String>, pub ed25519_host_cert: Option<String>, + pub base: Option<PathBuf>, + pub image: PathBuf, + pub image_size_gib: u64, + pub memory_mib: u64, + pub cpus: u64, +} + +#[derive(Debug)] +pub struct Specification { + pub name: String, + pub ssh_keys: Vec<String>, + pub rsa_host_key: Option<String>, + pub rsa_host_cert: Option<String>, + pub dsa_host_key: Option<String>, + pub dsa_host_cert: Option<String>, + pub ecdsa_host_key: Option<String>, + pub ecdsa_host_cert: Option<String>, + pub ed25519_host_key: Option<String>, + pub ed25519_host_cert: Option<String>, + pub base: PathBuf, pub image: PathBuf, pub image_size_gib: u64, @@ -27,21 +51,71 @@ pub struct Specification { #[derive(Debug, thiserror::Error)] pub enum SpecificationError { + #[error("No base image or default base image specified: {0}")] + NoBaseImage(PathBuf), + + #[error("Failed to read SSH public key file {0}")] + SshKeyRead(PathBuf, #[source] std::io::Error), + #[error(transparent)] IoError(#[from] std::io::Error), #[error(transparent)] FromUtf8Error(#[from] std::string::FromUtf8Error), + + #[error(transparent)] + YamlError(#[from] serde_yaml::Error), } impl Specification { - pub fn ssh_keys(&self) -> Result<String, SpecificationError> { - let mut keys = String::new(); - for filename in self.ssh_key_files.iter() { - let key = std::fs::read(filename)?; - let key = String::from_utf8(key)?; - keys.push_str(&key); - } - Ok(keys) + pub fn from_file( + config: &Configuration, + filename: &Path, + ) -> Result<Specification, SpecificationError> { + debug!("reading specification from {}", filename.display()); + let spec = fs::read(filename)?; + let input: InputSpecification = serde_yaml::from_slice(&spec)?; + debug!("specification as read from file: {:#?}", input); + + 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())); + }; + + let spec = Specification { + name: input.name.clone(), + 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, + base, + image: input.image.clone(), + image_size_gib: input.image_size_gib, + memory_mib: input.memory_mib, + cpus: input.cpus, + }; + + debug!("specification as with defaults applied: {:#?}", spec); + Ok(spec) + } +} + +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 key = String::from_utf8(key)?; + let key = key.strip_suffix("\n").or(Some(&key)).unwrap(); + keys.push(key.to_string()); } + Ok(keys) } |