1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
//! Utilities.
use home_dir::HomeDirExt;
use lazy_static::lazy_static;
use log::debug;
use regex::Regex;
use std::net::TcpStream;
use std::path::{Path, PathBuf};
const SSH_PORT: i32 = 22;
// Wait for a virtual machine to have opened its SSH port.
pub fn wait_for_ssh(name: &str) {
debug!("waiting for {} to respond to SSH", name);
let addr = format!("{}:{}", name, SSH_PORT);
loop {
if TcpStream::connect(&addr).is_ok() {
return;
}
}
}
/// Expand a ~/ at the beginning of a Path to refer to the home directory.
pub fn expand_tilde(path: &Path) -> Result<PathBuf, home_dir::Error> {
path.expand_home()
}
pub fn expand_optional_pathbuf(maybe_path: &mut Option<PathBuf>) -> Result<(), home_dir::Error> {
if let Some(path) = maybe_path {
*maybe_path = Some(expand_tilde(path)?);
}
Ok(())
}
pub fn expand_optional_pathbufs(
maybe_paths: &mut Option<Vec<PathBuf>>,
) -> Result<(), home_dir::Error> {
if let Some(paths) = maybe_paths {
let mut expanded = vec![];
for path in paths {
expanded.push(expand_tilde(path)?);
}
*maybe_paths = Some(expanded);
}
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());
}
}
|