icinga2_api/api/action/
schedule_downtime.rs1use 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#[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 author: String,
28 comment: String,
30 #[serde(
32 serialize_with = "serialize_icinga_timestamp",
33 deserialize_with = "deserialize_icinga_timestamp"
34 )]
35 start_time: time::OffsetDateTime,
36 #[serde(
38 serialize_with = "serialize_icinga_timestamp",
39 deserialize_with = "deserialize_icinga_timestamp"
40 )]
41 end_time: time::OffsetDateTime,
42 fixed: Option<bool>,
44 #[serde(
46 serialize_with = "serialize_optional_duration_as_seconds",
47 deserialize_with = "deserialize_optional_seconds_as_duration"
48 )]
49 duration: Option<time::Duration>,
50 all_services: Option<bool>,
52 trigger_name: Option<IcingaDowntimeName>,
54 child_options: Option<IcingaDowntimeChildOptions>,
56 #[builder(default, setter(strip_option, into))]
58 #[serde(flatten)]
59 filter: Option<IcingaFilter>,
60}
61
62impl ScheduleDowntime {
63 #[must_use]
67 pub fn builder() -> ScheduleDowntimeBuilder {
68 ScheduleDowntimeBuilder::default()
69 }
70}
71
72impl ScheduleDowntimeBuilder {
73 pub fn validate(&self) -> Result<(), crate::error::Error> {
83 if matches!(&self.fixed, Some(Some(false))) && self.duration.is_none() {
84 return Err(crate::error::Error::DurationRequiredOnFlexibleDowntime);
85 }
86 if let Some(Some(filter)) = &self.filter {
87 if filter.object_type != IcingaObjectType::Host
88 && filter.object_type != IcingaObjectType::Service
89 {
90 return Err(crate::error::Error::FilterObjectTypeMismatch(
91 vec![IcingaObjectType::Host, IcingaObjectType::Service],
92 filter.object_type.to_owned(),
93 ));
94 }
95 if filter.object_type == IcingaObjectType::Service {
96 return Err(crate::error::Error::AllServicesInvalidOnServiceDowntime);
97 }
98 }
99 Ok(())
100 }
101}
102
103impl RestApiEndpoint for ScheduleDowntime {
104 type RequestBody = Self;
105
106 fn method(&self) -> Result<reqwest::Method, crate::error::Error> {
107 Ok(reqwest::Method::POST)
108 }
109
110 fn url(&self, base_url: &url::Url) -> Result<url::Url, crate::error::Error> {
111 base_url
112 .join("v1/actions/schedule-downtime")
113 .map_err(crate::error::Error::CouldNotParseUrlFragment)
114 }
115
116 fn request_body(
117 &self,
118 ) -> Result<Option<std::borrow::Cow<'_, Self::RequestBody>>, crate::error::Error>
119 where
120 Self::RequestBody: Clone + serde::Serialize + std::fmt::Debug,
121 {
122 Ok(Some(std::borrow::Cow::Borrowed(self)))
123 }
124}
125
126impl RestApiResponse<ScheduleDowntime> for ResultsWrapper<StatusResponse> {}