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;
|
||||
|
||||
pub mod bin;
|
||||
pub mod build;
|
||||
pub mod command_runner;
|
||||
pub mod factory;
|
||||
pub mod loggers;
|
||||
|
|
|
|||
|
|
@ -2,31 +2,50 @@ use std::ops::Deref;
|
|||
use std::path::Path;
|
||||
|
||||
use command_runner::{CommandRunner, SetuidCommandRunner};
|
||||
use storage::SimpleStorage;
|
||||
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::nginx::server::NginxServer;
|
||||
use symbols::mariadb::{DatabaseDump, MariaDBDatabase, MariaDBUser};
|
||||
use symbols::nginx::server::{NginxServer, server_config};
|
||||
use symbols::owner::Owner;
|
||||
use symbols::stored_directory::{StoredDirectory, StorageDirection};
|
||||
use symbols::systemd::reload::ReloadService;
|
||||
use symbols::tls::SelfSignedTlsCert;
|
||||
|
||||
pub struct SymbolFactory<'a, C: 'a + CommandRunner, R: 'a + SymbolRunner>{
|
||||
command_runner: &'a C,
|
||||
acme_command_runner: SetuidCommandRunner<'a, C>,
|
||||
symbol_runner: &'a R
|
||||
pub trait Policy {
|
||||
fn user_name_for_host(&self, host_name: &'static str) -> String;
|
||||
}
|
||||
|
||||
impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
|
||||
pub fn new(command_runner: &'b C, symbol_runner: &'b R) -> Self {
|
||||
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,
|
||||
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_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> {
|
||||
|
|
@ -61,11 +80,11 @@ impl<'b, C: 'b + CommandRunner, R: 'b + SymbolRunner> SymbolFactory<'b, C, R> {
|
|||
)).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)
|
||||
}
|
||||
|
||||
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);
|
||||
Box::new(Hook::new(
|
||||
File::new(
|
||||
|
|
@ -84,14 +103,63 @@ pm.max_children = 10"
|
|||
)).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);
|
||||
NginxServer::new_php(
|
||||
host_name,
|
||||
socket.into(),
|
||||
root_dir,
|
||||
self.command_runner
|
||||
)
|
||||
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(
|
||||
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>) {
|
||||
|
|
@ -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> {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::borrow::Cow;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
|
@ -7,14 +6,14 @@ use command_runner::CommandRunner;
|
|||
use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
|
||||
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,
|
||||
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 {
|
||||
db_name: db_name,
|
||||
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 {
|
||||
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>> {
|
||||
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); }
|
||||
Ok(try!(u64::from_str(modified_date.trim_right())) <= dump_date)
|
||||
}
|
||||
|
||||
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> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue