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.

770 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. // First three could be parallel
  409. FileSymbol<PathBuf, String>,
  410. SystemdUserSessionSymbol<'static, String, StdCommandRunner>,
  411. OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
  412. UserServiceSymbol<'static, PathBuf, String, StdCommandRunner>,
  413. );
  414. fn create(
  415. resource: &SystemdSocketService<D, P>,
  416. (socket_path, conf_path, user_name): &<SystemdSocketService<D, P> as Resource>::Artifact,
  417. (): <Self::Prerequisites as ToArtifact>::Artifact,
  418. ) -> Self::Implementation {
  419. (
  420. FileSymbol::new(
  421. conf_path.clone().into(),
  422. if resource.4 {
  423. systemd_nodejs_service(&resource.2, socket_path, &resource.3)
  424. } else {
  425. systemd_socket_service(
  426. socket_path,
  427. resource.2.as_ref().to_str().unwrap(),
  428. &resource.3,
  429. "",
  430. )
  431. },
  432. ),
  433. SystemdUserSessionSymbol::new(user_name.0.clone(), &StdCommandRunner),
  434. OwnerSymbol::new(
  435. conf_path.as_ref().parent().unwrap().to_path_buf(),
  436. user_name.0.clone(),
  437. StdCommandRunner,
  438. ),
  439. UserServiceSymbol::new(
  440. socket_path.clone().into(),
  441. user_name.0.clone(),
  442. resource.1,
  443. &StdCommandRunner,
  444. ),
  445. )
  446. }
  447. }
  448. impl<P: Clone> ImplementationBuilder<Dir<P>> for DefaultBuilder {
  449. type Prerequisites = ();
  450. fn prerequisites(_resource: &Dir<P>) -> Self::Prerequisites {}
  451. type Implementation = DirSymbol<P>;
  452. fn create(
  453. resource: &Dir<P>,
  454. _target: &<Dir<P> as Resource>::Artifact,
  455. (): <Self::Prerequisites as ToArtifact>::Artifact,
  456. ) -> Self::Implementation {
  457. DirSymbol::new(resource.0.clone())
  458. }
  459. }
  460. impl<P: Clone + AsRef<Path>> ImplementationBuilder<NpmInstall<P>> for DefaultBuilder {
  461. type Prerequisites = ();
  462. fn prerequisites(_resource: &NpmInstall<P>) -> Self::Prerequisites {}
  463. type Implementation = NpmInstallSymbol<'static, P, StdCommandRunner>;
  464. fn create(
  465. resource: &NpmInstall<P>,
  466. _target: &<NpmInstall<P> as Resource>::Artifact,
  467. (): <Self::Prerequisites as ToArtifact>::Artifact,
  468. ) -> Self::Implementation {
  469. NpmInstallSymbol::new(resource.0.clone(), &StdCommandRunner)
  470. }
  471. }
  472. impl<P: Clone + AsRef<Path>> ImplementationBuilder<StoredDirectory<P>> for DefaultBuilder {
  473. type Prerequisites = ();
  474. fn prerequisites(_resource: &StoredDirectory<P>) -> Self::Prerequisites {}
  475. type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
  476. fn create(
  477. resource: &StoredDirectory<P>,
  478. target: &<StoredDirectory<P> as Resource>::Artifact,
  479. (): <Self::Prerequisites as ToArtifact>::Artifact,
  480. ) -> Self::Implementation {
  481. SavedDirectorySymbol::new(
  482. resource.1.clone(),
  483. SimpleStorage::new(target.clone().into()),
  484. StorageDirection::Store,
  485. StdCommandRunner,
  486. )
  487. }
  488. }
  489. impl<P: Clone + AsRef<Path>> ImplementationBuilder<LoadedDirectory<P>> for DefaultBuilder {
  490. type Prerequisites = ();
  491. fn prerequisites(_resource: &LoadedDirectory<P>) -> Self::Prerequisites {}
  492. type Implementation = SavedDirectorySymbol<StdCommandRunner, StdCommandRunner, P, SimpleStorage>;
  493. fn create(
  494. resource: &LoadedDirectory<P>,
  495. target: &<LoadedDirectory<P> as Resource>::Artifact,
  496. (): <Self::Prerequisites as ToArtifact>::Artifact,
  497. ) -> Self::Implementation {
  498. SavedDirectorySymbol::new(
  499. resource.1.clone(),
  500. SimpleStorage::new(target.clone().into()),
  501. StorageDirection::Load,
  502. StdCommandRunner,
  503. )
  504. }
  505. }
  506. impl<D: Clone> ImplementationBuilder<UserForDomain<D>> for DefaultBuilder {
  507. type Prerequisites = ();
  508. fn prerequisites(_resource: &UserForDomain<D>) -> Self::Prerequisites {}
  509. type Implementation = UserSymbol<String, StdCommandRunner>;
  510. fn create(
  511. _resource: &UserForDomain<D>,
  512. (user_name, _home_path): &<UserForDomain<D> as Resource>::Artifact,
  513. (): <Self::Prerequisites as ToArtifact>::Artifact,
  514. ) -> Self::Implementation {
  515. UserSymbol::new(user_name.0.clone(), StdCommandRunner)
  516. }
  517. }
  518. impl ImplementationBuilder<User> for DefaultBuilder {
  519. type Prerequisites = ();
  520. fn prerequisites(_resource: &User) -> Self::Prerequisites {}
  521. type Implementation = UserSymbol<String, StdCommandRunner>;
  522. fn create(
  523. resource: &User,
  524. (): &<User as Resource>::Artifact,
  525. (): <Self::Prerequisites as ToArtifact>::Artifact,
  526. ) -> Self::Implementation {
  527. UserSymbol::new(resource.0.clone(), StdCommandRunner)
  528. }
  529. }
  530. impl<P: AsRef<Path> + Clone> ImplementationBuilder<Owner<P>> for DefaultBuilder {
  531. type Prerequisites = ();
  532. fn prerequisites(_resource: &Owner<P>) -> Self::Prerequisites {}
  533. type Implementation = OwnerSymbol<StdCommandRunner, StdCommandRunner, P, String>;
  534. fn create(
  535. resource: &Owner<P>,
  536. (): &<Owner<P> as Resource>::Artifact,
  537. (): <Self::Prerequisites as ToArtifact>::Artifact,
  538. ) -> Self::Implementation {
  539. OwnerSymbol::new(resource.1.clone(), resource.0.clone(), StdCommandRunner)
  540. }
  541. }
  542. impl ImplementationBuilder<AcmeUser> for DefaultBuilder {
  543. type Prerequisites = ();
  544. fn prerequisites(_resource: &AcmeUser) -> Self::Prerequisites {}
  545. type Implementation = UserSymbol<String, StdCommandRunner>;
  546. fn create(
  547. _resource: &AcmeUser,
  548. user_name: &<AcmeUser as Resource>::Artifact,
  549. (): <Self::Prerequisites as ToArtifact>::Artifact,
  550. ) -> Self::Implementation {
  551. UserSymbol::new(user_name.0.clone(), StdCommandRunner)
  552. }
  553. }
  554. impl ImplementationBuilder<AcmeChallengesDir> for DefaultBuilder {
  555. type Prerequisites = AcmeUser;
  556. fn prerequisites(_resource: &AcmeChallengesDir) -> Self::Prerequisites {
  557. AcmeUser
  558. }
  559. type Implementation = (
  560. DirSymbol<PathBuf>,
  561. OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
  562. );
  563. fn create(
  564. _resource: &AcmeChallengesDir,
  565. target: &<AcmeChallengesDir as Resource>::Artifact,
  566. user_name: <Self::Prerequisites as ToArtifact>::Artifact,
  567. ) -> Self::Implementation {
  568. (
  569. DirSymbol::new(target.clone().into()),
  570. OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
  571. )
  572. }
  573. }
  574. impl ImplementationBuilder<AcmeChallengesNginxSnippet> for DefaultBuilder {
  575. type Prerequisites = AcmeChallengesDir;
  576. fn prerequisites(_resource: &AcmeChallengesNginxSnippet) -> Self::Prerequisites {
  577. AcmeChallengesDir
  578. }
  579. type Implementation = FileSymbol<PathBuf, String>;
  580. fn create(
  581. _resource: &AcmeChallengesNginxSnippet,
  582. target: &<AcmeChallengesNginxSnippet as Resource>::Artifact,
  583. challenges_dir: <Self::Prerequisites as ToArtifact>::Artifact,
  584. ) -> Self::Implementation {
  585. FileSymbol::new(
  586. target.clone().into(),
  587. nginx::acme_challenges_snippet(challenges_dir),
  588. )
  589. }
  590. }
  591. impl ImplementationBuilder<AcmeAccountKey> for DefaultBuilder {
  592. type Prerequisites = AcmeUser;
  593. fn prerequisites(_resource: &AcmeAccountKey) -> Self::Prerequisites {
  594. AcmeUser
  595. }
  596. type Implementation = (
  597. KeySymbol<StdCommandRunner, PathBuf>,
  598. OwnerSymbol<StdCommandRunner, StdCommandRunner, PathBuf, String>,
  599. );
  600. fn create(
  601. _resource: &AcmeAccountKey,
  602. target: &<AcmeAccountKey as Resource>::Artifact,
  603. user_name: <Self::Prerequisites as ToArtifact>::Artifact,
  604. ) -> Self::Implementation {
  605. (
  606. KeySymbol::new(StdCommandRunner, target.clone().into()),
  607. OwnerSymbol::new(target.clone().into(), user_name.0, StdCommandRunner),
  608. )
  609. }
  610. }
  611. impl ImplementationBuilder<AcmeRootCert> for DefaultBuilder {
  612. type Prerequisites = ();
  613. fn prerequisites(_resource: &AcmeRootCert) -> Self::Prerequisites {}
  614. type Implementation = FileSymbol<PathBuf, &'static str>;
  615. fn create(
  616. _resource: &AcmeRootCert,
  617. target: &<AcmeRootCert as Resource>::Artifact,
  618. (): <Self::Prerequisites as ToArtifact>::Artifact,
  619. ) -> Self::Implementation {
  620. FileSymbol::new(target.clone().into(), LETS_ENCRYPT_X3_CROSS_SIGNED)
  621. }
  622. }
  623. impl<D> ImplementationBuilder<MariaDbUser<D>> for DefaultBuilder {
  624. type Prerequisites = ();
  625. fn prerequisites(_resource: &MariaDbUser<D>) -> Self::Prerequisites {}
  626. type Implementation = MariaDbUserSymbol<'static, String, StdCommandRunner>;
  627. fn create(
  628. _resource: &MariaDbUser<D>,
  629. user_name: &<MariaDbUser<D> as Resource>::Artifact,
  630. _: <Self::Prerequisites as ToArtifact>::Artifact,
  631. ) -> Self::Implementation {
  632. MariaDbUserSymbol::new(user_name.0.clone(), &StdCommandRunner)
  633. }
  634. }
  635. impl<D: Clone> ImplementationBuilder<MariaDbDatabase<D>> for DefaultBuilder {
  636. type Prerequisites = MariaDbUser<D>;
  637. fn prerequisites(resource: &MariaDbDatabase<D>) -> Self::Prerequisites {
  638. MariaDbUser(resource.0.clone())
  639. }
  640. type Implementation = (
  641. MariaDbDatabaseSymbol<'static, String, SimpleStorage, StdCommandRunner>,
  642. MariaDbDumpSymbol<'static, String, StdCommandRunner, SimpleStorage>,
  643. );
  644. fn create(
  645. _resource: &MariaDbDatabase<D>,
  646. (db_name, _, data_path): &<MariaDbDatabase<D> as Resource>::Artifact,
  647. _: <Self::Prerequisites as ToArtifact>::Artifact,
  648. ) -> Self::Implementation {
  649. let db_dump = SimpleStorage::new(data_path.clone().into());
  650. (
  651. MariaDbDatabaseSymbol::new(db_name.0.clone(), db_dump.clone(), &StdCommandRunner),
  652. MariaDbDumpSymbol::new(db_name.0.clone(), db_dump, &StdCommandRunner),
  653. )
  654. }
  655. }
  656. impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressPlugin<P>> for DefaultBuilder {
  657. type Prerequisites = Dir<PathBuf>;
  658. fn prerequisites(resource: &WordpressPlugin<P>) -> Self::Prerequisites {
  659. Dir(resource.0.as_ref().join("wp-content/plugins"))
  660. }
  661. type Implementation = WordpressPluginSymbol<'static, P, &'static str, StdCommandRunner>;
  662. fn create(
  663. resource: &WordpressPlugin<P>,
  664. (): &<WordpressPlugin<P> as Resource>::Artifact,
  665. _: <Self::Prerequisites as ToArtifact>::Artifact,
  666. ) -> Self::Implementation {
  667. WordpressPluginSymbol::new(resource.0.clone(), resource.1, &StdCommandRunner)
  668. }
  669. }
  670. impl<P: Clone + AsRef<Path>> ImplementationBuilder<WordpressTranslation<P>> for DefaultBuilder {
  671. type Prerequisites = Dir<PathBuf>;
  672. fn prerequisites(resource: &WordpressTranslation<P>) -> Self::Prerequisites {
  673. Dir(resource.0.as_ref().join("wp-content/languages"))
  674. }
  675. type Implementation =
  676. WordpressTranslationSymbol<'static, &'static str, PathBuf, StdCommandRunner>;
  677. fn create(
  678. resource: &WordpressTranslation<P>,
  679. (): &<WordpressTranslation<P> as Resource>::Artifact,
  680. _: <Self::Prerequisites as ToArtifact>::Artifact,
  681. ) -> Self::Implementation {
  682. WordpressTranslationSymbol::new(
  683. resource.0.as_ref().join("wp-content/languages"),
  684. resource.1,
  685. resource.2,
  686. &StdCommandRunner,
  687. )
  688. }
  689. }
  690. impl<D: Clone> ImplementationBuilder<Cron<D>> for DefaultBuilder {
  691. type Prerequisites = UserForDomain<D>;
  692. fn prerequisites(resource: &Cron<D>) -> Self::Prerequisites {
  693. UserForDomain(resource.0.clone())
  694. }
  695. type Implementation = CronSymbol<'static, String, String, StdCommandRunner>;
  696. fn create(
  697. resource: &Cron<D>,
  698. (): &<Cron<D> as Resource>::Artifact,
  699. user_name: <Self::Prerequisites as ToArtifact>::Artifact,
  700. ) -> Self::Implementation {
  701. CronSymbol::new((user_name.0).0, resource.1.clone(), &StdCommandRunner)
  702. }
  703. }