a way better config merge system

This commit is contained in:
core 2023-06-22 11:09:59 -04:00
parent 8d4d2d4264
commit e6e646b888
Signed by: core
GPG Key ID: FDBF740DADDCEECF
2 changed files with 14 additions and 46 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "trifid-api" name = "trifid-api"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
description = "Pure-rust Defined Networking compatible management server" description = "Pure-rust Defined Networking compatible management server"
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"

View File

@ -197,63 +197,31 @@ pub async fn generate_config(
local_range: None, local_range: None,
}; };
let mut val = Mapping::new(); // Merge with config overrides and re-parse
let config_str = serde_yaml::to_string(&nebula_config)?;
let mut value: serde_yaml::Value = serde_yaml::from_str(&config_str)?;
for (k, v) in &info.config_overrides { for (key, kv_value) in &info.config_overrides {
let key_split = k.split('.').collect::<Vec<&str>>(); // split up the key
// a.b.c.d = ['a']['b']['c']['d'] = value
let key_split = key.split('.').collect::<Vec<_>>();
let mut value = &mut val; let mut current_val = &mut value;
for ks_k in &key_split[..key_split.len()-1] { for key_iter in &key_split[..key_split.len()-1] {
if !value.contains_key(ks_k) { current_val = current_val.as_mapping_mut().unwrap().entry(Value::String(key_iter.to_string())).or_insert(Value::Mapping(Mapping::new()));
value.insert(Value::String(ks_k.to_string()), Value::Mapping(Mapping::new()));
}
value = value.get_mut(ks_k).ok_or("Invalid key-value pair")?.as_mapping_mut().unwrap();
} }
value.insert(Value::String(key_split[key_split.len()-1].to_string()), serde_yaml::from_str(v)?); current_val.as_mapping_mut().unwrap().insert(Value::String(key_split[key_split.len()-1].to_string()), serde_yaml::from_str(kv_value)?);
} }
let overrides_value = Value::Mapping(val); let config_str_merged = serde_yaml::to_string(&value)?;
debug!("{:?}", overrides_value); let nebula_config = serde_yaml::from_str(&config_str_merged)?;
let mut value = serde_yaml::to_value(nebula_config)?;
debug!("{:?}", value);
merge_yaml(&mut value, overrides_value);
debug!("{:?}", value);
let nebula_config = serde_yaml::from_value(value)?;
Ok((nebula_config, cert)) Ok((nebula_config, cert))
} }
// This cursed abomination credit https://stackoverflow.com/questions/67727239/how-to-combine-including-nested-array-values-two-serde-yamlvalue-objects
fn merge_yaml(a: &mut serde_yaml::Value, b: serde_yaml::Value) {
match (a, b) {
(a @ &mut serde_yaml::Value::Mapping(_), serde_yaml::Value::Mapping(b)) => {
let a = a.as_mapping_mut().unwrap();
for (k, v) in b {
if v.is_sequence() && a.contains_key(&k) && a[&k].is_sequence() {
let mut _b = a.get(&k).unwrap().as_sequence().unwrap().to_owned();
_b.append(&mut v.as_sequence().unwrap().to_owned());
a[&k] = serde_yaml::Value::from(_b);
continue;
}
if !a.contains_key(&k) {a.insert(k.to_owned(), v.to_owned());}
else { merge_yaml(&mut a[&k], v); }
}
}
(a, b) => *a = b,
}
}
pub async fn collect_info<'a>( pub async fn collect_info<'a>(
db: &'a Data<AppState>, db: &'a Data<AppState>,
host: &'a str, host: &'a str,