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.

792 lines
26 KiB

2 years ago
2 years ago
2 years ago
4 years ago
  1. use crate::command_runner::{SetuidCommandRunner, StdCommandRunner};
  2. use crate::resources::{
  3. AcmeAccountKey, AcmeChallengesDir, AcmeChallengesNginxSnippet, AcmeRootCert, AcmeUser, Cert,
  4. CertChain, Cron, Csr, DefaultServer, Dir, File, GitCheckout, Key, KeyAndCertBundle,
  5. LoadedDirectory, MariaDbDatabase, MariaDbUser, NpmInstall, Owner, PhpFpmPool, PostgresqlDatabase,
  6. Resource, ServeCustom, ServePhp, ServeRedir, ServeService, ServeStatic, StoredDirectory,
  7. SystemdSocketService, User, UserForDomain, WordpressPlugin, WordpressTranslation,
  8. };
  9. use crate::static_files::LETS_ENCRYPT_R3;
  10. use crate::storage::SimpleStorage;
  11. use crate::storage::Storage;
  12. use crate::symbols::acme::Cert as CertSymbol;
  13. use crate::symbols::concat::Concat as ConcatSymbol;
  14. use crate::symbols::cron::Cron as CronSymbol;
  15. use crate::symbols::dir::Dir as DirSymbol;
  16. use crate::symbols::file::File as FileSymbol;
  17. use crate::symbols::git::Checkout as GitCheckoutSymbol;
  18. use crate::symbols::mariadb::{
  19. Database as MariaDbDatabaseSymbol, Dump as MariaDbDumpSymbol, User as MariaDbUserSymbol,
  20. };
  21. use crate::symbols::npm::Install as NpmInstallSymbol;
  22. use crate::symbols::owner::Owner as OwnerSymbol;
  23. use crate::symbols::postgresql::PostgreSQLDatabase as PostgreSQLDatabaseSymbol;
  24. use crate::symbols::saved_directory::{SavedDirectory as SavedDirectorySymbol, StorageDirection};
  25. use crate::symbols::systemd::{
  26. ReloadService as ReloadServiceSymbol, UserService as UserServiceSymbol,
  27. UserSession as SystemdUserSessionSymbol,
  28. };
  29. use crate::symbols::tls::Csr as CsrSymbol;
  30. use crate::symbols::tls::Key as KeySymbol;
  31. use crate::symbols::user::User as UserSymbol;
  32. use crate::symbols::wordpress::{
  33. Plugin as WordpressPluginSymbol, Translation as WordpressTranslationSymbol,
  34. };
  35. use crate::templates::nginx;
  36. use crate::templates::php::{
  37. fpm_pool_config as php_fpm_pool_config, FpmPoolConfig as PhpFpmPoolConfig,
  38. };
  39. use crate::templates::systemd::{
  40. nodejs_service as systemd_nodejs_service, socket_service as systemd_socket_service,
  41. };
  42. use crate::to_artifact::ToArtifact;
  43. use std::fmt::Display;
  44. use std::path::Path;
  45. use std::rc::Rc;
  46. pub trait ImplementationBuilder<R> {
  47. type Prerequisites: ToArtifact;
  48. fn prerequisites(resource: &R) -> Self::Prerequisites;
  49. type Implementation;
  50. fn create(
  51. resource: &R,
  52. target: &R::Artifact,
  53. inputs: <Self::Prerequisites as ToArtifact>::Artifact,
  54. ) -> Self::Implementation
  55. where
  56. R: Resource;
  57. }
  58. #[derive(Debug)]
  59. pub struct DefaultBuilder;
  60. impl<D> ImplementationBuilder<Key<D>> for DefaultBuilder {
  61. type Prerequisites = ();
  62. fn prerequisites(_resource: &Key<D>) -> Self::Prerequisites {}
  63. type Implementation = KeySymbol<StdCommandRunner, Rc<Path>>;
  64. fn create(
  65. _resource: &Key<D>,
  66. target: &<Key<D> as Resource>::Artifact,
  67. (): <Self::Prerequisites as ToArtifact>::Artifact,
  68. ) -> Self::Implementation {
  69. KeySymbol::new(StdCommandRunner, target.clone_rc())
  70. }
  71. }
  72. impl<D: Clone> ImplementationBuilder<Csr<D>> for DefaultBuilder {
  73. type Prerequisites = Key<D>;
  74. fn prerequisites(resource: &Csr<D>) -> Self::Prerequisites {
  75. Key(resource.0.clone())
  76. }
  77. type Implementation = CsrSymbol<StdCommandRunner, D, Rc<Path>, Rc<Path>>;
  78. fn create(
  79. resource: &Csr<D>,
  80. target: &<Csr<D> as Resource>::Artifact,
  81. key: <Self::Prerequisites as ToArtifact>::Artifact,
  82. ) -> Self::Implementation {
  83. CsrSymbol::new(
  84. StdCommandRunner,
  85. resource.0.clone(),
  86. key.clone_rc(),
  87. target.clone_rc(),
  88. )
  89. }
  90. }
  91. impl<D: Clone> ImplementationBuilder<Cert<D>> for DefaultBuilder {
  92. type Prerequisites = (
  93. Csr<D>,
  94. AcmeRootCert,
  95. AcmeAccountKey,
  96. AcmeChallengesDir,
  97. AcmeUser,
  98. DefaultServer,
  99. );
  100. fn prerequisites(resource: &Cert<D>) -> Self::Prerequisites {
  101. (
  102. Csr(resource.0.clone()),
  103. AcmeRootCert,
  104. AcmeAccountKey,
  105. AcmeChallengesDir,
  106. AcmeUser,
  107. DefaultServer,
  108. )
  109. }
  110. type Implementation =
  111. CertSymbol<SetuidCommandRunner<Rc<str>>, SetuidCommandRunner<Rc<str>>, D, Rc<Path>>;
  112. fn create(
  113. resource: &Cert<D>,
  114. target: &<Cert<D> as Resource>::Artifact,
  115. (csr, root_cert, account_key, challenges_dir, (user_name, _), _): <Self::Prerequisites as ToArtifact>::Artifact,
  116. ) -> Self::Implementation {
  117. CertSymbol::new(
  118. resource.0.clone(),
  119. SetuidCommandRunner::new(user_name.0),
  120. root_cert.clone_rc(),
  121. account_key.clone_rc(),
  122. challenges_dir.clone_rc(),
  123. csr.clone_rc(),
  124. target.clone_rc(),
  125. )
  126. }
  127. }
  128. impl<D: Clone> ImplementationBuilder<CertChain<D>> for DefaultBuilder {
  129. type Prerequisites = (Cert<D>, AcmeRootCert);
  130. fn prerequisites(resource: &CertChain<D>) -> Self::Prerequisites {
  131. (Cert(resource.0.clone()), AcmeRootCert)
  132. }
  133. type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>;
  134. fn create(
  135. _resource: &CertChain<D>,
  136. target: &<CertChain<D> as Resource>::Artifact,
  137. (cert, root_cert): <Self::Prerequisites as ToArtifact>::Artifact,
  138. ) -> Self::Implementation {
  139. ConcatSymbol::new([cert.clone_rc(), root_cert.clone_rc()], target.clone_rc())
  140. }
  141. }
  142. impl<D: Clone> ImplementationBuilder<KeyAndCertBundle<D>> for DefaultBuilder {
  143. type Prerequisites = (CertChain<D>, Key<D>);
  144. fn prerequisites(resource: &KeyAndCertBundle<D>) -> Self::Prerequisites {
  145. (CertChain(resource.0.clone()), Key(resource.0.clone()))
  146. }
  147. type Implementation = ConcatSymbol<[Rc<Path>; 2], Rc<Path>, Rc<Path>>;
  148. fn create(
  149. _resource: &KeyAndCertBundle<D>,
  150. target: &<KeyAndCertBundle<D> as Resource>::Artifact,
  151. (cert_chain, key): <Self::Prerequisites as ToArtifact>::Artifact,
  152. ) -> Self::Implementation {
  153. ConcatSymbol::new([key.clone_rc(), cert_chain.clone_rc()], target.clone_rc())
  154. }
  155. }
  156. impl<P: AsRef<Path> + Clone> ImplementationBuilder<File<P>> for DefaultBuilder {
  157. type Prerequisites = ();
  158. fn prerequisites(_resource: &File<P>) -> Self::Prerequisites {}
  159. type Implementation = FileSymbol<P, Rc<str>>;
  160. fn create(
  161. resource: &File<P>,
  162. _target: &<File<P> as Resource>::Artifact,
  163. (): <Self::Prerequisites as ToArtifact>::Artifact,
  164. ) -> Self::Implementation {
  165. FileSymbol::new(resource.0.clone(), resource.1.clone())
  166. }
  167. }
  168. impl<'a, P: AsRef<Path> + Clone> ImplementationBuilder<GitCheckout<'a, P>> for DefaultBuilder {
  169. type Prerequisites = ();
  170. fn prerequisites(_resource: &GitCheckout<'a, P>) -> Self::Prerequisites {}
  171. type Implementation = GitCheckoutSymbol<StdCommandRunner, StdCommandRunner, P, &'a str, &'a str>;
  172. fn create(
  173. resource: &GitCheckout<'a, P>,
  174. _target: &<GitCheckout<'a, P> as Resource>::Artifact,
  175. (): <Self::Prerequisites as ToArtifact>::Artifact,
  176. ) -> Self::Implementation {
  177. GitCheckoutSymbol::new(resource.0.clone(), resource.1, resource.2, StdCommandRunner)
  178. }
  179. }
  180. impl ImplementationBuilder<DefaultServer> for DefaultBuilder {
  181. type Prerequisites = AcmeChallengesNginxSnippet;
  182. fn prerequisites(_resource: &DefaultServer) -> Self::Prerequisites {
  183. AcmeChallengesNginxSnippet
  184. }
  185. type Implementation = (
  186. FileSymbol<Rc<Path>, Box<str>>,
  187. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  188. );
  189. fn create(
  190. _resource: &DefaultServer,
  191. target: &<DefaultServer as Resource>::Artifact,
  192. challenges_snippet_path: <Self::Prerequisites as ToArtifact>::Artifact,
  193. ) -> Self::Implementation {
  194. (
  195. FileSymbol::new(
  196. target.clone_rc(),
  197. nginx::default_server(challenges_snippet_path).into(),
  198. ),
  199. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  200. )
  201. }
  202. }
  203. impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeCustom<D>> for DefaultBuilder {
  204. type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
  205. fn prerequisites(resource: &ServeCustom<D>) -> Self::Prerequisites {
  206. (
  207. CertChain(resource.0.clone()),
  208. Key(resource.0.clone()),
  209. AcmeChallengesNginxSnippet,
  210. )
  211. }
  212. type Implementation = (
  213. FileSymbol<Rc<Path>, Box<str>>,
  214. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  215. );
  216. fn create(
  217. resource: &ServeCustom<D>,
  218. target: &<ServeCustom<D> as Resource>::Artifact,
  219. (cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
  220. ) -> Self::Implementation {
  221. (
  222. FileSymbol::new(
  223. target.clone_rc(),
  224. nginx::server_config(&resource.0, cert, key, &resource.1, challenges_snippet_path).into(),
  225. ),
  226. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  227. )
  228. }
  229. }
  230. impl<D: Clone + Display, P: AsRef<Path>, C: Clone + Into<PhpFpmPoolConfig>>
  231. ImplementationBuilder<ServePhp<D, P, C>> for DefaultBuilder
  232. {
  233. type Prerequisites = (
  234. PhpFpmPool<D>,
  235. CertChain<D>,
  236. Key<D>,
  237. AcmeChallengesNginxSnippet,
  238. );
  239. fn prerequisites(resource: &ServePhp<D, P, C>) -> Self::Prerequisites {
  240. (
  241. PhpFpmPool(resource.0.clone(), resource.4.clone().into()),
  242. CertChain(resource.0.clone()),
  243. Key(resource.0.clone()),
  244. AcmeChallengesNginxSnippet,
  245. )
  246. }
  247. type Implementation = (
  248. FileSymbol<Rc<Path>, Box<str>>,
  249. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  250. );
  251. fn create(
  252. resource: &ServePhp<D, P, C>,
  253. target: &<ServePhp<D, P, C> as Resource>::Artifact,
  254. (pool, cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
  255. ) -> Self::Implementation {
  256. (
  257. FileSymbol::new(
  258. target.clone_rc(),
  259. nginx::server_config(
  260. &resource.0,
  261. cert,
  262. key,
  263. nginx::php_snippet(resource.2, pool.0, &resource.1) + &resource.3,
  264. challenges_snippet_path,
  265. )
  266. .into(),
  267. ),
  268. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  269. )
  270. }
  271. }
  272. impl<D: Clone + Display, P: Clone + AsRef<Path>> ImplementationBuilder<ServeService<D, P>>
  273. for DefaultBuilder
  274. {
  275. type Prerequisites = (
  276. SystemdSocketService<D, P>,
  277. CertChain<D>,
  278. Key<D>,
  279. AcmeChallengesNginxSnippet,
  280. );
  281. fn prerequisites(resource: &ServeService<D, P>) -> Self::Prerequisites {
  282. (
  283. SystemdSocketService(
  284. resource.0.clone(),
  285. resource.1,
  286. resource.2.clone(),
  287. resource.4.clone(),
  288. resource.5,
  289. ),
  290. CertChain(resource.0.clone()),
  291. Key(resource.0.clone()),
  292. AcmeChallengesNginxSnippet,
  293. )
  294. }
  295. type Implementation = (
  296. FileSymbol<Rc<Path>, Box<str>>,
  297. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  298. );
  299. fn create(
  300. resource: &ServeService<D, P>,
  301. target: &<ServeService<D, P> as Resource>::Artifact,
  302. (socket, cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
  303. ) -> Self::Implementation {
  304. (
  305. FileSymbol::new(
  306. target.clone_rc(),
  307. nginx::server_config(
  308. &resource.0,
  309. cert,
  310. key,
  311. nginx::proxy_snippet(&socket.0, &resource.3),
  312. challenges_snippet_path,
  313. )
  314. .into(),
  315. ),
  316. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  317. )
  318. }
  319. }
  320. impl<D: AsRef<str> + Clone + Display> ImplementationBuilder<ServeRedir<D>> for DefaultBuilder {
  321. type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
  322. fn prerequisites(resource: &ServeRedir<D>) -> Self::Prerequisites {
  323. (
  324. CertChain(resource.0.clone()),
  325. Key(resource.0.clone()),
  326. AcmeChallengesNginxSnippet,
  327. )
  328. }
  329. type Implementation = (
  330. FileSymbol<Rc<Path>, Box<str>>,
  331. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  332. );
  333. fn create(
  334. resource: &ServeRedir<D>,
  335. target: &<ServeRedir<D> as Resource>::Artifact,
  336. (cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
  337. ) -> Self::Implementation {
  338. (
  339. FileSymbol::new(
  340. target.clone_rc(),
  341. nginx::server_config(
  342. &resource.0,
  343. cert,
  344. key,
  345. nginx::redir_snippet(resource.1.as_ref()),
  346. challenges_snippet_path,
  347. )
  348. .into(),
  349. ),
  350. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  351. )
  352. }
  353. }
  354. impl<D: AsRef<str> + Clone + Display, P: AsRef<Path>> ImplementationBuilder<ServeStatic<D, P>>
  355. for DefaultBuilder
  356. {
  357. type Prerequisites = (CertChain<D>, Key<D>, AcmeChallengesNginxSnippet);
  358. fn prerequisites(resource: &ServeStatic<D, P>) -> Self::Prerequisites {
  359. (
  360. CertChain(resource.0.clone()),
  361. Key(resource.0.clone()),
  362. AcmeChallengesNginxSnippet,
  363. )
  364. }
  365. type Implementation = (
  366. FileSymbol<Rc<Path>, Box<str>>,
  367. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, &'static str>,
  368. );
  369. fn create(
  370. resource: &ServeStatic<D, P>,
  371. target: &<ServeStatic<D, P> as Resource>::Artifact,
  372. (cert, key, challenges_snippet_path): <Self::Prerequisites as ToArtifact>::Artifact,
  373. ) -> Self::Implementation {
  374. (
  375. FileSymbol::new(
  376. target.clone_rc(),
  377. nginx::server_config(
  378. &resource.0,
  379. cert,
  380. key,
  381. nginx::static_snippet(resource.1.as_ref()),
  382. challenges_snippet_path,
  383. )
  384. .into(),
  385. ),
  386. ReloadServiceSymbol::new(StdCommandRunner, "nginx"),
  387. )
  388. }
  389. }
  390. impl<D: Clone> ImplementationBuilder<PhpFpmPool<D>> for DefaultBuilder {
  391. type Prerequisites = ();
  392. fn prerequisites(_resource: &PhpFpmPool<D>) -> Self::Prerequisites {}
  393. type Implementation = (
  394. FileSymbol<Rc<Path>, Box<str>>,
  395. ReloadServiceSymbol<StdCommandRunner, StdCommandRunner, Rc<str>>,
  396. );
  397. fn create(
  398. resource: &PhpFpmPool<D>,
  399. (socket_path, conf_path, user_name, service_name): &<PhpFpmPool<D> as Resource>::Artifact,
  400. (): <Self::Prerequisites as ToArtifact>::Artifact,
  401. ) -> Self::Implementation {
  402. (
  403. FileSymbol::new(
  404. conf_path.clone_rc(),
  405. php_fpm_pool_config(&user_name.0, socket_path, &resource.1).into(),
  406. ),
  407. ReloadServiceSymbol::new(StdCommandRunner, service_name.0.clone()),
  408. )
  409. }
  410. }
  411. impl<D, P: AsRef<Path>> ImplementationBuilder<SystemdSocketService<D, P>> for DefaultBuilder {
  412. type Prerequisites = ();
  413. fn prerequisites(_resource: &SystemdSocketService<D, P>) -> Self::Prerequisites {}
  414. type Implementation = (
  415. // First three could be parallel
  416. FileSymbol<Rc<Path>, Box<str>>,
  417. SystemdUserSessionSymbol<'static, Rc<str>, StdCommandRunner>,
  418. OwnerSymbol<StdCommandRunner, StdCommandRunner, Box<Path>, Rc<str>>,
  419. UserServiceSymbol<'static, Rc<Path>, Rc<str>>,
  420. );
  421. fn create(
  422. resource: &SystemdSocketService<D, P>,
  423. (socket_path, conf_path, user_name): &<SystemdSocketService<D, P> as Resource>::Artifact,
  424. (): <Self::Prerequisites as ToArtifact>::Artifact,
  425. ) -> Self::Implementation {
  426. (
  427. FileSymbol::new(
  428. conf_path.clone_rc(),
  429. if resource.4 {
  430. systemd_nodejs_service(&resource.2, socket_path, &resource.3)
  431. } else {
  432. systemd_socket_service(
  433. socket_path,
  434. resource.2.as_ref().to_str().unwrap(),
  435. &resource.3,
  436. "",
  437. )
  438. }
  439. .into(),
  440. ),
  441. SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner),
  442. OwnerSymbol::new(
  443. conf_path.as_ref().parent().unwrap().into(),
  444. user_name.0.clone(),
  445. StdCommandRunner,
  446. ),
  447. UserServiceSymbol::new(socket_path.clone_rc(), user_name.0.clone(), resource.1),
  448. )
  449. }
  450. }
  451. impl<P: Clone> ImplementationBuilder<Dir<P>> for DefaultBuilder {
  452. type Prerequisites = ();
  453. fn prerequisites(_resource: &Dir<P>) -> Self::Prerequisites {}
  454. type Implementation = DirSymbol<P>;
  455. fn create(
  456. resource: &Dir<P>,
  457. _target: &<Dir<P> as Resource>::Artifact,
  458. (): <Self::Prerequisites as ToArtifact>::Artifact,
  459. ) -> Self::Implementation {
  460. DirSymbol::new(resource.0.clone())
  461. }
  462. }
  463. impl<P: Clone + AsRef<Path>> ImplementationBuilder<NpmInstall<P>> for DefaultBuilder {
  464. type Prerequisites = ();
  465. fn prerequisites(_resource: &NpmInstall<P>) -> Self::Prerequisites {}
  466. type Implementation = NpmInstallSymbol<'static, P, StdCommandRunner>;
  467. fn create(
  468. resource: &NpmInstall<P>,
  469. _target: &<NpmInstall<P> as Resource>::Artifact,
  470. (): <Self::Prerequisites as ToArtifact>::Artifact,
  471. ) -> Self::Implementation {
  472. NpmInstallSymbol::new(resource.0.clone(), &StdCommandRunner)
  473. }
  474. }
  475. impl<P: Clone + AsRef<Path>> ImplementationBuilder<StoredDirectory<P>> for DefaultBuilder {
  476. type Prerequisites = ();
  477. fn prerequisites(_resource: &StoredDirectory<P>) -> Self::Prerequisites {}
  478. type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
  479. fn create(
  480. resource: &StoredDirectory<P>,
  481. target: &<StoredDirectory<P> as Resource>::Artifact,
  482. (): <Self::Prerequisites as ToArtifact>::Artifact,
  483. ) -> Self::Implementation {
  484. SavedDirectorySymbol::new(
  485. resource.1.clone(),
  486. SimpleStorage::new(target.clone_rc()),
  487. StorageDirection::Store,
  488. StdCommandRunner,
  489. )
  490. }
  491. }
  492. impl<P: Clone + AsRef<Path>> ImplementationBuilder<LoadedDirectory<P>> for DefaultBuilder {
  493. type Prerequisites = ();
  494. fn prerequisites(_resource: &LoadedDirectory<P>) -> Self::Prerequisites {}
  495. type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
  496. fn create(
  497. resource: &LoadedDirectory<P>,
  498. target: &<LoadedDirectory<P> as Resource>::Artifact,
  499. (): <Self::Prerequisites as ToArtifact>::Artifact,
  500. ) -> Self::Implementation {
  501. SavedDirectorySymbol::new(
  502. resource.1.clone(),
  503. SimpleStorage::new(target.clone_rc()),
  504. StorageDirection::Load,
  505. StdCommandRunner,
  506. )
  507. }
  508. }
  509. impl<D: Clone> ImplementationBuilder<UserForDomain<D>> for DefaultBuilder {
  510. type Prerequisites = ();
  511. fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {}
  512. type Implementation = UserSymbol<Rc<str>, Rc<Path>, StdCommandRunner>;
  513. fn create(
  514. _resource: &UserForDomain<D>,
  515. (user_name, home_path): &<UserForDomain<D> as Resource>::Artifact,
  516. (): <Self::Prerequisites as ToArtifact>::Artifact,
  517. ) -> Self::Implementation {
  518. UserSymbol::new(user_name.0.clone(), home_path.into(), StdCommandRunner)
  519. }
  520. }
  521. impl ImplementationBuilder<User> for DefaultBuilder {
  522. type Prerequisites = ();
  523. fn prerequisites(_resource: &User) -> Self::Prerequisites {}
  524. type Implementation = UserSymbol<Rc<str>, Rc<Path>, StdCommandRunner>;
  525. fn create(
  526. resource: &User,
  527. home_path: &<User as Resource>::Artifact,
  528. (): <Self::Prerequisites as ToArtifact>::Artifact,
  529. ) -> Self::Implementation {
  530. UserSymbol::new(resource.0.clone(), home_path.into(), StdCommandRunner)
  531. }
  532. }
  533. impl<P: AsRef<Path> + Clone> ImplementationBuilder<Owner<P>> for DefaultBuilder {
  534. type Prerequisites = ();
  535. fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {}
  536. type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, Rc<str>>;
  537. fn create(
  538. resource: &Owner<P>,
  539. (): &<Owner<P> as Resource>::Artifact,
  540. (): <Self::Prerequisites as ToArtifact>::Artifact,
  541. ) -> Self::Implementation {
  542. OwnerSymbol::new(resource.1.clone(), resource.0.clone(), StdCommandRunner)
  543. }
  544. }
  545. impl ImplementationBuilder<AcmeUser> for DefaultBuilder {
  546. type Prerequisites = ();
  547. fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {}
  548. type Implementation = UserSymbol<Rc<str>, Rc<Path>, StdCommandRunner>;
  549. fn create(
  550. _resource: &AcmeUser,
  551. (user_name, home_path): &<AcmeUser as Resource>::Artifact,
  552. (): <Self::Prerequisites as ToArtifact>::Artifact,
  553. ) -> Self::Implementation {
  554. UserSymbol::new(user_name.0.clone(), home_path.into(), StdCommandRunner)
  555. }
  556. }
  557. impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
  558. type Prerequisites = AcmeUser;
  559. fn prerequisites(_resource: &AcmeChallengesDir) -> Self::Prerequisites {
  560. AcmeUser
  561. }
  562. type Implementation = (
  563. DirSymbol<Rc<Path>>,
  564. OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>,
  565. );
  566. fn create(
  567. _resource: &AcmeChallengesDir,
  568. target: &<AcmeChallengesDir as Resource>::Artifact,
  569. (user_name, _): <Self::Prerequisites as ToArtifact>::Artifact,
  570. ) -> Self::Implementation {
  571. (
  572. DirSymbol::new(target.clone_rc()),
  573. OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner),
  574. )
  575. }
  576. }
  577. impl ImplementationBuilder<AcmeChallengesNginxSnippet> for DefaultBuilder {
  578. type Prerequisites = AcmeChallengesDir;
  579. fn prerequisites(_resource: &AcmeChallengesNginxSnippet) -> Self::Prerequisites {
  580. AcmeChallengesDir
  581. }
  582. type Implementation = FileSymbol<Rc<Path>, Box<str>>;
  583. fn create(
  584. _resource: &AcmeChallengesNginxSnippet,
  585. target: &<AcmeChallengesNginxSnippet as Resource>::Artifact,
  586. challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact,
  587. ) -> Self::Implementation {
  588. FileSymbol::new(
  589. target.clone_rc(),
  590. nginx::acme_challenges_snippet(challenges_dir).into(),
  591. )
  592. }
  593. }
  594. impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
  595. type Prerequisites = AcmeUser;
  596. fn prerequisites(_resource: &AcmeAccountKey) -> Self::Prerequisites {
  597. AcmeUser
  598. }
  599. type Implementation = (
  600. KeySymbol<StdCommandRunner, Rc<Path>>,
  601. OwnerSymbol<StdCommandRunner, StdCommandRunner, Rc<Path>, Rc<str>>,
  602. );
  603. fn create(
  604. _resource: &AcmeAccountKey,
  605. target: &<AcmeAccountKey as Resource>::Artifact,
  606. (user_name, _): <Self::Prerequisites as ToArtifact>::Artifact,
  607. ) -> Self::Implementation {
  608. (
  609. KeySymbol::new(StdCommandRunner, target.clone_rc()),
  610. OwnerSymbol::new(target.clone_rc(), user_name.0, StdCommandRunner),
  611. )
  612. }
  613. }
  614. impl ImplementationBuilder<AcmeRootCert> for DefaultBuilder {
  615. type Prerequisites = ();
  616. fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {}
  617. type Implementation = FileSymbol<Rc<Path>, &'static str>;
  618. fn create(
  619. _resource: &AcmeRootCert,
  620. target: &<AcmeRootCert as Resource>::Artifact,
  621. (): <Self::Prerequisites as ToArtifact>::Artifact,
  622. ) -> Self::Implementation {
  623. FileSymbol::new(target.clone_rc(), LETS_ENCRYPT_R3)
  624. }
  625. }
  626. impl<D> ImplementationBuilder<MariaDbUser<D>> for DefaultBuilder {
  627. type Prerequisites = ();
  628. fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {}
  629. type Implementation = MariaDbUserSymbol<'static, Rc<str>, StdCommandRunner>;
  630. fn create(
  631. _resource: &MariaDbUser<D>,
  632. user_name: &<MariaDbUser<D> as Resource>::Artifact,
  633. _: <Self::Prerequisites as ToArtifact>::Artifact,
  634. ) -> Self::Implementation {
  635. MariaDbUserSymbol::new(user_name.0.clone(), &StdCommandRunner)
  636. }
  637. }
  638. impl<D: Clone> ImplementationBuilder<MariaDbDatabase<D>> for DefaultBuilder {
  639. type Prerequisites = MariaDbUser<D>;
  640. fn prerequisites(resource: &MariaDbDatabase<D>) -> Self::Prerequisites {
  641. MariaDbUser(resource.0.clone())
  642. }
  643. type Implementation = (
  644. MariaDbDatabaseSymbol<'static, Rc<str>, SimpleStorage, StdCommandRunner>,
  645. MariaDbDumpSymbol<'static, Rc<str>, StdCommandRunner, SimpleStorage>,
  646. );
  647. fn create(
  648. _resource: &MariaDbDatabase<D>,
  649. (db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact,
  650. _: <Self::Prerequisites as ToArtifact>::Artifact,
  651. ) -> Self::Implementation {
  652. let db_dump = SimpleStorage::new(data_path.clone_rc());
  653. (
  654. MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner),
  655. MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner),
  656. )
  657. }
  658. }
  659. impl<D: Clone> ImplementationBuilder<PostgresqlDatabase<D>> for DefaultBuilder {
  660. type Prerequisites = ();
  661. fn prerequisites(_: &PostgresqlDatabase<D>) -> Self::Prerequisites {}
  662. type Implementation = (PostgreSQLDatabaseSymbol<'static, Rc<str>, Rc<str>, StdCommandRunner>,);
  663. fn create(
  664. _resource: &PostgresqlDatabase<D>,
  665. (db_name, data_path): &<PostgresqlDatabase<D> as Resource>::Artifact,
  666. _: <Self::Prerequisites as ToArtifact>::Artifact,
  667. ) -> Self::Implementation {
  668. let db_dump = SimpleStorage::new(data_path.clone_rc());
  669. (PostgreSQLDatabaseSymbol::new(
  670. db_name.0.clone(),
  671. db_dump.read_filename().unwrap().to_str().unwrap().into(),
  672. &StdCommandRunner,
  673. ),)
  674. }
  675. }
  676. impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder {
  677. type Prerequisites = Dir<Rc<Path>>;
  678. fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites {
  679. Dir::new(resource.0.as_ref().join("wp-content/plugins"))
  680. }
  681. type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>;
  682. fn create(
  683. resource: &WordpressPlugin<P>,
  684. (): &<WordpressPlugin<P> as Resource>::Artifact,
  685. _: <Self::Prerequisites as ToArtifact>::Artifact,
  686. ) -> Self::Implementation {
  687. WordpressPluginSymbol::new(resource.0.clone(), resource.1, &StdCommandRunner)
  688. }
  689. }
  690. impl<P: AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
  691. type Prerequisites = Dir<Rc<Path>>;
  692. fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites {
  693. Dir::new(resource.0.as_ref().join("wp-content/languages"))
  694. }
  695. type Implementation =
  696. WordpressTranslationSymbol<'static, &'static str, Box<Path>, StdCommandRunner>;
  697. fn create(
  698. resource: &WordpressTranslation<P>,
  699. (): &<WordpressTranslation<P> as Resource>::Artifact,
  700. _: <Self::Prerequisites as ToArtifact>::Artifact,
  701. ) -> Self::Implementation {
  702. WordpressTranslationSymbol::new(
  703. (*resource.0.as_ref().join("wp-content/languages")).into(),
  704. resource.1,
  705. resource.2,
  706. &StdCommandRunner,
  707. )
  708. }
  709. }
  710. impl<D: Clone> ImplementationBuilder<Cron<D>> for DefaultBuilder {
  711. type Prerequisites = UserForDomain<D>;
  712. fn prerequisites(resource: &Cron<D>) -> Self::Prerequisites {
  713. UserForDomain(resource.0.clone())
  714. }
  715. type Implementation = CronSymbol<'static, Box<[u8]>, Rc<str>, StdCommandRunner>;
  716. fn create(
  717. resource: &Cron<D>,
  718. (): &<Cron<D> as Resource>::Artifact,
  719. user_name: <Self::Prerequisites as ToArtifact>::Artifact,
  720. ) -> Self::Implementation {
  721. CronSymbol::new((user_name.0).0, &resource.1, &StdCommandRunner)
  722. }
  723. }