Skip to main content

elasticctl_api/
observe.rs

1//! States read from the stack for later comparison.
2
3use elasticctl_core::{Error, ErrorKind, Result};
4
5/// One object's state as read from the stack, in comparison form.
6#[derive(Debug, Clone, PartialEq, serde::Serialize)]
7pub struct Observed {
8    /// The object kind: "rule", "alert", or "case".
9    pub object: &'static str,
10    /// The object identifier.
11    pub id: String,
12    /// `None` when the object does not exist.
13    pub state: Option<serde_json::Value>,
14}
15
16/// The object states read for a plan or re-check.
17#[derive(Debug, Clone, PartialEq, Default, serde::Serialize)]
18pub struct Preconditions(pub Vec<Observed>);
19
20impl Preconditions {
21    /// Order by `object`, then `id`.
22    pub fn sorted(mut self) -> Self {
23        self.0
24            .sort_by(|a, b| a.object.cmp(b.object).then_with(|| a.id.cmp(&b.id)));
25        self
26    }
27}
28
29/// Fail with kind `conflict` unless each present rule state has the expected `rule_id`.
30pub fn require_rule_identity(seen: &Preconditions) -> Result<()> {
31    for entry in &seen.0 {
32        if entry.object == "rule"
33            && let Some(state) = &entry.state
34            && state.get("rule_id").and_then(serde_json::Value::as_str) != Some(&entry.id)
35        {
36            return Err(Error::new(
37                ErrorKind::Conflict,
38                "a rule read returned a different rule_id",
39            ));
40        }
41    }
42    Ok(())
43}