dump config support

serde_yaml_ng
This commit is contained in:
Christien Rioux 2024-11-16 21:28:44 -05:00
parent 1349f753b6
commit 5c0e973e4a
5 changed files with 54 additions and 28 deletions

18
Cargo.lock generated
View File

@ -5126,6 +5126,19 @@ dependencies = [
"unsafe-libyaml", "unsafe-libyaml",
] ]
[[package]]
name = "serde_yaml_ng"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f"
dependencies = [
"indexmap 2.6.0",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]] [[package]]
name = "serial_test" name = "serial_test"
version = "2.0.0" version = "2.0.0"
@ -6521,7 +6534,7 @@ dependencies = [
"rpassword", "rpassword",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_yaml", "serde_yaml_ng",
"serial_test 3.1.1", "serial_test 3.1.1",
"signal-hook", "signal-hook",
"signal-hook-async-std", "signal-hook-async-std",
@ -6559,7 +6572,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"chrono", "chrono",
"clap 4.5.20", "clap 4.5.20",
"config 0.13.4", "config 0.14.1",
"console_error_panic_hook", "console_error_panic_hook",
"ctrlc", "ctrlc",
"eyre", "eyre",
@ -6592,6 +6605,7 @@ dependencies = [
"rtnetlink", "rtnetlink",
"send_wrapper 0.6.0", "send_wrapper 0.6.0",
"serde", "serde",
"serde_yaml_ng",
"serial_test 2.0.0", "serial_test 2.0.0",
"simplelog", "simplelog",
"socket2 0.5.7", "socket2 0.5.7",

View File

@ -68,7 +68,7 @@ config = { version = "^0.14.0", default-features = false, features = ["yaml"] }
cfg-if = "^1.0.0" cfg-if = "^1.0.0"
serde = "^1.0.204" serde = "^1.0.204"
serde_derive = "^1.0.204" serde_derive = "^1.0.204"
serde_yaml = "^0.9.34" serde_yaml = { package = "serde_yaml_ng", version = "^0.10.0" }
json = "^0" json = "^0"
futures-util = { version = "^0", default-features = false, features = [ futures-util = { version = "^0", default-features = false, features = [
"alloc", "alloc",

View File

@ -45,11 +45,12 @@ debug-locks = []
virtual-network = [] virtual-network = []
virtual-network-server = [ virtual-network-server = [
"dep:ws_stream_tungstenite",
"dep:async-tungstenite", "dep:async-tungstenite",
"dep:clap", "dep:clap",
"dep:config", "dep:config",
"dep:ipnet", "dep:ipnet",
"dep:serde_yaml",
"dep:ws_stream_tungstenite",
] ]
[dependencies] [dependencies]
@ -109,6 +110,7 @@ config = { version = "^0", default-features = false, features = [
"yaml", "yaml",
], optional = true } ], optional = true }
ipnet = { version = "2", features = ["serde"], optional = true } ipnet = { version = "2", features = ["serde"], optional = true }
serde_yaml = { package = "serde_yaml_ng", version = "^0.10.0", optional = true }
# Dependencies for WASM builds only # Dependencies for WASM builds only
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] [target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]

View File

@ -43,6 +43,9 @@ struct CmdlineArgs {
/// Specify a configuration file to use /// Specify a configuration file to use
#[arg(short = 'c', long, value_name = "FILE")] #[arg(short = 'c', long, value_name = "FILE")]
config_file: Option<PathBuf>, config_file: Option<PathBuf>,
/// Instead of running the virtual router, print the configuration it would use to the console
#[arg(long)]
dump_config: bool,
} }
fn main() -> Result<(), String> { fn main() -> Result<(), String> {
@ -64,6 +67,13 @@ fn main() -> Result<(), String> {
let config = let config =
Config::new(args.config_file).map_err(|e| format!("Error loading config: {}", e))?; Config::new(args.config_file).map_err(|e| format!("Error loading config: {}", e))?;
if args.dump_config {
let cfg_yaml = serde_yaml::to_string(&config)
.map_err(|e| format!("Error serializing config: {}", e))?;
println!("{}", cfg_yaml);
return Ok(());
}
let router_server = virtual_network::RouterServer::new(config); let router_server = virtual_network::RouterServer::new(config);
let _ss_tcp = if !args.no_tcp { let _ss_tcp = if !args.no_tcp {
Some( Some(

View File

@ -8,7 +8,7 @@ pub use ::config::ConfigError;
const PREDEFINED_CONFIG: &str = include_str!("predefined_config.yml"); const PREDEFINED_CONFIG: &str = include_str!("predefined_config.yml");
const DEFAULT_CONFIG: &str = include_str!("default_config.yml"); const DEFAULT_CONFIG: &str = include_str!("default_config.yml");
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum WeightedList<T: fmt::Debug + Clone> { pub enum WeightedList<T: fmt::Debug + Clone> {
Single(T), Single(T),
@ -22,26 +22,26 @@ impl<T: fmt::Debug + Clone> Default for WeightedList<T> {
pub type Probability = f32; pub type Probability = f32;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum Weighted<T: fmt::Debug + Clone> { pub enum Weighted<T: fmt::Debug + Clone> {
Weighted(T, f32), Weighted { item: T, weight: f32 },
Unweighted(T), Unweighted(T),
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Profile { pub struct Profile {
instances: Vec<Instance>, instances: Vec<Instance>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum Instance { pub enum Instance {
Machine { machine: WeightedList<String> }, Machine { machine: WeightedList<String> },
Template { template: WeightedList<String> }, Template { template: WeightedList<String> },
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Machine { pub struct Machine {
#[serde(flatten)] #[serde(flatten)]
location: Location, location: Location,
@ -55,7 +55,7 @@ pub struct Machine {
bootstrap: bool, bootstrap: bool,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Template { pub struct Template {
#[serde(flatten)] #[serde(flatten)]
location: Location, location: Location,
@ -65,12 +65,12 @@ pub struct Template {
disable_capabilities: Vec<String>, disable_capabilities: Vec<String>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Limits { pub struct Limits {
machine_count: WeightedList<u32>, machine_count: WeightedList<u32>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum Location { pub enum Location {
Network { network: WeightedList<String> }, Network { network: WeightedList<String> },
@ -79,7 +79,7 @@ pub enum Location {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Network { pub struct Network {
#[serde(default)] #[serde(default)]
model: Option<String>, model: Option<String>,
@ -89,20 +89,20 @@ pub struct Network {
ipv6: Option<NetworkIpv6>, ipv6: Option<NetworkIpv6>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkIpv4 { pub struct NetworkIpv4 {
allocation: String, allocation: String,
#[serde(default)] #[serde(default)]
gateway: Option<NetworkGateway>, gateway: Option<NetworkGateway>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkIpv6 { pub struct NetworkIpv6 {
allocation: String, allocation: String,
#[serde(default)] #[serde(default)]
gateway: Option<NetworkGateway>, gateway: Option<NetworkGateway>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkGateway { pub struct NetworkGateway {
translation: Translation, translation: Translation,
upnp: bool, upnp: bool,
@ -111,7 +111,7 @@ pub struct NetworkGateway {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Blueprint { pub struct Blueprint {
#[serde(default)] #[serde(default)]
model: WeightedList<String>, model: WeightedList<String>,
@ -121,7 +121,7 @@ pub struct Blueprint {
ipv6: Option<BlueprintIpv6>, ipv6: Option<BlueprintIpv6>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlueprintIpv4 { pub struct BlueprintIpv4 {
#[serde(default)] #[serde(default)]
allocation: Option<String>, allocation: Option<String>,
@ -129,7 +129,7 @@ pub struct BlueprintIpv4 {
#[serde(default)] #[serde(default)]
gateway: Option<BlueprintGateway>, gateway: Option<BlueprintGateway>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlueprintIpv6 { pub struct BlueprintIpv6 {
#[serde(default)] #[serde(default)]
allocation: Option<String>, allocation: Option<String>,
@ -138,7 +138,7 @@ pub struct BlueprintIpv6 {
gateway: Option<BlueprintGateway>, gateway: Option<BlueprintGateway>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlueprintGateway { pub struct BlueprintGateway {
translation: WeightedList<Translation>, translation: WeightedList<Translation>,
upnp: Probability, upnp: Probability,
@ -147,7 +147,7 @@ pub struct BlueprintGateway {
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Subnets { pub struct Subnets {
#[serde(default)] #[serde(default)]
subnet4: Vec<Ipv4Net>, subnet4: Vec<Ipv4Net>,
@ -155,13 +155,13 @@ pub struct Subnets {
subnet6: Vec<Ipv6Net>, subnet6: Vec<Ipv6Net>,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Distance { pub struct Distance {
min: f32, min: f32,
max: f32, max: f32,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Distribution { pub struct Distribution {
mean: f32, mean: f32,
sigma: f32, sigma: f32,
@ -170,7 +170,7 @@ pub struct Distribution {
max: f32, max: f32,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum Translation { pub enum Translation {
None, None,
@ -185,7 +185,7 @@ impl Default for Translation {
} }
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Model { pub struct Model {
latency: Distribution, latency: Distribution,
#[serde(default)] #[serde(default)]
@ -194,13 +194,13 @@ pub struct Model {
loss: Probability, loss: Probability,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Allocation { pub struct Allocation {
#[serde(flatten)] #[serde(flatten)]
subnets: Subnets, subnets: Subnets,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config { pub struct Config {
seed: Option<u32>, seed: Option<u32>,
default_network: String, default_network: String,