Browse Source

Update

master
Adrian Heine 6 years ago
parent
commit
fd8fe9ce11
  1. 24
      src/build.rs
  2. 1
      src/lib.rs
  3. 104
      src/symbols/factory.rs
  4. 19
      src/symbols/mariadb/database_dump.rs

24
src/build.rs

@ -0,0 +1,24 @@
use std::env;
use std::fs::{read_dir, File};
use std::io::Read;
use std::io::Write;
use std::path::{Path, PathBuf};
fn get_const_name<P: Clone + Into<PathBuf>>(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()
}
pub fn create_static_output_files(source_dir: &str) {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("static_files.rs");
let mut f = File::create(&dest_path).unwrap();
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();
let fence = buffer.chars().filter(|c| *c == '#').collect::<String>() + "#";
f.write_all(format!("pub const {}: &'static str = r{1}\"{2}\"{1};\n", get_const_name(&file_path), fence, buffer).as_bytes()).unwrap();
}
}

1
src/lib.rs

@ -23,6 +23,7 @@ extern crate regex;
extern crate users; extern crate users;
pub mod bin; pub mod bin;
pub mod build;
pub mod command_runner; pub mod command_runner;
pub mod factory; pub mod factory;
pub mod loggers; pub mod loggers;

104
src/symbols/factory.rs

@ -2,31 +2,50 @@ use std::ops::Deref;
use std::path::Path; use std::path::Path;
use command_runner::{CommandRunner, SetuidCommandRunner}; use command_runner::{CommandRunner, SetuidCommandRunner};
use storage::SimpleStorage;
use storage::{SimpleStorage, Storage};
use symbols::{Action, Symbol, SymbolRunner}; use symbols::{Action, Symbol, SymbolRunner};
use symbols::acme::{AcmeCert, AcmeCertChain}; use symbols::acme::{AcmeCert, AcmeCertChain};
use symbols::file::File; use symbols::file::File;
use symbols::git::checkout::GitCheckout; use symbols::git::checkout::GitCheckout;
use symbols::hook::Hook; use symbols::hook::Hook;
use symbols::list::ListAction; use symbols::list::ListAction;
use symbols::nginx::server::NginxServer;
use symbols::mariadb::{DatabaseDump, MariaDBDatabase, MariaDBUser};
use symbols::nginx::server::{NginxServer, server_config};
use symbols::owner::Owner; use symbols::owner::Owner;
use symbols::stored_directory::{StoredDirectory, StorageDirection}; use symbols::stored_directory::{StoredDirectory, StorageDirection};
use symbols::systemd::reload::ReloadService; use symbols::systemd::reload::ReloadService;
use symbols::tls::SelfSignedTlsCert; use symbols::tls::SelfSignedTlsCert;
pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner>{
pub trait Policy {
fn user_name_for_host(&self, host_name: &'static str) -> String;
}
pub struct DefaultPolicy;
impl Policy for DefaultPolicy {
fn user_name_for_host(&self, host_name: &'static str) -> String {
host_name.split('.').rev().fold(String::new(), |result, part| if result.len() > 0 { result + "_" } else { result } + part)
}
}
pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner, P: 'a + Policy>{
command_runner: &'a C, command_runner: &'a C,
acme_command_runner: SetuidCommandRunner<'a, C>, acme_command_runner: SetuidCommandRunner<'a, C>,
symbol_runner: &'a R
symbol_runner: &'a R,
policy: &'a P
} }
impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
pub fn new(command_runner: &'b C, symbol_runner: &'b R) -> Self {
impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner, P: 'b + Policy> SymbolFactory<'b, C, R, P> {
pub fn new(command_runner: &'b C, symbol_runner: &'b R, policy: &'b P) -> Self {
let acme_user = "acme"; // FIXME: CONFIG let acme_user = "acme"; // FIXME: CONFIG
let acme_command_runner = SetuidCommandRunner::new(acme_user, command_runner); let acme_command_runner = SetuidCommandRunner::new(acme_user, command_runner);
SymbolFactory { command_runner: command_runner, acme_command_runner: acme_command_runner, symbol_runner: symbol_runner }
SymbolFactory {
command_runner: command_runner,
acme_command_runner: acme_command_runner,
symbol_runner: symbol_runner,
policy: policy
}
} }
pub fn get_nginx_acme_server<'a, 'c: 'a, S: 'a + Symbol>(&'c self, host: &'static str, nginx_server_symbol: S) -> Box<Action + 'a> { pub fn get_nginx_acme_server<'a, 'c: 'a, S: 'a + Symbol>(&'c self, host: &'static str, nginx_server_symbol: S) -> Box<Action + 'a> {
@ -61,11 +80,11 @@ impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
)).into_action(self.symbol_runner) )).into_action(self.symbol_runner)
} }
pub fn get_php_fpm_pool_socket_path<'a>(&'a self, user_name: &'static str) -> String {
fn get_php_fpm_pool_socket_path<'a>(&'a self, user_name: &str) -> String {
format!("/run/php/{}.sock", user_name) format!("/run/php/{}.sock", user_name)
} }
pub fn get_php_fpm_pool<'a>(&'a self, user_name: &'static str) -> Box<Action + 'a> {
fn get_php_fpm_pool<'a>(&'a self, user_name: &str) -> Box<Action + 'a> {
let socket = self.get_php_fpm_pool_socket_path(user_name); let socket = self.get_php_fpm_pool_socket_path(user_name);
Box::new(Hook::new( Box::new(Hook::new(
File::new( File::new(
@ -84,14 +103,63 @@ pm.max_children = 10"
)).into_action(self.symbol_runner) )).into_action(self.symbol_runner)
} }
pub fn get_nginx_php_server<'a>(&'a self, host_name: &'static str, user_name: &'static str, root_dir: &'static str) -> NginxServer<'a, C, String> {
let socket = self.get_php_fpm_pool_socket_path(user_name);
pub fn serve_php<'a>(&'a self, host_name: &'static str, root_dir: &'static str) -> Box<Action + 'a> {
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( NginxServer::new_php(
host_name, host_name,
socket.into(), socket.into(),
root_dir, root_dir,
self.command_runner self.command_runner
) )
)
]))
}
pub fn serve_dokuwiki<'a>(&'a self, host_name: &'static str, root_dir: &'static str) -> Box<Action + 'a> {
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(
host_name,
server_config("hostname", &format!("
root {};
index doku.php;
location ~ [^/]\\.php(/|$) {{
fastcgi_pass unix:{};
include \"snippets/fastcgi-php.conf\";
}}
location ~ /(data/|conf/|bin/|inc/|install.php) {{ deny all; }}
location / {{ try_files $uri $uri/ @dokuwiki; }}
location @dokuwiki {{
# rewrites \"doku.php/\" out of the URLs if you set the userewrite setting to .htaccess in dokuwiki config page
rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last;
rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last;
rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last;
rewrite ^/(.*) /doku.php?id=$1&$args last;
}}
",
root_dir,
socket)),
self.command_runner
))
]))
}
pub fn serve_redir<'a>(&'a self, host_name: &'static str, target: &'static str) -> Box<Action + 'a> {
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<Action + 'a> {
self.get_nginx_acme_server(host_name, NginxServer::new_static(host_name, dir, self.command_runner))
} }
pub fn get_stored_directory<'a, T: Into<String>>(&'a self, storage_name: &'static str, target: T) -> (Box<Action + 'a>, Box<Action + 'a>) { pub fn get_stored_directory<'a, T: Into<String>>(&'a self, storage_name: &'static str, target: T) -> (Box<Action + 'a>, Box<Action + 'a>) {
@ -103,6 +171,18 @@ pm.max_children = 10"
) )
} }
pub fn get_mariadb_database<'a>(&'a self, name: &'static str) -> Box<Action + 'a> {
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)
]))
}
pub fn get_mariadb_user<'a>(&'a self, user_name: &'static str) -> Box<Action + 'a> {
Box::new(MariaDBUser::new(user_name.into(), self.command_runner)).into_action(self.symbol_runner)
}
pub fn get_git_checkout<'a, T: 'a + AsRef<str>>(&'a self, target: T, source: &'a str, branch: &'a str) -> Box<Action + 'a> { pub fn get_git_checkout<'a, T: 'a + AsRef<str>>(&'a self, target: T, source: &'a str, branch: &'a str) -> Box<Action + 'a> {
Box::new(GitCheckout::new(target, source, branch, self.command_runner)).into_action(self.symbol_runner) Box::new(GitCheckout::new(target, source, branch, self.command_runner)).into_action(self.symbol_runner)
} }
@ -111,7 +191,7 @@ pm.max_children = 10"
Box::new(Owner::new(file, user.into(), self.command_runner)).into_action(self.symbol_runner) Box::new(Owner::new(file, user.into(), self.command_runner)).into_action(self.symbol_runner)
} }
pub fn get_file<'a, F: 'a + Deref<Target=str>, P: 'a + AsRef<Path>>(&'a self, path: P, content: F) -> Box<Action + 'a> {
pub fn get_file<'a, F: 'a + Deref<Target=str>, Q: 'a + AsRef<Path>>(&'a self, path: Q, content: F) -> Box<Action + 'a> {
Box::new(File::new(path, content)).into_action(self.symbol_runner) Box::new(File::new(path, content)).into_action(self.symbol_runner)
} }
} }

19
src/symbols/mariadb/database_dump.rs

@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
@ -7,14 +6,14 @@ use command_runner::CommandRunner;
use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
use storage::Storage; use storage::Storage;
pub struct DatabaseDump<'a, C, S> where C: 'a + CommandRunner, S: Storage {
db_name: Cow<'a, str>,
pub struct DatabaseDump<'a, N, C, S> where N: 'a + AsRef<str>, C: 'a + CommandRunner, S: Storage {
db_name: N,
storage: S, storage: S,
command_runner: &'a C command_runner: &'a C
} }
impl<'a, C: CommandRunner, S> DatabaseDump<'a, C, S> where S: Storage {
pub fn new(db_name: Cow<'a, str>, storage: S, command_runner: &'a C) -> Self {
impl<'a, N: AsRef<str>, C: CommandRunner, S: Storage> DatabaseDump<'a, N, C, S> {
pub fn new(db_name: N, storage: S, command_runner: &'a C) -> Self {
DatabaseDump { DatabaseDump {
db_name: db_name, db_name: db_name,
storage: storage, storage: storage,
@ -28,22 +27,22 @@ impl<'a, C: CommandRunner, S> DatabaseDump<'a, C, S> where S: Storage {
} }
} }
impl<'a, C: CommandRunner, S> fmt::Display for DatabaseDump<'a, C, S> where S: Storage {
impl<'a, N: AsRef<str>, C: CommandRunner, S: Storage> fmt::Display for DatabaseDump<'a, N, C, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Dump MariaDB Database {}", self.db_name)
write!(f, "Dump MariaDB Database {}", self.db_name.as_ref())
} }
} }
impl<'a, C: CommandRunner, S> Symbol for DatabaseDump<'a, C, S> where S: Storage {
impl<'a, N: AsRef<str>, C: CommandRunner, S: Storage> Symbol for DatabaseDump<'a, N, C, S> {
fn target_reached(&self) -> Result<bool, Box<Error>> { fn target_reached(&self) -> Result<bool, Box<Error>> {
let dump_date = try!(self.storage.recent_date()); 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)));
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_right() == "NULL" { return Ok(false); } if modified_date.trim_right() == "NULL" { return Ok(false); }
Ok(try!(u64::from_str(modified_date.trim_right())) <= dump_date) Ok(try!(u64::from_str(modified_date.trim_right())) <= dump_date)
} }
fn execute(&self) -> Result<(), Box<Error>> { fn execute(&self) -> Result<(), Box<Error>> {
self.command_runner.run_successfully("sh", &["-c", &format!("mysqldump '{}' > {}", self.db_name, 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 SymbolRunner) -> Box<Action + 'b> { fn as_action<'b>(&'b self, runner: &'b SymbolRunner) -> Box<Action + 'b> {

Loading…
Cancel
Save