icinga2_api/api/action/
schedule_downtime.rs

1//! API Action schedule-downtime
2//!
3//! [Official Documentation](https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#schedule-downtime)
4
5use serde::{Deserialize, Serialize};
6
7use crate::serde::{
8    deserialize_icinga_timestamp, deserialize_optional_seconds_as_duration,
9    serialize_icinga_timestamp, serialize_optional_duration_as_seconds,
10};
11use crate::types::action::StatusResponse;
12use crate::types::enums::downtime_child_options::IcingaDowntimeChildOptions;
13use crate::types::enums::object_type::IcingaObjectType;
14use crate::types::filter::IcingaFilter;
15use crate::types::names::IcingaDowntimeName;
16use crate::types::query::ResultsWrapper;
17use crate::types::rest::{RestApiEndpoint, RestApiResponse};
18
19/// REST API Endpoint for the schedule-downtime call
20#[derive(Debug, Clone, derive_builder::Builder, Serialize, Deserialize)]
21#[builder(
22    build_fn(error = "crate::error::Error", validate = "Self::validate"),
23    derive(Debug)
24)]
25pub struct ScheduleDowntime {
26    /// the author of the downtime
27    author: String,
28    /// the body of the downtime comment
29    comment: String,
30    /// beginning of the downtime
31    #[serde(
32        serialize_with = "serialize_icinga_timestamp",
33        deserialize_with = "deserialize_icinga_timestamp"
34    )]
35    start_time: time::OffsetDateTime,
36    /// end of the downtime
37    #[serde(
38        serialize_with = "serialize_icinga_timestamp",
39        deserialize_with = "deserialize_icinga_timestamp"
40    )]
41    end_time: time::OffsetDateTime,
42    /// Defaults to true. If true, the downtime is fixed otherwise flexible.
43    fixed: Option<bool>,
44    /// the duration of the downtime
45    #[serde(
46        serialize_with = "serialize_optional_duration_as_seconds",
47        deserialize_with = "deserialize_optional_seconds_as_duration"
48    )]
49    duration: Option<time::Duration>,
50    /// Sets downtime for all services for the matched host objects. If child_options are set, all child hosts and their services will schedule a downtime too. Defaults to false.
51    all_services: Option<bool>,
52    /// Sets the trigger for a triggered downtime.
53    trigger_name: Option<IcingaDowntimeName>,
54    /// Schedule child downtimes.
55    child_options: Option<IcingaDowntimeChildOptions>,
56    /// filter to target which host and/or service to schedule a downtime for
57    #[builder(default, setter(strip_option, into))]
58    #[serde(flatten)]
59    filter: Option<IcingaFilter>,
60}
61
62impl ScheduleDowntime {
63    /// create a new builder for this endpoint
64    ///
65    /// this is usually the first step to calling this REST API endpoint
66    #[must_use]
67    pub fn builder() -> ScheduleDowntimeBuilder {
68        ScheduleDowntimeBuilder::default()
69    }
70}
71
72impl ScheduleDowntimeBuilder {
73    /// makes sure the filter object type is valid for this call (either Host or Service)
74    ///
75    /// validates all_services is only used on host downtimes
76    ///
77    /// validates duration is specified if fixed is set to false
78    ///
79    /// # Errors
80    ///
81    /// this returns an error if the filter field object type is not Host or Service
82    pub fn validate(&self) -> Result<(), crate::error::Error> {
83        if let Some(Some(false)) = &self.fixed {
84            if self.duration.is_none() {
85                return Err(crate::error::Error::DurationRequiredOnFlexibleDowntime);
86            }
87        }
88        if let Some(Some(filter)) = &self.filter {
89            if filter.object_type != IcingaObjectType::Host
90                && filter.object_type != IcingaObjectType::Service
91            {
92                return Err(crate::error::Error::FilterObjectTypeMismatch(
93                    vec![IcingaObjectType::Host, IcingaObjectType::Service],
94                    filter.object_type.to_owned(),
95                ));
96            }
97            if filter.object_type == IcingaObjectType::Service {
98                return Err(crate::error::Error::AllServicesInvalidOnServiceDowntime);
99            }
100        }
101        Ok(())
102    }
103}
104
105impl RestApiEndpoint for ScheduleDowntime {
106    type RequestBody = ScheduleDowntime;
107
108    fn method(&self) -> Result<reqwest::Method, crate::error::Error> {
109        Ok(reqwest::Method::POST)
110    }
111
112    fn url(&self, base_url: &url::Url) -> Result<url::Url, crate::error::Error> {
113        base_url
114            .join("v1/actions/schedule-downtime")
115            .map_err(crate::error::Error::CouldNotParseUrlFragment)
116    }
117
118    fn request_body(
119        &self,
120    ) -> Result<Option<std::borrow::Cow<Self::RequestBody>>, crate::error::Error>
121    where
122        Self::RequestBody: Clone + serde::Serialize + std::fmt::Debug,
123    {
124        Ok(Some(std::borrow::Cow::Borrowed(self)))
125    }
126}
127
128impl RestApiResponse<ScheduleDowntime> for ResultsWrapper<StatusResponse> {}