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.

791 lines
25 KiB

use crate::command_runner::{SetuidCommandRunner, StdCommandRunner};
use crate::resources::{
AcmeAccountKey, AcmeChallengesDir, AcmeChallengesNginxSnippet, AcmeRootCert, AcmeUser, Cert,
CertChain, Cron, Csr, DefaultServer, Dir, File, GitCheckout, Key, KeyAndCertBundle,
LoadedDirectory, MariaDbDatabase, MariaDbUser, NpmInstall, Owner, PhpFpmPool, PostgresqlDatabase,
Resource, ServeCustom, ServePhp, ServeRedir, ServeService, ServeStatic, StoredDirectory,
SystemdSocketService, User, UserForDomain, WordpressPlugin, WordpressTranslation,
};
use crate::static_files::LETS_ENCRYPT_R3;
use crate::storage::SimpleStorage;
use crate::storage::Storage;
use crate::symbols::acme::Cert as CertSymbol;
use crate::symbols::concat::Concat as ConcatSymbol;
use crate::symbols::cron::Cron as CronSymbol;
use crate::symbols::dir::Dir as DirSymbol;
use crate::symbols::file::File as FileSymbol;
use crate::symbols::git::Checkout as GitCheckoutSymbol;
use crate::symbols::mariadb::{
Database as MariaDbDatabaseSymbol, Dump as MariaDbDumpSymbol, User as MariaDbUserSymbol,
};
use crate::symbols::npm::Install as NpmInstallSymbol;
use crate::symbols::owner::Owner as OwnerSymbol;
use crate::symbols::postgresql::PostgreSQLDatabase as PostgreSQLDatabaseSymbol;
use crate::symbols::saved_directory::{SavedDirectory as SavedDirectorySymbol, StorageDirection};
use crate::symbols::systemd::{
ReloadService as ReloadServiceSymbol, UserService as UserServiceSymbol,
UserSession as SystemdUserSessionSymbol,
};
use crate::symbols::tls::Csr as CsrSymbol;
use crate::symbols::tls::Key as KeySymbol;
use crate::symbols::user::User as UserSymbol;
use crate::symbols::wordpress::{
Plugin as WordpressPluginSymbol, Translation as WordpressTranslationSymbol,
};
use crate::templates::nginx;
use crate::templates::php::fpm_pool_config as php_fpm_pool_config;
use crate::templates::systemd::{
nodejs_service as systemd_nodejs_service, socket_service as systemd_socket_service,
};
use crate::to_artifact::ToArtifact;
use std::fmt::Display;
use std::path::{Path, PathBuf};
pub trait ImplementationBuilder<R> {
type Prerequisites: ToArtifact;
fn prerequisites(resource: &R) -> Self::Prerequisites;
type Implementation;
fn create(
resource: &R,
target: &R::Artifact,
inputs: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation
where
R: Resource;
}
#[derive(Debug)]
pub struct DefaultBuilder;
impl<D> ImplementationBuilder<Key<D>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &Key<D>) -> Self::Prerequisites {}
type Implementation = KeySymbol<StdCommandRunner, PathBuf>;
fn create(
_resource: &Key<D>,
target: &<Key<D> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
KeySymbol::new(StdCommandRunner, target.clone().into())
}
}
impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
type Prerequisites = Key<D>;
fn prerequisites(resource: &Csr<D>) -> Self::Prerequisites {
Key(resource.0.clone())
}
type Implementation = CsrSymbol<StdCommandRunner, D, PathBuf, PathBuf>;
fn create(
resource: &Csr<D>,
target: &<Csr<D> as Resource>::Artifact,
key: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
CsrSymbol::new(
StdCommandRunner,
resource.0.clone(),
key.into(),
target.clone().into(),
)
}
}
impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
type Prerequisites = (
Csr<D>,
AcmeRootCert,
AcmeAccountKey,
AcmeChallengesDir,
AcmeUser,
DefaultServer,
);
fn prerequisites(resource: &Cert<D>) -> Self::Prerequisites {
(
Csr(resource.0.clone()),
AcmeRootCert,
AcmeAccountKey,
AcmeChallengesDir,
AcmeUser,
DefaultServer,
)
}
type Implementation = CertSymbol<
SetuidCommandRunner<'static, String, StdCommandRunner>,
SetuidCommandRunner<'static, String, StdCommandRunner>,
D,
PathBuf,
>;
fn create(
resource: &Cert<D>,
target: &<Cert<D> as Resource>::Artifact,
(csr, root_cert, account_key, challenges_dir, user_name, _): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
CertSymbol::new(
resource.0.clone(),
SetuidCommandRunner::new(user_name.0, &StdCommandRunner),
root_cert.into(),
account_key.into(),
challenges_dir.into(),
csr.into(),
target.clone().into(),
)
}
}
impl<D: Clone> ImplementationBuilder<CertChain<D>> for DefaultBuilder {
type Prerequisites = (Cert<D>, AcmeRootCert);
fn prerequisites(resource: &CertChain<D>) -> Self::Prerequisites {
(Cert(resource.0.clone()), AcmeRootCert)
}
type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
fn create(
_resource: &CertChain<D>,
target: &<CertChain<D> as Resource>::Artifact,
(cert, root_cert): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
ConcatSymbol::new([cert.into(), root_cert.into()], target.clone().into())
}
}
impl<D: Clone> ImplementationBuilder<KeyAndCertBundle<D>> for DefaultBuilder {
type Prerequisites = (CertChain<D>, Key<D>);
fn prerequisites(resource: &KeyAndCertBundle<D>) -> Self::Prerequisites {
(CertChain(resource.0.clone()), Key(resource.0.clone()))
}
type Implementation = ConcatSymbol<[PathBuf; 2], PathBuf, PathBuf>;
fn create(
_resource: &KeyAndCertBundle<D>,
target: &<KeyAndCertBundle<D> as Resource>::Artifact,
(cert_chain, key): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
ConcatSymbol::new([key.into(), cert_chain.into()], target.clone().into())
}
}
impl<P: AsRef<Path> + Clone> ImplementationBuilder<File<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &File<P>) -> Self::Prerequisites {}
type Implementation = FileSymbol<P, String>;
fn create(
resource: &File<P>,
_target: &<File<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
FileSymbol::new(resource.0.clone(), resource.1.clone())
}
}
impl<'a, P: AsRef<Path> + Clone> ImplementationBuilder<GitCheckout<'a, P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &GitCheckout<'a, P>) -> Self::Prerequisites {}
type Implementation = GitCheckoutSymbol<StdCommandRunner, StdCommandRunner, P, &'a str, &'a str>;
fn create(
resource: &GitCheckout<'a, P>,
_target: &<GitCheckout<'a, P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
GitCheckoutSymbol::new(resource.0.clone(), resource.1, resource.2, StdCommandRunner)
}
}
impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
type Prerequisites = AcmeChallengesNginxSnippet;
fn prerequisites(_resource: &DefaultServer) -> Self::Prerequisites {
AcmeChallengesNginxSnippet
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
_resource: &DefaultServer,
target: &<DefaultServer as Resource>::Artifact,
challenges_snippet_path: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::default_server(challenges_snippet_path),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for DefaultBuilder {
type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
fn prerequisites(resource: &ServeCustom<D>) -> Self::Prerequisites {
(
CertChain(resource.0.clone()),
Key(resource.0.clone()),
AcmeChallengesNginxSnippet,
)
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
resource: &ServeCustom<D>,
target: &<ServeCustom<D> as Resource>::Artifact,
(cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: Clone + Display, P: AsRef<Path>> ImplementationBuilder<ServePhp<D, P>> for DefaultBuilder {
type Prerequisites = (
PhpFpmPool<D>,
CertChain<D>,
Key<D>,
AcmeChallengesNginxSnippet,
);
fn prerequisites(resource: &ServePhp<D, P>) -> Self::Prerequisites {
(
PhpFpmPool(resource.0.clone(), 10),
CertChain(resource.0.clone()),
Key(resource.0.clone()),
AcmeChallengesNginxSnippet,
)
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
resource: &ServePhp<D, P>,
target: &<ServePhp<D, P> as Resource>::Artifact,
(pool, cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::server_config(
&resource.0,
cert,
key,
nginx::php_snippet(resource.2, &pool.0, &resource.1) + &resource.3,
challenges_snippet_path,
),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeService<D, P>>
for DefaultBuilder
{
type Prerequisites = (
SystemdSocketService<D, P>,
CertChain<D>,
Key<D>,
AcmeChallengesNginxSnippet,
);
fn prerequisites(resource: &ServeService<D, P>) -> Self::Prerequisites {
(
SystemdSocketService(
resource.0.clone(),
resource.1,
resource.2.clone(),
resource.4.clone(),
resource.5,
),
CertChain(resource.0.clone()),
Key(resource.0.clone()),
AcmeChallengesNginxSnippet,
)
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
resource: &ServeService<D, P>,
target: &<ServeService<D, P> as Resource>::Artifact,
(socket, cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::server_config(
&resource.0,
cert,
key,
nginx::proxy_snippet(&socket.0, &resource.3),
challenges_snippet_path,
),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for DefaultBuilder {
type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
fn prerequisites(resource: &ServeRedir<D>) -> Self::Prerequisites {
(
CertChain(resource.0.clone()),
Key(resource.0.clone()),
AcmeChallengesNginxSnippet,
)
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
resource: &ServeRedir<D>,
target: &<ServeRedir<D> as Resource>::Artifact,
(cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::server_config(
&resource.0,
cert,
key,
nginx::redir_snippet(resource.1.as_ref()),
challenges_snippet_path,
),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<ServeStatic<D, P>>
for DefaultBuilder
{
type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
fn prerequisites(resource: &ServeStatic<D, P>) -> Self::Prerequisites {
(
CertChain(resource.0.clone()),
Key(resource.0.clone()),
AcmeChallengesNginxSnippet,
)
}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
);
fn create(
resource: &ServeStatic<D, P>,
target: &<ServeStatic<D, P> as Resource>::Artifact,
(cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
target.clone().into(),
nginx::server_config(
&resource.0,
cert,
key,
nginx::static_snippet(resource.1.as_ref()),
challenges_snippet_path,
),
),
ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
)
}
}
impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &PhpFpmPool<D>) -> Self::Prerequisites {}
type Implementation = (
FileSymbol<PathBuf, String>,
ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, String>,
);
fn create(
resource: &PhpFpmPool<D>,
(socket_path, conf_path, user_name, service_name): &<PhpFpmPool<D> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
conf_path.clone().into(),
php_fpm_pool_config(&user_name.0, &socket_path, resource.1),
),
ReloadServiceSymbol::new(StdCommandRunner, service_name.0.clone()),
)
}
}
impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &SystemdSocketService<D, P>) -> Self::Prerequisites {}
type Implementation = (
// First three could be parallel
FileSymbol<PathBuf, String>,
SystemdUserSessionSymbol<'static, String, StdCommandRunner>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
UserServiceSymbol<'static, PathBuf, String, StdCommandRunner>,
);
fn create(
resource: &SystemdSocketService<D, P>,
(socket_path, conf_path, user_name): &<SystemdSocketService<D, P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
FileSymbol::new(
conf_path.clone().into(),
if resource.4 {
systemd_nodejs_service(&resource.2, socket_path, &resource.3)
} else {
systemd_socket_service(
socket_path,
resource.2.as_ref().to_str().unwrap(),
&resource.3,
"",
)
},
),
SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner),
OwnerSymbol::new(
conf_path.as_ref().parent().unwrap().to_path_buf(),
user_name.0.clone(),
StdCommandRunner,
),
UserServiceSymbol::new(
socket_path.clone().into(),
user_name.0.clone(),
resource.1,
&StdCommandRunner,
),
)
}
}
impl<P: Clone> ImplementationBuilder<Dir<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &Dir<P>) -> Self::Prerequisites {}
type Implementation = DirSymbol<P>;
fn create(
resource: &Dir<P>,
_target: &<Dir<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
DirSymbol::new(resource.0.clone())
}
}
impl<P: Clone + AsRef<Path>> ImplementationBuilder<NpmInstall<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &NpmInstall<P>) -> Self::Prerequisites {}
type Implementation = NpmInstallSymbol<'static, P, StdCommandRunner>;
fn create(
resource: &NpmInstall<P>,
_target: &<NpmInstall<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
NpmInstallSymbol::new(resource.0.clone(), &StdCommandRunner)
}
}
impl<P: Clone + AsRef<Path>> ImplementationBuilder<StoredDirectory<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &StoredDirectory<P>) -> Self::Prerequisites {}
type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
fn create(
resource: &StoredDirectory<P>,
target: &<StoredDirectory<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
SavedDirectorySymbol::new(
resource.1.clone(),
SimpleStorage::new(target.clone().into()),
StorageDirection::Store,
StdCommandRunner,
)
}
}
impl<P: Clone + AsRef<Path>> ImplementationBuilder<LoadedDirectory<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &LoadedDirectory<P>) -> Self::Prerequisites {}
type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
fn create(
resource: &LoadedDirectory<P>,
target: &<LoadedDirectory<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
SavedDirectorySymbol::new(
resource.1.clone(),
SimpleStorage::new(target.clone().into()),
StorageDirection::Load,
StdCommandRunner,
)
}
}
impl<D: Clone> ImplementationBuilder<UserForDomain<D>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {}
type Implementation = UserSymbol<String, StdCommandRunner>;
fn create(
_resource: &UserForDomain<D>,
(user_name, _home_path): &<UserForDomain<D> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
UserSymbol::new(user_name.0.clone(), StdCommandRunner)
}
}
impl ImplementationBuilder<User> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &User) -> Self::Prerequisites {}
type Implementation = UserSymbol<String, StdCommandRunner>;
fn create(
resource: &User,
(): &<User as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
UserSymbol::new(resource.0.clone(), StdCommandRunner)
}
}
impl<P: AsRef<Path> + Clone> ImplementationBuilder<Owner<P>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {}
type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, String>;
fn create(
resource: &Owner<P>,
(): &<Owner<P> as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
OwnerSymbol::new(resource.1.clone(), resource.0.clone(), StdCommandRunner)
}
}
impl ImplementationBuilder<AcmeUser> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {}
type Implementation = UserSymbol<String, StdCommandRunner>;
fn create(
_resource: &AcmeUser,
user_name: &<AcmeUser as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
UserSymbol::new(user_name.0.clone(), StdCommandRunner)
}
}
impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
type Prerequisites = AcmeUser;
fn prerequisites(_resource: &AcmeChallengesDir) -> Self::Prerequisites {
AcmeUser
}
type Implementation = (
DirSymbol<PathBuf>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
);
fn create(
_resource: &AcmeChallengesDir,
target: &<AcmeChallengesDir as Resource>::Artifact,
user_name: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
DirSymbol::new(target.clone().into()),
OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
)
}
}
impl ImplementationBuilder<AcmeChallengesNginxSnippet> for DefaultBuilder {
type Prerequisites = AcmeChallengesDir;
fn prerequisites(_resource: &AcmeChallengesNginxSnippet) -> Self::Prerequisites {
AcmeChallengesDir
}
type Implementation = FileSymbol<PathBuf, String>;
fn create(
_resource: &AcmeChallengesNginxSnippet,
target: &<AcmeChallengesNginxSnippet as Resource>::Artifact,
challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
FileSymbol::new(
target.clone().into(),
nginx::acme_challenges_snippet(challenges_dir),
)
}
}
impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
type Prerequisites = AcmeUser;
fn prerequisites(_resource: &AcmeAccountKey) -> Self::Prerequisites {
AcmeUser
}
type Implementation = (
KeySymbol<StdCommandRunner, PathBuf>,
OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
);
fn create(
_resource: &AcmeAccountKey,
target: &<AcmeAccountKey as Resource>::Artifact,
user_name: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
(
KeySymbol::new(StdCommandRunner, target.clone().into()),
OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
)
}
}
impl ImplementationBuilder<AcmeRootCert> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {}
type Implementation = FileSymbol<PathBuf, &'static str>;
fn create(
_resource: &AcmeRootCert,
target: &<AcmeRootCert as Resource>::Artifact,
(): <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
FileSymbol::new(target.clone().into(), LETS_ENCRYPT_R3)
}
}
impl<D> ImplementationBuilder<MariaDbUser<D>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {}
type Implementation = MariaDbUserSymbol<'static, String, StdCommandRunner>;
fn create(
_resource: &MariaDbUser<D>,
user_name: &<MariaDbUser<D> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
MariaDbUserSymbol::new(user_name.0.clone(), &StdCommandRunner)
}
}
impl<D: Clone> ImplementationBuilder<MariaDbDatabase<D>> for DefaultBuilder {
type Prerequisites = MariaDbUser<D>;
fn prerequisites(resource: &MariaDbDatabase<D>) -> Self::Prerequisites {
MariaDbUser(resource.0.clone())
}
type Implementation = (
MariaDbDatabaseSymbol<'static, String, SimpleStorage, StdCommandRunner>,
MariaDbDumpSymbol<'static, String, StdCommandRunner, SimpleStorage>,
);
fn create(
_resource: &MariaDbDatabase<D>,
(db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
let db_dump = SimpleStorage::new(data_path.clone().into());
(
MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner),
MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner),
)
}
}
impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
type Prerequisites = ();
fn prerequisites(_: &PostgresqlDatabase<D>) -> Self::Prerequisites {}
type Implementation = (PostgreSQLDatabaseSymbol<'static, String, String, StdCommandRunner>,);
fn create(
_resource: &PostgresqlDatabase<D>,
(db_name, data_path): &<PostgresqlDatabase<D> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
let db_dump = SimpleStorage::new(data_path.clone().into());
(PostgreSQLDatabaseSymbol::new(
db_name.0.clone(),
db_dump.read_filename().unwrap().to_str().unwrap().into(),
&StdCommandRunner,
),)
}
}
impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder {
type Prerequisites = Dir<PathBuf>;
fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites {
Dir(resource.0.as_ref().join("wp-content/plugins"))
}
type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>;
fn create(
resource: &WordpressPlugin<P>,
(): &<WordpressPlugin<P> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
WordpressPluginSymbol::new(resource.0.clone(), resource.1, &StdCommandRunner)
}
}
impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
type Prerequisites = Dir<PathBuf>;
fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites {
Dir(resource.0.as_ref().join("wp-content/languages"))
}
type Implementation =
WordpressTranslationSymbol<'static, &'static str, PathBuf, StdCommandRunner>;
fn create(
resource: &WordpressTranslation<P>,
(): &<WordpressTranslation<P> as Resource>::Artifact,
_: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
WordpressTranslationSymbol::new(
resource.0.as_ref().join("wp-content/languages"),
resource.1,
resource.2,
&StdCommandRunner,
)
}
}
impl<D: Clone> ImplementationBuilder<Cron<D>> for DefaultBuilder {
type Prerequisites = UserForDomain<D>;
fn prerequisites(resource: &Cron<D>) -> Self::Prerequisites {
UserForDomain(resource.0.clone())
}
type Implementation = CronSymbol<'static, String, String, StdCommandRunner>;
fn create(
resource: &Cron<D>,
(): &<Cron<D> as Resource>::Artifact,
user_name: <Self::Prerequisites as ToArtifact>::Artifact,
) -> Self::Implementation {
CronSymbol::new((user_name.0).0, resource.1.clone(), &StdCommandRunner)
}
}