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.

278 lines
7.1 KiB

7 years ago
8 years ago
8 years ago
8 years ago
5 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
7 years ago
5 years ago
8 years ago
7 years ago
5 years ago
7 years ago
8 years ago
7 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
8 years ago
7 years ago
5 years ago
7 years ago
8 years ago
7 years ago
5 years ago
7 years ago
7 years ago
8 years ago
7 years ago
5 years ago
7 years ago
5 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
8 years ago
5 years ago
5 years ago
8 years ago
5 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
5 years ago
8 years ago
8 years ago
5 years ago
8 years ago
  1. use crate::loggers::Logger;
  2. use crate::symbols::Symbol;
  3. use std::cell::RefCell;
  4. use std::error::Error;
  5. use std::fmt;
  6. use std::fmt::Debug;
  7. pub trait SymbolRunner {
  8. fn run_symbol<S: Symbol + Debug>(&self, symbol: &S, force: bool) -> Result<bool, Box<dyn Error>>;
  9. }
  10. impl<R: SymbolRunner + ?Sized> SymbolRunner for Box<R> {
  11. fn run_symbol<S: Symbol + Debug>(&self, symbol: &S, force: bool) -> Result<bool, Box<dyn Error>> {
  12. (**self).run_symbol(symbol, force)
  13. }
  14. }
  15. #[derive(Debug)]
  16. pub enum SymbolRunError {
  17. Symbol(Box<dyn Error>),
  18. ExecuteDidNotReach(()),
  19. }
  20. impl Error for SymbolRunError {
  21. fn description(&self) -> &str {
  22. match self {
  23. Self::Symbol(_) => "Symbol execution error",
  24. Self::ExecuteDidNotReach(_) => "Target not reached after executing symbol",
  25. }
  26. }
  27. fn cause(&self) -> Option<&dyn Error> {
  28. match self {
  29. Self::Symbol(ref e) => Some(&**e),
  30. Self::ExecuteDidNotReach(_) => None,
  31. }
  32. }
  33. }
  34. impl fmt::Display for SymbolRunError {
  35. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  36. match self {
  37. Self::Symbol(ref e) => write!(f, "{}", e),
  38. Self::ExecuteDidNotReach(_) => write!(f, "{}", self.description()),
  39. }
  40. }
  41. }
  42. pub struct InitializingSymbolRunner<L: Logger> {
  43. logger: RefCell<L>,
  44. }
  45. impl<L: Logger> InitializingSymbolRunner<L> {
  46. pub fn new(logger: L) -> Self {
  47. Self {
  48. logger: RefCell::new(logger),
  49. }
  50. }
  51. fn exec_symbol<S: Symbol + Debug>(&self, symbol: &S) -> Result<(), Box<dyn Error>> {
  52. let mut logger = self.logger.borrow_mut();
  53. logger.write(format!("Executing {:?}", symbol).as_str());
  54. symbol.execute()?;
  55. let target_reached = symbol.target_reached()?;
  56. logger.debug(
  57. format!(
  58. "Symbol reports target_reached: {:?} (should be true)",
  59. target_reached
  60. )
  61. .as_str(),
  62. );
  63. if target_reached {
  64. Ok(())
  65. } else {
  66. Err(Box::new(SymbolRunError::ExecuteDidNotReach(())))
  67. }
  68. }
  69. }
  70. impl<L: Logger> SymbolRunner for InitializingSymbolRunner<L> {
  71. fn run_symbol<S: Symbol + Debug>(&self, symbol: &S, force: bool) -> Result<bool, Box<dyn Error>> {
  72. let mut logger = self.logger.borrow_mut();
  73. let executed = if force {
  74. logger.debug("Forcing symbol execution");
  75. drop(logger);
  76. self.exec_symbol(symbol)?;
  77. true
  78. } else {
  79. let target_reached = symbol.target_reached()?;
  80. if target_reached {
  81. logger.write(format!("{:?} already reached", symbol).as_str());
  82. } else {
  83. logger.debug(format!("Symbol reports target_reached: {:?}", target_reached).as_str());
  84. drop(logger);
  85. self.exec_symbol(symbol)?;
  86. }
  87. !target_reached
  88. };
  89. Ok(executed)
  90. }
  91. }
  92. pub struct DrySymbolRunner<L: Logger> {
  93. logger: RefCell<L>,
  94. }
  95. impl<L: Logger> DrySymbolRunner<L> {
  96. pub fn new(logger: L) -> Self {
  97. Self {
  98. logger: RefCell::new(logger),
  99. }
  100. }
  101. }
  102. impl<L: Logger> SymbolRunner for DrySymbolRunner<L> {
  103. fn run_symbol<S: Symbol + Debug>(&self, symbol: &S, force: bool) -> Result<bool, Box<dyn Error>> {
  104. let mut logger = self.logger.borrow_mut();
  105. let would_execute = if force {
  106. logger.write(format!("Would force-execute {:?}", symbol).as_str());
  107. true
  108. } else {
  109. let target_reached = symbol.target_reached()?;
  110. logger.debug(format!("Symbol reports target_reached: {:?}", target_reached).as_str());
  111. if !target_reached {
  112. logger.write(format!("Would execute {:?}", symbol).as_str());
  113. }
  114. !target_reached
  115. };
  116. Ok(would_execute)
  117. }
  118. }
  119. pub struct ReportingSymbolRunner<'a, R, L>(&'a R, RefCell<L>);
  120. impl<'a, R, L> ReportingSymbolRunner<'a, R, L> {
  121. pub fn new(symbol_runner: &'a R, logger: L) -> Self {
  122. ReportingSymbolRunner(symbol_runner, RefCell::new(logger))
  123. }
  124. }
  125. impl<'a, R, L> SymbolRunner for ReportingSymbolRunner<'a, R, L>
  126. where
  127. R: SymbolRunner,
  128. L: Logger,
  129. {
  130. fn run_symbol<S: Symbol + Debug>(&self, symbol: &S, force: bool) -> Result<bool, Box<dyn Error>> {
  131. let mut logger = self.1.borrow_mut();
  132. logger.debug(format!("Running symbol {:?}", symbol).as_str());
  133. let res = self.0.run_symbol(symbol, force);
  134. if let Err(ref e) = res {
  135. logger.write(format!("Failed on {:?} with {}, aborting.", symbol, e).as_str())
  136. } else {
  137. logger.debug(format!("Successfully finished {:?}", symbol).as_str())
  138. }
  139. res
  140. }
  141. }
  142. /*
  143. #[cfg(test)]
  144. mod test {
  145. use std::cell::RefCell;
  146. use std::error::Error;
  147. use std::fmt;
  148. use crate::loggers::Logger;
  149. use crate::schema::InitializingSymbolRunner;
  150. use crate::schema::SymbolRunner;
  151. use crate::symbols::Symbol;
  152. #[derive(Debug, PartialEq, Clone)]
  153. enum DummySymbolError {
  154. Error(()),
  155. }
  156. impl Error for DummySymbolError {
  157. fn description(&self) -> &str {
  158. return "Description";
  159. }
  160. }
  161. impl fmt::Display for DummySymbolError {
  162. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  163. write!(f, "Dummy symbol error")
  164. }
  165. }
  166. #[derive(Debug)]
  167. struct DummySymbol<'a> {
  168. _execute: &'a dyn Fn() -> Result<(), Box<dyn Error>>,
  169. _target_reached: &'a dyn Fn() -> Result<bool, Box<dyn Error>>,
  170. }
  171. impl<'b> Symbol for DummySymbol<'b> {
  172. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  173. (self._target_reached)()
  174. }
  175. fn execute(&self) -> Result<(), Box<dyn Error>> {
  176. (self._execute)()
  177. }
  178. }
  179. impl<'a> DummySymbol<'a> {
  180. fn new(
  181. target_reached: &'a dyn Fn() -> Result<bool, Box<dyn Error>>,
  182. execute: &'a dyn Fn() -> Result<(), Box<dyn Error>>,
  183. ) -> DummySymbol<'a> {
  184. DummySymbol {
  185. _target_reached: target_reached,
  186. _execute: execute,
  187. }
  188. }
  189. }
  190. struct DummyLogger {
  191. log: Vec<String>,
  192. }
  193. impl DummyLogger {
  194. fn new() -> DummyLogger {
  195. DummyLogger { log: Vec::new() }
  196. }
  197. }
  198. impl Logger for DummyLogger {
  199. fn write(&mut self, line: &str) {
  200. self.log.push(From::from(line));
  201. }
  202. fn debug(&mut self, line: &str) {
  203. self.log.push(From::from(line));
  204. }
  205. }
  206. #[test]
  207. fn nothing_needed_to_be_done() {
  208. let result = InitializingSymbolRunner::new(DummyLogger::new())
  209. .run_symbol(&DummySymbol::new(&|| Ok(true), &|| Ok(())));
  210. assert!(result.is_ok());
  211. }
  212. #[test]
  213. fn everything_is_ok() {
  214. let first = RefCell::new(true);
  215. let result = InitializingSymbolRunner::new(DummyLogger::new()).run_symbol(&DummySymbol::new(
  216. &|| {
  217. let mut _first = first.borrow_mut();
  218. Ok(if *_first {
  219. *_first = false;
  220. true
  221. } else {
  222. false
  223. })
  224. },
  225. &|| Ok(()),
  226. ));
  227. assert!(result.is_ok());
  228. }
  229. #[test]
  230. fn executing_did_not_change_state() {
  231. let result = InitializingSymbolRunner::new(DummyLogger::new())
  232. .run_symbol(&DummySymbol::new(&|| Ok(false), &|| Ok(())));
  233. assert_eq!(
  234. result.unwrap_err().description(),
  235. "Target not reached after executing symbol"
  236. );
  237. }
  238. #[test]
  239. fn executing_did_not_work() {
  240. let err = InitializingSymbolRunner::new(DummyLogger::new())
  241. .run_symbol(&DummySymbol::new(&|| Ok(false), &|| {
  242. Err(Box::new(DummySymbolError::Error(())))
  243. }))
  244. .unwrap_err();
  245. assert_eq!(err.description(), "Description");
  246. }
  247. }
  248. */