extern crate hex;
use std::fs::File;
use std::io::Read;
use std::time::Duration;
use yaml_rust::YamlLoader;
use config::ServerConfig;
use config::{DEFAULT_BATCH_SIZE, DEFAULT_STATUS_INTERVAL};
use key::KmsProtection;
use Error;
pub struct FileConfig {
port: u16,
interface: String,
seed: Vec<u8>,
batch_size: u8,
status_interval: Duration,
kms_protection: KmsProtection,
health_check_port: Option<u16>,
}
impl FileConfig {
pub fn new(config_file: &str) -> Result<Self, Error> {
let mut infile = File::open(config_file).expect("failed to open config file");
let mut contents = String::new();
infile
.read_to_string(&mut contents)
.expect("could not read config file");
let cfg = YamlLoader::load_from_str(&contents).expect("could not parse config file");
if cfg.len() != 1 {
return Err(Error::InvalidConfiguration(
"Empty or malformed config file".to_string(),
));
}
let mut config = FileConfig {
port: 0,
interface: "".to_string(),
seed: Vec::new(),
batch_size: DEFAULT_BATCH_SIZE,
status_interval: DEFAULT_STATUS_INTERVAL,
kms_protection: KmsProtection::Plaintext,
health_check_port: None,
};
for (key, value) in cfg[0].as_hash().unwrap() {
match key.as_str().unwrap() {
"port" => config.port = value.as_i64().unwrap() as u16,
"interface" => config.interface = value.as_str().unwrap().to_string(),
"batch_size" => config.batch_size = value.as_i64().unwrap() as u8,
"seed" => {
let val = value.as_str().unwrap().to_string();
config.seed = hex::decode(val)
.expect("seed value invalid; 'seed' should be 32 byte hex value");
}
"status_interval" => {
let val = value.as_i64().expect("status_interval value invalid");
config.status_interval = Duration::from_secs(val as u64)
}
"kms_protection" => {
let val =
value.as_str().unwrap().parse().unwrap_or_else(|_| {
panic!("invalid kms_protection value: {:?}", value)
});
config.kms_protection = val
}
"health_check_port" => {
let val = value.as_i64().unwrap() as u16;
config.health_check_port = Some(val);
}
unknown => {
return Err(Error::InvalidConfiguration(format!(
"unknown config key: {}",
unknown
)));
}
}
}
Ok(config)
}
}
impl ServerConfig for FileConfig {
fn interface(&self) -> &str {
self.interface.as_ref()
}
fn port(&self) -> u16 {
self.port
}
fn seed(&self) -> Vec<u8> {
self.seed.clone()
}
fn batch_size(&self) -> u8 {
self.batch_size
}
fn status_interval(&self) -> Duration {
self.status_interval
}
fn kms_protection(&self) -> &KmsProtection {
&self.kms_protection
}
fn health_check_port(&self) -> Option<u16> {
self.health_check_port
}
}