A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.7 KiB

use regex::Regex;
use command_runner::CommandRunner;
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;
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
}
}
}