//use erased_serde::Serialize; use serde::Serialize; use crate::Facts; pub mod package; pub mod command; #[derive(Clone, Debug, Serialize)] pub struct TaskRun { /// the arguments passed to the module module_args: serde_json::Value, //name: String, /// the name of the module module: String, #[serde(flatten)] /// the status of the task run (ok, skip, fail) status: TaskStatus, } #[derive(Clone, Debug, Serialize)] #[serde(tag="status", content = "return")] pub enum TaskStatus { #[serde(rename="ok")] Ok(serde_json::Value), #[serde(rename="skip")] Skip(serde_json::Value), #[serde(rename="fail")] Fail(serde_json::Value), } impl TaskStatus { pub fn ok(val: T) -> TaskStatus { TaskStatus::Ok(serde_json::to_value(val).unwrap()) } pub fn skip(val: T) -> TaskStatus { TaskStatus::Skip(serde_json::to_value(val).unwrap()) } pub fn fail(val: T) -> TaskStatus { TaskStatus::Fail(serde_json::to_value(val).unwrap()) } } #[derive(Clone, Debug, Serialize)] pub struct PlaybookRun { pub facts: Facts, pub steps: Vec, } impl PlaybookRun { pub fn new() -> PlaybookRun { PlaybookRun { facts: Facts::new(), steps: Vec::new(), } } pub fn add_step(&mut self, step: TaskRun) { self.steps.push(step); } pub fn print_json(&self) { println!("{}", serde_json::to_string(&self).unwrap()); } pub fn print_json_pretty(&self) { println!("{}", serde_json::to_string_pretty(&self).unwrap()); } pub fn run, A: Serialize, S: Serialize, E: Serialize>(&mut self, cmd: MS) -> Result { let module = cmd.with_facts(&self.facts); self.run_inner(module) } pub fn run_inner(&mut self, cmd: Box>) -> Result { // TODO: Check conditions for skip let module_name = cmd.module_name().to_string(); let args = cmd.serialize_args(); let res = cmd.run(); let status = match &res { Ok(s) => { //self.add_step(s) TaskStatus::ok(s) }, Err(e) => { TaskStatus::fail(e) } }; let run = TaskRun { module_args: args, module: module_name, status, }; self.add_step(run); res } } // pub trait Loopable { // fn loop_with(self, looped: dyn Fn(Self) -> Self, with: Vec); // } /// A trait for modules to be run in the context of a playbook, by gathering facts pub trait ModuleSetup { // type module: Module; fn with_facts(self, facts: &Facts) -> Box>; } /// A Module takes some arguments which can be serialized back to the playbook run, and can be run to produce /// a certain result. pub trait Module { /// Return the module name as string slice fn module_name(&self) -> &'static str; /// Clone the arguments to be stored in the playbook's task run fn serialize_args(&self) -> serde_json::Value; /// Run the module, producing a result fn run(self) -> Result; } /// Declare module types pub use command::CommandModule as Command;