icinga2_api/api/action/
add_comment.rs

1//! API Action add-comment
2//!
3//! [Official Documentation](https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#add-comment)
4
5use serde::{Deserialize, Serialize};
6
7use crate::serde::{deserialize_optional_icinga_timestamp, serialize_optional_icinga_timestamp};
8use crate::types::action::StatusResponse;
9use crate::types::enums::object_type::IcingaObjectType;
10use crate::types::filter::IcingaFilter;
11use crate::types::query::ResultsWrapper;
12use crate::types::rest::{RestApiEndpoint, RestApiResponse};
13
14/// REST API Endpoint for the add-comment call
15#[derive(Debug, Clone, derive_builder::Builder, Serialize, Deserialize)]
16#[builder(
17    build_fn(error = "crate::error::Error", validate = "Self::validate"),
18    derive(Debug)
19)]
20pub struct AddComment {
21    /// the author of the comment
22    author: String,
23    /// the body of the comment
24    comment: String,
25    /// expiry time for the comment
26    #[serde(
27        serialize_with = "serialize_optional_icinga_timestamp",
28        deserialize_with = "deserialize_optional_icinga_timestamp"
29    )]
30    expiry: Option<time::OffsetDateTime>,
31    /// filter to target which host and/or service to attach the comment to
32    #[builder(default, setter(strip_option, into))]
33    #[serde(flatten)]
34    filter: Option<IcingaFilter>,
35}
36
37impl AddComment {
38    /// create a new builder for this endpoint
39    ///
40    /// this is usually the first step to calling this REST API endpoint
41    #[must_use]
42    pub fn builder() -> AddCommentBuilder {
43        AddCommentBuilder::default()
44    }
45}
46
47impl AddCommentBuilder {
48    /// makes sure the filter object type is valid for this call (either Host or Service)
49    ///
50    /// # Errors
51    ///
52    /// this returns an error if the filter field object type is not Host or Service
53    pub fn validate(&self) -> Result<(), crate::error::Error> {
54        if let Some(Some(filter)) = &self.filter {
55            if filter.object_type != IcingaObjectType::Host
56                && filter.object_type != IcingaObjectType::Service
57            {
58                Err(crate::error::Error::FilterObjectTypeMismatch(
59                    vec![IcingaObjectType::Host, IcingaObjectType::Service],
60                    filter.object_type.to_owned(),
61                ))
62            } else {
63                Ok(())
64            }
65        } else {
66            Ok(())
67        }
68    }
69}
70
71impl RestApiEndpoint for AddComment {
72    type RequestBody = AddComment;
73
74    fn method(&self) -> Result<reqwest::Method, crate::error::Error> {
75        Ok(reqwest::Method::POST)
76    }
77
78    fn url(&self, base_url: &url::Url) -> Result<url::Url, crate::error::Error> {
79        base_url
80            .join("v1/actions/add-comment")
81            .map_err(crate::error::Error::CouldNotParseUrlFragment)
82    }
83
84    fn request_body(
85        &self,
86    ) -> Result<Option<std::borrow::Cow<Self::RequestBody>>, crate::error::Error>
87    where
88        Self::RequestBody: Clone + serde::Serialize + std::fmt::Debug,
89    {
90        Ok(Some(std::borrow::Cow::Borrowed(self)))
91    }
92}
93
94impl RestApiResponse<AddComment> for ResultsWrapper<StatusResponse> {}