diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-11-10 08:38:36 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-11-10 08:38:36 +0000 |
commit | d261395df880cae2e7ffaf187b29f8e5f12d8d0e (patch) | |
tree | 96a392797b77e98d3ce2b26358b9c250db65e1e2 | |
parent | 73d9542edf54dd05bcdc0a6096c8cb224b6f51c9 (diff) | |
parent | 22cc382f9e9aa38f3adad18acd426bf0292bbf00 (diff) | |
download | vmadm-d261395df880cae2e7ffaf187b29f8e5f12d8d0e.tar.gz |
Merge branch 'net-syntax' into 'main'
check network names
Closes #25
See merge request larswirzenius/vmadm!51
-rw-r--r-- | Cargo.lock | 34 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/config.rs | 10 | ||||
-rw-r--r-- | src/spec.rs | 12 | ||||
-rw-r--r-- | src/util.rs | 48 | ||||
-rw-r--r-- | subplot/vmadm.py | 6 | ||||
-rw-r--r-- | vmadm.md | 60 |
7 files changed, 144 insertions, 28 deletions
@@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.15" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.3.4" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "nix" @@ -222,12 +222,6 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" - -[[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -352,21 +346,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.22" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" @@ -526,15 +519,6 @@ dependencies = [ ] [[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] name = "unicode-segmentation" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -581,8 +565,10 @@ dependencies = [ "bytesize", "directories-next", "home-dir", + "lazy_static", "log", "pretty_env_logger", + "regex", "serde", "serde_json", "serde_yaml", @@ -15,8 +15,10 @@ anyhow = "1" bytesize = "1" directories-next = "2" home-dir = "0.1.0" +lazy_static = "1.4.0" log = "0.4" pretty_env_logger = "0.4" +regex = "1.5.4" serde = { version = "1", features = ["derive"] } serde_json = "1.0.64" serde_yaml = "0.8" diff --git a/src/config.rs b/src/config.rs index a444d4e..f85ef38 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,6 @@ //! Tool configuration. -use crate::util::{expand_optional_pathbuf, expand_optional_pathbufs}; +use crate::util::{check_network_names, expand_optional_pathbuf, expand_optional_pathbufs}; use log::debug; use serde::{Deserialize, Serialize}; use std::default::Default; @@ -46,6 +46,10 @@ pub struct Configuration { /// Errors from this module. #[derive(Debug, thiserror::Error)] pub enum ConfigurationError { + /// Network name error. + #[error(transparent)] + NetworkNameError(#[from] crate::util::NetworkNameError), + /// Error reading configuration file. #[error("couldn't read configuration file {0}")] ReadError(PathBuf, #[source] std::io::Error), @@ -67,6 +71,10 @@ impl Configuration { let config = fs::read(filename) .map_err(|err| ConfigurationError::ReadError(filename.to_path_buf(), err))?; let mut config: Configuration = serde_yaml::from_slice(&config)?; + eprintln!("raw config: {:#?}", config); + if let Some(ref networks) = config.default_networks { + check_network_names(networks)?; + } config.expand_tildes()?; config.fill_in_missing_networks(); debug!("config: {:#?}", config); diff --git a/src/spec.rs b/src/spec.rs index 4e5665e..e91c044 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -1,7 +1,7 @@ //! Virtual machine specification. use crate::config::Configuration; -use crate::util::expand_tilde; +use crate::util::{check_network_names, expand_tilde}; use log::debug; use serde::{Deserialize, Serialize}; @@ -238,6 +238,10 @@ pub enum SpecificationError { #[error("Failed to read SSH public key file {0}")] SshKeyRead(PathBuf, #[source] std::io::Error), + /// Network name error. + #[error(transparent)] + NetworkNameError(#[from] crate::util::NetworkNameError), + /// Error parsing string as UTF8. #[error(transparent)] FromUtf8Error(#[from] std::string::FromUtf8Error), @@ -300,6 +304,10 @@ impl Specification { false }; + let networks = input.networks(config); + check_network_names(&networks)?; + eprintln!("checked names: {:?}", networks); + let spec = Specification { name: name.to_string(), ssh_keys, @@ -319,7 +327,7 @@ impl Specification { generate_host_certificate: gen_cert, autostart: input.autostart(config), ca_key, - networks: input.networks(config), + networks, }; debug!("specification as with defaults applied: {:#?}", spec); diff --git a/src/util.rs b/src/util.rs index c3565e0..cf60bf9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,7 +2,9 @@ use home_dir::HomeDirExt; +use lazy_static::lazy_static; use log::debug; +use regex::Regex; use std::net::TcpStream; use std::path::{Path, PathBuf}; @@ -43,3 +45,49 @@ pub fn expand_optional_pathbufs( } Ok(()) } + +pub fn check_network_names(networks: &[String]) -> Result<(), NetworkNameError> { + lazy_static! { + static ref RE: Regex = Regex::new("^(network|bridge)=[a-z0-9-]*$").unwrap(); + } + for name in networks.iter() { + if !RE.is_match(name) { + return Err(NetworkNameError::BadNetworkName(name.to_string())); + } + } + Ok(()) +} + +#[derive(Debug, thiserror::Error)] +pub enum NetworkNameError { + /// Bad network name. + #[error("Network name should be network=foo or bridge=bar, not: {0}")] + BadNetworkName(String), +} + +#[cfg(test)] +mod test { + use super::check_network_names; + + fn networks(names: &[&str]) -> Vec<String> { + names.iter().map(|s| s.to_string()).collect() + } + + #[test] + fn accepts_network_name() { + let names = networks(&["network=foo"]); + assert!(check_network_names(&names).is_ok()); + } + + #[test] + fn accepts_bridge_name() { + let names = networks(&["bridge=foo"]); + assert!(check_network_names(&names).is_ok()); + } + + #[test] + fn rejects_plain_name() { + let names = networks(&["foo"]); + assert!(check_network_names(&names).is_err()); + } +} diff --git a/subplot/vmadm.py b/subplot/vmadm.py index 473a673..e6cd234 100644 --- a/subplot/vmadm.py +++ b/subplot/vmadm.py @@ -9,7 +9,11 @@ import yaml def install_vmadm(ctx): runcmd_prepend_to_path = globals()["runcmd_prepend_to_path"] srcdir = globals()["srcdir"] - runcmd_prepend_to_path(ctx, os.path.join(srcdir, "target", "debug")) + + # Add the directory with built Rust binaries to the path. + default_target = os.path.join(srcdir, "target") + target = os.environ.get("CARGO_TARGET_DIR", default_target) + runcmd_prepend_to_path(ctx, dirname=os.path.join(target, "debug")) # Set permissions on the datadir and its parent. They are 0o700 by default, # which means that the libvirt daemon can't access the virtual machine @@ -346,6 +346,66 @@ foo: - bridge=br1 ~~~ +# Check that network name is OK + +vmadm must check that the virtual network name is OK. The scenarios +in this chapter verify that for the configuration and spec files. + +## Check network name in config + +~~~scenario +given an installed vmadm +given a Debian 10 OpenStack cloud image +given file .config/vmadm/config.yaml from bad-network-config.yaml +given file ca_key +given file .ssh/id_rsa from ssh_key +given file .ssh/id_rsa.pub from ssh_key_pub +given file .ssh/config from ssh_config +given file .ssh/known_hosts from known_hosts +when I try to run vmadm config +then command fails +then stderr contains ": br0" +~~~ + +~~~{#bad-network-config.yaml .file .yaml} +image_directory: ~/images +default_base_image: ~/base.qcow2 +default_image_gib: 5 +default_memory_mib: 2048 +default_cpus: 1 +default_generate_host_certificate: true +default_autostart: true +ca_key: ~/ca_key +authorized_keys: + - ~/.ssh/id_rsa.pub +default_networks: +- br0 +~~~ + +## Check network name in spec + +~~~scenario +given an installed vmadm +given a Debian 10 OpenStack cloud image +given file .config/vmadm/config.yaml from config.yaml +given file ca_key +given file .ssh/id_rsa from ssh_key +given file .ssh/id_rsa.pub from ssh_key_pub +given file .ssh/config from ssh_config +given file .ssh/known_hosts from known_hosts +given file bad-network-spec.yaml +when I try to run vmadm spec bad-network-spec.yaml +then command fails +then stderr contains ": br0" +~~~ + +~~~{#bad-network-spec.yaml .file .yaml} +foo: + networks: + - br0 +~~~ + + # Colophon This is a document meant to be processed with [Subplot][] into an HTML |