agent: use macro to simplify parse_cmdline function in config.rs

In function parse_cmdline there are some similar codes, if we want
to add more commandline arguments, the code will grow too long.
Use macro can reduce some codes with the same logic/processing.

Fixes: #914

Signed-off-by: bin liu <bin@hyper.sh>
This commit is contained in:
bin liu 2020-10-10 15:11:46 +08:00
parent 291257c0df
commit b7309943af

View File

@ -40,6 +40,36 @@ pub struct agentConfig {
pub unified_cgroup_hierarchy: bool, pub unified_cgroup_hierarchy: bool,
} }
// parse_cmdline_param parse commandline parameters.
macro_rules! parse_cmdline_param {
// commandline flags, without func to parse the option values
($param:ident, $key:ident, $field:expr) => {
if $param.eq(&$key) {
$field = true;
continue;
}
};
// commandline options, with func to parse the option values
($param:ident, $key:ident, $field:expr, $func:ident) => {
if $param.starts_with(format!("{}=", $key).as_str()) {
let val = $func($param)?;
$field = val;
continue;
}
};
// commandline options, with func to parse the option values, and match func
// to valid the values
($param:ident, $key:ident, $field:expr, $func:ident, $guard:expr) => {
if $param.starts_with(format!("{}=", $key).as_str()) {
let val = $func($param)?;
if $guard(val) {
$field = val;
}
continue;
}
};
}
impl agentConfig { impl agentConfig {
pub fn new() -> agentConfig { pub fn new() -> agentConfig {
agentConfig { agentConfig {
@ -60,51 +90,49 @@ impl agentConfig {
let params: Vec<&str> = cmdline.split_ascii_whitespace().collect(); let params: Vec<&str> = cmdline.split_ascii_whitespace().collect();
for param in params.iter() { for param in params.iter() {
// parse cmdline flags // parse cmdline flags
if param.eq(&DEBUG_CONSOLE_FLAG) { parse_cmdline_param!(param, DEBUG_CONSOLE_FLAG, self.debug_console);
self.debug_console = true; parse_cmdline_param!(param, DEV_MODE_FLAG, self.dev_mode);
}
if param.eq(&DEV_MODE_FLAG) {
self.dev_mode = true;
}
// parse cmdline options // parse cmdline options
if param.starts_with(format!("{}=", LOG_LEVEL_OPTION).as_str()) { parse_cmdline_param!(param, LOG_LEVEL_OPTION, self.log_level, get_log_level);
let level = get_log_level(param)?;
self.log_level = level;
}
if param.starts_with(format!("{}=", HOTPLUG_TIMOUT_OPTION).as_str()) { // ensure the timeout is a positive value
let hotplugTimeout = get_hotplug_timeout(param)?; parse_cmdline_param!(
// ensure the timeout is a positive value param,
if hotplugTimeout.as_secs() > 0 { HOTPLUG_TIMOUT_OPTION,
self.hotplug_timeout = hotplugTimeout; self.hotplug_timeout,
} get_hotplug_timeout,
} |hotplugTimeout: time::Duration| hotplugTimeout.as_secs() > 0
);
if param.starts_with(format!("{}=", DEBUG_CONSOLE_VPORT_OPTION).as_str()) { // vsock port should be positive values
let port = get_vsock_port(param)?; parse_cmdline_param!(
if port > 0 { param,
self.debug_console_vport = port; DEBUG_CONSOLE_VPORT_OPTION,
} self.debug_console_vport,
} get_vsock_port,
|port| port > 0
);
parse_cmdline_param!(
param,
LOG_VPORT_OPTION,
self.log_vport,
get_vsock_port,
|port| port > 0
);
if param.starts_with(format!("{}=", LOG_VPORT_OPTION).as_str()) { parse_cmdline_param!(
let port = get_vsock_port(param)?; param,
if port > 0 { CONTAINER_PIPE_SIZE_OPTION,
self.log_vport = port; self.container_pipe_size,
} get_container_pipe_size
} );
parse_cmdline_param!(
if param.starts_with(format!("{}=", CONTAINER_PIPE_SIZE_OPTION).as_str()) { param,
let container_pipe_size = get_container_pipe_size(param)?; UNIFIED_CGROUP_HIERARCHY_OPTION,
self.container_pipe_size = container_pipe_size self.unified_cgroup_hierarchy,
} get_bool_value
);
if param.starts_with(format!("{}=", UNIFIED_CGROUP_HIERARCHY_OPTION).as_str()) {
let b = get_bool_value(param, false);
self.unified_cgroup_hierarchy = b;
}
} }
if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) { if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) {
@ -185,11 +213,11 @@ fn get_hotplug_timeout(param: &str) -> Result<time::Duration> {
Ok(time::Duration::from_secs(value.unwrap())) Ok(time::Duration::from_secs(value.unwrap()))
} }
fn get_bool_value(param: &str, default: bool) -> bool { fn get_bool_value(param: &str) -> Result<bool> {
let fields: Vec<&str> = param.split("=").collect(); let fields: Vec<&str> = param.split("=").collect();
if fields.len() != 2 { if fields.len() != 2 {
return default; return Ok(false);
} }
let v = fields[1]; let v = fields[1];
@ -197,20 +225,20 @@ fn get_bool_value(param: &str, default: bool) -> bool {
// bool // bool
let t: std::result::Result<bool, std::str::ParseBoolError> = v.parse(); let t: std::result::Result<bool, std::str::ParseBoolError> = v.parse();
if t.is_ok() { if t.is_ok() {
return t.unwrap(); return Ok(t.unwrap());
} }
// integer // integer
let i: std::result::Result<u64, std::num::ParseIntError> = v.parse(); let i: std::result::Result<u64, std::num::ParseIntError> = v.parse();
if i.is_err() { if i.is_err() {
return default; return Ok(false);
} }
// only `0` returns false, otherwise returns true // only `0` returns false, otherwise returns true
match i.unwrap() { Ok(match i.unwrap() {
0 => false, 0 => false,
_ => true, _ => true,
} })
} }
fn get_container_pipe_size(param: &str) -> Result<i32> { fn get_container_pipe_size(param: &str) -> Result<i32> {