use std::path::Path;
use crate::monitor::{Verb, arming, row};
use crate::opslog::{self, OpEntry, Origin};
use super::dispatch::Deps;
use super::reply::Reply;
const ARM_STEP: &str = "arm-monitor";
const DISARM_STEP: &str = "disarm-monitor";
pub(super) fn dispatch(deps: &Deps, ts: &str, verb: &Verb) -> Result<Reply, String> {
match verb {
Verb::Arm { workspace, model } => arm(deps, ts, workspace, Some(model)),
Verb::Disarm { workspace } => arm(deps, ts, workspace, None),
Verb::Flag {
workspace,
agent,
reason,
} => flag(deps, ts, workspace, agent, reason),
}
}
fn arm(deps: &Deps, ts: &str, workspace: &Path, model: Option<&str>) -> Result<Reply, String> {
let path = deps.state_root.join(crate::app::cadence::CADENCE_YAML);
let before = std::fs::read_to_string(&path).unwrap_or_default();
let key = crate::nav::ws_key(workspace);
let after = match model {
Some(model) => arming::arm(&before, &key, model).ok_or_else(|| {
format!(
"{}: monitor: carries an inline value; edit it by hand and try again",
crate::app::cadence::CADENCE_YAML
)
})?,
None => arming::disarm(&before, &key),
};
std::fs::create_dir_all(&deps.state_root).map_err(|e| e.to_string())?;
std::fs::write(&path, after).map_err(|e| e.to_string())?;
if model.is_some() {
seed_policy(&deps.state_root)?;
}
let step = if model.is_some() {
ARM_STEP
} else {
DISARM_STEP
};
let done = OpEntry::step_done(
ts.to_owned(),
step,
crate::nav::ws_key(workspace),
Origin::World,
);
opslog::append(&deps.state_root, &done).map_err(|e| e.to_string())?;
Ok(Reply::Armed {
armed: model.is_some(),
})
}
fn seed_policy(state_root: &Path) -> Result<(), String> {
let path = state_root.join(arming::PROMPT_FILE);
if path.exists() {
return Ok(());
}
std::fs::write(&path, arming::TEMPLATE).map_err(|e| e.to_string())
}
fn flag(
deps: &Deps,
ts: &str,
workspace: &Path,
agent: &str,
reason: &str,
) -> Result<Reply, String> {
let entry = row::flagged(ts.to_owned(), workspace, agent, reason);
opslog::append(&deps.state_root, &entry).map_err(|e| e.to_string())?;
Ok(Reply::Flagged)
}
#[cfg(test)]
mod tests;