Refactor to chain realm specific config to global config

Now if a variable is not set in a realm config file (or the file does
not exist), the 'global' config file will also be searched in the
parent directory (ie: /storage/realms/config). If the variable is
still not found, the value from the default instance is returned.
This commit is contained in:
Bruce Leidl 2019-01-30 14:09:34 -05:00
parent 6215b58167
commit 0b2480f849

View File

@ -1,112 +1,172 @@
use std::path::Path;
use std::fs::File;
use std::io::Read;
use std::fs;
use toml;
use crate::Result;
fn default_true() -> bool {
true
lazy_static! {
pub static ref GLOBAL_CONFIG: RealmConfig = RealmConfig::load_global_config();
}
fn default_zone() -> String {
"clear".to_owned()
}
fn default_realmfs() -> String {
"base".to_owned()
}
#[derive (Deserialize,Clone)]
pub struct RealmConfig {
#[serde(default = "default_true", rename="use-shared-dir")]
use_shared_dir: bool,
#[serde(rename="use-shared-dir")]
use_shared_dir: Option<bool>,
#[serde(default, rename="use-ephemeral-home")]
use_ephemeral_home: bool,
#[serde(rename="use-ephemeral-home")]
use_ephemeral_home: Option<bool>,
#[serde(default = "default_true", rename="use-sound")]
use_sound: bool,
#[serde(rename="use-sound")]
use_sound: Option<bool>,
#[serde(default = "default_true", rename="use-x11")]
use_x11: bool,
#[serde(rename="use-x11")]
use_x11: Option<bool>,
#[serde(default = "default_true", rename="use-wayland")]
use_wayland: bool,
#[serde(rename="use-wayland")]
use_wayland: Option<bool>,
#[serde(default, rename="use-kvm")]
use_kvm: bool,
#[serde(rename="use-kvm")]
use_kvm: Option<bool>,
#[serde(default,rename="use-gpu")]
use_gpu: bool,
#[serde(rename="use-gpu")]
use_gpu: Option<bool>,
#[serde(default = "default_true", rename="use-network")]
use_network: bool,
#[serde(rename="use-network")]
use_network: Option<bool>,
#[serde(rename="network-zone")]
network_zone: Option<String>,
realmfs: Option<String>,
#[serde(rename="realmfs-write")]
realmfs_write: Option<bool>,
#[serde(skip)]
parent: Option<Box<RealmConfig>>,
#[serde(default = "default_zone", rename="network-zone")]
network_zone: String,
}
impl RealmConfig {
pub fn load_or_default(path: &Path) -> Result<RealmConfig> {
if path.exists() {
let s = load_as_string(&path)?;
let config = toml::from_str::<RealmConfig>(&s)?;
Ok(config)
} else {
Ok(RealmConfig::default())
pub fn load_or_default<P: AsRef<Path>>(path: P) -> RealmConfig {
match RealmConfig::load_config(path) {
Some(config) => config,
None => GLOBAL_CONFIG.clone()
}
}
fn load_global_config() -> RealmConfig {
if let Some(mut global) = RealmConfig::load_config("/storage/realms/config") {
global.parent = Some(Box::new(RealmConfig::default()));
return global;
}
RealmConfig::default()
}
fn load_config<P: AsRef<Path>>(path: P) -> Option<RealmConfig> {
if path.as_ref().exists() {
match fs::read_to_string(path.as_ref()) {
Ok(s) => return toml::from_str::<RealmConfig>(&s).ok(),
Err(e) => warn!("Error reading config file: {}", e),
}
}
None
}
pub fn default() -> RealmConfig {
RealmConfig {
use_shared_dir: true,
use_ephemeral_home: false,
use_sound: true,
use_x11: true,
use_wayland: true,
use_kvm: false,
use_gpu: false,
use_network: true,
network_zone: default_zone(),
use_shared_dir: Some(true),
use_ephemeral_home: Some(false),
use_sound: Some(true),
use_x11: Some(true),
use_wayland: Some(true),
use_kvm: Some(false),
use_gpu: Some(false),
use_network: Some(true),
network_zone: Some(default_zone()),
realmfs: Some(default_realmfs()),
realmfs_write: Some(false),
parent: None,
}
}
pub fn kvm(&self) -> bool {
self.use_kvm
self.bool_value(|c| c.use_kvm)
}
pub fn gpu(&self) -> bool {
self.use_gpu
self.bool_value(|c| c.use_gpu)
}
pub fn shared_dir(&self) -> bool {
self.use_shared_dir
self.bool_value(|c| c.use_shared_dir)
}
pub fn emphemeral_home(&self) -> bool {
self.use_ephemeral_home
self.bool_value(|c| c.use_ephemeral_home)
}
pub fn sound(&self) -> bool {
self.use_sound
self.bool_value(|c| c.use_sound)
}
pub fn x11(&self) -> bool {
self.use_x11
self.bool_value(|c| c.use_x11)
}
pub fn wayland(&self) -> bool {
self.use_wayland
self.bool_value(|c| c.use_network)
}
pub fn network(&self) -> bool {
self.use_network
self.bool_value(|c| c.use_network)
}
pub fn network_zone(&self) -> &str {
&self.network_zone
self.str_value(|c| c.network_zone.as_ref())
}
pub fn realmfs(&self) -> &str {
self.str_value(|c| c.realmfs.as_ref())
}
pub fn realmfs_write(&self) -> bool {
self.bool_value(|c| c.realmfs_write)
}
fn str_value<F>(&self, get: F) -> &str
where F: Fn(&RealmConfig) -> Option<&String>
{
if let Some(ref val) = get(self) {
return val
}
if let Some(ref parent) = self.parent {
if let Some(val) = get(parent) {
return val;
}
}
""
}
fn bool_value<F>(&self, get: F) -> bool
where F: Fn(&RealmConfig) -> Option<bool>
{
if let Some(val) = get(self) {
return val
}
if let Some(ref parent) = self.parent {
return get(parent).unwrap_or(false);
}
false
}
}
fn load_as_string(path: &Path) -> Result<String> {
let mut f = File::open(path)?;
let mut buffer = String::new();
f.read_to_string(&mut buffer)?;
Ok(buffer)
}