summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-11-10 10:34:05 +0200
committerLars Wirzenius <liw@liw.fi>2021-11-10 10:34:05 +0200
commit22cc382f9e9aa38f3adad18acd426bf0292bbf00 (patch)
tree96a392797b77e98d3ce2b26358b9c250db65e1e2
parent96c3606757750dadfcf31ec5ccd7787292da9273 (diff)
downloadvmadm-22cc382f9e9aa38f3adad18acd426bf0292bbf00.tar.gz
feat: check that virtual network names are syntactically correct
Sponsored-by: author
-rw-r--r--Cargo.lock34
-rw-r--r--Cargo.toml2
-rw-r--r--src/config.rs10
-rw-r--r--src/spec.rs12
-rw-r--r--src/util.rs48
-rw-r--r--vmadm.md60
6 files changed, 139 insertions, 27 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 79748ba..6337d51 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index 43e4436..92dbf41 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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/vmadm.md b/vmadm.md
index 6d0491a..85df349 100644
--- a/vmadm.md
+++ b/vmadm.md
@@ -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