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.

104 lines
2.4 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. use std::error::Error;
  2. use std::fmt;
  3. use command_runner::CommandRunner;
  4. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  5. pub struct PostgreSQLDatabase<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> {
  6. name: N,
  7. seed_file: S,
  8. command_runner: &'a C,
  9. }
  10. impl<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> PostgreSQLDatabase<'a, N, S, C> {
  11. pub fn new(name: N, seed_file: S, command_runner: &'a C) -> Self {
  12. PostgreSQLDatabase {
  13. name,
  14. seed_file,
  15. command_runner,
  16. }
  17. }
  18. fn run_sql(&self, sql: &str) -> Result<String, Box<dyn Error>> {
  19. let b = self.command_runner.get_output(
  20. "su",
  21. args!["-", "postgres", "-c", format!("psql -t -c \"{}\"", sql)],
  22. )?;
  23. Ok(String::from_utf8(b)?)
  24. }
  25. }
  26. impl<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> fmt::Display
  27. for PostgreSQLDatabase<'a, N, S, C>
  28. {
  29. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  30. write!(f, "PostgreSQL Database {}", self.name.as_ref())
  31. }
  32. }
  33. impl<'a, N: AsRef<str>, S: AsRef<str>, C: CommandRunner> Symbol
  34. for PostgreSQLDatabase<'a, N, S, C>
  35. {
  36. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  37. Ok(
  38. self
  39. .run_sql(&format!(
  40. "SELECT datname FROM pg_database WHERE datname LIKE '{}'",
  41. self.name.as_ref()
  42. ))?
  43. .trim()
  44. == self.name.as_ref(),
  45. )
  46. }
  47. fn execute(&self) -> Result<(), Box<dyn Error>> {
  48. self.command_runner.run_successfully(
  49. "su",
  50. args![
  51. "-",
  52. "postgres",
  53. "-c",
  54. format!("createuser {}", self.name.as_ref())
  55. ],
  56. )?;
  57. self.command_runner.run_successfully(
  58. "su",
  59. args![
  60. "-",
  61. "postgres",
  62. "-c",
  63. format!(
  64. "createdb -E UTF8 -T template0 -O {} {0}",
  65. self.name.as_ref()
  66. ),
  67. ],
  68. )?;
  69. self.command_runner.run_successfully(
  70. "su",
  71. args![
  72. "-",
  73. "postgres",
  74. "-c",
  75. format!(
  76. "psql '{}' < {}",
  77. self.name.as_ref(),
  78. self.seed_file.as_ref()
  79. ),
  80. ],
  81. )
  82. }
  83. fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b> {
  84. Box::new(SymbolAction::new(runner, self))
  85. }
  86. fn into_action<'b>(self: Box<Self>, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b>
  87. where
  88. Self: 'b,
  89. {
  90. Box::new(OwnedSymbolAction::new(runner, *self))
  91. }
  92. }
  93. #[cfg(test)]
  94. mod test {}