Browse Source

Start with SchematicsFactory and bin

master
Adrian Heine 5 years ago
parent
commit
0bc56a8f69
  1. 13
      src/bin.rs
  2. 110
      src/factory.rs
  3. 2
      src/lib.rs
  4. 6
      src/repository.rs
  5. 18
      src/schema.rs
  6. 1
      src/symbols/factory.rs
  7. 6
      src/symbols/mod.rs
  8. 31
      src/symbols/user.rs

13
src/bin.rs

@ -0,0 +1,13 @@
use std::process::exit;
use std::env;
pub fn schematics_main(run: &Fn (bool) -> Result<(), ()>) {
let args: Vec<String> = env::args().collect();
let dry_run = match args.len() {
1 => false,
2 => if args[1] == "--dry-run" { true } else { panic!() },
_ => panic!()
};
exit(match run(dry_run) { Ok(_) => 0, Err(_) => 1 });
}

110
src/factory.rs

@ -0,0 +1,110 @@
use regex::Regex;
use std::collections::HashMap;
use command_runner::CommandRunner;
use command_runner::StdCommandRunner;
use loggers::StdErrLogger;
use repository::{DispatchingSymbolRepository, 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;
use symbols::tls::TlsKey;
use symbols::user::{User, UserAdder};
use symbols::user::SystemUserAdder;
pub struct Factory {
}
impl Factory {
pub fn new() -> Self {
Self {}
}
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<'a + SymbolRunner> {
let runner1 = ReportingSymbolRunner::new(symbol_runner, StdErrLogger);
let runner2 = NonRepeatingSymbolRunner::new(runner1);
Box::new(RequirementsResolvingSymbolRunner::new(runner2, repo))
}
}
pub struct DefaultSymbolRepository<'a, A: 'a + UserAdder, C: 'a + CommandRunner> {
user_adder: A,
command_runner: &'a C,
home: Regex,
home_config: Regex,
csr: Regex,
private_key: Regex,
systemd_linger: Regex
}
impl<'a, C: 'a + CommandRunner> DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> {
pub fn new(command_runner: &'a C) -> Self {
Self {
command_runner: command_runner,
user_adder: SystemUserAdder::new(command_runner),
home: Regex::new("^/home/([^/]+)$").unwrap(),
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()
}
}
}
impl<'a, C: CommandRunner> SymbolRepository<'a> for DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> {
fn get_symbol(&'a self, resource: &Resource) -> Option<Box<Symbol + 'a>> {
match resource.get_type() {
"user" => Some(Box::new(User::new(
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<Symbol>
} 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<Symbol>
} else { Box::new(Dir::new(value.to_string())) as Box<Symbol> }
)
},
"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
)) as Box<Symbol>)
} else if let Some(matches) = self.private_key.captures(value) {
Some(Box::new(TlsKey::new(
matches[1].to_string().into(),
self.command_runner
)) as Box<Symbol>)
} else if let Some(matches) = self.systemd_linger.captures(value) {
Some(Box::new(SystemdUserSession::new(
matches[1].to_string().into(),
self.command_runner
)) as Box<Symbol>)
} else { None }
},
_ => None
}
}
}

2
src/lib.rs

@ -23,7 +23,9 @@ missing_debug_implementations
extern crate regex;
extern crate users;
pub mod bin;
pub mod command_runner;
pub mod factory;
pub mod loggers;
pub mod symbols;
pub mod schema;

6
src/repository.rs

@ -4,11 +4,11 @@ use symbols::Symbol;
use resources::Resource;
pub trait SymbolRepository<'a> {
fn get_symbol(&self, resource: &Resource) -> Option<Box<Symbol + 'a>>;
fn get_symbol(&'a self, resource: &Resource) -> Option<Box<Symbol + 'a>>;
}
impl<'a, C> SymbolRepository<'a> for C where C: Fn(&Resource) -> Option<Box<Symbol + 'a>> {
fn get_symbol(&self, resource: &Resource) -> Option<Box<Symbol + 'a>> {
fn get_symbol(&'a self, resource: &Resource) -> Option<Box<Symbol + 'a>> {
self(resource)
}
}
@ -24,7 +24,7 @@ impl<'a> DispatchingSymbolRepository<'a> {
}
impl<'a> SymbolRepository<'a> for DispatchingSymbolRepository<'a> {
fn get_symbol(&self, resource: &Resource) -> Option<Box<Symbol + 'a>> {
fn get_symbol(&'a self, resource: &Resource) -> Option<Box<Symbol + 'a>> {
self.repositories.get(resource.get_type()).and_then(|repo| repo.get_symbol(resource))
}
}

18
src/schema.rs

@ -119,18 +119,18 @@ impl<'a, R, L> SymbolRunner for ReportingSymbolRunner<'a, R, L> where R: SymbolR
use std::collections::HashSet;
use resources::Resource;
pub struct NonRepeatingSymbolRunner<'a, R> where R: 'a + SymbolRunner {
upstream: &'a R,
pub struct NonRepeatingSymbolRunner<R: SymbolRunner> {
upstream: R,
done: RefCell<HashSet<Resource>>
}
impl<'a, R> NonRepeatingSymbolRunner<'a, R> where R: SymbolRunner {
pub fn new(symbol_runner: &'a R) -> Self {
impl<R> NonRepeatingSymbolRunner<R> where R: SymbolRunner {
pub fn new(symbol_runner: R) -> Self {
NonRepeatingSymbolRunner{ upstream: symbol_runner, done: RefCell::new(HashSet::new()) }
}
}
impl<'a, R> SymbolRunner for NonRepeatingSymbolRunner<'a, R> where R: SymbolRunner {
impl<R: SymbolRunner> SymbolRunner for NonRepeatingSymbolRunner<R> {
fn run_symbol(&self, symbol: &Symbol) -> Result<(), Box<Error>>
{
if let Some(resources) = symbol.provides() {
@ -151,15 +151,15 @@ impl<'a, R> SymbolRunner for NonRepeatingSymbolRunner<'a, R> where R: SymbolRunn
}
use std::marker::PhantomData;
pub struct RequirementsResolvingSymbolRunner<'a, 's, R: 'a + SymbolRunner, G: 'a + SymbolRepository<'s>>(&'a R, &'a G, PhantomData<Box<Symbol + 's>>);
pub struct RequirementsResolvingSymbolRunner<'a, 's, R: 'a + SymbolRunner, G: 'a + SymbolRepository<'s>>(R, &'a G, PhantomData<Box<Symbol + 's>>);
impl<'a, 's, R, G> RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> {
pub fn new(symbol_runner: &'a R, symbol_repo: &'a G) -> Self {
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<'a, 's, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> {
impl<'s, 'a: 's, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> {
fn run_symbol(&self, symbol: &Symbol) -> Result<(), Box<Error>>
{
for resource in symbol.get_prerequisites() {

1
src/symbols/factory.rs

@ -13,7 +13,6 @@ pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner>{
}
impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
pub fn new(command_runner: &'b C, symbol_runner: &'b R) -> Self {
let acme_user = "acme"; // FIXME: CONFIG

6
src/symbols/mod.rs

@ -10,6 +10,12 @@ pub trait SymbolRunner {
fn run_symbol(&self, symbol: &Symbol) -> Result<(), Box<Error>>;
}
impl<R: SymbolRunner + ?Sized> SymbolRunner for Box<R> {
fn run_symbol(&self, symbol: &Symbol) -> Result<(), Box<Error>> {
(**self).run_symbol(symbol)
}
}
// Symbol
pub trait Symbol: Display {
fn target_reached(&self) -> Result<bool, Box<Error>>;

31
src/symbols/user.rs

@ -7,14 +7,14 @@ use command_runner::CommandRunner;
use resources::Resource;
use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
#[derive(Debug, PartialEq)]
pub enum UserAdderError<E: Error> {
#[derive(Debug)]
pub enum UserAdderError {
AlreadyExists,
UnknownError,
ImplError(E)
ImplError(Box<Error>)
}
impl<E: Error> Error for UserAdderError<E> {
impl Error for UserAdderError {
fn description(&self) -> &str {
match self {
&UserAdderError::AlreadyExists => "User already exists",
@ -24,13 +24,13 @@ impl<E: Error> Error for UserAdderError<E> {
}
fn cause(&self) -> Option<&Error> {
match self {
&UserAdderError::ImplError(ref e) => Some(e),
&UserAdderError::ImplError(ref e) => Some(e.as_ref()),
_ => None
}
}
}
impl<E: Error> fmt::Display for UserAdderError<E> {
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),
@ -40,8 +40,7 @@ impl<E: Error> fmt::Display for UserAdderError<E> {
}
pub trait UserAdder {
type SubE: Error;
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<Self::SubE>>;
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError>;
}
#[derive(Debug, PartialEq)]
@ -71,13 +70,13 @@ impl fmt::Display for UserError {
}
}
pub struct User<'a, C: 'a + CommandRunner, E, A> where E: Error + Sized, A: 'a + UserAdder<SubE=E> {
pub struct User<'a, C: 'a + CommandRunner, A: 'a + UserAdder> {
user_name: Cow<'a, str>,
command_runner: &'a C,
user_adder: &'a A
}
impl<'a, C: CommandRunner, E: Error + Sized, A: 'a + UserAdder<SubE=E>> User<'a, C, E, 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: user_name,
@ -87,13 +86,13 @@ impl<'a, C: CommandRunner, E: Error + Sized, A: 'a + UserAdder<SubE=E>> User<'a,
}
}
impl<'a, C: CommandRunner, E: Error, A: UserAdder<SubE=E>> fmt::Display for User<'a, C, E, A> {
impl<'a, C: CommandRunner, A: 'a + UserAdder> fmt::Display for User<'a, C, A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "User {}", self.user_name)
}
}
impl<'a, C: CommandRunner, E: 'static + Error, A: UserAdder<SubE=E>> Symbol for User<'a, C, E, A> {
impl<'a, C: CommandRunner, A: 'a + UserAdder> Symbol for User<'a, C, A> {
fn target_reached(&self) -> Result<bool, Box<Error>> {
let output = try!(self.command_runner.run_with_args("getent", &["passwd", &*self.user_name]));
match output.status.code() {
@ -131,8 +130,7 @@ impl<'a, C: CommandRunner> SystemUserAdder<'a, C> {
}
impl<'a, C: CommandRunner> UserAdder for SystemUserAdder<'a, C> {
type SubE = IoError;
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<IoError>> {
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError> {
let output = self.command_runner.run_with_args(
"adduser",
&[
@ -157,7 +155,7 @@ Err(UserAdderError::UnknownError)
Err(UserAdderError::UnknownError)
},
},
Err(e) => Err(UserAdderError::ImplError(e))
Err(e) => Err(UserAdderError::ImplError(Box::new(e)))
}
}
}
@ -190,8 +188,7 @@ mod test {
struct DummyUserAdder;
impl UserAdder for DummyUserAdder {
type SubE = DummyError;
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError<Self::SubE>> {
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError> {
Ok(())
}
}

Loading…
Cancel
Save