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.

330 lines
8.4 KiB

2 years ago
7 years ago
2 years ago
2 years ago
  1. use crate::artifacts::{
  2. DatabaseName as DatabaseNameArtifact, Path as PathArtifact, ServiceName as ServiceNameArtifact,
  3. UserName as UserNameArtifact,
  4. };
  5. use crate::templates::php::FpmPoolConfig;
  6. use std::hash::Hash;
  7. use std::path::PathBuf;
  8. pub trait Resource {
  9. type Artifact;
  10. }
  11. #[derive(Debug, Hash, PartialEq, Eq)]
  12. pub struct Key<D>(pub D);
  13. impl<D> Resource for Key<D> {
  14. type Artifact = PathArtifact;
  15. }
  16. #[derive(Debug, Hash, PartialEq, Eq)]
  17. pub struct Csr<D>(pub D);
  18. impl<D> Resource for Csr<D> {
  19. type Artifact = PathArtifact;
  20. }
  21. #[derive(Debug, Hash, PartialEq, Eq)]
  22. pub struct Cert<D>(pub D);
  23. impl<D> Resource for Cert<D> {
  24. type Artifact = PathArtifact;
  25. }
  26. #[derive(Debug, Hash, PartialEq, Eq)]
  27. pub struct CertChain<D>(pub D);
  28. impl<D> Resource for CertChain<D> {
  29. type Artifact = PathArtifact;
  30. }
  31. #[derive(Debug, Hash, PartialEq, Eq)]
  32. pub struct KeyAndCertBundle<D>(pub D);
  33. impl<D> Resource for KeyAndCertBundle<D> {
  34. type Artifact = PathArtifact;
  35. }
  36. #[derive(Debug, Hash, PartialEq, Eq)]
  37. pub struct File<P>(pub P, pub String);
  38. impl<'a, P> Resource for File<P> {
  39. type Artifact = ();
  40. }
  41. #[derive(Debug, Hash, PartialEq, Eq)]
  42. pub struct GitCheckout<'a, P>(pub P, pub &'a str, pub &'a str);
  43. impl<'a, P> Resource for GitCheckout<'a, P> {
  44. type Artifact = ();
  45. }
  46. #[derive(Debug, Hash, PartialEq, Eq)]
  47. pub struct Dir<P>(pub P);
  48. impl<P> Resource for Dir<P> {
  49. type Artifact = ();
  50. }
  51. #[derive(Debug, Hash, PartialEq, Eq)]
  52. pub struct UserForDomain<D>(pub D);
  53. impl<D> Resource for UserForDomain<D> {
  54. type Artifact = (UserNameArtifact, PathArtifact);
  55. }
  56. #[derive(Debug, Hash, PartialEq, Eq)]
  57. pub struct AcmeAccountKey;
  58. impl Resource for AcmeAccountKey {
  59. type Artifact = PathArtifact;
  60. }
  61. #[derive(Debug, Hash, PartialEq, Eq)]
  62. pub struct AcmeUser;
  63. impl Resource for AcmeUser {
  64. type Artifact = UserNameArtifact;
  65. }
  66. #[derive(Debug, Hash, PartialEq, Eq)]
  67. pub struct AcmeRootCert;
  68. impl Resource for AcmeRootCert {
  69. type Artifact = PathArtifact;
  70. }
  71. #[derive(Debug, Hash, PartialEq, Eq)]
  72. pub struct AcmeChallengesDir;
  73. impl Resource for AcmeChallengesDir {
  74. type Artifact = PathArtifact;
  75. }
  76. #[derive(Debug, Hash, PartialEq, Eq)]
  77. pub struct AcmeChallengesNginxSnippet;
  78. impl Resource for AcmeChallengesNginxSnippet {
  79. type Artifact = PathArtifact;
  80. }
  81. #[derive(Debug, Hash, PartialEq, Eq)]
  82. pub struct StoredDirectory<P>(pub &'static str, pub P);
  83. impl<P> Resource for StoredDirectory<P> {
  84. type Artifact = PathArtifact;
  85. }
  86. #[derive(Debug, Hash, PartialEq, Eq)]
  87. pub struct LoadedDirectory<P>(pub &'static str, pub P);
  88. impl<P> Resource for LoadedDirectory<P> {
  89. type Artifact = PathArtifact;
  90. }
  91. pub fn get_saved_directory<P: Clone>(
  92. storage_name: &'static str,
  93. target: P,
  94. ) -> (StoredDirectory<P>, LoadedDirectory<P>) {
  95. (
  96. StoredDirectory(storage_name, target.clone()),
  97. LoadedDirectory(storage_name, target),
  98. )
  99. }
  100. #[derive(Debug, Hash, PartialEq, Eq)]
  101. pub struct User(pub String);
  102. impl Resource for User {
  103. type Artifact = ();
  104. }
  105. #[derive(Debug, Hash, PartialEq, Eq)]
  106. pub struct SystemdSocketService<D, P>(pub D, pub &'static str, pub P, pub P, pub bool);
  107. impl<D, P> Resource for SystemdSocketService<D, P> {
  108. type Artifact = (PathArtifact, PathArtifact, UserNameArtifact);
  109. }
  110. #[derive(Debug, Hash, PartialEq, Eq)]
  111. pub struct NpmInstall<P>(pub P);
  112. impl<P> Resource for NpmInstall<P> {
  113. type Artifact = ();
  114. }
  115. #[derive(Debug, Hash, PartialEq, Eq)]
  116. pub struct Owner<P>(pub String, pub P);
  117. impl<P> Resource for Owner<P> {
  118. type Artifact = ();
  119. }
  120. #[derive(Debug, Hash, PartialEq, Eq)]
  121. pub struct ServeCustom<D>(pub D, pub String);
  122. impl<D> Resource for ServeCustom<D> {
  123. type Artifact = PathArtifact;
  124. }
  125. #[derive(Debug, Hash, PartialEq, Eq)]
  126. pub struct ServePhp<D, P, C>(pub D, pub P, pub &'static str, pub String, pub C);
  127. impl<D, P, C> Resource for ServePhp<D, P, C> {
  128. type Artifact = PathArtifact;
  129. }
  130. // Domain, service name, exec, static, dir
  131. #[derive(Debug, Hash, PartialEq, Eq)]
  132. pub struct ServeService<D, P>(pub D, pub &'static str, pub P, pub P, pub P, pub bool);
  133. impl<D, P> Resource for ServeService<D, P> {
  134. type Artifact = PathArtifact;
  135. }
  136. #[derive(Debug, Hash, PartialEq, Eq)]
  137. pub struct ServeRedir<D>(pub D, pub D);
  138. impl<D> Resource for ServeRedir<D> {
  139. type Artifact = PathArtifact;
  140. }
  141. #[derive(Debug, Hash, PartialEq, Eq)]
  142. pub struct ServeStatic<D, P>(pub D, pub P);
  143. impl<D, P> Resource for ServeStatic<D, P> {
  144. type Artifact = PathArtifact;
  145. }
  146. #[derive(Debug, Hash, PartialEq, Eq)]
  147. pub struct DefaultServer;
  148. impl Resource for DefaultServer {
  149. type Artifact = PathArtifact;
  150. }
  151. #[derive(Debug, Hash, PartialEq, Eq)]
  152. pub struct PhpFpmPool<D>(pub D, pub FpmPoolConfig);
  153. impl<D> Resource for PhpFpmPool<D> {
  154. type Artifact = (
  155. PathArtifact,
  156. PathArtifact,
  157. UserNameArtifact,
  158. ServiceNameArtifact,
  159. );
  160. }
  161. // A single domain could possibly need multiple databases
  162. #[derive(Debug, Hash, PartialEq, Eq)]
  163. pub struct MariaDbDatabase<D>(pub D);
  164. impl<D> Resource for MariaDbDatabase<D> {
  165. type Artifact = (DatabaseNameArtifact, UserNameArtifact, PathArtifact);
  166. }
  167. #[derive(Debug, Hash, PartialEq, Eq)]
  168. pub struct MariaDbUser<D>(pub D);
  169. impl<D> Resource for MariaDbUser<D> {
  170. type Artifact = UserNameArtifact;
  171. }
  172. #[derive(Debug, Hash, PartialEq, Eq)]
  173. pub struct PostgresqlDatabase<D>(pub D);
  174. impl<D> Resource for PostgresqlDatabase<D> {
  175. type Artifact = (DatabaseNameArtifact, PathArtifact);
  176. }
  177. #[derive(Debug, Hash, PartialEq, Eq)]
  178. pub struct WordpressPlugin<P>(pub P, pub &'static str);
  179. impl<P> Resource for WordpressPlugin<P> {
  180. type Artifact = ();
  181. }
  182. #[derive(Debug, Hash, PartialEq, Eq)]
  183. pub struct WordpressTranslation<P>(pub P, pub &'static str, pub &'static str);
  184. impl<P> Resource for WordpressTranslation<P> {
  185. type Artifact = ();
  186. }
  187. #[derive(Debug, Hash, PartialEq, Eq)]
  188. pub struct Cron<D>(pub D, pub String);
  189. impl<D> Resource for Cron<D> {
  190. type Artifact = ();
  191. }
  192. use std::rc::{Rc, Weak};
  193. pub trait FromResource<R> {
  194. fn from_resource(from: R) -> (Self, Weak<R>)
  195. where
  196. Self: Sized;
  197. }
  198. pub trait FromArtifact<R: Resource> {
  199. fn from_artifact(from: R::Artifact) -> Self
  200. where
  201. Self: Sized;
  202. fn into_artifact(self) -> R::Artifact
  203. where
  204. Self: Sized;
  205. }
  206. macro_rules! default_resources {
  207. ( $($name:ident: $type:ty,)* ) => {
  208. #[derive(Debug, PartialEq, Eq, Hash)]
  209. pub enum DefaultResources<'a, D> {
  210. $( $name(Rc<$type>) ),*
  211. }
  212. $(impl<'a, D> FromResource<$type> for DefaultResources<'a, D> {
  213. fn from_resource(from: $type) -> (Self, Weak<$type>) {
  214. let inner = Rc::new(from);
  215. (Self::$name(Rc::clone(&inner)), Rc::downgrade(&inner))
  216. }
  217. })*
  218. #[derive(Clone, Debug)]
  219. pub enum DefaultArtifacts<'a, D> {
  220. $( $name(<$type as Resource>::Artifact) ),*
  221. }
  222. $(impl<'a, D> FromArtifact<$type> for DefaultArtifacts<'a, D> {
  223. fn from_artifact(from: <$type as Resource>::Artifact) -> Self {
  224. Self::$name(from)
  225. }
  226. fn into_artifact(self) -> <$type as Resource>::Artifact {
  227. match self {
  228. Self::$name(inner) => inner,
  229. _ => panic!()
  230. }
  231. }
  232. })*
  233. }
  234. }
  235. // Only one enum entry per resource type, otherwise the equality checks fail
  236. default_resources!(
  237. AcmeAccountKey: AcmeAccountKey,
  238. AcmeChallengesDir: AcmeChallengesDir,
  239. AcmeChallengesNginxSnippet: AcmeChallengesNginxSnippet,
  240. AcmeRootCert: AcmeRootCert,
  241. AcmeUser: AcmeUser,
  242. Cert: Cert<D>,
  243. CertChain: CertChain<D>,
  244. Cron: Cron<D>,
  245. Csr: Csr<D>,
  246. DefaultServer: DefaultServer,
  247. Dir: Dir<PathBuf>,
  248. File: File<PathBuf>,
  249. GitCheckout: GitCheckout<'a, PathBuf>,
  250. Key: Key<D>,
  251. KeyAndCertBundle: KeyAndCertBundle<D>,
  252. LoadedDirectory: LoadedDirectory<PathBuf>,
  253. MariaDbDatabase: MariaDbDatabase<D>,
  254. MariaDbUser: MariaDbUser<D>,
  255. PostgresqlDatabase: PostgresqlDatabase<D>,
  256. SystemdSocketService: SystemdSocketService<D, PathBuf>,
  257. NpmInstall: NpmInstall<PathBuf>,
  258. Owner: Owner<PathBuf>,
  259. PhpFpmPool: PhpFpmPool<D>,
  260. ServeCustom: ServeCustom<D>,
  261. ServeService: ServeService<D, PathBuf>,
  262. ServePhp: ServePhp<D, PathBuf, FpmPoolConfig>,
  263. ServeRedir: ServeRedir<D>,
  264. ServeStatic: ServeStatic<D, PathBuf>,
  265. StoredDirectory: StoredDirectory<PathBuf>,
  266. User: User,
  267. UserForDomain: UserForDomain<D>,
  268. WordpressPlugin: WordpressPlugin<PathBuf>,
  269. WordpressTranslation: WordpressTranslation<PathBuf>,
  270. );
  271. pub fn serve_php<D, P: Into<PathBuf>, C: Into<FpmPoolConfig>>(
  272. domain: D,
  273. path: P,
  274. root_filename: &'static str,
  275. nginx_config: impl Into<String>,
  276. pool_config: C,
  277. ) -> ServePhp<D, PathBuf, FpmPoolConfig> {
  278. ServePhp(
  279. domain,
  280. path.into(),
  281. root_filename,
  282. nginx_config.into(),
  283. pool_config.into(),
  284. )
  285. }