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.

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