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

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