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.

763 lines
24 KiB

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