Update
This commit is contained in:
parent
34f8dbffab
commit
fd8fe9ce11
4 changed files with 134 additions and 30 deletions
24
src/build.rs
Normal file
24
src/build.rs
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
command_runner: &'a C,
|
fn user_name_for_host(&self, host_name: &'static str) -> String;
|
||||||
acme_command_runner: SetuidCommandRunner<'a, C>,
|
|
||||||
symbol_runner: &'a R
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
|
pub struct DefaultPolicy;
|
||||||
pub fn new(command_runner: &'b C, symbol_runner: &'b R) -> Self {
|
|
||||||
|
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,
|
||||||
|
acme_command_runner: SetuidCommandRunner<'a, C>,
|
||||||
|
symbol_runner: &'a R,
|
||||||
|
policy: &'a P
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
pub fn serve_php<'a>(&'a self, host_name: &'static str, root_dir: &'static str) -> Box<Action + 'a> {
|
||||||
let socket = self.get_php_fpm_pool_socket_path(user_name);
|
let user_name = self.policy.user_name_for_host(host_name);
|
||||||
NginxServer::new_php(
|
let socket = self.get_php_fpm_pool_socket_path(&user_name);
|
||||||
host_name,
|
Box::new(ListAction::new(vec![
|
||||||
socket.into(),
|
self.get_php_fpm_pool(&user_name),
|
||||||
root_dir,
|
self.get_nginx_acme_server(host_name,
|
||||||
self.command_runner
|
NginxServer::new_php(
|
||||||
)
|
host_name,
|
||||||
|
socket.into(),
|
||||||
|
root_dir,
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
pub struct DatabaseDump<'a, N, C, S> where N: 'a + AsRef<str>, C: 'a + CommandRunner, S: Storage {
|
||||||
db_name: Cow<'a, str>,
|
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 {
|
impl<'a, N: AsRef<str>, C: CommandRunner, S: Storage> DatabaseDump<'a, N, C, S> {
|
||||||
pub fn new(db_name: Cow<'a, str>, storage: S, command_runner: &'a C) -> Self {
|
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…
Add table
Add a link
Reference in a new issue