Files
oss-backupd/src/config_util.rs
2019-12-15 11:25:09 +08:00

296 lines
10 KiB
Rust

use std::{
fs,
path::Path,
};
use rust_util::{
XResult,
new_box_ioerror,
util_msg::*,
};
use chrono::{
Utc,
};
pub const ETC_OSS_BACKUPD_CONFIG: &str = "/etc/oss-backupd/config.json";
pub const OSS_BACKUPD_CONFIG: &str = "oss-backupd-config.json";
pub const DOT_OSS_BACKUPD_CONFIG: &str = ".oss-backupd-config.json";
/*
{
"oss_config": {
"endpoint": "",
"access_key_id": "",
"access_key_secret": "",
"bucket": "",
"path": ""
},
"host": "",
"encrypt_pubkey_file": "",
"items": [
{
"oss_config": null,
"target": "",
"file_name": "",
"encrypt_pubkey_file": null
}
]
}
*/
#[derive(Debug, Clone)]
pub struct OSSConfig {
pub endpoint: Option<String>,
pub access_key_id: Option<String>,
pub access_key_secret: Option<String>,
pub bucket: Option<String>,
pub path: Option<String>,
}
#[derive(Debug)]
pub struct OSSBackupdConfigItem {
pub target: Option<String>,
pub file_name: Option<String>,
pub oss_config: Option<OSSConfig>,
pub encrypt_pubkey_file: Option<String>,
}
#[derive(Debug)]
pub struct OSSBackupdConfig {
pub oss_config: Option<OSSConfig>,
pub prefix: Option<String>,
pub host: Option<String>,
pub items: Vec<OSSBackupdConfigItem>,
}
pub fn make_oss_key(oss_backupd_config: &OSSBackupdConfig, oss_backupd_config_item: &OSSBackupdConfigItem, suffix: &str) -> String {
let mut key = String::with_capacity(1024);
key.push_str(&(if oss_backupd_config.prefix.is_some() {
remove_start_end_slash(&oss_backupd_config.prefix.as_ref().unwrap().as_str())
} else {
"default_oss_backupd".to_string()
}));
key.push_str("/");
key.push_str(&(if oss_backupd_config.host.is_some() {
remove_start_end_slash(&oss_backupd_config.host.as_ref().unwrap().as_str())
} else {
"default_host".to_string()
}));
key.push_str("/");
key.push_str(if oss_backupd_config_item.file_name.is_some() {
oss_backupd_config_item.file_name.as_ref().unwrap().as_str()
} else {
"default_file_name"
});
key.push_str("_");
let ymdhms = Utc::now().format("%Y%m%d_%H%M%S").to_string();
key.push_str(&ymdhms);
if suffix != "" {
key.push_str(&format!(".{}", suffix));
}
key
}
pub fn remove_start_end_slash(s: &str) -> String {
let mut ss = s;
while ss.starts_with("/") {
ss = &ss[1..]
}
while ss.ends_with("/") {
ss = &ss[0..(ss.len() - 1)];
}
ss.to_string()
}
pub fn parse_config(config_json: &json::JsonValue) -> OSSBackupdConfig {
let root_oss_config_object = parse_sub_oss_config(config_json);
let encrypt_pubkey_file = get_string_value(config_json, "encrypt_pubkey_file");
let prefix = get_string_value(config_json, "prefix");
let host = get_string_value(config_json, "host");
let items = &config_json["items"];
let mut items_objects: Vec<OSSBackupdConfigItem> = vec![];
if items.is_array() {
for i in 0..items.len() {
items_objects.push(parse_oss_backupd_config_item(&items[i], &root_oss_config_object, &encrypt_pubkey_file));
}
}
OSSBackupdConfig {
oss_config: root_oss_config_object,
prefix: prefix,
host: host,
items: items_objects,
}
}
fn parse_oss_backupd_config_item(item: &json::JsonValue, root_oss_config_object: &Option<OSSConfig>, root_encrypt_pubkey_file: &Option<String>) -> OSSBackupdConfigItem {
let target = get_string_value(item, "target");
let file_name = get_string_value(item, "file_name");
let mut encrypt_pubkey_file = get_string_value(item, "encrypt_pubkey_file");
let mut oss_config = parse_sub_oss_config(item);
if root_oss_config_object.is_some() {
if oss_config.is_some() {
let mut oc = oss_config.unwrap();
let root_oc = root_oss_config_object.as_ref().unwrap();
if oc.endpoint.is_none() && root_oc.endpoint.is_some() {
oc.endpoint = root_oc.endpoint.clone()
}
if oc.access_key_id.is_none() && root_oc.access_key_id.is_some() {
oc.access_key_id = root_oc.access_key_id.clone()
}
if oc.access_key_secret.is_none() && root_oc.access_key_secret.is_some() {
oc.access_key_secret = root_oc.access_key_secret.clone();
}
if oc.bucket.is_none() && root_oc.bucket.is_some() {
oc.bucket = root_oc.bucket.clone();
}
if oc.path.is_none() && root_oc.path.is_some() {
oc.path = root_oc.path.clone();
}
oss_config = Some(oc);
} else {
oss_config = root_oss_config_object.clone();
}
}
if encrypt_pubkey_file.is_none() && root_encrypt_pubkey_file.is_some() {
encrypt_pubkey_file = root_encrypt_pubkey_file.clone();
}
OSSBackupdConfigItem {
target: target,
file_name: file_name,
oss_config: oss_config,
encrypt_pubkey_file: encrypt_pubkey_file,
}
}
fn parse_sub_oss_config(json: &json::JsonValue) -> Option<OSSConfig> {
let root_oss_config = &json["oss_config"];
let root_oss_config_object: Option<OSSConfig> = match root_oss_config.is_null() {
true => None,
false => Some(parse_oss_config(root_oss_config)),
};
root_oss_config_object
}
fn parse_oss_config(oss_config: &json::JsonValue) -> OSSConfig {
OSSConfig {
endpoint: get_string_value(oss_config, "endpoint"),
access_key_id: get_string_value(oss_config, "access_key_id"),
access_key_secret: get_string_value(oss_config, "access_key_secret"),
bucket: get_string_value(oss_config, "bucket"),
path: get_string_value(oss_config, "path"),
}
}
fn get_string_value(json: &json::JsonValue, key: &str) -> Option<String> {
let value = &json[key];
match value.is_string() {
true => Some(value.as_str().unwrap().to_string()),
false => None,
}
}
pub fn get_config_json(custom_oss_backupd_config: Option<&str>, verbose: bool) -> Option<json::JsonValue> {
let config_content = get_config_content(custom_oss_backupd_config, verbose)?;
match json::parse(&config_content) {
Err(e) => {
print_message(MessageType::ERROR, &format!("Parse config json failed: {}", e));
None
},
Ok(o) => Some(o),
}
}
fn get_config_content(custom_oss_backupd_config: Option<&str>, verbose: bool) -> Option<String> {
if custom_oss_backupd_config.is_some() {
let custom_oss_backupd_config_unrwaped = custom_oss_backupd_config.unwrap();
if verbose {
print_message(MessageType::DEBUG, &format!("Read config from: {}", custom_oss_backupd_config_unrwaped));
}
let custom_oss_backupd_config_path = Path::new(custom_oss_backupd_config_unrwaped);
if custom_oss_backupd_config_path.exists() {
match fs::read_to_string(custom_oss_backupd_config_path) {
Err(e) => {
print_message(MessageType::ERROR, &format!("Read config file {} error: {}", custom_oss_backupd_config_unrwaped, e));
return None;
},
Ok(o) => return Some(o),
};
} else {
print_message(MessageType::ERROR, &format!("Custom config file not found: {}", custom_oss_backupd_config_unrwaped));
return None;
}
}
// is not assigned by -c or --conifg FILE
let oss_backupd_config_path = Path::new(OSS_BACKUPD_CONFIG);
if oss_backupd_config_path.exists() {
if verbose {
print_message(MessageType::DEBUG, &format!("Read config from: {}", OSS_BACKUPD_CONFIG));
}
match fs::read_to_string(oss_backupd_config_path) {
Err(e) => {
print_message(MessageType::ERROR, &format!("Read config file {} error: {}", OSS_BACKUPD_CONFIG, e));
return None;
},
Ok(o) => return Some(o),
};
}
let home_dot_oss_backupd_config = & match get_user_home_dir(DOT_OSS_BACKUPD_CONFIG) {
Err(e) => {
print_message(MessageType::WARN, &format!("Get user home error: {}", e));
String::new()
},
Ok(o) => o,
};
if home_dot_oss_backupd_config != "" {
let home_dot_oss_backupd_config_path = Path::new(home_dot_oss_backupd_config);
if home_dot_oss_backupd_config_path.exists() {
if verbose {
print_message(MessageType::DEBUG, &format!("Read config from: {}", home_dot_oss_backupd_config));
}
match fs::read_to_string(home_dot_oss_backupd_config_path) {
Err(e) => {
print_message(MessageType::ERROR, &format!("Read config file {} error: {}", home_dot_oss_backupd_config, e));
return None;
},
Ok(o) => return Some(o),
};
}
}
let etc_oss_backupd_config_path = Path::new(ETC_OSS_BACKUPD_CONFIG);
if etc_oss_backupd_config_path.exists() {
if verbose {
print_message(MessageType::DEBUG, &format!("Read config from: {}", ETC_OSS_BACKUPD_CONFIG));
}
match fs::read_to_string(etc_oss_backupd_config_path) {
Err(e) => {
print_message(MessageType::ERROR, &format!("Read config file {} error: {}", ETC_OSS_BACKUPD_CONFIG, e));
return None;
},
Ok(o) => return Some(o),
};
}
print_message(MessageType::ERROR, "Cannot find config file");
None
}
fn get_user_home() -> XResult<String> {
match dirs::home_dir() {
None => Err(new_box_ioerror("Home dir not found!")),
Some(home_dir_o) => match home_dir_o.to_str() {
None => Err(new_box_ioerror("Home dir not found!")),
Some(home_dir_str) => Ok(home_dir_str.to_string()),
},
}
}
fn get_user_home_dir(dir: &str) -> XResult<String> {
Ok(format!("{}/{}", get_user_home()?, dir))
}