1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Command - shared fields in the various command types
//!
//! [Definition in Icinga Source](https://github.com/Icinga/icinga2/blob/master/lib/icinga/command.ti)

use std::collections::BTreeMap;

use serde::{Deserialize, Serialize};

use crate::serde::{
    deserialize_optional_seconds_as_duration, serialize_optional_duration_as_seconds,
};

use super::{
    custom_var_object::{CustomVarHolder, IcingaCustomVarObject},
    function::IcingaFunction,
};

/// shared fields in the various command objects
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct IcingaCommand {
    /// shared config object and custom variable fields
    #[serde(flatten)]
    pub custom_var: IcingaCustomVarObject,
    /// the descriptions of the command arguments
    pub arguments: Option<BTreeMap<String, IcingaCommandArgumentDescription>>,
    /// the actual command
    pub command: Option<IcingaCommandLine>,
    /// environment variables
    pub env: Option<BTreeMap<String, String>>,
    /// function for execution
    pub execute: IcingaFunction,
    /// command timeout
    #[serde(default)]
    #[serde(
        serialize_with = "serialize_optional_duration_as_seconds",
        deserialize_with = "deserialize_optional_seconds_as_duration"
    )]
    pub timeout: Option<time::Duration>,
}

impl CustomVarHolder for IcingaCommand {
    fn custom_var_value(&self, name: &str) -> Option<&serde_json::Value> {
        self.custom_var.custom_var_value(name)
    }
}

/// command parameters (scalar values basically)
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(untagged)]
pub enum IcingaCommandParameter {
    /// string value
    String(String),
    /// Boolean
    Boolean(bool),
    /// Integer
    Integer(i64),
}

/// command to execute with parameters
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(untagged)]
pub enum IcingaCommandLine {
    /// a single string for the whole command, will likely need a shell to do
    /// word splitting
    Shell(String),
    /// an icinga function
    Function(IcingaFunction),
    /// individual command and parameters
    Exec(Vec<IcingaCommandParameter>),
}

/// set_if condition in command argument description
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(untagged)]
pub enum IcingaArgumentCondition {
    /// a string condition, most likely a boolean variable
    String(String),
    /// a function condition
    Function(IcingaFunction),
}

/// the description of a single command argument
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(untagged)]
pub enum IcingaCommandArgumentDescription {
    /// a simple string with the argument(s)
    String(String),
    /// an icinga function
    Function(IcingaFunction),
    /// a full description with details
    FullDescription {
        /// the description of this argument
        description: Option<String>,
        /// the default value for this argument
        value: Option<String>,
        /// name of an argument to set
        key: Option<String>,
        /// should the key be skipped
        skip_key: Option<bool>,
        /// should the key be repeated
        repeat_key: Option<bool>,
        /// condition when to set it
        set_if: Option<IcingaArgumentCondition>,
        /// is this argument required
        required: Option<bool>,
        /// determines the order in which the arguments are used
        order: Option<u64>,
        /// separator for multiple values
        separator: Option<String>,
    },
}