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 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> {}