diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..b196eaa --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +tab_spaces = 2 diff --git a/src/bin.rs b/src/bin.rs index 97f5bcb..91b66e9 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,13 +1,22 @@ -use std::process::exit; use std::env; +use std::process::exit; -pub fn schematics_main(run: &dyn Fn (bool) -> Result<(), ()>) { +pub fn schematics_main(run: &dyn Fn(bool) -> Result<(), ()>) { let args: Vec = env::args().collect(); let dry_run = match args.len() { 1 => false, - 2 => if args[1] == "--dry-run" { true } else { panic!() }, - _ => panic!() + 2 => { + if args[1] == "--dry-run" { + true + } else { + panic!() + } + } + _ => panic!(), }; - exit(match run(dry_run) { Ok(_) => 0, Err(_) => 1 }); + exit(match run(dry_run) { + Ok(_) => 0, + Err(_) => 1, + }); } diff --git a/src/build.rs b/src/build.rs index d61b81b..492cfad 100644 --- a/src/build.rs +++ b/src/build.rs @@ -7,7 +7,13 @@ use std::path::{Path, PathBuf}; fn get_const_name>(p: &P) -> String { let mut file_name_without_extension = p.clone().into(); file_name_without_extension.set_extension(""); - String::from(file_name_without_extension.file_name().unwrap().to_string_lossy()).to_uppercase() + String::from( + file_name_without_extension + .file_name() + .unwrap() + .to_string_lossy(), + ) + .to_uppercase() } pub fn create_static_output_files(source_dir: &str) { @@ -17,8 +23,20 @@ pub fn create_static_output_files(source_dir: &str) { for maybe_dir_entry in read_dir(source_dir).unwrap() { let file_path = maybe_dir_entry.unwrap().path(); let mut buffer = String::new(); - File::open(file_path.clone()).unwrap().read_to_string(&mut buffer).unwrap(); + File::open(file_path.clone()) + .unwrap() + .read_to_string(&mut buffer) + .unwrap(); let fence = buffer.chars().filter(|c| *c == '#').collect::() + "#"; - f.write_all(format!("pub const {}: &str = r{1}\"{2}\"{1};\n", get_const_name(&file_path), fence, buffer).as_bytes()).unwrap(); + f.write_all( + format!( + "pub const {}: &str = r{1}\"{2}\"{1};\n", + get_const_name(&file_path), + fence, + buffer + ) + .as_bytes(), + ) + .unwrap(); } } diff --git a/src/command_runner.rs b/src/command_runner.rs index 39a7250..74a2967 100644 --- a/src/command_runner.rs +++ b/src/command_runner.rs @@ -5,22 +5,35 @@ use std::process::Command; use std::process::Output; pub trait CommandRunner { - fn run_with_args + ?Sized>(&self, program: &str, args: &[&S]) -> IoResult; - fn get_output + ?Sized>(&self, program: &str, args: &[&S]) -> Result, Box> { + fn run_with_args + ?Sized>(&self, program: &str, args: &[&S]) + -> IoResult; + fn get_output + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> Result, Box> { let output = try!(self.run_with_args(program, args)); if !output.status.success() { return Err(try!(String::from_utf8(output.stderr)).into()); } Ok(output.stdout) } - fn get_stderr + ?Sized>(&self, program: &str, args: &[&S]) -> Result, Box> { + fn get_stderr + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> Result, Box> { let output = try!(self.run_with_args(program, args)); if !output.status.success() { return Err(try!(String::from_utf8(output.stderr)).into()); } Ok(output.stderr) } - fn run_successfully + ?Sized>(&self, program: &str, args: &[&S]) -> Result<(), Box> { + fn run_successfully + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> Result<(), Box> { let output = try!(self.run_with_args(program, args)); if output.status.success() { Ok(()) @@ -34,7 +47,11 @@ pub trait CommandRunner { pub struct StdCommandRunner; impl CommandRunner for StdCommandRunner { - fn run_with_args + ?Sized>(&self, program: &str, args: &[&S]) -> IoResult { + fn run_with_args + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> IoResult { // FIXME: logger //println!("{} {:?}", program, args); let res = Command::new(program).args(args).output(); @@ -44,28 +61,43 @@ impl CommandRunner for StdCommandRunner { } #[derive(Debug)] -pub struct SetuidCommandRunner<'a, C> where C: 'a + CommandRunner { +pub struct SetuidCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ command_runner: &'a C, - user_name: &'a str + user_name: &'a str, } -impl<'a, C> SetuidCommandRunner<'a, C> where C: 'a + CommandRunner { +impl<'a, C> SetuidCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ pub fn new(user_name: &'a str, command_runner: &'a C) -> SetuidCommandRunner<'a, C> { - SetuidCommandRunner { command_runner, user_name } + SetuidCommandRunner { + command_runner, + user_name, + } } } -use std::os::unix::process::CommandExt; use std::env; +use std::os::unix::process::CommandExt; use users::get_user_by_name; -struct TempSetEnv<'a> { name: &'a str, old_value: Option } +struct TempSetEnv<'a> { + name: &'a str, + old_value: Option, +} impl<'a> TempSetEnv<'a> { fn new(name: &'a str, new_value: String) -> TempSetEnv<'a> { let old_value = env::var(name); env::set_var(name, new_value); - TempSetEnv { name, old_value: old_value.ok() } + TempSetEnv { + name, + old_value: old_value.ok(), + } } } @@ -73,14 +105,23 @@ impl<'a> Drop for TempSetEnv<'a> { fn drop(&mut self) { match self.old_value { Some(ref val) => env::set_var(self.name, val), - None => env::remove_var(self.name) + None => env::remove_var(self.name), } } } -impl<'a, C> CommandRunner for SetuidCommandRunner<'a, C> where C: 'a + CommandRunner { - fn run_with_args + ?Sized>(&self, program: &str, args: &[&S]) -> IoResult { - let uid = get_user_by_name(self.user_name).expect("User does not exist").uid(); +impl<'a, C> CommandRunner for SetuidCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ + fn run_with_args + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> IoResult { + let uid = get_user_by_name(self.user_name) + .expect("User does not exist") + .uid(); let set_home = TempSetEnv::new("HOME", format!("/home/{}", self.user_name)); let set_dbus = TempSetEnv::new("XDG_RUNTIME_DIR", format!("/run/user/{}", uid)); //println!("{} {:?}", program, args); @@ -91,21 +132,37 @@ impl<'a, C> CommandRunner for SetuidCommandRunner<'a, C> where C: 'a + CommandRu } #[derive(Debug)] -pub struct SuCommandRunner<'a, C> where C: 'a + CommandRunner { +pub struct SuCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ command_runner: &'a C, - user_name: &'a str + user_name: &'a str, } -impl<'a, C> SuCommandRunner<'a, C> where C: 'a + CommandRunner { +impl<'a, C> SuCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ pub fn new(user_name: &'a str, command_runner: &'a C) -> SuCommandRunner<'a, C> { - SuCommandRunner { command_runner, user_name } + SuCommandRunner { + command_runner, + user_name, + } } } // Su doesn't set XDG_RUNTIME_DIR // https://github.com/systemd/systemd/blob/master/src/login/pam_systemd.c#L439 -impl<'a, C> CommandRunner for SuCommandRunner<'a, C> where C: 'a + CommandRunner { - fn run_with_args + ?Sized>(&self, program: &str, args: &[&S]) -> IoResult { +impl<'a, C> CommandRunner for SuCommandRunner<'a, C> +where + C: 'a + CommandRunner, +{ + fn run_with_args + ?Sized>( + &self, + program: &str, + args: &[&S], + ) -> IoResult { let raw_new_args = [self.user_name, "-s", "/usr/bin/env", "--", program]; let mut new_args: Vec<&OsStr> = raw_new_args.iter().map(|s| s.as_ref()).collect(); let old_args: Vec<&OsStr> = args.iter().map(|s| s.as_ref()).collect(); @@ -115,5 +172,4 @@ impl<'a, C> CommandRunner for SuCommandRunner<'a, C> where C: 'a + CommandRunner } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/factory.rs b/src/factory.rs index b09bdf2..5b3eea6 100644 --- a/src/factory.rs +++ b/src/factory.rs @@ -5,29 +5,35 @@ use loggers::StdErrLogger; use repository::SymbolRepository; use resources::Resource; use schema::{NonRepeatingSymbolRunner, ReportingSymbolRunner, RequirementsResolvingSymbolRunner}; -use symbols::{Symbol, SymbolRunner}; use symbols::dir::Dir; use symbols::list::List; use symbols::owner::Owner; use symbols::systemd::user_session::SystemdUserSession; use symbols::tls::{TlsCsr, TlsKey}; -use symbols::user::{User, UserAdder}; use symbols::user::SystemUserAdder; +use symbols::user::{User, UserAdder}; +use symbols::{Symbol, SymbolRunner}; #[derive(Default)] -pub struct Factory { -} +pub struct Factory {} impl Factory { pub fn new() -> Self { Default::default() } - pub fn get_repo<'a, CR: CommandRunner>(&self, command_runner: &'a CR) -> DefaultSymbolRepository<'a, SystemUserAdder<'a, CR>, CR> { + pub fn get_repo<'a, CR: CommandRunner>( + &self, + command_runner: &'a CR, + ) -> DefaultSymbolRepository<'a, SystemUserAdder<'a, CR>, CR> { DefaultSymbolRepository::new(command_runner) } - pub fn get_symbol_runner<'a, RUNNER: SymbolRunner, REPO: SymbolRepository<'a>>(&self, symbol_runner: &'a RUNNER, repo: &'a REPO) -> Box { + pub fn get_symbol_runner<'a, RUNNER: SymbolRunner, REPO: SymbolRepository<'a>>( + &self, + symbol_runner: &'a RUNNER, + repo: &'a REPO, + ) -> Box { let runner1 = ReportingSymbolRunner::new(symbol_runner, StdErrLogger); let runner2 = NonRepeatingSymbolRunner::new(runner1); Box::new(RequirementsResolvingSymbolRunner::new(runner2, repo)) @@ -42,7 +48,7 @@ pub struct DefaultSymbolRepository<'a, A: 'a + UserAdder, C: 'a + CommandRunner> home_config: Regex, csr: Regex, private_key: Regex, - systemd_linger: Regex + systemd_linger: Regex, } impl<'a, C: 'a + CommandRunner> DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> { @@ -54,54 +60,64 @@ impl<'a, C: 'a + CommandRunner> DefaultSymbolRepository<'a, SystemUserAdder<'a, home_config: Regex::new("^/home/([^/]+)/.config(?:/|$)").unwrap(), csr: Regex::new("^/etc/ssl/local_certs/([^/]+).csr$").unwrap(), private_key: Regex::new("^/etc/ssl/private/([^/]+).key$").unwrap(), - systemd_linger: Regex::new("^/var/lib/systemd/linger/([^/]+)$").unwrap() + systemd_linger: Regex::new("^/var/lib/systemd/linger/([^/]+)$").unwrap(), } } } -impl<'a, C: CommandRunner> SymbolRepository<'a> for DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> { +impl<'a, C: CommandRunner> SymbolRepository<'a> + for DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> +{ fn get_symbol(&'a self, resource: &Resource) -> Option> { match resource.get_type() { "user" => Some(Box::new(User::new( - resource.get_value().to_string().into(), - self.command_runner, - &self.user_adder - ))), + resource.get_value().to_string().into(), + self.command_runner, + &self.user_adder, + ))), "dir" => { let value = resource.get_value(); - Some( - if let Some(matches) = self.home_config.captures(value) { - Box::new(List::new(vec![ - Box::new(Dir::new(value.to_string())), - Box::new(Owner::new(value.to_string(), matches[1].to_string().into(), self.command_runner)) - ])) as Box - } else if let Some(matches) = self.home.captures(value) { - Box::new( - User::new(matches[1].to_string().into(), self.command_runner, &self.user_adder) - ) as Box - } else { Box::new(Dir::new(value.to_string())) as Box } - ) - }, + Some(if let Some(matches) = self.home_config.captures(value) { + Box::new(List::new(vec![ + Box::new(Dir::new(value.to_string())), + Box::new(Owner::new( + value.to_string(), + matches[1].to_string().into(), + self.command_runner, + )), + ])) as Box + } else if let Some(matches) = self.home.captures(value) { + Box::new(User::new( + matches[1].to_string().into(), + self.command_runner, + &self.user_adder, + )) as Box + } else { + Box::new(Dir::new(value.to_string())) as Box + }) + } "file" => { let value = resource.get_value(); if let Some(matches) = self.csr.captures(value) { Some(Box::new(TlsCsr::new( matches[1].to_string().into(), - self.command_runner + self.command_runner, )) as Box) } else if let Some(matches) = self.private_key.captures(value) { Some(Box::new(TlsKey::new( matches[1].to_string().into(), - self.command_runner + self.command_runner, )) as Box) } else if let Some(matches) = self.systemd_linger.captures(value) { Some(Box::new(SystemdUserSession::new( matches[1].to_string().into(), - self.command_runner + self.command_runner, )) as Box) - } else { None } - }, - _ => None + } else { + None + } + } + _ => None, } } } diff --git a/src/lib.rs b/src/lib.rs index 9e65852..b3186a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,22 +1,21 @@ // rustfmt -#![deny(trivial_numeric_casts, unsafe_code, -unstable_features, unused_extern_crates, -unused_import_braces, unused_qualifications, -variant_size_differences +#![deny( + trivial_numeric_casts, + unsafe_code, + unstable_features, + unused_extern_crates, + unused_import_braces, + unused_qualifications, + variant_size_differences )] - -#![warn( -unused_results -)] - +#![warn(unused_results)] /* #![warn(missing_docs, trivial_casts, missing_copy_implementations, missing_debug_implementations )] */ - #![allow(box_pointers)] extern crate regex; @@ -27,8 +26,8 @@ pub mod build; pub mod command_runner; pub mod factory; pub mod loggers; -pub mod symbols; -pub mod schema; pub mod repository; pub mod resources; +pub mod schema; pub mod storage; +pub mod symbols; diff --git a/src/loggers.rs b/src/loggers.rs index 99994ff..0ad3c0d 100644 --- a/src/loggers.rs +++ b/src/loggers.rs @@ -18,7 +18,7 @@ impl Logger for StdErrLogger { } pub struct FilteringLogger<'a> { - logger: &'a mut dyn Logger + logger: &'a mut dyn Logger, } impl<'a> FilteringLogger<'a> { @@ -28,14 +28,11 @@ impl<'a> FilteringLogger<'a> { } impl<'a> Logger for FilteringLogger<'a> { - fn debug(&mut self, _str: &str) { - return - } + fn debug(&mut self, _str: &str) {} fn write(&mut self, str: &str) { self.logger.write(str) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/repository.rs b/src/repository.rs index 752bb28..943590b 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -1,20 +1,23 @@ use std::collections::HashMap; -use symbols::Symbol; use resources::Resource; +use symbols::Symbol; pub trait SymbolRepository<'a> { fn get_symbol(&'a self, resource: &Resource) -> Option>; } -impl<'a, C> SymbolRepository<'a> for C where C: Fn(&Resource) -> Option> { +impl<'a, C> SymbolRepository<'a> for C +where + C: Fn(&Resource) -> Option>, +{ fn get_symbol(&'a self, resource: &Resource) -> Option> { self(resource) } } pub struct DispatchingSymbolRepository<'a> { - repositories: HashMap<&'a str, Box + 'a>> + repositories: HashMap<&'a str, Box + 'a>>, } impl<'a> DispatchingSymbolRepository<'a> { @@ -25,6 +28,9 @@ impl<'a> DispatchingSymbolRepository<'a> { impl<'a> SymbolRepository<'a> for DispatchingSymbolRepository<'a> { fn get_symbol(&'a self, resource: &Resource) -> Option> { - self.repositories.get(resource.get_type()).and_then(|repo| repo.get_symbol(resource)) + self + .repositories + .get(resource.get_type()) + .and_then(|repo| repo.get_symbol(resource)) } } diff --git a/src/schema.rs b/src/schema.rs index 46901a7..9f40dd7 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -9,20 +9,20 @@ use symbols::{Symbol, SymbolRunner}; #[derive(Debug)] pub enum SymbolRunError { Symbol(Box), - ExecuteDidNotReach(()) + ExecuteDidNotReach(()), } impl Error for SymbolRunError { fn description(&self) -> &str { match self { SymbolRunError::Symbol(_) => "Symbol execution error", - SymbolRunError::ExecuteDidNotReach(_) => "Target not reached after executing symbol" + SymbolRunError::ExecuteDidNotReach(_) => "Target not reached after executing symbol", } } fn cause(&self) -> Option<&dyn Error> { match self { SymbolRunError::Symbol(ref e) => Some(&**e), - SymbolRunError::ExecuteDidNotReach(_) => None + SymbolRunError::ExecuteDidNotReach(_) => None, } } } @@ -31,24 +31,25 @@ impl fmt::Display for SymbolRunError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { SymbolRunError::Symbol(ref e) => write!(f, "{}", e), - SymbolRunError::ExecuteDidNotReach(_) => write!(f, "{}", self.description()) + SymbolRunError::ExecuteDidNotReach(_) => write!(f, "{}", self.description()), } } } pub struct InitializingSymbolRunner { - logger: RefCell + logger: RefCell, } impl InitializingSymbolRunner { pub fn new(logger: L) -> Self { - Self { logger: RefCell::new(logger) } + Self { + logger: RefCell::new(logger), + } } } impl SymbolRunner for InitializingSymbolRunner { - fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> - { + fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> { let mut logger = self.logger.borrow_mut(); let target_reached = try!(symbol.target_reached()); if target_reached { @@ -58,7 +59,13 @@ impl SymbolRunner for InitializingSymbolRunner { logger.write(format!("Executing {}", symbol).as_str()); try!(symbol.execute()); let target_reached = try!(symbol.target_reached()); - logger.debug(format!("Symbol reports target_reached: {:?} (should be true)", target_reached).as_str()); + logger.debug( + format!( + "Symbol reports target_reached: {:?} (should be true)", + target_reached + ) + .as_str(), + ); if !target_reached { return Err(Box::new(SymbolRunError::ExecuteDidNotReach(()))); } @@ -68,18 +75,19 @@ impl SymbolRunner for InitializingSymbolRunner { } pub struct DrySymbolRunner { - logger: RefCell + logger: RefCell, } impl DrySymbolRunner { pub fn new(logger: L) -> Self { - Self { logger: RefCell::new(logger) } + Self { + logger: RefCell::new(logger), + } } } impl SymbolRunner for DrySymbolRunner { - fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> - { + fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> { let mut logger = self.logger.borrow_mut(); let target_reached = try!(symbol.target_reached()); logger.debug(format!("Symbol reports target_reached: {:?}", target_reached).as_str()); @@ -92,22 +100,29 @@ impl SymbolRunner for DrySymbolRunner { pub struct ReportingSymbolRunner<'a, R: 'a + SymbolRunner, L: Logger>(&'a R, RefCell); -impl<'a, R, L> ReportingSymbolRunner<'a, R, L> where R: SymbolRunner, L: Logger { +impl<'a, R, L> ReportingSymbolRunner<'a, R, L> +where + R: SymbolRunner, + L: Logger, +{ pub fn new(symbol_runner: &'a R, logger: L) -> Self { ReportingSymbolRunner(symbol_runner, RefCell::new(logger)) } } -impl<'a, R, L> SymbolRunner for ReportingSymbolRunner<'a, R, L> where R: SymbolRunner, L: Logger { - fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> - { +impl<'a, R, L> SymbolRunner for ReportingSymbolRunner<'a, R, L> +where + R: SymbolRunner, + L: Logger, +{ + fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> { let mut logger = self.1.borrow_mut(); logger.debug(format!("Running symbol {}", symbol).as_str()); let res = self.0.run_symbol(symbol); match res { Err(ref e) => { logger.write(format!("Failed on {} with {}, aborting.", symbol, e).as_str()); - }, + } Ok(_) => { logger.debug(format!("Successfully finished {}", symbol).as_str()); } @@ -116,23 +131,28 @@ impl<'a, R, L> SymbolRunner for ReportingSymbolRunner<'a, R, L> where R: SymbolR } } -use std::collections::HashSet; use resources::Resource; +use std::collections::HashSet; pub struct NonRepeatingSymbolRunner { upstream: R, - done: RefCell> + done: RefCell>, } -impl NonRepeatingSymbolRunner where R: SymbolRunner { +impl NonRepeatingSymbolRunner +where + R: SymbolRunner, +{ pub fn new(symbol_runner: R) -> Self { - NonRepeatingSymbolRunner{ upstream: symbol_runner, done: RefCell::new(HashSet::new()) } + NonRepeatingSymbolRunner { + upstream: symbol_runner, + done: RefCell::new(HashSet::new()), + } } } impl SymbolRunner for NonRepeatingSymbolRunner { - fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> - { + fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> { if let Some(resources) = symbol.provides() { let mut done = self.done.borrow_mut(); let mut has_to_run = false; @@ -151,17 +171,29 @@ impl SymbolRunner for NonRepeatingSymbolRunner { } use std::marker::PhantomData; -pub struct RequirementsResolvingSymbolRunner<'a, 's, R: 'a + SymbolRunner, G: 'a + SymbolRepository<'s>>(R, &'a G, PhantomData>); - -impl<'s, 'a: 's, R, G> RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { +pub struct RequirementsResolvingSymbolRunner< + 'a, + 's, + R: 'a + SymbolRunner, + G: 'a + SymbolRepository<'s>, +>(R, &'a G, PhantomData>); + +impl<'s, 'a: 's, R, G> RequirementsResolvingSymbolRunner<'a, 's, R, G> +where + R: SymbolRunner, + G: SymbolRepository<'s>, +{ pub fn new(symbol_runner: R, symbol_repo: &'a G) -> Self { RequirementsResolvingSymbolRunner(symbol_runner, symbol_repo, PhantomData) } } -impl<'s, 'a: 's, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { - fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> - { +impl<'s, 'a: 's, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'a, 's, R, G> +where + R: SymbolRunner, + G: SymbolRepository<'s>, +{ + fn run_symbol(&self, symbol: &dyn Symbol) -> Result<(), Box> { for resource in symbol.get_prerequisites() { if let Some(dep) = self.1.get_symbol(&resource) { try!(dep.as_action(self).run()); @@ -180,13 +212,13 @@ mod test { use std::fmt; use loggers::Logger; - use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction}; - use schema::SymbolRunner; use schema::InitializingSymbolRunner; + use schema::SymbolRunner; + use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction}; #[derive(Debug, PartialEq, Clone)] enum DummySymbolError { - Error(()) + Error(()), } impl Error for DummySymbolError { @@ -203,7 +235,7 @@ mod test { struct DummySymbol<'a> { _execute: &'a dyn Fn() -> Result<(), Box>, - _target_reached: &'a dyn Fn() -> Result> + _target_reached: &'a dyn Fn() -> Result>, } impl<'b> Symbol for DummySymbol<'b> { @@ -218,7 +250,10 @@ mod test { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } @@ -230,13 +265,19 @@ mod test { } impl<'a> DummySymbol<'a> { - fn new(target_reached: &'a dyn Fn() -> Result>, execute: &'a dyn Fn() -> Result<(), Box>) -> DummySymbol<'a> { - DummySymbol { _target_reached: target_reached, _execute: execute } + fn new( + target_reached: &'a dyn Fn() -> Result>, + execute: &'a dyn Fn() -> Result<(), Box>, + ) -> DummySymbol<'a> { + DummySymbol { + _target_reached: target_reached, + _execute: execute, + } } } struct DummyLogger { - log: Vec + log: Vec, } impl DummyLogger { @@ -256,28 +297,33 @@ mod test { #[test] fn nothing_needed_to_be_done() { - let result = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new(&|| Ok(true), &|| Ok(()))); + let result = InitializingSymbolRunner::new(DummyLogger::new()) + .run_symbol(&DummySymbol::new(&|| Ok(true), &|| Ok(()))); assert!(result.is_ok()); } #[test] fn everything_is_ok() { let first = RefCell::new(true); - let result = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new(&|| { - let mut _first = first.borrow_mut(); - Ok(if *_first { - *_first = false; - true - } else { - false - }) - }, &|| Ok(()))); + let result = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new( + &|| { + let mut _first = first.borrow_mut(); + Ok(if *_first { + *_first = false; + true + } else { + false + }) + }, + &|| Ok(()), + )); assert!(result.is_ok()); } #[test] fn executing_did_not_change_state() { - let result = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new(&|| Ok(false), &|| Ok(()))); + let result = InitializingSymbolRunner::new(DummyLogger::new()) + .run_symbol(&DummySymbol::new(&|| Ok(false), &|| Ok(()))); assert_eq!( result.unwrap_err().description(), "Target not reached after executing symbol" @@ -286,7 +332,11 @@ mod test { #[test] fn executing_did_not_work() { - let err = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new(&|| Ok(false), &|| Err(Box::new(DummySymbolError::Error(()))))).unwrap_err(); + let err = InitializingSymbolRunner::new(DummyLogger::new()) + .run_symbol(&DummySymbol::new(&|| Ok(false), &|| { + Err(Box::new(DummySymbolError::Error(()))) + })) + .unwrap_err(); assert_eq!(err.description(), "Description"); } } diff --git a/src/storage.rs b/src/storage.rs index 7c93bfd..1b61334 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -20,14 +20,19 @@ impl SimpleStorage { fn get_path(&self, date: Option) -> String { match date { Some(d) => format!("{}/_{}/{}", self.0, self.1, d), - None => format!("{}/_{}", self.0, self.1) + None => format!("{}/_{}", self.0, self.1), } } } impl Storage for SimpleStorage { fn write_filename(&self) -> String { - self.get_path(Some(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs())) + self.get_path(Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(), + )) } fn read_filename(&self) -> Result> { @@ -37,8 +42,15 @@ impl Storage for SimpleStorage { fn recent_date(&self) -> Result> { let dir = self.get_path(None); try!(read_dir(dir)) - .map(|entry| entry.ok().and_then(|e| e.file_name().into_string().ok()).and_then(|filename| u64::from_str(&filename).ok())) - .fold(None, |maybe_newest, maybe_time| maybe_newest.into_iter().chain(maybe_time).max()) - .ok_or_else(|| "Not found".to_string().into()) + .map(|entry| { + entry + .ok() + .and_then(|e| e.file_name().into_string().ok()) + .and_then(|filename| u64::from_str(&filename).ok()) + }) + .fold(None, |maybe_newest, maybe_time| { + maybe_newest.into_iter().chain(maybe_time).max() + }) + .ok_or_else(|| "Not found".to_string().into()) } } diff --git a/src/symbols/acme/account_key.rs b/src/symbols/acme/account_key.rs index 2c06288..37373d8 100644 --- a/src/symbols/acme/account_key.rs +++ b/src/symbols/acme/account_key.rs @@ -9,12 +9,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct AcmeAccountKey<'a, C: 'a + CommandRunner> { path: Cow<'a, Path>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> AcmeAccountKey<'a, C> { pub fn new(path: Cow<'a, Path>, command_runner: &'a C) -> Self { - AcmeAccountKey { path, command_runner } + AcmeAccountKey { + path, + command_runner, + } } fn get_bytes(&self) -> u32 { @@ -33,27 +36,50 @@ impl<'a, C: CommandRunner> Symbol for AcmeAccountKey<'a, C> { if !self.path.exists() { return Ok(false); } - let stdout = try!(self.command_runner.get_output("openssl", &["rsa".as_ref(), "-in".as_ref(), self.path.as_os_str(), "-noout".as_ref(), "-check".as_ref(), "-text".as_ref()])); + let stdout = try!(self.command_runner.get_output( + "openssl", + &[ + "rsa".as_ref(), + "-in".as_ref(), + self.path.as_os_str(), + "-noout".as_ref(), + "-check".as_ref(), + "-text".as_ref() + ] + )); Ok(stdout.starts_with(&format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes())) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("openssl", &["genrsa".as_ref(), "-out".as_ref(), self.path.as_os_str(), self.get_bytes().to_string().as_ref()]) + self.command_runner.run_successfully( + "openssl", + &[ + "genrsa".as_ref(), + "-out".as_ref(), + self.path.as_os_str(), + self.get_bytes().to_string().as_ref(), + ], + ) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("dir", self.path.parent().unwrap().to_string_lossy() ) ] + vec![Resource::new( + "dir", + self.path.parent().unwrap().to_string_lossy(), + )] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/acme/cert.rs b/src/symbols/acme/cert.rs index 895a8e6..480b593 100644 --- a/src/symbols/acme/cert.rs +++ b/src/symbols/acme/cert.rs @@ -6,17 +6,20 @@ use std::io::Write; use std::path::Path; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use resources::Resource; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct AcmeCert<'a, C: 'a + CommandRunner> { domain: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> AcmeCert<'a, C> { pub fn new(domain: Cow<'a, str>, command_runner: &'a C) -> Self { - AcmeCert { domain, command_runner } + AcmeCert { + domain, + command_runner, + } } fn get_csr_path(&self) -> String { @@ -34,7 +37,7 @@ impl<'a, C: CommandRunner> fmt::Display for AcmeCert<'a, C> { } } -const DAYS_IN_SECONDS: u32 = 24*60*60; +const DAYS_IN_SECONDS: u32 = 24 * 60 * 60; impl<'a, C: CommandRunner> Symbol for AcmeCert<'a, C> { fn target_reached(&self) -> Result> { @@ -42,10 +45,44 @@ impl<'a, C: CommandRunner> Symbol for AcmeCert<'a, C> { return Ok(false); } - let output = try!(self.command_runner.run_with_args("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()])); - if output.status.success() && output.stdout == format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes() { - Ok(self.command_runner.run_successfully("openssl", &["verify", "--untrusted", "/home/acme/lets_encrypt_x3_cross_signed.pem", &self.get_cert_path()]).is_ok()) - } else if output.status.code() == Some(1) && output.stdout == format!("subject=CN = {}\nCertificate will expire\n", self.domain).as_bytes() { + let output = try!(self.command_runner.run_with_args( + "openssl", + &[ + "x509", + "-in", + &self.get_cert_path(), + "-noout", + "-subject", + "-checkend", + &(30 * DAYS_IN_SECONDS).to_string() + ] + )); + if output.status.success() + && output.stdout + == format!( + "subject=CN = {}\nCertificate will not expire\n", + self.domain + ) + .as_bytes() + { + Ok( + self + .command_runner + .run_successfully( + "openssl", + &[ + "verify", + "--untrusted", + "/home/acme/lets_encrypt_x3_cross_signed.pem", + &self.get_cert_path(), + ], + ) + .is_ok(), + ) + } else if output.status.code() == Some(1) + && output.stdout + == format!("subject=CN = {}\nCertificate will expire\n", self.domain).as_bytes() + { Ok(false) } else { Err(try!(String::from_utf8(output.stderr)).into()) @@ -53,25 +90,37 @@ impl<'a, C: CommandRunner> Symbol for AcmeCert<'a, C> { } fn execute(&self) -> Result<(), Box> { - let output = try!(self.command_runner.get_output("acme-tiny", &["--account-key", "/home/acme/account.key", "--csr", &self.get_csr_path(), "--acme-dir", "/home/acme/challenges/"])); + let output = try!(self.command_runner.get_output( + "acme-tiny", + &[ + "--account-key", + "/home/acme/account.key", + "--csr", + &self.get_csr_path(), + "--acme-dir", + "/home/acme/challenges/" + ] + )); let mut file = try!(FsFile::create(self.get_cert_path())); try!(file.write_all(&output)); Ok(()) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("file", self.get_csr_path()) ] + vec![Resource::new("file", self.get_csr_path())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/acme/chain.rs b/src/symbols/acme/chain.rs index a5ba0fe..ebfb0e2 100644 --- a/src/symbols/acme/chain.rs +++ b/src/symbols/acme/chain.rs @@ -6,17 +6,20 @@ use std::io::Write; use std::path::Path; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use resources::Resource; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct AcmeCertChain<'a, C: 'a + CommandRunner> { domain: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> AcmeCertChain<'a, C> { pub fn new(domain: Cow<'a, str>, command_runner: &'a C) -> Self { - AcmeCertChain { domain, command_runner } + AcmeCertChain { + domain, + command_runner, + } } fn get_single_cert_path(&self) -> String { @@ -34,7 +37,7 @@ impl<'a, C: CommandRunner> fmt::Display for AcmeCertChain<'a, C> { } } -const DAYS_IN_SECONDS: u32 = 24*60*60; +const DAYS_IN_SECONDS: u32 = 24 * 60 * 60; impl<'a, C: CommandRunner> Symbol for AcmeCertChain<'a, C> { fn target_reached(&self) -> Result> { @@ -42,34 +45,72 @@ impl<'a, C: CommandRunner> Symbol for AcmeCertChain<'a, C> { return Ok(false); } - let stdout = try!(self.command_runner.get_output("openssl", &["x509", "-in", &self.get_cert_chain_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()])); - if stdout != format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes() { + let stdout = try!(self.command_runner.get_output( + "openssl", + &[ + "x509", + "-in", + &self.get_cert_chain_path(), + "-noout", + "-subject", + "-checkend", + &(30 * DAYS_IN_SECONDS).to_string() + ] + )); + if stdout + != format!( + "subject=CN = {}\nCertificate will not expire\n", + self.domain + ) + .as_bytes() + { return Ok(false); } // FIXME: From my understanding, the -untrusted *.pem parameter shouldn't be necessary, but is necessary with openssl 1.1.0f-3 - Ok(self.command_runner.run_successfully("openssl", &["verify", "-untrusted", "/home/acme/lets_encrypt_x3_cross_signed.pem", &self.get_cert_chain_path()]).is_ok()) + Ok( + self + .command_runner + .run_successfully( + "openssl", + &[ + "verify", + "-untrusted", + "/home/acme/lets_encrypt_x3_cross_signed.pem", + &self.get_cert_chain_path(), + ], + ) + .is_ok(), + ) } fn execute(&self) -> Result<(), Box> { - let output = try!(self.command_runner.get_output("cat", &[self.get_single_cert_path().as_ref(), "/home/acme/lets_encrypt_x3_cross_signed.pem"])); + let output = try!(self.command_runner.get_output( + "cat", + &[ + self.get_single_cert_path().as_ref(), + "/home/acme/lets_encrypt_x3_cross_signed.pem" + ] + )); let mut file = try!(FsFile::create(self.get_cert_chain_path())); try!(file.write_all(&output)); Ok(()) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("file", self.get_single_cert_path()) ] + vec![Resource::new("file", self.get_single_cert_path())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/acme/user.rs b/src/symbols/acme/user.rs index ad4fcad..773c642 100644 --- a/src/symbols/acme/user.rs +++ b/src/symbols/acme/user.rs @@ -1,17 +1,17 @@ +use resources::Resource; use std::borrow::{Borrow, Cow}; use std::error::Error; use std::fmt; use std::ops::Deref; use std::path::PathBuf; -use resources::Resource; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, SymbolAction, SymbolRunner, Symbol}; use symbols::acme::AcmeAccountKey; use symbols::dir::Dir; use symbols::file::File; use symbols::list::List; use symbols::owner::Owner; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct AcmeUser<'a>(Cow<'a, str>); @@ -38,7 +38,10 @@ impl<'a> Symbol for AcmeUser<'a> { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } @@ -49,17 +52,41 @@ impl<'a> fmt::Display for AcmeUser<'a> { } } -pub fn new<'a, S: Into>, C: CommandRunner, P: 'a + Deref>(command_runner: &'a C, cert: P, user_name: S) -> Box { // impl trait +pub fn new<'a, S: Into>, C: CommandRunner, P: 'a + Deref>( + command_runner: &'a C, + cert: P, + user_name: S, +) -> Box { + // impl trait let user_name_cow = user_name.into(); - let account_key_file: PathBuf = ["/home", user_name_cow.borrow(), "account.key"].iter().collect(); + let account_key_file: PathBuf = ["/home", user_name_cow.borrow(), "account.key"] + .iter() + .collect(); Box::new(List::new(vec![ - Box::new(AcmeAccountKey::new(account_key_file.clone().into(), command_runner)), - Box::new(Owner::new(account_key_file.to_string_lossy().into_owned(), user_name_cow.clone(), command_runner)), + Box::new(AcmeAccountKey::new( + account_key_file.clone().into(), + command_runner, + )), + Box::new(Owner::new( + account_key_file.to_string_lossy().into_owned(), + user_name_cow.clone(), + command_runner, + )), Box::new(Dir::new("/home/acme/challenges")), - Box::new(Owner::new("/home/acme/challenges", user_name_cow.clone(), command_runner)), + Box::new(Owner::new( + "/home/acme/challenges", + user_name_cow.clone(), + command_runner, + )), Box::new(Dir::new("/etc/ssl/local_certs")), - Box::new(Owner::new("/etc/ssl/local_certs", user_name_cow, command_runner)), - Box::new(File::new("/home/acme/lets_encrypt_x3_cross_signed.pem", cert)) + Box::new(Owner::new( + "/etc/ssl/local_certs", + user_name_cow, + command_runner, + )), + Box::new(File::new( + "/home/acme/lets_encrypt_x3_cross_signed.pem", + cert, + )), ])) } - diff --git a/src/symbols/dir.rs b/src/symbols/dir.rs index 2fac061..7b38b77 100644 --- a/src/symbols/dir.rs +++ b/src/symbols/dir.rs @@ -7,17 +7,26 @@ use std::path::Path; use resources::Resource; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct Dir where D: AsRef { - path: D +pub struct Dir +where + D: AsRef, +{ + path: D, } -impl Dir where D: AsRef { +impl Dir +where + D: AsRef, +{ pub fn new(path: D) -> Self { Dir { path } } } -impl Symbol for Dir where D: AsRef { +impl Symbol for Dir +where + D: AsRef, +{ fn target_reached(&self) -> Result> { let metadata = fs::metadata(self.path.as_ref()); // Check if dir exists @@ -31,7 +40,10 @@ impl Symbol for Dir where D: AsRef { if metadata.unwrap().is_dir() { Ok(true) } else { - Err(Box::new(io::Error::new(io::ErrorKind::AlreadyExists, "Could not create a directory, non-directory file exists"))) + Err(Box::new(io::Error::new( + io::ErrorKind::AlreadyExists, + "Could not create a directory, non-directory file exists", + ))) } } @@ -41,27 +53,33 @@ impl Symbol for Dir where D: AsRef { fn get_prerequisites(&self) -> Vec { if let Some(parent) = Path::new(self.path.as_ref()).parent() { - vec![ Resource::new("dir", parent.to_string_lossy()) ] + vec![Resource::new("dir", parent.to_string_lossy())] } else { vec![] } } fn provides(&self) -> Option> { - Some(vec![ Resource::new("dir", self.path.as_ref()) ]) + Some(vec![Resource::new("dir", self.path.as_ref())]) } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl fmt::Display for Dir where D: AsRef { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl fmt::Display for Dir +where + D: AsRef, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Dir {}", self.path.as_ref()) } } diff --git a/src/symbols/factory.rs b/src/symbols/factory.rs index e586356..cf6c1f0 100644 --- a/src/symbols/factory.rs +++ b/src/symbols/factory.rs @@ -4,18 +4,18 @@ use std::path::Path; use command_runner::{CommandRunner, SetuidCommandRunner}; use storage::{SimpleStorage, Storage}; -use symbols::{Action, Symbol, SymbolRunner}; use symbols::acme::{AcmeCert, AcmeCertChain}; use symbols::file::File; use symbols::git::checkout::GitCheckout; use symbols::hook::Hook; use symbols::list::ListAction; use symbols::mariadb::{DatabaseDump, MariaDBDatabase, MariaDBUser}; -use symbols::nginx::server::{NginxServer, server_config, php_server_config_snippet}; +use symbols::nginx::server::{php_server_config_snippet, server_config, NginxServer}; use symbols::owner::Owner; -use symbols::stored_directory::{StoredDirectory, StorageDirection}; +use symbols::stored_directory::{StorageDirection, StoredDirectory}; use symbols::systemd::reload::ReloadService; use symbols::tls::SelfSignedTlsCert; +use symbols::{Action, Symbol, SymbolRunner}; pub trait Policy { fn user_name_for_host(&self, host_name: &'static str) -> String; @@ -32,11 +32,11 @@ impl Policy for DefaultPolicy { } } -pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner, P: 'a + Policy>{ +pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner, P: 'a + Policy> { command_runner: &'a C, acme_command_runner: SetuidCommandRunner<'a, C>, symbol_runner: &'a R, - policy: &'a P + policy: &'a P, } impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner, P: 'b + Policy> SymbolFactory<'b, C, R, P> { @@ -44,39 +44,45 @@ impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner, P: 'b + Policy> SymbolFact let acme_user = "acme"; // FIXME: CONFIG let acme_command_runner = SetuidCommandRunner::new(acme_user, command_runner); - SymbolFactory { command_runner, acme_command_runner, symbol_runner, policy } + SymbolFactory { + command_runner, + acme_command_runner, + symbol_runner, + policy, + } } - pub fn get_nginx_acme_server<'a, 'c: 'a, S: 'a + Symbol>(&'c self, host: &'static str, nginx_server_symbol: S) -> Box { + pub fn get_nginx_acme_server<'a, 'c: 'a, S: 'a + Symbol>( + &'c self, + host: &'static str, + nginx_server_symbol: S, + ) -> Box { Box::new(ListAction::new(vec![ - Box::new(SelfSignedTlsCert::new( - host.into(), - self.command_runner - )).into_action(self.symbol_runner), + Box::new(SelfSignedTlsCert::new(host.into(), self.command_runner)) + .into_action(self.symbol_runner), Box::new(Hook::new( nginx_server_symbol, - ReloadService::new("nginx", self.command_runner) - )).into_action(self.symbol_runner), - Box::new(AcmeCert::new( - host.into(), - &self.acme_command_runner - )).into_action(self.symbol_runner), + ReloadService::new("nginx", self.command_runner), + )) + .into_action(self.symbol_runner), + Box::new(AcmeCert::new(host.into(), &self.acme_command_runner)) + .into_action(self.symbol_runner), Box::new(Hook::new( - AcmeCertChain::new( - host.into(), - &self.acme_command_runner - ), - ReloadService::new("nginx", self.command_runner) - )).into_action(self.symbol_runner) + AcmeCertChain::new(host.into(), &self.acme_command_runner), + ReloadService::new("nginx", self.command_runner), + )) + .into_action(self.symbol_runner), ])) } pub fn get_nginx_acme_challenge_config<'a>(&'a self) -> Box { Box::new(File::new( - "/etc/nginx/snippets/acme-challenge.conf", "location ^~ /.well-known/acme-challenge/ { + "/etc/nginx/snippets/acme-challenge.conf", + "location ^~ /.well-known/acme-challenge/ { alias /home/acme/challenges/; try_files $uri =404; -}" - )).into_action(self.symbol_runner) +}", + )) + .into_action(self.symbol_runner) } fn get_php_fpm_pool_socket_path<'a>(&'a self, user_name: &str) -> String { @@ -89,7 +95,7 @@ impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner, P: 'b + Policy> SymbolFact File::new( format!("/etc/php/7.0/fpm/pool.d/{}.conf", user_name), format!( - "[{0}] + "[{0}] user = {0} group = www-data @@ -99,47 +105,66 @@ pm = ondemand pm.max_children = 10 catch_workers_output = yes env[PATH] = /usr/local/bin:/usr/bin:/bin -" - , user_name, socket)), - ReloadService::new("php7.0-fpm", self.command_runner) - )).into_action(self.symbol_runner) +", + user_name, socket + ), + ), + ReloadService::new("php7.0-fpm", self.command_runner), + )) + .into_action(self.symbol_runner) } - pub fn serve_php<'a>(&'a self, host_name: &'static str, root_dir: Cow<'a, str>) -> Box { + pub fn serve_php<'a>( + &'a self, + host_name: &'static str, + root_dir: Cow<'a, str>, + ) -> Box { let user_name = self.policy.user_name_for_host(host_name); let socket = self.get_php_fpm_pool_socket_path(&user_name); Box::new(ListAction::new(vec![ self.get_php_fpm_pool(&user_name), - self.get_nginx_acme_server(host_name, - NginxServer::new_php( - host_name, - socket.into(), - root_dir, - self.command_runner - ) - ) + self.get_nginx_acme_server( + host_name, + NginxServer::new_php(host_name, socket.into(), root_dir, self.command_runner), + ), ])) } - pub fn serve_wordpress<'a>(&'a self, host_name: &'static str, root_dir: Cow<'a, str>) -> Box { + pub fn serve_wordpress<'a>( + &'a self, + host_name: &'static str, + root_dir: Cow<'a, str>, + ) -> Box { let user_name = self.policy.user_name_for_host(host_name); let socket = self.get_php_fpm_pool_socket_path(&user_name); Box::new(ListAction::new(vec![ self.get_php_fpm_pool(&user_name), - self.get_nginx_acme_server(host_name, + self.get_nginx_acme_server( + host_name, NginxServer::new( host_name, - server_config(host_name, &format!("{} + server_config( + host_name, + &format!( + "{} location / {{ try_files $uri $uri/ /index.php?$args; }} - ", php_server_config_snippet(socket.into(), root_dir))), - self.command_runner - )) + ", + php_server_config_snippet(socket.into(), root_dir) + ), + ), + self.command_runner, + ), + ), ])) } - pub fn serve_dokuwiki<'a>(&'a self, host_name: &'static str, root_dir: &'static str) -> Box { + pub fn serve_dokuwiki<'a>( + &'a self, + host_name: &'static str, + root_dir: &'static str, + ) -> Box { let user_name = self.policy.user_name_for_host(host_name); let socket = self.get_php_fpm_pool_socket_path(&user_name); Box::new(ListAction::new(vec![ @@ -174,15 +199,23 @@ env[PATH] = /usr/local/bin:/usr/bin:/bin ])) } - pub fn serve_nextcloud<'a>(&'a self, host_name: &'static str, root_dir: Cow<'a, str>) -> Box { + pub fn serve_nextcloud<'a>( + &'a self, + host_name: &'static str, + root_dir: Cow<'a, str>, + ) -> Box { let user_name = self.policy.user_name_for_host(host_name); let socket = self.get_php_fpm_pool_socket_path(&user_name); Box::new(ListAction::new(vec![ self.get_php_fpm_pool(&user_name), - self.get_nginx_acme_server(host_name, + self.get_nginx_acme_server( + host_name, NginxServer::new( host_name, - server_config(host_name, &format!("{} + server_config( + host_name, + &format!( + "{} client_max_body_size 500M; # Disable gzip to avoid the removal of the ETag header @@ -230,50 +263,106 @@ env[PATH] = /usr/local/bin:/usr/bin:/bin location ~* \\.(?:jpg|jpeg|gif|bmp|ico|png|swf)$ {{ access_log off; }} - ", php_server_config_snippet(socket.into(), root_dir))), - self.command_runner - )) + ", + php_server_config_snippet(socket.into(), root_dir) + ), + ), + self.command_runner, + ), + ), ])) } - pub fn serve_redir<'a>(&'a self, host_name: &'static str, target: &'static str) -> Box { - self.get_nginx_acme_server(host_name, NginxServer::new_redir(host_name, target, self.command_runner)) + pub fn serve_redir<'a>( + &'a self, + host_name: &'static str, + target: &'static str, + ) -> Box { + self.get_nginx_acme_server( + host_name, + NginxServer::new_redir(host_name, target, self.command_runner), + ) } pub fn serve_static<'a>(&'a self, host_name: &'static str, dir: &'a str) -> Box { - self.get_nginx_acme_server(host_name, NginxServer::new_static(host_name, dir, self.command_runner)) + self.get_nginx_acme_server( + host_name, + NginxServer::new_static(host_name, dir, self.command_runner), + ) } - pub fn get_stored_directory<'a, T: Into>(&'a self, storage_name: &'static str, target: T) -> (Box, Box) { + pub fn get_stored_directory<'a, T: Into>( + &'a self, + storage_name: &'static str, + target: T, + ) -> (Box, Box) { let data = SimpleStorage::new("/root/data".to_string(), storage_name.to_string()); let string_target = target.into(); ( - Box::new(StoredDirectory::new(string_target.clone().into(), data.clone(), StorageDirection::Save, self.command_runner)).into_action(self.symbol_runner), - Box::new(StoredDirectory::new(string_target.into(), data.clone(), StorageDirection::Load, self.command_runner)).into_action(self.symbol_runner) + Box::new(StoredDirectory::new( + string_target.clone().into(), + data.clone(), + StorageDirection::Save, + self.command_runner, + )) + .into_action(self.symbol_runner), + Box::new(StoredDirectory::new( + string_target.into(), + data.clone(), + StorageDirection::Load, + self.command_runner, + )) + .into_action(self.symbol_runner), ) } pub fn get_mariadb_database<'a>(&'a self, name: &'static str) -> Box { let db_dump = SimpleStorage::new("/root/data".to_string(), format!("{}.sql", name)); Box::new(ListAction::new(vec![ - Box::new(MariaDBDatabase::new(name.into(), db_dump.read_filename().unwrap().into(), self.command_runner)).into_action(self.symbol_runner), - Box::new(DatabaseDump::new(name, db_dump, self.command_runner)).into_action(self.symbol_runner) + Box::new(MariaDBDatabase::new( + name.into(), + db_dump.read_filename().unwrap().into(), + self.command_runner, + )) + .into_action(self.symbol_runner), + Box::new(DatabaseDump::new(name, db_dump, self.command_runner)) + .into_action(self.symbol_runner), ])) } pub fn get_mariadb_user<'a>(&'a self, user_name: &'static str) -> Box { - Box::new(MariaDBUser::new(user_name.into(), self.command_runner)).into_action(self.symbol_runner) + Box::new(MariaDBUser::new(user_name.into(), self.command_runner)) + .into_action(self.symbol_runner) } - pub fn get_git_checkout<'a, T: 'a + AsRef>(&'a self, target: T, source: &'a str, branch: &'a str) -> Box { - Box::new(GitCheckout::new(target, source, branch, self.command_runner)).into_action(self.symbol_runner) + pub fn get_git_checkout<'a, T: 'a + AsRef>( + &'a self, + target: T, + source: &'a str, + branch: &'a str, + ) -> Box { + Box::new(GitCheckout::new( + target, + source, + branch, + self.command_runner, + )) + .into_action(self.symbol_runner) } - pub fn get_owner<'a, F: 'a + AsRef>(&'a self, file: F, user: &'a str) -> Box { + pub fn get_owner<'a, F: 'a + AsRef>( + &'a self, + file: F, + user: &'a str, + ) -> Box { Box::new(Owner::new(file, user.into(), self.command_runner)).into_action(self.symbol_runner) } - pub fn get_file<'a, F: 'a + Deref, Q: 'a + AsRef>(&'a self, path: Q, content: F) -> Box { + pub fn get_file<'a, F: 'a + Deref, Q: 'a + AsRef>( + &'a self, + path: Q, + content: F, + ) -> Box { Box::new(File::new(path, content)).into_action(self.symbol_runner) } } diff --git a/src/symbols/file.rs b/src/symbols/file.rs index db9f692..0cb3bcb 100644 --- a/src/symbols/file.rs +++ b/src/symbols/file.rs @@ -6,21 +6,33 @@ use std::io::{Read, Write}; use std::ops::Deref; use std::path::Path; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use resources::Resource; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct File where C: Deref, D: AsRef { +pub struct File +where + C: Deref, + D: AsRef, +{ path: D, - content: C + content: C, } -impl File where C: Deref, D: AsRef { +impl File +where + C: Deref, + D: AsRef, +{ pub fn new(path: D, content: C) -> Self { File { path, content } } } -impl Symbol for File where C: Deref, D: AsRef { +impl Symbol for File +where + C: Deref, + D: AsRef, +{ fn target_reached(&self) -> Result> { let file = FsFile::open(self.path.as_ref()); // Check if file exists @@ -37,9 +49,9 @@ impl Symbol for File where C: Deref, D: AsRef { loop { match (file_content.next(), target_content.next()) { (None, None) => return Ok(true), - (Some(Ok(a)), Some(b)) if a == b => {}, + (Some(Ok(a)), Some(b)) if a == b => {} (Some(Err(e)), _) => return Err(Box::new(e)), - (_, _) => return Ok(false) + (_, _) => return Ok(false), } } } @@ -51,20 +63,33 @@ impl Symbol for File where C: Deref, D: AsRef { } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("dir", Path::new(self.path.as_ref()).parent().unwrap().to_string_lossy() ) ] + vec![Resource::new( + "dir", + Path::new(self.path.as_ref()) + .parent() + .unwrap() + .to_string_lossy(), + )] } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl fmt::Display for File where C: Deref, D: AsRef { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl fmt::Display for File +where + C: Deref, + D: AsRef, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "File {}", self.path.as_ref().display()) } } diff --git a/src/symbols/git/checkout.rs b/src/symbols/git/checkout.rs index 52c71df..e3e82ee 100644 --- a/src/symbols/git/checkout.rs +++ b/src/symbols/git/checkout.rs @@ -11,18 +11,29 @@ pub struct GitCheckout<'a, C: 'a + CommandRunner, T: AsRef> { target: T, source: &'a str, branch: &'a str, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner, T: AsRef> GitCheckout<'a, C, T> { pub fn new(target: T, source: &'a str, branch: &'a str, command_runner: &'a C) -> Self { - GitCheckout { target, source, branch, command_runner } + GitCheckout { + target, + source, + branch, + command_runner, + } } } impl<'a, C: CommandRunner, T: AsRef> fmt::Display for GitCheckout<'a, C, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Checkout {} (branch {}) into {}", self.source, self.branch, self.target.as_ref()) + write!( + f, + "Checkout {} (branch {}) into {}", + self.source, + self.branch, + self.target.as_ref() + ) } } @@ -54,7 +65,18 @@ impl<'a, C: CommandRunner, T: AsRef> Symbol for GitCheckout<'a, C, T> { fn execute(&self) -> Result<(), Box> { if !Path::new(self.target.as_ref()).exists() { - return self.command_runner.run_successfully("git", &["clone", "--depth", "1", "-b", self.branch, self.source, self.target.as_ref()]); + return self.command_runner.run_successfully( + "git", + &[ + "clone", + "--depth", + "1", + "-b", + self.branch, + self.source, + self.target.as_ref(), + ], + ); } try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"])); @@ -62,22 +84,30 @@ impl<'a, C: CommandRunner, T: AsRef> Symbol for GitCheckout<'a, C, T> { } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("dir", Path::new(self.target.as_ref()).parent().unwrap().to_string_lossy()) ] + vec![Resource::new( + "dir", + Path::new(self.target.as_ref()) + .parent() + .unwrap() + .to_string_lossy(), + )] } fn provides(&self) -> Option> { - Some(vec![ Resource::new("dir", self.target.as_ref().to_string()) ]) + Some(vec![Resource::new("dir", self.target.as_ref().to_string())]) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/git/submodules.rs b/src/symbols/git/submodules.rs index a044e01..0437f0f 100644 --- a/src/symbols/git/submodules.rs +++ b/src/symbols/git/submodules.rs @@ -7,12 +7,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct GitSubmodules<'a, C: 'a + CommandRunner> { target: &'a str, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> GitSubmodules<'a, C> { pub fn new(target: &'a str, command_runner: &'a C) -> Self { - GitSubmodules { target, command_runner } + GitSubmodules { + target, + command_runner, + } } } @@ -35,8 +38,14 @@ impl<'a, C: CommandRunner> Symbol for GitSubmodules<'a, C> { if !Path::new(self.target).exists() { return Ok(false); } - let output = try!(String::from_utf8(try!(self._run_in_target_repo(&["submodule", "status"])))); - Ok(output.lines().all(|line| line.is_empty() || line.starts_with(' '))) + let output = try!(String::from_utf8(try!( + self._run_in_target_repo(&["submodule", "status"]) + ))); + Ok( + output + .lines() + .all(|line| line.is_empty() || line.starts_with(' ')), + ) } fn execute(&self) -> Result<(), Box> { @@ -48,11 +57,13 @@ impl<'a, C: CommandRunner> Symbol for GitSubmodules<'a, C> { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/hook.rs b/src/symbols/hook.rs index 2387563..319d75d 100644 --- a/src/symbols/hook.rs +++ b/src/symbols/hook.rs @@ -4,21 +4,39 @@ use std::fmt; use resources::Resource; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct Hook where A: Symbol, B: Symbol { +pub struct Hook +where + A: Symbol, + B: Symbol, +{ a: A, - b: B + b: B, } // A and B are executed if either A or B are not reached -impl Hook where A: Symbol, B: Symbol { +impl Hook +where + A: Symbol, + B: Symbol, +{ pub fn new(a: A, b: B) -> Self { Hook { a, b } } } -impl Symbol for Hook where A: Symbol, B: Symbol { +impl Symbol for Hook +where + A: Symbol, + B: Symbol, +{ fn target_reached(&self) -> Result> { - self.a.target_reached().and_then(|reached| if reached { self.b.target_reached() } else { Ok(reached) }) + self.a.target_reached().and_then(|reached| { + if reached { + self.b.target_reached() + } else { + Ok(reached) + } + }) } fn execute(&self) -> Result<(), Box> { @@ -41,20 +59,31 @@ impl Symbol for Hook where A: Symbol, B: Symbol { if let Some(provides) = self.b.provides() { r.extend(provides.into_iter()); } - if r.is_empty() { None } else { Some(r) } + if r.is_empty() { + None + } else { + Some(r) + } } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl fmt::Display for Hook where A: Symbol, B: Symbol { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl fmt::Display for Hook +where + A: Symbol, + B: Symbol, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Hook {} and then {}", self.a, self.b) } } @@ -64,36 +93,58 @@ mod test { use std::error::Error; use std::fmt; - use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use symbols::hook::Hook; + use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; struct ErrSymbol(String); impl Symbol for ErrSymbol { - fn target_reached(&self) -> Result> { Err(self.0.clone().into()) } - fn execute(&self) -> Result<(), Box> { Err(self.0.clone().into()) } + fn target_reached(&self) -> Result> { + Err(self.0.clone().into()) + } + fn execute(&self) -> Result<(), Box> { + Err(self.0.clone().into()) + } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } - impl fmt::Display for ErrSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } } + impl fmt::Display for ErrSymbol { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "") + } + } struct OkSymbol(bool); impl Symbol for OkSymbol { - fn target_reached(&self) -> Result> { Ok(self.0) } - fn execute(&self) -> Result<(), Box> { Ok(()) } + fn target_reached(&self) -> Result> { + Ok(self.0) + } + fn execute(&self) -> Result<(), Box> { + Ok(()) + } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } - impl fmt::Display for OkSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } } + impl fmt::Display for OkSymbol { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "") + } + } #[test] fn first_target_reached_fails() { diff --git a/src/symbols/list.rs b/src/symbols/list.rs index 17e3c20..7d83523 100644 --- a/src/symbols/list.rs +++ b/src/symbols/list.rs @@ -5,7 +5,7 @@ use resources::Resource; use symbols::{Action, Symbol, SymbolRunner}; pub struct List<'a> { - symbols: Vec> + symbols: Vec>, } impl<'a> List<'a> { @@ -35,7 +35,9 @@ impl<'a> Symbol for List<'a> { let mut r = vec![]; for symbol in &self.symbols { for req in symbol.get_prerequisites() { - if self.provides().map_or(true, |p| !p.contains(&req)) { r.push(req) } + if self.provides().map_or(true, |p| !p.contains(&req)) { + r.push(req) + } } } r @@ -48,21 +50,34 @@ impl<'a> Symbol for List<'a> { r.extend(provides.into_iter()); } } - if r.is_empty() { None } else { Some(r) } + if r.is_empty() { + None + } else { + Some(r) + } } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolListAction::new(runner, &self.symbols)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { - Box::new(ListAction::new(self.symbols.into_iter().map(|s| s.into_action(runner)).collect())) + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { + Box::new(ListAction::new( + self + .symbols + .into_iter() + .map(|s| s.into_action(runner)) + .collect(), + )) } } struct SymbolListAction<'a> { runner: &'a dyn SymbolRunner, - symbols: &'a [Box] + symbols: &'a [Box], } impl<'a> SymbolListAction<'a> { @@ -81,7 +96,7 @@ impl<'a> Action for SymbolListAction<'a> { } pub struct ListAction<'a> { - actions: Vec> + actions: Vec>, } impl<'a> ListAction<'a> { @@ -100,7 +115,7 @@ impl<'a> Action for ListAction<'a> { } impl<'a> fmt::Display for List<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { try!(write!(f, "List [ ")); for symbol in &self.symbols { try!(write!(f, "{} ", symbol)); diff --git a/src/symbols/mariadb/database.rs b/src/symbols/mariadb/database.rs index 38569eb..5d5501c 100644 --- a/src/symbols/mariadb/database.rs +++ b/src/symbols/mariadb/database.rs @@ -8,16 +8,22 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct MariaDBDatabase<'a, C: 'a + CommandRunner> { db_name: Cow<'a, str>, seed_file: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> MariaDBDatabase<'a, C> { pub fn new(db_name: Cow<'a, str>, seed_file: Cow<'a, str>, command_runner: &'a C) -> Self { - MariaDBDatabase { db_name, seed_file, command_runner } + MariaDBDatabase { + db_name, + seed_file, + command_runner, + } } fn run_sql(&self, sql: &str) -> Result> { - let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); + let b = try!(self + .command_runner + .get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); Ok(try!(String::from_utf8(b))) } } @@ -30,23 +36,34 @@ impl<'a, C: CommandRunner> fmt::Display for MariaDBDatabase<'a, C> { impl<'a, C: CommandRunner> Symbol for MariaDBDatabase<'a, C> { fn target_reached(&self) -> Result> { - Ok(try!(self.run_sql(&format!("SHOW DATABASES LIKE '{}'", self.db_name))).trim_end() == self.db_name) + Ok( + try!(self.run_sql(&format!("SHOW DATABASES LIKE '{}'", self.db_name))).trim_end() + == self.db_name, + ) } fn execute(&self) -> Result<(), Box> { try!(self.run_sql(&format!("CREATE DATABASE {}", self.db_name))); - self.command_runner.run_successfully("sh", &["-c", &format!("mariadb '{}' < {}", self.db_name, self.seed_file)]) + self.command_runner.run_successfully( + "sh", + &[ + "-c", + &format!("mariadb '{}' < {}", self.db_name, self.seed_file), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/mariadb/database_dump.rs b/src/symbols/mariadb/database_dump.rs index 14b2e8b..f5551be 100644 --- a/src/symbols/mariadb/database_dump.rs +++ b/src/symbols/mariadb/database_dump.rs @@ -3,22 +3,33 @@ use std::fmt; use std::str::FromStr; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use storage::Storage; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct DatabaseDump<'a, N, C, S> where N: 'a + AsRef, C: 'a + CommandRunner, S: Storage { +pub struct DatabaseDump<'a, N, C, S> +where + N: 'a + AsRef, + C: 'a + CommandRunner, + S: Storage, +{ db_name: N, storage: S, - command_runner: &'a C + command_runner: &'a C, } impl<'a, N: AsRef, C: CommandRunner, S: Storage> DatabaseDump<'a, N, C, S> { pub fn new(db_name: N, storage: S, command_runner: &'a C) -> Self { - DatabaseDump { db_name, storage, command_runner } + DatabaseDump { + db_name, + storage, + command_runner, + } } fn run_sql(&self, sql: &str) -> Result> { - let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); + let b = try!(self + .command_runner + .get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); Ok(try!(String::from_utf8(b))) } } @@ -33,23 +44,37 @@ impl<'a, N: AsRef, C: CommandRunner, S: Storage> Symbol for DatabaseDump<'a fn target_reached(&self) -> Result> { let dump_date = try!(self.storage.recent_date()); let modified_date = try!(self.run_sql(&format!("select UNIX_TIMESTAMP(MAX(UPDATE_TIME)) from information_schema.tables WHERE table_schema = '{}'", self.db_name.as_ref()))); - if modified_date.trim_end() == "NULL" { return Ok(false); } + if modified_date.trim_end() == "NULL" { + return Ok(false); + } Ok(try!(u64::from_str(modified_date.trim_end())) <= dump_date) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("sh", &["-c", &format!("mysqldump '{}' > {}", self.db_name.as_ref(), self.storage.write_filename())]) + self.command_runner.run_successfully( + "sh", + &[ + "-c", + &format!( + "mysqldump '{}' > {}", + self.db_name.as_ref(), + self.storage.write_filename() + ), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/mariadb/mod.rs b/src/symbols/mariadb/mod.rs index 30077f2..584a74c 100644 --- a/src/symbols/mariadb/mod.rs +++ b/src/symbols/mariadb/mod.rs @@ -1,6 +1,6 @@ mod database; -mod user; mod database_dump; +mod user; pub use self::database::MariaDBDatabase; pub use self::database_dump::DatabaseDump; diff --git a/src/symbols/mariadb/user.rs b/src/symbols/mariadb/user.rs index 566aaa2..7ef9467 100644 --- a/src/symbols/mariadb/user.rs +++ b/src/symbols/mariadb/user.rs @@ -8,16 +8,21 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct MariaDBUser<'a, C: 'a + CommandRunner> { user_name: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> MariaDBUser<'a, C> { pub fn new(user_name: Cow<'a, str>, command_runner: &'a C) -> Self { - MariaDBUser { user_name, command_runner } + MariaDBUser { + user_name, + command_runner, + } } fn run_sql(&self, sql: &str) -> Result> { - let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); + let b = try!(self + .command_runner + .get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); Ok(try!(String::from_utf8(b))) } } @@ -30,27 +35,39 @@ impl<'a, C: CommandRunner> fmt::Display for MariaDBUser<'a, C> { impl<'a, C: CommandRunner> Symbol for MariaDBUser<'a, C> { fn target_reached(&self) -> Result> { - Ok(try!(self.run_sql(&format!("SELECT User FROM mysql.user WHERE User = '{}' AND plugin = 'unix_socket'", self.user_name))).trim_end() == self.user_name) + Ok( + try!(self.run_sql(&format!( + "SELECT User FROM mysql.user WHERE User = '{}' AND plugin = 'unix_socket'", + self.user_name + ))) + .trim_end() + == self.user_name, + ) } fn execute(&self) -> Result<(), Box> { - try!(self.run_sql(&format!("GRANT ALL ON {0}.* TO {0} IDENTIFIED VIA unix_socket", self.user_name))); + try!(self.run_sql(&format!( + "GRANT ALL ON {0}.* TO {0} IDENTIFIED VIA unix_socket", + self.user_name + ))); Ok(()) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("user", self.user_name.to_string()) ] + vec![Resource::new("user", self.user_name.to_string())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs index 3796cb2..26edc37 100644 --- a/src/symbols/mod.rs +++ b/src/symbols/mod.rs @@ -1,6 +1,6 @@ +use resources::Resource; use std::error::Error; use std::fmt::Display; -use resources::Resource; pub trait Action { fn run(&self) -> Result<(), Box>; @@ -27,13 +27,15 @@ pub trait Symbol: Display { None } fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box; - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a; + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a; } // SymbolAction pub struct SymbolAction<'a, S: Symbol + 'a> { runner: &'a dyn SymbolRunner, - symbol: &'a S + symbol: &'a S, } impl<'a, S: Symbol> SymbolAction<'a, S> { @@ -50,7 +52,7 @@ impl<'a, S: Symbol> Action for SymbolAction<'a, S> { pub struct OwnedSymbolAction<'a, S: Symbol + 'a> { runner: &'a dyn SymbolRunner, - symbol: S + symbol: S, } impl<'a, S: Symbol + 'a> OwnedSymbolAction<'a, S> { diff --git a/src/symbols/nginx/server.rs b/src/symbols/nginx/server.rs index f2fa645..537763d 100644 --- a/src/symbols/nginx/server.rs +++ b/src/symbols/nginx/server.rs @@ -4,14 +4,14 @@ use std::io; use std::ops::Deref; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -use symbols::file::File as FileSymbol; use resources::Resource; +use symbols::file::File as FileSymbol; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; #[derive(Debug)] pub enum NginxServerError { ExecError(E), - GenericError + GenericError, } impl From for NginxServerError { @@ -24,13 +24,13 @@ impl Error for NginxServerError { fn description(&self) -> &str { match self { NginxServerError::ExecError(ref e) => e.description(), - NginxServerError::GenericError => "Generic error" + NginxServerError::GenericError => "Generic error", } } fn cause(&self) -> Option<&dyn Error> { match self { NginxServerError::ExecError(ref e) => Some(e), - _ => None + _ => None, } } } @@ -41,7 +41,10 @@ impl fmt::Display for NginxServerError { } } -pub struct NginxServer<'a, C: 'a + CommandRunner, T> where T: Deref { +pub struct NginxServer<'a, C: 'a + CommandRunner, T> +where + T: Deref, +{ command_runner: &'a C, file: FileSymbol, } @@ -49,7 +52,8 @@ pub struct NginxServer<'a, C: 'a + CommandRunner, T> where T: Deref use std::borrow::Cow; pub fn server_config(domain: &str, content: &str) -> String { - format!("server {{ + format!( + "server {{ listen 443 ssl http2; server_name {0}; include \"snippets/acme-challenge.conf\"; @@ -71,17 +75,25 @@ server {{ return 301 https://$host$request_uri; }} }} -", domain, content) +", + domain, content + ) } -pub fn php_server_config_snippet<'a>(socket_path: Cow<'a, str>, static_path: Cow<'a, str>) -> String { - format!(" +pub fn php_server_config_snippet<'a>( + socket_path: Cow<'a, str>, + static_path: Cow<'a, str>, +) -> String { + format!( + " root {}; index index.html index.php; location ~ [^/]\\.php(/|$) {{ fastcgi_pass unix:{}; include \"snippets/fastcgi-php.conf\"; - }}", static_path, socket_path) + }}", + static_path, socket_path + ) } pub trait SocketSpec { @@ -110,14 +122,26 @@ impl SocketSpec for LocalTcpSocket { impl<'a, C: CommandRunner> NginxServer<'a, C, String> { pub fn new_redir(domain: &'a str, target: &'a str, command_runner: &'a C) -> Self { - let content = server_config(domain, &format!("location / {{ + let content = server_config( + domain, + &format!( + "location / {{ return 301 $scheme://{}$request_uri; -}}", target)); +}}", + target + ), + ); NginxServer::new(domain, content, command_runner) } - pub fn new_proxy(domain: &'a str, socket_path: S, static_path: &'a str, command_runner: &'a C) -> Self { - let proxy_content = format!("location / {{ + pub fn new_proxy( + domain: &'a str, + socket_path: S, + static_path: &'a str, + command_runner: &'a C, + ) -> Self { + let proxy_content = format!( + "location / {{ try_files $uri @proxy; }} @@ -125,25 +149,44 @@ location @proxy {{ include fastcgi_params; proxy_pass http://{}; proxy_redirect off; -}}", socket_path.to_nginx()); - - let content = server_config(domain, &format!(" +}}", + socket_path.to_nginx() + ); + + let content = server_config( + domain, + &format!( + " root {}; {} -", static_path, proxy_content)); +", + static_path, proxy_content + ), + ); NginxServer::new(domain, content, command_runner) } - pub fn new_php(domain: &'a str, socket_path: Cow<'a, str>, static_path: Cow<'a, str>, command_runner: &'a C) -> Self { + pub fn new_php( + domain: &'a str, + socket_path: Cow<'a, str>, + static_path: Cow<'a, str>, + command_runner: &'a C, + ) -> Self { let content = server_config(domain, &php_server_config_snippet(socket_path, static_path)); NginxServer::new(domain, content, command_runner) } pub fn new_static(domain: &'a str, static_path: &'a str, command_runner: &'a C) -> Self { - let content = server_config(domain, &format!(" + let content = server_config( + domain, + &format!( + " root {}; try_files $uri $uri/ $uri.html =404; -", static_path)); +", + static_path + ), + ); NginxServer::new(domain, content, command_runner) } @@ -151,12 +194,15 @@ location @proxy {{ let file_path = String::from("/etc/nginx/sites-enabled/") + domain; NginxServer { command_runner, - file: FileSymbol::new(file_path, content) + file: FileSymbol::new(file_path, content), } } } -impl<'a, C: CommandRunner, T> Symbol for NginxServer<'a, C, T> where T: Deref { +impl<'a, C: CommandRunner, T> Symbol for NginxServer<'a, C, T> +where + T: Deref, +{ fn target_reached(&self) -> Result> { if !try!(self.file.target_reached()) { return Ok(false); @@ -167,7 +213,9 @@ impl<'a, C: CommandRunner, T> Symbol for NginxServer<'a, C, T> where T: Deref Result<(), Box> { try!(self.file.execute()); - self.command_runner.run_successfully("systemctl", &["reload-or-restart", "nginx"]) + self + .command_runner + .run_successfully("systemctl", &["reload-or-restart", "nginx"]) } fn get_prerequisites(&self) -> Vec { @@ -178,13 +226,19 @@ impl<'a, C: CommandRunner, T> Symbol for NginxServer<'a, C, T> where T: Deref(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl<'a, C: CommandRunner, T> fmt::Display for NginxServer<'a, C, T> where T: Deref { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ +impl<'a, C: CommandRunner, T> fmt::Display for NginxServer<'a, C, T> +where + T: Deref, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Nginx server config") } } diff --git a/src/symbols/noop.rs b/src/symbols/noop.rs index b76e1e8..2f21443 100644 --- a/src/symbols/noop.rs +++ b/src/symbols/noop.rs @@ -16,14 +16,16 @@ impl Symbol for NoopSymbol { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box where Self: 'a { + fn into_action<'a>(self: Box, runner: &'a dyn SymbolRunner) -> Box + where + Self: 'a, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } impl Display for NoopSymbol { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Noop") } } - diff --git a/src/symbols/npm.rs b/src/symbols/npm.rs index 7f90582..3e05f69 100644 --- a/src/symbols/npm.rs +++ b/src/symbols/npm.rs @@ -7,12 +7,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct NpmInstall<'a, C: 'a + CommandRunner> { target: &'a str, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> NpmInstall<'a, C> { pub fn new(target: &'a str, command_runner: &'a C) -> Self { - NpmInstall { target, command_runner } + NpmInstall { + target, + command_runner, + } } } @@ -27,23 +30,41 @@ impl<'a, C: CommandRunner> Symbol for NpmInstall<'a, C> { if !Path::new(self.target).exists() { return Ok(false); } - let result = try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm ls", self.target)])); - Ok(result.status.success() && !String::from_utf8(result.stdout).unwrap().contains("(empty)")) + let result = try!(self + .command_runner + .run_with_args("sh", &["-c", &format!("cd '{}' && npm ls", self.target)])); + Ok( + result.status.success() + && !String::from_utf8(result.stdout) + .unwrap() + .contains("(empty)"), + ) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("sh", &["-c", &format!("cd '{}' && npm install --production --unsafe-perm", self.target)]) + self.command_runner.run_successfully( + "sh", + &[ + "-c", + &format!( + "cd '{}' && npm install --production --unsafe-perm", + self.target + ), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/owner.rs b/src/symbols/owner.rs index 90d6394..29d7c5a 100644 --- a/src/symbols/owner.rs +++ b/src/symbols/owner.rs @@ -1,4 +1,4 @@ -use std::borrow::{ Borrow, Cow }; +use std::borrow::{Borrow, Cow}; use std::error::Error; use std::fmt; use std::fs; @@ -11,19 +11,32 @@ use command_runner::CommandRunner; use resources::Resource; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct Owner<'a, C: 'a + CommandRunner, D> where D: AsRef { +pub struct Owner<'a, C: 'a + CommandRunner, D> +where + D: AsRef, +{ path: D, user_name: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } -impl<'a, C: CommandRunner, D> Owner<'a, C, D> where D: AsRef { +impl<'a, C: CommandRunner, D> Owner<'a, C, D> +where + D: AsRef, +{ pub fn new(path: D, user_name: Cow<'a, str>, command_runner: &'a C) -> Self { - Owner { path, user_name, command_runner } + Owner { + path, + user_name, + command_runner, + } } } -impl<'a, C: CommandRunner, D> Symbol for Owner<'a, C, D> where D: AsRef { +impl<'a, C: CommandRunner, D> Symbol for Owner<'a, C, D> +where + D: AsRef, +{ fn target_reached(&self) -> Result> { if !Path::new(self.path.as_ref()).exists() { return Ok(false); @@ -34,24 +47,33 @@ impl<'a, C: CommandRunner, D> Symbol for Owner<'a, C, D> where D: AsRef { } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("chown", &["-R", self.user_name.borrow(), self.path.as_ref()]) + self.command_runner.run_successfully( + "chown", + &["-R", self.user_name.borrow(), self.path.as_ref()], + ) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("user", self.user_name.to_string()) ] + vec![Resource::new("user", self.user_name.to_string())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl<'a, C: CommandRunner, D> fmt::Display for Owner<'a, C, D> where D: AsRef { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl<'a, C: CommandRunner, D> fmt::Display for Owner<'a, C, D> +where + D: AsRef, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Owner {} for {}", self.user_name, self.path.as_ref()) } } diff --git a/src/symbols/postgresql/database.rs b/src/symbols/postgresql/database.rs index 2ed22d5..16bbcea 100644 --- a/src/symbols/postgresql/database.rs +++ b/src/symbols/postgresql/database.rs @@ -8,16 +8,23 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct PostgreSQLDatabase<'a, C: 'a + CommandRunner> { name: Cow<'a, str>, seed_file: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> PostgreSQLDatabase<'a, C> { pub fn new(name: Cow<'a, str>, seed_file: Cow<'a, str>, command_runner: &'a C) -> Self { - PostgreSQLDatabase { name, seed_file, command_runner } + PostgreSQLDatabase { + name, + seed_file, + command_runner, + } } fn run_sql(&self, sql: &str) -> Result> { - let b = try!(self.command_runner.get_output("su", &["-", "postgres", "-c", &format!("psql -t -c \"{}\"", sql)])); + let b = try!(self.command_runner.get_output( + "su", + &["-", "postgres", "-c", &format!("psql -t -c \"{}\"", sql)] + )); Ok(try!(String::from_utf8(b))) } } @@ -30,24 +37,52 @@ impl<'a, C: CommandRunner> fmt::Display for PostgreSQLDatabase<'a, C> { impl<'a, C: CommandRunner> Symbol for PostgreSQLDatabase<'a, C> { fn target_reached(&self) -> Result> { - Ok(try!(self.run_sql(&format!("SELECT datname FROM pg_database WHERE datname LIKE '{}'", self.name))).trim() == self.name) + Ok( + try!(self.run_sql(&format!( + "SELECT datname FROM pg_database WHERE datname LIKE '{}'", + self.name + ))) + .trim() + == self.name, + ) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("su", &["-", "postgres", "-c", &format!("createuser {}", self.name)])?; - self.command_runner.run_successfully("su", &["-", "postgres", "-c", &format!("createdb -E UTF8 -T template0 -O {} {0}", self.name)])?; - self.command_runner.run_successfully("su", &["-", "postgres", "-c", &format!("psql '{}' < {}", self.name, self.seed_file)]) + self.command_runner.run_successfully( + "su", + &["-", "postgres", "-c", &format!("createuser {}", self.name)], + )?; + self.command_runner.run_successfully( + "su", + &[ + "-", + "postgres", + "-c", + &format!("createdb -E UTF8 -T template0 -O {} {0}", self.name), + ], + )?; + self.command_runner.run_successfully( + "su", + &[ + "-", + "postgres", + "-c", + &format!("psql '{}' < {}", self.name, self.seed_file), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/postgresql/database_dump.rs b/src/symbols/postgresql/database_dump.rs index 14b2e8b..f5551be 100644 --- a/src/symbols/postgresql/database_dump.rs +++ b/src/symbols/postgresql/database_dump.rs @@ -3,22 +3,33 @@ use std::fmt; use std::str::FromStr; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use storage::Storage; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct DatabaseDump<'a, N, C, S> where N: 'a + AsRef, C: 'a + CommandRunner, S: Storage { +pub struct DatabaseDump<'a, N, C, S> +where + N: 'a + AsRef, + C: 'a + CommandRunner, + S: Storage, +{ db_name: N, storage: S, - command_runner: &'a C + command_runner: &'a C, } impl<'a, N: AsRef, C: CommandRunner, S: Storage> DatabaseDump<'a, N, C, S> { pub fn new(db_name: N, storage: S, command_runner: &'a C) -> Self { - DatabaseDump { db_name, storage, command_runner } + DatabaseDump { + db_name, + storage, + command_runner, + } } fn run_sql(&self, sql: &str) -> Result> { - let b = try!(self.command_runner.get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); + let b = try!(self + .command_runner + .get_output("mariadb", &["--skip-column-names", "-B", "-e", sql])); Ok(try!(String::from_utf8(b))) } } @@ -33,23 +44,37 @@ impl<'a, N: AsRef, C: CommandRunner, S: Storage> Symbol for DatabaseDump<'a fn target_reached(&self) -> Result> { let dump_date = try!(self.storage.recent_date()); let modified_date = try!(self.run_sql(&format!("select UNIX_TIMESTAMP(MAX(UPDATE_TIME)) from information_schema.tables WHERE table_schema = '{}'", self.db_name.as_ref()))); - if modified_date.trim_end() == "NULL" { return Ok(false); } + if modified_date.trim_end() == "NULL" { + return Ok(false); + } Ok(try!(u64::from_str(modified_date.trim_end())) <= dump_date) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("sh", &["-c", &format!("mysqldump '{}' > {}", self.db_name.as_ref(), self.storage.write_filename())]) + self.command_runner.run_successfully( + "sh", + &[ + "-c", + &format!( + "mysqldump '{}' > {}", + self.db_name.as_ref(), + self.storage.write_filename() + ), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/stored_directory.rs b/src/symbols/stored_directory.rs index 046fb1b..996c476 100644 --- a/src/symbols/stored_directory.rs +++ b/src/symbols/stored_directory.rs @@ -8,32 +8,52 @@ use std::str::FromStr; use command_runner::CommandRunner; use resources::Resource; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use storage::Storage; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; #[derive(Debug, PartialEq)] -pub enum StorageDirection { Load, Save } +pub enum StorageDirection { + Load, + Save, +} -pub struct StoredDirectory<'a, S, C: 'a + CommandRunner> where S: Storage { +pub struct StoredDirectory<'a, S, C: 'a + CommandRunner> +where + S: Storage, +{ path: Cow<'a, str>, storage: S, dir: StorageDirection, - command_runner: &'a C + command_runner: &'a C, } -impl<'a, S, C: CommandRunner> StoredDirectory<'a, S, C> where S: Storage { +impl<'a, S, C: CommandRunner> StoredDirectory<'a, S, C> +where + S: Storage, +{ pub fn new(path: Cow<'a, str>, storage: S, dir: StorageDirection, command_runner: &'a C) -> Self { - StoredDirectory { path, storage, dir, command_runner } + StoredDirectory { + path, + storage, + dir, + command_runner, + } } } -impl<'a, S, C: CommandRunner> fmt::Display for StoredDirectory<'a, S, C> where S: Storage { +impl<'a, S, C: CommandRunner> fmt::Display for StoredDirectory<'a, S, C> +where + S: Storage, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Stored directory {} ({:?})", self.path, self.dir) } } -impl<'a, S, C: CommandRunner> Symbol for StoredDirectory<'a, S, C> where S: Storage { +impl<'a, S, C: CommandRunner> Symbol for StoredDirectory<'a, S, C> +where + S: Storage, +{ fn target_reached(&self) -> Result> { let metadata = fs::metadata(self.path.as_ref()); // Check if dir exists @@ -45,35 +65,74 @@ impl<'a, S, C: CommandRunner> Symbol for StoredDirectory<'a, S, C> where S: Stor }; } if !metadata.unwrap().is_dir() { - return Err(Box::new(io::Error::new(io::ErrorKind::AlreadyExists, "Could not create a directory, non-directory file exists"))); + return Err(Box::new(io::Error::new( + io::ErrorKind::AlreadyExists, + "Could not create a directory, non-directory file exists", + ))); } let dump_date = try!(self.storage.recent_date()); - let output = try!(self.command_runner.get_output("sh", &["-c", &format!("find {} -printf '%T@\\n' | sort -r | head -n1 | grep '^[0-9]\\+' -o", self.path)])); + let output = try!(self.command_runner.get_output( + "sh", + &[ + "-c", + &format!( + "find {} -printf '%T@\\n' | sort -r | head -n1 | grep '^[0-9]\\+' -o", + self.path + ) + ] + )); let modified_date = try!(u64::from_str(try!(String::from_utf8(output)).trim_end())); - if if self.dir == StorageDirection::Save { modified_date > dump_date } else { dump_date > modified_date } { - let output = try!(self.command_runner.run_with_args("diff", &["-rq", &try!(self.storage.read_filename()), self.path.borrow()])); + if if self.dir == StorageDirection::Save { + modified_date > dump_date + } else { + dump_date > modified_date + } { + let output = try!(self.command_runner.run_with_args( + "diff", + &[ + "-rq", + &try!(self.storage.read_filename()), + self.path.borrow() + ] + )); match output.status.code() { Some(0) => Ok(true), Some(1) => Ok(false), - _ => Err(try!(String::from_utf8(output.stderr)).into()) + _ => Err(try!(String::from_utf8(output.stderr)).into()), } - } else { Ok(true) } + } else { + Ok(true) + } } fn execute(&self) -> Result<(), Box> { if self.dir == StorageDirection::Load { - try!(self.command_runner.run_successfully("rm", &["-rf", self.path.borrow()])); - self.command_runner.run_successfully("cp", &["-a", &try!(self.storage.read_filename()), self.path.borrow()]) + try!(self + .command_runner + .run_successfully("rm", &["-rf", self.path.borrow()])); + self.command_runner.run_successfully( + "cp", + &[ + "-a", + &try!(self.storage.read_filename()), + self.path.borrow(), + ], + ) } else { - self.command_runner.run_successfully("cp", &["-a", self.path.borrow(), &self.storage.write_filename()]) + self.command_runner.run_successfully( + "cp", + &["-a", self.path.borrow(), &self.storage.write_filename()], + ) } } fn get_prerequisites(&self) -> Vec { - if self.dir == StorageDirection::Save { return vec![]; } + if self.dir == StorageDirection::Save { + return vec![]; + } if let Some(parent) = Path::new(self.path.as_ref()).parent() { - vec![ Resource::new("dir", parent.to_string_lossy()) ] + vec![Resource::new("dir", parent.to_string_lossy())] } else { vec![] } @@ -81,7 +140,7 @@ impl<'a, S, C: CommandRunner> Symbol for StoredDirectory<'a, S, C> where S: Stor fn provides(&self) -> Option> { if self.dir == StorageDirection::Load { - Some(vec![ Resource::new("dir", self.path.to_string()) ]) + Some(vec![Resource::new("dir", self.path.to_string())]) } else { None } @@ -91,11 +150,13 @@ impl<'a, S, C: CommandRunner> Symbol for StoredDirectory<'a, S, C> where S: Stor Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/systemd/node_js_user_service.rs b/src/symbols/systemd/node_js_user_service.rs index 50aa02b..f4e3d92 100644 --- a/src/symbols/systemd/node_js_user_service.rs +++ b/src/symbols/systemd/node_js_user_service.rs @@ -1,22 +1,22 @@ use std::error::Error; use std::fmt; -use std::io; use std::fs; +use std::io; +use std::ops::Deref; use std::process::Output; use std::thread::sleep; use std::time::Duration; -use std::ops::Deref; use command_runner::{CommandRunner, SetuidCommandRunner}; use resources::Resource; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use symbols::file::File as FileSymbol; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; #[derive(Debug)] pub enum NodeJsSystemdUserServiceError { ActivationFailed(io::Result), ExecError(E), - GenericError + GenericError, } impl From for NodeJsSystemdUserServiceError { @@ -30,13 +30,13 @@ impl Error for NodeJsSystemdUserServiceError { match self { NodeJsSystemdUserServiceError::ExecError(ref e) => e.description(), NodeJsSystemdUserServiceError::GenericError => "Generic error", - NodeJsSystemdUserServiceError::ActivationFailed(_) => "Activation of service failed" + NodeJsSystemdUserServiceError::ActivationFailed(_) => "Activation of service failed", } } fn cause(&self) -> Option<&dyn Error> { match self { NodeJsSystemdUserServiceError::ExecError(ref e) => Some(e), - _ => None + _ => None, } } } @@ -51,19 +51,37 @@ impl fmt::Display for NodeJsSystemdUserServiceError { } } -pub struct NodeJsSystemdUserService<'a, C, R> where C: Deref, R: CommandRunner { +pub struct NodeJsSystemdUserService<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ service_name: &'a str, user_name: &'a str, command_runner: R, - file: FileSymbol + file: FileSymbol, } -impl<'a, R> NodeJsSystemdUserService<'a, String, SetuidCommandRunner<'a, R>> where R: CommandRunner { - pub fn new(home: &'a str, user_name: &'a str, service_name: &'a str, path: &'a str, command_runner: &'a R) -> Self { - let file_path = format!("{}/.config/systemd/user/{}.service", home.trim_end(), service_name); +impl<'a, R> NodeJsSystemdUserService<'a, String, SetuidCommandRunner<'a, R>> +where + R: CommandRunner, +{ + pub fn new( + home: &'a str, + user_name: &'a str, + service_name: &'a str, + path: &'a str, + command_runner: &'a R, + ) -> Self { + let file_path = format!( + "{}/.config/systemd/user/{}.service", + home.trim_end(), + service_name + ); let port = format!("/var/tmp/{}-{}.socket", user_name, service_name); - let content = format!("[Service] + let content = format!( + "[Service] Environment=NODE_ENV=production Environment=PORT={1} ExecStartPre=/bin/rm -f {1} @@ -78,19 +96,24 @@ Restart=always [Install] WantedBy=default.target -", path, port); +", + path, port + ); NodeJsSystemdUserService { service_name, user_name, command_runner: SetuidCommandRunner::new(user_name, command_runner), - file: FileSymbol::new(file_path, content) + file: FileSymbol::new(file_path, content), } } } -impl<'a, C, R> NodeJsSystemdUserService<'a, C, R> where C: Deref, R: CommandRunner { - +impl<'a, C, R> NodeJsSystemdUserService<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ fn systemctl_wait_for_dbus(&self, args: &[&str]) -> Result> { let mut tries = 5; loop { @@ -102,7 +125,11 @@ impl<'a, C, R> NodeJsSystemdUserService<'a, C, R> where C: Deref, R: return Err(stderr.into()); } } else { - return Ok(try!(String::from_utf8(result.stdout)).trim_end().to_string()); + return Ok( + try!(String::from_utf8(result.stdout)) + .trim_end() + .to_string(), + ); } tries -= 1; if tries == 0 { @@ -114,18 +141,36 @@ impl<'a, C, R> NodeJsSystemdUserService<'a, C, R> where C: Deref, R: fn check_if_service(&self) -> Result> { loop { - let active_state = try!(self.systemctl_wait_for_dbus(&["--user", "show", "--property", "ActiveState", self.service_name])); + let active_state = try!(self.systemctl_wait_for_dbus(&[ + "--user", + "show", + "--property", + "ActiveState", + self.service_name + ])); match active_state.as_ref() { "ActiveState=activating" => sleep(Duration::from_millis(500)), "ActiveState=active" => return Ok(true), - "ActiveState=failed" => return Err(Box::new(NodeJsSystemdUserServiceError::ActivationFailed(self.command_runner.run_with_args("journalctl", &["--user", &format!("--user-unit={}", self.service_name)])) as NodeJsSystemdUserServiceError)), - _ => return Ok(false) + "ActiveState=failed" => { + return Err(Box::new(NodeJsSystemdUserServiceError::ActivationFailed( + self.command_runner.run_with_args( + "journalctl", + &["--user", &format!("--user-unit={}", self.service_name)], + ), + ) + as NodeJsSystemdUserServiceError)) + } + _ => return Ok(false), } } } } -impl<'a, C, R> Symbol for NodeJsSystemdUserService<'a, C, R> where C: Deref, R: CommandRunner { +impl<'a, C, R> Symbol for NodeJsSystemdUserService<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ fn target_reached(&self) -> Result> { if !(try!(self.file.target_reached())) { return Ok(false); @@ -139,15 +184,22 @@ impl<'a, C, R> Symbol for NodeJsSystemdUserService<'a, C, R> where C: Deref)); + return Err(Box::new( + NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError, + )); } let file_name = format!("/var/tmp/{}-{}.socket", self.user_name, self.service_name); - fs::metadata(&file_name).map(|_| ()).map_err(|e| Box::new(e) as Box) + fs::metadata(&file_name) + .map(|_| ()) + .map_err(|e| Box::new(e) as Box) } fn get_prerequisites(&self) -> Vec { - let mut r = vec![ Resource::new("file", format!("/var/lib/systemd/linger/{}", self.user_name)) ]; + let mut r = vec![Resource::new( + "file", + format!("/var/lib/systemd/linger/{}", self.user_name), + )]; r.extend(self.file.get_prerequisites().into_iter()); r } @@ -156,13 +208,24 @@ impl<'a, C, R> Symbol for NodeJsSystemdUserService<'a, C, R> where C: Deref(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl<'a, C, R> fmt::Display for NodeJsSystemdUserService<'a, C, R> where C: Deref, R: CommandRunner { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ - write!(f, "Systemd Node.js user service unit for {}", self.service_name) +impl<'a, C, R> fmt::Display for NodeJsSystemdUserService<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "Systemd Node.js user service unit for {}", + self.service_name + ) } } diff --git a/src/symbols/systemd/reload.rs b/src/symbols/systemd/reload.rs index 039350f..106df23 100644 --- a/src/symbols/systemd/reload.rs +++ b/src/symbols/systemd/reload.rs @@ -6,12 +6,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct ReloadService<'a, C: 'a + CommandRunner> { service: &'a str, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> ReloadService<'a, C> { pub fn new(service: &'a str, command_runner: &'a C) -> Self { - ReloadService { service, command_runner } + ReloadService { + service, + command_runner, + } } } @@ -21,20 +24,25 @@ impl<'a, C: CommandRunner> Symbol for ReloadService<'a, C> { } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("systemctl", &["reload-or-restart", self.service]) + self + .command_runner + .run_successfully("systemctl", &["reload-or-restart", self.service]) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } impl<'a, C: CommandRunner> fmt::Display for ReloadService<'a, C> { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Reload service {}", self.service) } } diff --git a/src/symbols/systemd/user_session.rs b/src/symbols/systemd/user_session.rs index 4278aba..92c7e78 100644 --- a/src/symbols/systemd/user_session.rs +++ b/src/symbols/systemd/user_session.rs @@ -1,4 +1,4 @@ -use std::borrow::{ Borrow, Cow }; +use std::borrow::{Borrow, Cow}; use std::error::Error; use std::fmt; use std::path::PathBuf; @@ -9,20 +9,20 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; #[derive(Debug)] pub enum SystemdUserSessionError { ExecError(E), - GenericError + GenericError, } impl Error for SystemdUserSessionError { fn description(&self) -> &str { match self { SystemdUserSessionError::ExecError(ref e) => e.description(), - SystemdUserSessionError::GenericError => "Generic error" + SystemdUserSessionError::GenericError => "Generic error", } } fn cause(&self) -> Option<&dyn Error> { match self { SystemdUserSessionError::ExecError(ref e) => Some(e), - _ => None + _ => None, } } } @@ -35,12 +35,15 @@ impl fmt::Display for SystemdUserSessionError { pub struct SystemdUserSession<'a, C: 'a + CommandRunner> { user_name: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> SystemdUserSession<'a, C> { pub fn new(user_name: Cow<'a, str>, command_runner: &'a C) -> Self { - SystemdUserSession { user_name, command_runner } + SystemdUserSession { + user_name, + command_runner, + } } } @@ -53,20 +56,25 @@ impl<'a, C: CommandRunner> Symbol for SystemdUserSession<'a, C> { } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("loginctl", &["enable-linger", self.user_name.borrow()]) + self + .command_runner + .run_successfully("loginctl", &["enable-linger", self.user_name.borrow()]) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } impl<'a, C: CommandRunner> fmt::Display for SystemdUserSession<'a, C> { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Systemd user session for {}", self.user_name) } } diff --git a/src/symbols/tls/csr.rs b/src/symbols/tls/csr.rs index a761496..091f92b 100644 --- a/src/symbols/tls/csr.rs +++ b/src/symbols/tls/csr.rs @@ -9,12 +9,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct TlsCsr<'a, C: 'a + CommandRunner> { domain: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> TlsCsr<'a, C> { pub fn new(domain: Cow<'a, str>, command_runner: &'a C) -> Self { - TlsCsr { domain, command_runner } + TlsCsr { + domain, + command_runner, + } } fn get_key_path(&self) -> String { @@ -38,12 +41,28 @@ impl<'a, C: CommandRunner> Symbol for TlsCsr<'a, C> { return Ok(false); } - let output = try!(self.command_runner.get_stderr("openssl", &["req", "-in", &self.get_csr_path(), "-noout", "-verify"])); + let output = try!(self.command_runner.get_stderr( + "openssl", + &["req", "-in", &self.get_csr_path(), "-noout", "-verify"] + )); Ok(output == b"verify OK\n") } fn execute(&self) -> Result<(), Box> { - try!(self.command_runner.run_successfully("openssl", &["req", "-new", "-sha256", "-key", &self.get_key_path(), "-out", &self.get_csr_path(), "-subj", &format!("/CN={}", self.domain)])); + try!(self.command_runner.run_successfully( + "openssl", + &[ + "req", + "-new", + "-sha256", + "-key", + &self.get_key_path(), + "-out", + &self.get_csr_path(), + "-subj", + &format!("/CN={}", self.domain) + ] + )); Ok(()) } @@ -55,11 +74,13 @@ impl<'a, C: CommandRunner> Symbol for TlsCsr<'a, C> { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/tls/key.rs b/src/symbols/tls/key.rs index 3ba01b6..4f69a52 100644 --- a/src/symbols/tls/key.rs +++ b/src/symbols/tls/key.rs @@ -8,12 +8,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct TlsKey<'a, C: 'a + CommandRunner> { domain: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> TlsKey<'a, C> { pub fn new(domain: Cow<'a, str>, command_runner: &'a C) -> Self { - TlsKey { domain, command_runner } + TlsKey { + domain, + command_runner, + } } fn get_path(&self) -> String { @@ -37,23 +40,36 @@ impl<'a, C: CommandRunner> Symbol for TlsKey<'a, C> { return Ok(false); } - let output = try!(self.command_runner.get_output("openssl", &["rsa", "-in", &self.get_path(), "-noout", "-check", "-text"])); + let output = try!(self.command_runner.get_output( + "openssl", + &["rsa", "-in", &self.get_path(), "-noout", "-check", "-text"] + )); Ok(output.starts_with(&format!("Private-Key: ({} bit)\n", self.get_bytes()).as_bytes())) } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("openssl", &["genrsa", "-out", &self.get_path(), &self.get_bytes().to_string()]) + self.command_runner.run_successfully( + "openssl", + &[ + "genrsa", + "-out", + &self.get_path(), + &self.get_bytes().to_string(), + ], + ) } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/tls/self_signed_cert.rs b/src/symbols/tls/self_signed_cert.rs index a5e4e1e..0895cb3 100644 --- a/src/symbols/tls/self_signed_cert.rs +++ b/src/symbols/tls/self_signed_cert.rs @@ -9,12 +9,15 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct SelfSignedTlsCert<'a, C: 'a + CommandRunner> { domain: Cow<'a, str>, - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> SelfSignedTlsCert<'a, C> { pub fn new(domain: Cow<'a, str>, command_runner: &'a C) -> Self { - SelfSignedTlsCert { domain, command_runner } + SelfSignedTlsCert { + domain, + command_runner, + } } fn get_key_path(&self) -> String { @@ -32,29 +35,65 @@ impl<'a, C: CommandRunner> fmt::Display for SelfSignedTlsCert<'a, C> { } } -const DAYS_IN_SECONDS: u32 = 24*60*60; +const DAYS_IN_SECONDS: u32 = 24 * 60 * 60; impl<'a, C: CommandRunner> Symbol for SelfSignedTlsCert<'a, C> { fn target_reached(&self) -> Result> { if !Path::new(&self.get_cert_path()).exists() { return Ok(false); } - let output = try!(self.command_runner.run_with_args("openssl", &["x509", "-in", &self.get_cert_path(), "-noout", "-subject", "-checkend", &(30*DAYS_IN_SECONDS).to_string()])); -println!("{}", output.status.code().unwrap()); + let output = try!(self.command_runner.run_with_args( + "openssl", + &[ + "x509", + "-in", + &self.get_cert_path(), + "-noout", + "-subject", + "-checkend", + &(30 * DAYS_IN_SECONDS).to_string() + ] + )); + println!("{}", output.status.code().unwrap()); match output.status.code() { - Some(0) => Ok(output.stdout == format!("subject=CN = {}\nCertificate will not expire\n", self.domain).as_bytes()), - Some(_) => if output.stdout == format!("subject=CN = {}\nCertificate will expire\n", self.domain).as_bytes() { - Ok(false) - } else { - Err("Exit code non-zero, but wrong stdout".to_string().into()) - }, - _ => Err("Apparently killed by signal".to_string().into()) + Some(0) => Ok( + output.stdout + == format!( + "subject=CN = {}\nCertificate will not expire\n", + self.domain + ) + .as_bytes(), + ), + Some(_) => { + if output.stdout + == format!("subject=CN = {}\nCertificate will expire\n", self.domain).as_bytes() + { + Ok(false) + } else { + Err("Exit code non-zero, but wrong stdout".to_string().into()) + } + } + _ => Err("Apparently killed by signal".to_string().into()), } - } fn execute(&self) -> Result<(), Box> { - self.command_runner.run_successfully("openssl", &["req", "-x509", "-sha256", "-days", "90", "-key", &self.get_key_path(), "-out", &self.get_cert_path(), "-subj", &format!("/CN={}", self.domain)]) + self.command_runner.run_successfully( + "openssl", + &[ + "req", + "-x509", + "-sha256", + "-days", + "90", + "-key", + &self.get_key_path(), + "-out", + &self.get_cert_path(), + "-subj", + &format!("/CN={}", self.domain), + ], + ) } fn get_prerequisites(&self) -> Vec { @@ -65,11 +104,13 @@ println!("{}", output.status.code().unwrap()); Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } #[cfg(test)] -mod test { -} +mod test {} diff --git a/src/symbols/user.rs b/src/symbols/user.rs index e8f7cde..24bfecf 100644 --- a/src/symbols/user.rs +++ b/src/symbols/user.rs @@ -10,7 +10,7 @@ use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub enum UserAdderError { AlreadyExists, UnknownError, - ImplError(Box) + ImplError(Box), } impl Error for UserAdderError { @@ -18,13 +18,13 @@ impl Error for UserAdderError { match self { UserAdderError::AlreadyExists => "User already exists", UserAdderError::UnknownError => "Unknown error", - UserAdderError::ImplError(_) => "User adding error" + UserAdderError::ImplError(_) => "User adding error", } } fn cause(&self) -> Option<&dyn Error> { match self { UserAdderError::ImplError(ref e) => Some(e.as_ref()), - _ => None + _ => None, } } } @@ -33,7 +33,7 @@ impl fmt::Display for UserAdderError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.cause() { Some(e) => write!(f, "{} (cause: {})", self.description(), e), - None => write!(f, "{}", self.description()) + None => write!(f, "{}", self.description()), } } } @@ -44,18 +44,18 @@ pub trait UserAdder { #[derive(Debug, PartialEq)] pub enum UserError { - GenericError + GenericError, } impl Error for UserError { fn description(&self) -> &str { match self { - UserError::GenericError => "Could not find out if user exists" + UserError::GenericError => "Could not find out if user exists", } } fn cause(&self) -> Option<&dyn Error> { match self { - _ => None + _ => None, } } } @@ -64,7 +64,7 @@ impl fmt::Display for UserError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.cause() { Some(e) => write!(f, "{} (cause: {})", self.description(), e), - None => write!(f, "{}", self.description()) + None => write!(f, "{}", self.description()), } } } @@ -72,12 +72,16 @@ impl fmt::Display for UserError { pub struct User<'a, C: 'a + CommandRunner, A: 'a + UserAdder> { user_name: Cow<'a, str>, command_runner: &'a C, - user_adder: &'a A + user_adder: &'a A, } impl<'a, C: CommandRunner, A: 'a + UserAdder> User<'a, C, A> { pub fn new(user_name: Cow<'a, str>, command_runner: &'a C, user_adder: &'a A) -> Self { - User { user_name, command_runner, user_adder } + User { + user_name, + command_runner, + user_adder, + } } } @@ -89,16 +93,21 @@ impl<'a, C: CommandRunner, A: 'a + UserAdder> fmt::Display for User<'a, C, A> { impl<'a, C: CommandRunner, A: 'a + UserAdder> Symbol for User<'a, C, A> { fn target_reached(&self) -> Result> { - let output = try!(self.command_runner.run_with_args("getent", &["passwd", &*self.user_name])); + let output = try!(self + .command_runner + .run_with_args("getent", &["passwd", &*self.user_name])); match output.status.code() { Some(2) => Ok(false), Some(0) => Ok(true), - _ => Err(Box::new(UserError::GenericError)) + _ => Err(Box::new(UserError::GenericError)), } } fn execute(&self) -> Result<(), Box> { - self.user_adder.add_user(&*self.user_name).map_err(|e| Box::new(e) as Box) + self + .user_adder + .add_user(&*self.user_name) + .map_err(|e| Box::new(e) as Box) } fn provides(&self) -> Option> { @@ -109,13 +118,16 @@ impl<'a, C: CommandRunner, A: 'a + UserAdder> Symbol for User<'a, C, A> { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } pub struct SystemUserAdder<'a, C: 'a + CommandRunner> { - command_runner: &'a C + command_runner: &'a C, } impl<'a, C: CommandRunner> SystemUserAdder<'a, C> { @@ -130,27 +142,26 @@ impl<'a, C: CommandRunner> UserAdder for SystemUserAdder<'a, C> { "adduser", &[ // "-m", // Necessary for Fedora, not accepted in Debian - "--system", - user_name - ]); + "--system", user_name, + ], + ); match output { Ok(output) => match output.status.code() { Some(0) => Ok(()), - Some(1) => -{ - println!("{:?}", output); -Err(UserAdderError::AlreadyExists)}, - Some(_) => -{ - println!("{:?}", output); -Err(UserAdderError::UnknownError) -}, + Some(1) => { + println!("{:?}", output); + Err(UserAdderError::AlreadyExists) + } + Some(_) => { + println!("{:?}", output); + Err(UserAdderError::UnknownError) + } None => { - println!("{:?}", output); -Err(UserAdderError::UnknownError) -}, + println!("{:?}", output); + Err(UserAdderError::UnknownError) + } }, - Err(e) => Err(UserAdderError::ImplError(Box::new(e))) + Err(e) => Err(UserAdderError::ImplError(Box::new(e))), } } } @@ -161,10 +172,10 @@ mod test { use std::fmt; use command_runner::StdCommandRunner; - use symbols::Symbol; use symbols::user::User; use symbols::user::UserAdder; use symbols::user::UserAdderError; + use symbols::Symbol; #[derive(Debug, PartialEq)] struct DummyError; @@ -190,13 +201,21 @@ mod test { #[test] fn test_target_reached_nonexisting() { - let symbol = User { user_name: "nonexisting".into(), command_runner: &StdCommandRunner, user_adder: &DummyUserAdder }; + let symbol = User { + user_name: "nonexisting".into(), + command_runner: &StdCommandRunner, + user_adder: &DummyUserAdder, + }; assert_eq!(symbol.target_reached().unwrap(), false); } #[test] fn test_target_reached_root() { - let symbol = User { user_name: "root".into(), command_runner: &StdCommandRunner, user_adder: &DummyUserAdder }; + let symbol = User { + user_name: "root".into(), + command_runner: &StdCommandRunner, + user_adder: &DummyUserAdder, + }; assert_eq!(symbol.target_reached().unwrap(), true); } } diff --git a/src/symbols/wordpress/plugin.rs b/src/symbols/wordpress/plugin.rs index 8220086..2530ba9 100644 --- a/src/symbols/wordpress/plugin.rs +++ b/src/symbols/wordpress/plugin.rs @@ -8,26 +8,44 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use resources::Resource; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct WordpressPlugin<'a, C, R> where C: Deref, R: 'a + CommandRunner { +pub struct WordpressPlugin<'a, C, R> +where + C: Deref, + R: 'a + CommandRunner, +{ base: C, name: C, - command_runner: &'a R + command_runner: &'a R, } -impl<'a, C, R> WordpressPlugin<'a, C, R> where C: Deref, R: CommandRunner { +impl<'a, C, R> WordpressPlugin<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ pub fn new(base: C, name: C, command_runner: &'a R) -> Self { - WordpressPlugin { base, name, command_runner } + WordpressPlugin { + base, + name, + command_runner, + } } fn get_path(&self) -> PathBuf { - Path::new(&*self.base).join("wp-content/plugins").join(&*self.name) + Path::new(&*self.base) + .join("wp-content/plugins") + .join(&*self.name) } } -impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R> where C: Deref, R: CommandRunner { +impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ fn target_reached(&self) -> Result> { if !self.get_path().exists() { return Ok(false); @@ -43,7 +61,7 @@ impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R> where C: Deref, } else { Err(Box::new(e)) }; - }, + } Ok(file) => { let reader = BufReader::new(file); let regex = Regex::new("(?m)^(Plugin URI|Version): (.+)$")?; @@ -58,22 +76,45 @@ impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R> where C: Deref, } } } - let upstream = try!(self.command_runner.get_output("curl", &["--form", &format!(r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###, &*self.name, version, plugin_uri), "https://api.wordpress.org/plugins/update-check/1.1/"])); + let upstream = try!(self.command_runner.get_output( + "curl", + &[ + "--form", + &format!( + r###"plugins={{"plugins":{{"{0}/{0}.php":{{"Version":"{1}", "PluginURI":"{2}"}}}}}}"###, + &*self.name, version, plugin_uri + ), + "https://api.wordpress.org/plugins/update-check/1.1/" + ] + )); Ok(try!(String::from_utf8(upstream)).contains(r###""plugins":[]"###)) } fn execute(&self) -> Result<(), Box> { let source = format!("https://downloads.wordpress.org/plugin/{}.zip", &*self.name); let zip = format!("/tmp/{}.zip", &*self.name); - try!(self.command_runner.run_successfully("curl", &[source.as_ref() as &str, "-o", zip.as_ref()])); - try!(self.command_runner.run_successfully("rm", &["-rf", &self.get_path().to_string_lossy()])); - self.command_runner.run_successfully("unzip", &[zip.as_ref(), "-d".as_ref(), Path::new(&*self.base).join("wp-content/plugins").as_os_str()]) + try!(self + .command_runner + .run_successfully("curl", &[source.as_ref() as &str, "-o", zip.as_ref()])); + try!(self + .command_runner + .run_successfully("rm", &["-rf", &self.get_path().to_string_lossy()])); + self.command_runner.run_successfully( + "unzip", + &[ + zip.as_ref(), + "-d".as_ref(), + Path::new(&*self.base) + .join("wp-content/plugins") + .as_os_str(), + ], + ) } fn get_prerequisites(&self) -> Vec { match self.get_path().parent() { - Some(p) => vec![ Resource::new("dir", p.to_string_lossy()) ], - None => vec![] + Some(p) => vec![Resource::new("dir", p.to_string_lossy())], + None => vec![], } } @@ -81,14 +122,20 @@ impl<'a, C, R> Symbol for WordpressPlugin<'a, C, R> where C: Deref, Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl<'a, C, R> fmt::Display for WordpressPlugin<'a, C, R> where C: Deref, R: CommandRunner { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl<'a, C, R> fmt::Display for WordpressPlugin<'a, C, R> +where + C: Deref, + R: CommandRunner, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "WordpressPlugin {}", &*self.name) } } - diff --git a/src/symbols/wordpress/translation.rs b/src/symbols/wordpress/translation.rs index 9186268..a09a66e 100644 --- a/src/symbols/wordpress/translation.rs +++ b/src/symbols/wordpress/translation.rs @@ -8,34 +8,66 @@ use std::io::{BufRead, BufReader}; use std::path::Path; use command_runner::CommandRunner; -use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use resources::Resource; +use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; -pub struct WordpressTranslation<'a, C, D, R> where C: AsRef, D: AsRef, R: 'a + CommandRunner { +pub struct WordpressTranslation<'a, C, D, R> +where + C: AsRef, + D: AsRef, + R: 'a + CommandRunner, +{ path: D, version: &'a str, locale: C, - command_runner: &'a R + command_runner: &'a R, } -impl<'a, C, R> WordpressTranslation<'a, C, String, R> where C: AsRef, R: CommandRunner { +impl<'a, C, R> WordpressTranslation<'a, C, String, R> +where + C: AsRef, + R: CommandRunner, +{ pub fn new>(path: D, version: &'a str, locale: C, command_runner: &'a R) -> Self { WordpressTranslation { - path: Path::new(path.as_ref()).join("wp-content/languages").to_string_lossy().to_string(), + path: Path::new(path.as_ref()) + .join("wp-content/languages") + .to_string_lossy() + .to_string(), version, locale, - command_runner + command_runner, } } } -impl<'a, C, D, R> WordpressTranslation<'a, C, D, R> where C: AsRef, D: AsRef, R: CommandRunner { +impl<'a, C, D, R> WordpressTranslation<'a, C, D, R> +where + C: AsRef, + D: AsRef, + R: CommandRunner, +{ fn get_pairs(&self) -> Vec<(String, String)> { - let version_x = self.version.trim_end_matches(|c: char| c.is_digit(10)).to_owned() + "x"; + let version_x = self + .version + .trim_end_matches(|c: char| c.is_digit(10)) + .to_owned() + + "x"; let locale: &str = self.locale.as_ref(); - let path_locale = if locale == "de_DE" { "de".to_owned() } else { locale.to_lowercase().replace('_', "-") }; + let path_locale = if locale == "de_DE" { + "de".to_owned() + } else { + locale.to_lowercase().replace('_', "-") + }; let mut res = vec![]; - for &(in_slug, out_slug) in [("", ""), ("cc/", "continents-cities-"), ("admin/", "admin-"), ("admin/network/", "admin-network-")].iter() { + for &(in_slug, out_slug) in [ + ("", ""), + ("cc/", "continents-cities-"), + ("admin/", "admin-"), + ("admin/network/", "admin-network-"), + ] + .iter() + { for format in ["po", "mo"].iter() { res.push(( format!("https://translate.wordpress.org/projects/wp/{}/{}{}/default/export-translations?format={}", version_x, in_slug, path_locale, format), @@ -47,7 +79,12 @@ impl<'a, C, D, R> WordpressTranslation<'a, C, D, R> where C: AsRef, D: AsRe } } -impl<'a, C, D, R> Symbol for WordpressTranslation<'a, C, D, R> where C: AsRef, D: AsRef, R: CommandRunner { +impl<'a, C, D, R> Symbol for WordpressTranslation<'a, C, D, R> +where + C: AsRef, + D: AsRef, + R: CommandRunner, +{ fn target_reached(&self) -> Result> { let mut newest = String::new(); let match_date = Regex::new("(?m)^\"PO-Revision-Date: (.+)\\+0000\\\\n\"$").unwrap(); @@ -60,45 +97,68 @@ impl<'a, C, D, R> Symbol for WordpressTranslation<'a, C, D, R> where C: AsRef if target.ends_with(".po") { - let reader = BufReader::new(file); - for content in reader.lines() { - if let Some(match_result) = match_date.captures(&try!(content)) { - newest = max(newest, match_result[1].to_string()); - break; + } + Ok(file) => { + if target.ends_with(".po") { + let reader = BufReader::new(file); + for content in reader.lines() { + if let Some(match_result) = match_date.captures(&try!(content)) { + newest = max(newest, match_result[1].to_string()); + break; + } } } } } } - let upstream = try!(self.command_runner.get_output("curl", &[&format!("https://api.wordpress.org/core/version-check/1.7/?version={}&locale={}", self.version, self.locale.as_ref())])); - Ok(try!(String::from_utf8(upstream)).contains(&format!(r###"language":"{}","version":"{}","updated":"{}"###, self.locale.as_ref(), self.version, newest))) + let upstream = try!(self.command_runner.get_output( + "curl", + &[&format!( + "https://api.wordpress.org/core/version-check/1.7/?version={}&locale={}", + self.version, + self.locale.as_ref() + )] + )); + Ok(try!(String::from_utf8(upstream)).contains(&format!( + r###"language":"{}","version":"{}","updated":"{}"###, + self.locale.as_ref(), + self.version, + newest + ))) } fn execute(&self) -> Result<(), Box> { for (source, target) in self.get_pairs() { - try!(self.command_runner.run_successfully("curl", &["--compressed", "-o", &target, &source])); + try!(self + .command_runner + .run_successfully("curl", &["--compressed", "-o", &target, &source])); } Ok(()) } fn get_prerequisites(&self) -> Vec { - vec![ Resource::new("dir", self.path.as_ref()) ] + vec![Resource::new("dir", self.path.as_ref())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } - fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b { + fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box + where + Self: 'b, + { Box::new(OwnedSymbolAction::new(runner, *self)) } } -impl<'a, C, D, R> fmt::Display for WordpressTranslation<'a, C, D, R> where C: AsRef, D: AsRef, R: CommandRunner { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ +impl<'a, C, D, R> fmt::Display for WordpressTranslation<'a, C, D, R> +where + C: AsRef, + D: AsRef, + R: CommandRunner, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "WordpressTranslation {}", self.path.as_ref()) } } - diff --git a/tests/file.rs b/tests/file.rs index 2329ed6..6fe6d4f 100644 --- a/tests/file.rs +++ b/tests/file.rs @@ -1,12 +1,12 @@ extern crate schematics; extern crate tempdir; +use schematics::symbols::file::File as FileSymbol; +use schematics::symbols::Symbol; use std::fs::File; use std::io::Write; use std::path::Path; use tempdir::TempDir; -use schematics::symbols::Symbol; -use schematics::symbols::file::File as FileSymbol; fn get_dir(content: Option<&str>) -> TempDir { let tmp_dir = TempDir::new("unittest").expect("create temp dir"); @@ -15,12 +15,17 @@ fn get_dir(content: Option<&str>) -> TempDir { } let file_path = tmp_dir.path().join("filename"); let mut tmp_file = File::create(file_path).expect("create temp file"); - tmp_file.write_all(content.unwrap().as_bytes()).expect("write temp file"); + tmp_file + .write_all(content.unwrap().as_bytes()) + .expect("write temp file"); tmp_dir } fn get_symbol(path: &Path) -> FileSymbol<&str, String> { - FileSymbol::new(String::from(path.join("filename").to_str().unwrap()), "target content") + FileSymbol::new( + String::from(path.join("filename").to_str().unwrap()), + "target content", + ) } // Normal cases diff --git a/tests/storage.rs b/tests/storage.rs index eba8c0b..2396f55 100644 --- a/tests/storage.rs +++ b/tests/storage.rs @@ -3,12 +3,12 @@ extern crate schematics; extern crate tempdir; use regex::Regex; +use schematics::storage::{SimpleStorage, Storage}; use std::fs::{create_dir, File}; use std::path::Path; use tempdir::TempDir; -use schematics::storage::{SimpleStorage, Storage}; -fn get_dir<'a, I: IntoIterator>(content: I) -> TempDir { +fn get_dir<'a, I: IntoIterator>(content: I) -> TempDir { let tmp_dir = TempDir::new("unittest").expect("create temp dir"); let storage_path = tmp_dir.path().join("_filename"); create_dir(storage_path.clone()).unwrap(); @@ -30,8 +30,15 @@ fn single_file() { let dir = get_dir(&["12345"]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); - assert_eq!(dir.path().join("_filename").join("12345"), Path::new(&storage.read_filename().unwrap())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); + assert_eq!( + dir.path().join("_filename").join("12345"), + Path::new(&storage.read_filename().unwrap()) + ); assert_eq!(storage.recent_date().unwrap(), 12345); } @@ -40,8 +47,15 @@ fn two_files() { let dir = get_dir(&["12345", "23456"]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); - assert_eq!(dir.path().join("_filename").join("23456"), Path::new(&storage.read_filename().unwrap())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); + assert_eq!( + dir.path().join("_filename").join("23456"), + Path::new(&storage.read_filename().unwrap()) + ); assert_eq!(storage.recent_date().unwrap(), 23456); } @@ -50,8 +64,15 @@ fn another_two_files() { let dir = get_dir(&["23456", "12345"]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); - assert_eq!(dir.path().join("_filename").join("23456"), Path::new(&storage.read_filename().unwrap())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); + assert_eq!( + dir.path().join("_filename").join("23456"), + Path::new(&storage.read_filename().unwrap()) + ); assert_eq!(storage.recent_date().unwrap(), 23456); } @@ -60,8 +81,15 @@ fn three_files() { let dir = get_dir(&["23456", "9", "12345"]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); - assert_eq!(dir.path().join("_filename").join("23456"), Path::new(&storage.read_filename().unwrap())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); + assert_eq!( + dir.path().join("_filename").join("23456"), + Path::new(&storage.read_filename().unwrap()) + ); assert_eq!(storage.recent_date().unwrap(), 23456); } @@ -72,11 +100,21 @@ fn empty_storage() { let dir = TempDir::new("unittest").expect("create temp dir"); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); assert!(storage.read_filename().is_err()); - assert_eq!(storage.read_filename().unwrap_err().description(), "entity not found"); + assert_eq!( + storage.read_filename().unwrap_err().description(), + "entity not found" + ); assert!(storage.recent_date().is_err()); - assert_eq!(storage.recent_date().unwrap_err().description(), "entity not found"); + assert_eq!( + storage.recent_date().unwrap_err().description(), + "entity not found" + ); } #[test] @@ -84,11 +122,21 @@ fn empty_storage_for_filename() { let dir = get_dir(&[]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); assert!(storage.read_filename().is_err()); - assert_eq!(storage.read_filename().unwrap_err().description(), "Not found"); + assert_eq!( + storage.read_filename().unwrap_err().description(), + "Not found" + ); assert!(storage.recent_date().is_err()); - assert_eq!(storage.recent_date().unwrap_err().description(), "Not found"); + assert_eq!( + storage.recent_date().unwrap_err().description(), + "Not found" + ); } #[test] @@ -96,9 +144,19 @@ fn bad_file() { let dir = get_dir(&["abba"]); let storage = get_storage(dir.path()); - assert!(Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())).unwrap().is_match(&storage.write_filename())); + assert!( + Regex::new(&format!("^{}/_filename/\\d+$", dir.path().display())) + .unwrap() + .is_match(&storage.write_filename()) + ); assert!(storage.read_filename().is_err()); - assert_eq!(storage.read_filename().unwrap_err().description(), "Not found"); + assert_eq!( + storage.read_filename().unwrap_err().description(), + "Not found" + ); assert!(storage.recent_date().is_err()); - assert_eq!(storage.recent_date().unwrap_err().description(), "Not found"); + assert_eq!( + storage.recent_date().unwrap_err().description(), + "Not found" + ); }