Let's not break, shall we? ^^'

This commit is contained in:
Nadja Reitzenstein 2021-09-21 09:00:42 +02:00
parent bd635d97ac
commit aa58657122
6 changed files with 117 additions and 7 deletions

3
examples/actor.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "Bash actor called with $@"

View File

@ -1,19 +1,29 @@
-- { actor_connections = [] : List { _1 : Text, _2 : Text }
{ actor_connections =
[ { _1 = "Testmachine", _2 = "Actor" }
, { _1 = "Another", _2 = "Actor2" }
, { _1 = "Yetmore", _2 = "Actor3" }
, { _1 = "Another", _2 = "Bash" }
, { _1 = "Yetmore", _2 = "Bash2" }
]
, actors =
{ Actor = { module = "Dummy", params = {=} }
, Actor2 = { module = "Dummy", params = {=} }
, Actor3 = { module = "Dummy", params = {=} }
, Bash = { module = "Process", params =
{ cmd = "./examples/actor.sh"
, args = "your ad could be here"
}}
, Bash2 = { module = "Process", params =
{ cmd = "./examples/actor.sh"
, args = "this is a different one"
}}
, Bash3 = { module = "Process", params =
{ cmd = "./examples/actor.sh"
}}
}
, init_connections = [] : List { _1 : Text, _2 : Text }
--, init_connections = [{ _1 = "Initiator", _2 = "Testmachine" }]
, initiators =
{ Initiator = { module = "Dummy", params = {=} }
}
, initiators = --{=}
{ Initiator = { module = "Dummy", params = {=} } }
, listens =
[ { address = "127.0.0.1", port = Some 59661 }
, { address = "::1", port = Some 59661 }

View File

@ -161,6 +161,10 @@ fn load_single(
"Dummy" => {
Some(Box::new(Dummy::new(log)))
}
"Process" => {
Process::new(log.new(o!("name" => name.clone())), name.clone(), params)
.map(|a| a.into_boxed_actuator())
}
_ => {
error!(log, "No actor found with name \"{}\", configured as \"{}\".", module_name, name);
None

View File

@ -163,9 +163,7 @@ impl Inner {
}
pub fn do_state_change(&mut self, new_state: MachineState) {
print!("State {:?}", &new_state);
let old_state = self.state.replace(new_state);
print!("<- {:?}", &old_state);
self.reset.replace(old_state);
}

View File

@ -7,3 +7,6 @@
mod shelly;
pub use shelly::Shelly;
mod process;
pub use process::Process;

92
src/modules/process.rs Normal file
View File

@ -0,0 +1,92 @@
use std::collections::HashMap;
use std::process::Stdio;
use smol::process::Command;
use futures::future::FutureExt;
use crate::actor::Actuator;
use crate::db::machine::{MachineState, Status};
use futures::future::BoxFuture;
use slog::Logger;
pub struct Process {
log: Logger,
name: String,
cmd: String,
args: Vec<String>,
}
impl Process {
pub fn new(log: Logger, name: String, params: &HashMap<String, String>) -> Option<Self> {
let cmd = params.get("cmd").map(|s| s.to_string())?;
let args = params.get("args").map(|argv|
argv.split_whitespace()
.map(|s| s.to_string())
.collect())
.unwrap_or_else(Vec::new);
Some(Self { log, name, cmd, args })
}
pub fn into_boxed_actuator(self) -> Box<dyn Actuator + Sync + Send> {
Box::new(self)
}
}
impl Actuator for Process {
fn apply(&mut self, state: MachineState) -> BoxFuture<'static, ()> {
debug!(self.log, "Running {} ({}) for {:?}", &self.name, &self.cmd, &state);
let mut command = Command::new(&self.cmd);
command
.stdin(Stdio::null())
.args(self.args.iter())
.arg(&self.name);
let fstate = state.state.clone();
match state.state {
Status::Free => {
command.arg("free");
}
Status::InUse(by) => {
command.arg("inuse");
by.map(|user| command.arg(format!("{}", user)));
}
Status::ToCheck(by) => {
command.arg("tocheck")
.arg(format!("{}", by));
}
Status::Blocked(by) => {
command.arg("blocked")
.arg(format!("{}", by));
}
Status::Disabled => { command.arg("disabled"); },
Status::Reserved(by) => {
command.arg("reserved")
.arg(format!("{}", by));
}
}
let flog = self.log.new(o!());
let name = self.name.clone();
Box::pin(command.output().map(move |res| match res {
Ok(retv) if retv.status.success() => {
trace!(flog, "Actor was successful");
let outstr = String::from_utf8_lossy(&retv.stdout);
for line in outstr.lines() {
debug!(flog, "{}", line);
}
}
Ok(retv) => {
warn!(flog, "Actor {} returned nonzero output {} for {:?}", name, retv.status, fstate);
if !retv.stderr.is_empty() {
let errstr = String::from_utf8_lossy(&retv.stderr);
for line in errstr.lines() {
warn!(flog, "{}", line);
}
}
}
Err(err) => { warn!(flog, "Actor {} failed to run cmd: {}", name, err); }
}))
}
}