use crate::artifacts::{ DatabaseName as DatabaseNameArtifact, Path as PathArtifact, ServiceName as ServiceNameArtifact, UserName as UserNameArtifact, }; use crate::templates::php::FpmPoolConfig; use std::hash::Hash; use std::path::Path; pub trait Resource { type Artifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Key(pub D); impl Resource for Key { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Csr(pub D); impl Resource for Csr { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Cert(pub D); impl Resource for Cert { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct CertChain(pub D); impl Resource for CertChain { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct KeyAndCertBundle(pub D); impl Resource for KeyAndCertBundle { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct File

(pub P, pub Rc); impl

Resource for File

{ type Artifact = (); } impl File> { pub fn new(p: impl Into>, content: impl AsRef) -> Self { Self(p.into(), content.as_ref().into()) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct GitCheckout<'a, P>(pub P, pub &'a str, pub &'a str); impl<'a, P> Resource for GitCheckout<'a, P> { type Artifact = (); } impl<'a> GitCheckout<'a, Rc> { pub fn new(target: impl Into>, src: &'a str, head: &'a str) -> Self { Self(target.into(), src, head) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Dir

(pub P); impl

Resource for Dir

{ type Artifact = (); } impl Dir> { pub fn new(p: impl AsRef) -> Self { Self(p.as_ref().into()) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct UserForDomain(pub D); impl Resource for UserForDomain { type Artifact = (UserNameArtifact, PathArtifact); } #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeAccountKey; impl Resource for AcmeAccountKey { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeUser; impl Resource for AcmeUser { type Artifact = (UserNameArtifact, PathArtifact); } #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeRootCert; impl Resource for AcmeRootCert { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeChallengesDir; impl Resource for AcmeChallengesDir { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct AcmeChallengesNginxSnippet; impl Resource for AcmeChallengesNginxSnippet { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct StoredDirectory

(pub &'static str, pub P); impl

Resource for StoredDirectory

{ type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct LoadedDirectory

(pub &'static str, pub P); impl

Resource for LoadedDirectory

{ type Artifact = PathArtifact; } pub fn get_saved_directory( storage_name: &'static str, target: impl Into>, ) -> (StoredDirectory>, LoadedDirectory>) { let target = target.into(); ( StoredDirectory(storage_name, target.clone()), LoadedDirectory(storage_name, target), ) } #[derive(Debug, Hash, PartialEq, Eq)] pub struct User(pub Rc); impl Resource for User { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct SystemdSocketService(pub D, pub &'static str, pub P, pub P, pub bool); impl Resource for SystemdSocketService { type Artifact = (PathArtifact, PathArtifact, UserNameArtifact); } #[derive(Debug, Hash, PartialEq, Eq)] pub struct NpmInstall

(pub P); impl

Resource for NpmInstall

{ type Artifact = (); } impl NpmInstall> { pub fn new(path: impl Into>) -> Self { Self(path.into()) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Owner

(pub Rc, pub P); impl

Resource for Owner

{ type Artifact = (); } impl Owner> { pub fn new(user: &UserNameArtifact, p: impl Into>) -> Self { Self(user.0.clone(), p.into()) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct ServeCustom(pub D, pub Rc); impl Resource for ServeCustom { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct ServePhp(pub D, pub P, pub &'static str, pub Rc, pub C); impl Resource for ServePhp { type Artifact = PathArtifact; } // Domain, service name, exec, static, dir #[derive(Debug, Hash, PartialEq, Eq)] pub struct ServeService(pub D, pub &'static str, pub P, pub P, pub P, pub bool); impl Resource for ServeService { type Artifact = PathArtifact; } impl ServeService> { pub fn new( domain: D, service_name: &'static str, exec: impl Into>, static_path: impl Into>, working_directory: impl Into>, is_nodejs: bool, ) -> Self { Self( domain, service_name, exec.into(), static_path.into(), working_directory.into(), is_nodejs, ) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct ServeRedir(pub D, pub D); impl Resource for ServeRedir { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct ServeStatic(pub D, pub P); impl Resource for ServeStatic { type Artifact = PathArtifact; } impl ServeStatic> { pub fn new(domain: D, path: impl Into>) -> Self { Self(domain, path.into()) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct DefaultServer; impl Resource for DefaultServer { type Artifact = PathArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct PhpFpmPool(pub D, pub FpmPoolConfig); impl Resource for PhpFpmPool { type Artifact = ( PathArtifact, PathArtifact, UserNameArtifact, ServiceNameArtifact, ); } // A single domain could possibly need multiple databases #[derive(Debug, Hash, PartialEq, Eq)] pub struct MariaDbDatabase(pub D); impl Resource for MariaDbDatabase { type Artifact = (DatabaseNameArtifact, UserNameArtifact, PathArtifact); } #[derive(Debug, Hash, PartialEq, Eq)] pub struct MariaDbUser(pub D); impl Resource for MariaDbUser { type Artifact = UserNameArtifact; } #[derive(Debug, Hash, PartialEq, Eq)] pub struct PostgresqlDatabase(pub D); impl Resource for PostgresqlDatabase { type Artifact = (DatabaseNameArtifact, PathArtifact); } #[derive(Debug, Hash, PartialEq, Eq)] pub struct WordpressPlugin

(pub P, pub &'static str); impl

Resource for WordpressPlugin

{ type Artifact = (); } impl WordpressPlugin> { pub fn new(path: impl Into>, name: &'static str) -> Self { Self(path.into(), name) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct WordpressTranslation

(pub P, pub &'static str, pub &'static str); impl

Resource for WordpressTranslation

{ type Artifact = (); } impl WordpressTranslation> { pub fn new(path: impl Into>, version: &'static str, lang: &'static str) -> Self { Self(path.into(), version, lang) } } #[derive(Debug, Hash, PartialEq, Eq)] pub struct Cron(pub D, pub Rc); impl Resource for Cron { type Artifact = (); } use std::rc::{Rc, Weak}; pub trait FromResource { fn from_resource(from: &Rc) -> (Self, Weak) where Self: Sized; } pub trait FromArtifact { fn from_artifact(from: R::Artifact) -> Self where Self: Sized; fn into_artifact(self) -> R::Artifact where Self: Sized; } macro_rules! default_resources { ( $($name:ident: $type:ty,)* ) => { #[derive(Debug, PartialEq, Eq, Hash)] pub enum DefaultResources<'a, D> { $( $name(Rc<$type>) ),* } $(impl<'a, D> FromResource<$type> for DefaultResources<'a, D> { fn from_resource(inner: &Rc<$type>) -> (Self, Weak<$type>) { (Self::$name(Rc::clone(&inner)), Rc::downgrade(&inner)) } })* #[derive(Clone, Debug)] pub enum DefaultArtifacts<'a, D> { $( $name(<$type as Resource>::Artifact) ),* } $(impl<'a, D> FromArtifact<$type> for DefaultArtifacts<'a, D> { fn from_artifact(from: <$type as Resource>::Artifact) -> Self { Self::$name(from) } fn into_artifact(self) -> <$type as Resource>::Artifact { match self { Self::$name(inner) => inner, _ => panic!() } } })* } } // Only one enum entry per resource type, otherwise the equality checks fail default_resources!( AcmeAccountKey: AcmeAccountKey, AcmeChallengesDir: AcmeChallengesDir, AcmeChallengesNginxSnippet: AcmeChallengesNginxSnippet, AcmeRootCert: AcmeRootCert, AcmeUser: AcmeUser, Cert: Cert, CertChain: CertChain, Cron: Cron, Csr: Csr, DefaultServer: DefaultServer, Dir: Dir>, File: File>, GitCheckout: GitCheckout<'a, Rc>, Key: Key, KeyAndCertBundle: KeyAndCertBundle, LoadedDirectory: LoadedDirectory>, MariaDbDatabase: MariaDbDatabase, MariaDbUser: MariaDbUser, PostgresqlDatabase: PostgresqlDatabase, SystemdSocketService: SystemdSocketService>, NpmInstall: NpmInstall>, Owner: Owner>, PhpFpmPool: PhpFpmPool, ServeCustom: ServeCustom, ServeService: ServeService>, ServePhp: ServePhp, FpmPoolConfig>, ServeRedir: ServeRedir, ServeStatic: ServeStatic>, StoredDirectory: StoredDirectory>, User: User, UserForDomain: UserForDomain, WordpressPlugin: WordpressPlugin>, WordpressTranslation: WordpressTranslation>, ); pub fn serve_php>( domain: D, path: impl Into>, root_filename: &'static str, nginx_config: impl Into>, pool_config: C, ) -> ServePhp, FpmPoolConfig> { ServePhp( domain, path.into(), root_filename, nginx_config.into(), pool_config.into(), ) }