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.

125 lines
3.8 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. use regex::Regex;
  2. use crate::command_runner::CommandRunner;
  3. use crate::loggers::StdErrLogger;
  4. use crate::repository::SymbolRepository;
  5. use crate::resources::Resource;
  6. use crate::schema::{
  7. NonRepeatingSymbolRunner, ReportingSymbolRunner, RequirementsResolvingSymbolRunner,
  8. };
  9. use crate::symbols::dir::Dir;
  10. use crate::symbols::list::List;
  11. use crate::symbols::owner::Owner;
  12. use crate::symbols::systemd::user_session::SystemdUserSession;
  13. use crate::symbols::tls::{TlsCsr, TlsKey};
  14. use crate::symbols::user::SystemUserAdder;
  15. use crate::symbols::user::{User, UserAdder};
  16. use crate::symbols::{Symbol, SymbolRunner};
  17. #[derive(Default)]
  18. pub struct Factory {}
  19. impl Factory {
  20. pub fn new() -> Self {
  21. Self::default()
  22. }
  23. pub fn get_repo<'a, CR: CommandRunner>(
  24. &self,
  25. command_runner: &'a CR,
  26. ) -> DefaultSymbolRepository<'a, SystemUserAdder<'a, CR>, CR> {
  27. DefaultSymbolRepository::new(command_runner)
  28. }
  29. pub fn get_symbol_runner<'a, RUNNER: SymbolRunner, REPO: SymbolRepository<'a>>(
  30. &self,
  31. symbol_runner: &'a RUNNER,
  32. repo: &'a REPO,
  33. ) -> Box<dyn 'a + SymbolRunner> {
  34. let runner1 = ReportingSymbolRunner::new(symbol_runner, StdErrLogger);
  35. let runner2 = NonRepeatingSymbolRunner::new(runner1);
  36. Box::new(RequirementsResolvingSymbolRunner::new(runner2, repo))
  37. }
  38. }
  39. pub struct DefaultSymbolRepository<'a, A: 'a + UserAdder, C: CommandRunner> {
  40. user_adder: A,
  41. command_runner: &'a C,
  42. home: Regex,
  43. home_config: Regex,
  44. csr: Regex,
  45. private_key: Regex,
  46. systemd_linger: Regex,
  47. }
  48. impl<'a, C: 'a + CommandRunner> DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C> {
  49. pub fn new(command_runner: &'a C) -> Self {
  50. Self {
  51. command_runner,
  52. user_adder: SystemUserAdder::new(command_runner),
  53. home: Regex::new("^/home/([^/]+)$").unwrap(),
  54. home_config: Regex::new("^/home/([^/]+)/.config(?:/|$)").unwrap(),
  55. csr: Regex::new("^/etc/ssl/local_certs/([^/]+).csr$").unwrap(),
  56. private_key: Regex::new("^/etc/ssl/private/([^/]+).key$").unwrap(),
  57. systemd_linger: Regex::new("^/var/lib/systemd/linger/([^/]+)$").unwrap(),
  58. }
  59. }
  60. }
  61. impl<'a, C: CommandRunner> SymbolRepository<'a>
  62. for DefaultSymbolRepository<'a, SystemUserAdder<'a, C>, C>
  63. {
  64. fn get_symbol(&'a self, resource: &Resource) -> Option<Box<dyn Symbol + 'a>> {
  65. match resource.get_type() {
  66. "user" => Some(Box::new(User::new(
  67. resource.get_value().to_string().into(),
  68. self.command_runner,
  69. &self.user_adder,
  70. ))),
  71. "dir" => {
  72. let value = resource.get_value();
  73. Some(if let Some(matches) = self.home_config.captures(value) {
  74. Box::new(List::new(vec![
  75. Box::new(Dir::new(value.to_string())),
  76. Box::new(Owner::new(
  77. value.to_string(),
  78. matches[1].to_string(),
  79. self.command_runner,
  80. )),
  81. ]))
  82. } else if let Some(matches) = self.home.captures(value) {
  83. Box::new(User::new(
  84. matches[1].to_string().into(),
  85. self.command_runner,
  86. &self.user_adder,
  87. ))
  88. } else {
  89. Box::new(Dir::new(value.to_string()))
  90. })
  91. }
  92. "file" => {
  93. let value = resource.get_value();
  94. if let Some(matches) = self.csr.captures(value) {
  95. Some(Box::new(TlsCsr::new(
  96. matches[1].to_string().into(),
  97. self.command_runner,
  98. )))
  99. } else if let Some(matches) = self.private_key.captures(value) {
  100. Some(Box::new(TlsKey::new(
  101. matches[1].to_string().into(),
  102. self.command_runner,
  103. )))
  104. } else if let Some(matches) = self.systemd_linger.captures(value) {
  105. Some(Box::new(SystemdUserSession::new(
  106. matches[1].to_string(),
  107. self.command_runner,
  108. )))
  109. } else {
  110. None
  111. }
  112. }
  113. _ => None,
  114. }
  115. }
  116. }