datadog_api_client/datadogV2/api/
api_fleet_automation.rs

1// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
2// This product includes software developed at Datadog (https://www.datadoghq.com/).
3// Copyright 2019-Present Datadog, Inc.
4use crate::datadog;
5use flate2::{
6    write::{GzEncoder, ZlibEncoder},
7    Compression,
8};
9use log::warn;
10use reqwest::header::{HeaderMap, HeaderValue};
11use serde::{Deserialize, Serialize};
12use std::io::Write;
13
14/// ListFleetDeploymentsOptionalParams is a struct for passing parameters to the method [`FleetAutomationAPI::list_fleet_deployments`]
15#[non_exhaustive]
16#[derive(Clone, Default, Debug)]
17pub struct ListFleetDeploymentsOptionalParams {
18    /// Number of deployments to return per page. Maximum value is 100.
19    pub page_size: Option<i64>,
20    /// Index of the first deployment to return. Use this with `page_size` to paginate through results.
21    pub page_offset: Option<i64>,
22}
23
24impl ListFleetDeploymentsOptionalParams {
25    /// Number of deployments to return per page. Maximum value is 100.
26    pub fn page_size(mut self, value: i64) -> Self {
27        self.page_size = Some(value);
28        self
29    }
30    /// Index of the first deployment to return. Use this with `page_size` to paginate through results.
31    pub fn page_offset(mut self, value: i64) -> Self {
32        self.page_offset = Some(value);
33        self
34    }
35}
36
37/// CancelFleetDeploymentError is a struct for typed errors of method [`FleetAutomationAPI::cancel_fleet_deployment`]
38#[derive(Debug, Clone, Serialize, Deserialize)]
39#[serde(untagged)]
40pub enum CancelFleetDeploymentError {
41    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
42    UnknownValue(serde_json::Value),
43}
44
45/// CreateFleetDeploymentConfigureError is a struct for typed errors of method [`FleetAutomationAPI::create_fleet_deployment_configure`]
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(untagged)]
48pub enum CreateFleetDeploymentConfigureError {
49    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
50    UnknownValue(serde_json::Value),
51}
52
53/// GetFleetDeploymentError is a struct for typed errors of method [`FleetAutomationAPI::get_fleet_deployment`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum GetFleetDeploymentError {
57    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
58    UnknownValue(serde_json::Value),
59}
60
61/// ListFleetDeploymentsError is a struct for typed errors of method [`FleetAutomationAPI::list_fleet_deployments`]
62#[derive(Debug, Clone, Serialize, Deserialize)]
63#[serde(untagged)]
64pub enum ListFleetDeploymentsError {
65    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
66    UnknownValue(serde_json::Value),
67}
68
69/// Manage automated deployments across your fleet of hosts.
70/// Use these endpoints to create, retrieve, and cancel deployments
71/// that apply configuration changes to multiple hosts at once.
72#[derive(Debug, Clone)]
73pub struct FleetAutomationAPI {
74    config: datadog::Configuration,
75    client: reqwest_middleware::ClientWithMiddleware,
76}
77
78impl Default for FleetAutomationAPI {
79    fn default() -> Self {
80        Self::with_config(datadog::Configuration::default())
81    }
82}
83
84impl FleetAutomationAPI {
85    pub fn new() -> Self {
86        Self::default()
87    }
88    pub fn with_config(config: datadog::Configuration) -> Self {
89        let mut reqwest_client_builder = reqwest::Client::builder();
90
91        if let Some(proxy_url) = &config.proxy_url {
92            let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL");
93            reqwest_client_builder = reqwest_client_builder.proxy(proxy);
94        }
95
96        let mut middleware_client_builder =
97            reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap());
98
99        if config.enable_retry {
100            struct RetryableStatus;
101            impl reqwest_retry::RetryableStrategy for RetryableStatus {
102                fn handle(
103                    &self,
104                    res: &Result<reqwest::Response, reqwest_middleware::Error>,
105                ) -> Option<reqwest_retry::Retryable> {
106                    match res {
107                        Ok(success) => reqwest_retry::default_on_request_success(success),
108                        Err(_) => None,
109                    }
110                }
111            }
112            let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder()
113                .build_with_max_retries(config.max_retries);
114
115            let retry_middleware =
116                reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy(
117                    backoff_policy,
118                    RetryableStatus,
119                );
120
121            middleware_client_builder = middleware_client_builder.with(retry_middleware);
122        }
123
124        let client = middleware_client_builder.build();
125
126        Self { config, client }
127    }
128
129    pub fn with_client_and_config(
130        config: datadog::Configuration,
131        client: reqwest_middleware::ClientWithMiddleware,
132    ) -> Self {
133        Self { config, client }
134    }
135
136    /// Cancel this deployment and stop all associated operations.
137    /// If a workflow is currently running for this deployment, it is canceled immediately.
138    /// Changes already applied to hosts are not rolled back.
139    pub async fn cancel_fleet_deployment(
140        &self,
141        deployment_id: String,
142    ) -> Result<(), datadog::Error<CancelFleetDeploymentError>> {
143        match self
144            .cancel_fleet_deployment_with_http_info(deployment_id)
145            .await
146        {
147            Ok(_) => Ok(()),
148            Err(err) => Err(err),
149        }
150    }
151
152    /// Cancel this deployment and stop all associated operations.
153    /// If a workflow is currently running for this deployment, it is canceled immediately.
154    /// Changes already applied to hosts are not rolled back.
155    pub async fn cancel_fleet_deployment_with_http_info(
156        &self,
157        deployment_id: String,
158    ) -> Result<datadog::ResponseContent<()>, datadog::Error<CancelFleetDeploymentError>> {
159        let local_configuration = &self.config;
160        let operation_id = "v2.cancel_fleet_deployment";
161        if local_configuration.is_unstable_operation_enabled(operation_id) {
162            warn!("Using unstable operation {operation_id}");
163        } else {
164            let local_error = datadog::UnstableOperationDisabledError {
165                msg: "Operation 'v2.cancel_fleet_deployment' is not enabled".to_string(),
166            };
167            return Err(datadog::Error::UnstableOperationDisabledError(local_error));
168        }
169
170        let local_client = &self.client;
171
172        let local_uri_str = format!(
173            "{}/api/unstable/fleet/deployments/{deployment_id}/cancel",
174            local_configuration.get_operation_host(operation_id),
175            deployment_id = datadog::urlencode(deployment_id)
176        );
177        let mut local_req_builder =
178            local_client.request(reqwest::Method::POST, local_uri_str.as_str());
179
180        // build headers
181        let mut headers = HeaderMap::new();
182        headers.insert("Accept", HeaderValue::from_static("*/*"));
183
184        // build user agent
185        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
186            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
187            Err(e) => {
188                log::warn!("Failed to parse user agent header: {e}, falling back to default");
189                headers.insert(
190                    reqwest::header::USER_AGENT,
191                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
192                )
193            }
194        };
195
196        // build auth
197        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
198            headers.insert(
199                "DD-API-KEY",
200                HeaderValue::from_str(local_key.key.as_str())
201                    .expect("failed to parse DD-API-KEY header"),
202            );
203        };
204        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
205            headers.insert(
206                "DD-APPLICATION-KEY",
207                HeaderValue::from_str(local_key.key.as_str())
208                    .expect("failed to parse DD-APPLICATION-KEY header"),
209            );
210        };
211
212        local_req_builder = local_req_builder.headers(headers);
213        let local_req = local_req_builder.build()?;
214        log::debug!("request content: {:?}", local_req.body());
215        let local_resp = local_client.execute(local_req).await?;
216
217        let local_status = local_resp.status();
218        let local_content = local_resp.text().await?;
219        log::debug!("response content: {}", local_content);
220
221        if !local_status.is_client_error() && !local_status.is_server_error() {
222            Ok(datadog::ResponseContent {
223                status: local_status,
224                content: local_content,
225                entity: None,
226            })
227        } else {
228            let local_entity: Option<CancelFleetDeploymentError> =
229                serde_json::from_str(&local_content).ok();
230            let local_error = datadog::ResponseContent {
231                status: local_status,
232                content: local_content,
233                entity: local_entity,
234            };
235            Err(datadog::Error::ResponseError(local_error))
236        }
237    }
238
239    /// Create a new deployment to apply configuration changes
240    /// to a fleet of hosts matching the specified filter query.
241    pub async fn create_fleet_deployment_configure(
242        &self,
243        body: crate::datadogV2::model::FleetDeploymentConfigureCreateRequest,
244    ) -> Result<
245        crate::datadogV2::model::FleetDeploymentResponse,
246        datadog::Error<CreateFleetDeploymentConfigureError>,
247    > {
248        match self
249            .create_fleet_deployment_configure_with_http_info(body)
250            .await
251        {
252            Ok(response_content) => {
253                if let Some(e) = response_content.entity {
254                    Ok(e)
255                } else {
256                    Err(datadog::Error::Serde(serde::de::Error::custom(
257                        "response content was None",
258                    )))
259                }
260            }
261            Err(err) => Err(err),
262        }
263    }
264
265    /// Create a new deployment to apply configuration changes
266    /// to a fleet of hosts matching the specified filter query.
267    pub async fn create_fleet_deployment_configure_with_http_info(
268        &self,
269        body: crate::datadogV2::model::FleetDeploymentConfigureCreateRequest,
270    ) -> Result<
271        datadog::ResponseContent<crate::datadogV2::model::FleetDeploymentResponse>,
272        datadog::Error<CreateFleetDeploymentConfigureError>,
273    > {
274        let local_configuration = &self.config;
275        let operation_id = "v2.create_fleet_deployment_configure";
276        if local_configuration.is_unstable_operation_enabled(operation_id) {
277            warn!("Using unstable operation {operation_id}");
278        } else {
279            let local_error = datadog::UnstableOperationDisabledError {
280                msg: "Operation 'v2.create_fleet_deployment_configure' is not enabled".to_string(),
281            };
282            return Err(datadog::Error::UnstableOperationDisabledError(local_error));
283        }
284
285        let local_client = &self.client;
286
287        let local_uri_str = format!(
288            "{}/api/unstable/fleet/deployments/configure",
289            local_configuration.get_operation_host(operation_id)
290        );
291        let mut local_req_builder =
292            local_client.request(reqwest::Method::POST, local_uri_str.as_str());
293
294        // build headers
295        let mut headers = HeaderMap::new();
296        headers.insert("Content-Type", HeaderValue::from_static("application/json"));
297        headers.insert("Accept", HeaderValue::from_static("application/json"));
298
299        // build user agent
300        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
301            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
302            Err(e) => {
303                log::warn!("Failed to parse user agent header: {e}, falling back to default");
304                headers.insert(
305                    reqwest::header::USER_AGENT,
306                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
307                )
308            }
309        };
310
311        // build auth
312        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
313            headers.insert(
314                "DD-API-KEY",
315                HeaderValue::from_str(local_key.key.as_str())
316                    .expect("failed to parse DD-API-KEY header"),
317            );
318        };
319        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
320            headers.insert(
321                "DD-APPLICATION-KEY",
322                HeaderValue::from_str(local_key.key.as_str())
323                    .expect("failed to parse DD-APPLICATION-KEY header"),
324            );
325        };
326
327        // build body parameters
328        let output = Vec::new();
329        let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter);
330        if body.serialize(&mut ser).is_ok() {
331            if let Some(content_encoding) = headers.get("Content-Encoding") {
332                match content_encoding.to_str().unwrap_or_default() {
333                    "gzip" => {
334                        let mut enc = GzEncoder::new(Vec::new(), Compression::default());
335                        let _ = enc.write_all(ser.into_inner().as_slice());
336                        match enc.finish() {
337                            Ok(buf) => {
338                                local_req_builder = local_req_builder.body(buf);
339                            }
340                            Err(e) => return Err(datadog::Error::Io(e)),
341                        }
342                    }
343                    "deflate" => {
344                        let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
345                        let _ = enc.write_all(ser.into_inner().as_slice());
346                        match enc.finish() {
347                            Ok(buf) => {
348                                local_req_builder = local_req_builder.body(buf);
349                            }
350                            Err(e) => return Err(datadog::Error::Io(e)),
351                        }
352                    }
353                    "zstd1" => {
354                        let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap();
355                        let _ = enc.write_all(ser.into_inner().as_slice());
356                        match enc.finish() {
357                            Ok(buf) => {
358                                local_req_builder = local_req_builder.body(buf);
359                            }
360                            Err(e) => return Err(datadog::Error::Io(e)),
361                        }
362                    }
363                    _ => {
364                        local_req_builder = local_req_builder.body(ser.into_inner());
365                    }
366                }
367            } else {
368                local_req_builder = local_req_builder.body(ser.into_inner());
369            }
370        }
371
372        local_req_builder = local_req_builder.headers(headers);
373        let local_req = local_req_builder.build()?;
374        log::debug!("request content: {:?}", local_req.body());
375        let local_resp = local_client.execute(local_req).await?;
376
377        let local_status = local_resp.status();
378        let local_content = local_resp.text().await?;
379        log::debug!("response content: {}", local_content);
380
381        if !local_status.is_client_error() && !local_status.is_server_error() {
382            match serde_json::from_str::<crate::datadogV2::model::FleetDeploymentResponse>(
383                &local_content,
384            ) {
385                Ok(e) => {
386                    return Ok(datadog::ResponseContent {
387                        status: local_status,
388                        content: local_content,
389                        entity: Some(e),
390                    })
391                }
392                Err(e) => return Err(datadog::Error::Serde(e)),
393            };
394        } else {
395            let local_entity: Option<CreateFleetDeploymentConfigureError> =
396                serde_json::from_str(&local_content).ok();
397            let local_error = datadog::ResponseContent {
398                status: local_status,
399                content: local_content,
400                entity: local_entity,
401            };
402            Err(datadog::Error::ResponseError(local_error))
403        }
404    }
405
406    /// Retrieve the details of a specific deployment using its unique identifier.
407    pub async fn get_fleet_deployment(
408        &self,
409        deployment_id: String,
410    ) -> Result<
411        crate::datadogV2::model::FleetDeploymentResponse,
412        datadog::Error<GetFleetDeploymentError>,
413    > {
414        match self
415            .get_fleet_deployment_with_http_info(deployment_id)
416            .await
417        {
418            Ok(response_content) => {
419                if let Some(e) = response_content.entity {
420                    Ok(e)
421                } else {
422                    Err(datadog::Error::Serde(serde::de::Error::custom(
423                        "response content was None",
424                    )))
425                }
426            }
427            Err(err) => Err(err),
428        }
429    }
430
431    /// Retrieve the details of a specific deployment using its unique identifier.
432    pub async fn get_fleet_deployment_with_http_info(
433        &self,
434        deployment_id: String,
435    ) -> Result<
436        datadog::ResponseContent<crate::datadogV2::model::FleetDeploymentResponse>,
437        datadog::Error<GetFleetDeploymentError>,
438    > {
439        let local_configuration = &self.config;
440        let operation_id = "v2.get_fleet_deployment";
441        if local_configuration.is_unstable_operation_enabled(operation_id) {
442            warn!("Using unstable operation {operation_id}");
443        } else {
444            let local_error = datadog::UnstableOperationDisabledError {
445                msg: "Operation 'v2.get_fleet_deployment' is not enabled".to_string(),
446            };
447            return Err(datadog::Error::UnstableOperationDisabledError(local_error));
448        }
449
450        let local_client = &self.client;
451
452        let local_uri_str = format!(
453            "{}/api/unstable/fleet/deployments/{deployment_id}",
454            local_configuration.get_operation_host(operation_id),
455            deployment_id = datadog::urlencode(deployment_id)
456        );
457        let mut local_req_builder =
458            local_client.request(reqwest::Method::GET, local_uri_str.as_str());
459
460        // build headers
461        let mut headers = HeaderMap::new();
462        headers.insert("Accept", HeaderValue::from_static("application/json"));
463
464        // build user agent
465        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
466            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
467            Err(e) => {
468                log::warn!("Failed to parse user agent header: {e}, falling back to default");
469                headers.insert(
470                    reqwest::header::USER_AGENT,
471                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
472                )
473            }
474        };
475
476        // build auth
477        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
478            headers.insert(
479                "DD-API-KEY",
480                HeaderValue::from_str(local_key.key.as_str())
481                    .expect("failed to parse DD-API-KEY header"),
482            );
483        };
484        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
485            headers.insert(
486                "DD-APPLICATION-KEY",
487                HeaderValue::from_str(local_key.key.as_str())
488                    .expect("failed to parse DD-APPLICATION-KEY header"),
489            );
490        };
491
492        local_req_builder = local_req_builder.headers(headers);
493        let local_req = local_req_builder.build()?;
494        log::debug!("request content: {:?}", local_req.body());
495        let local_resp = local_client.execute(local_req).await?;
496
497        let local_status = local_resp.status();
498        let local_content = local_resp.text().await?;
499        log::debug!("response content: {}", local_content);
500
501        if !local_status.is_client_error() && !local_status.is_server_error() {
502            match serde_json::from_str::<crate::datadogV2::model::FleetDeploymentResponse>(
503                &local_content,
504            ) {
505                Ok(e) => {
506                    return Ok(datadog::ResponseContent {
507                        status: local_status,
508                        content: local_content,
509                        entity: Some(e),
510                    })
511                }
512                Err(e) => return Err(datadog::Error::Serde(e)),
513            };
514        } else {
515            let local_entity: Option<GetFleetDeploymentError> =
516                serde_json::from_str(&local_content).ok();
517            let local_error = datadog::ResponseContent {
518                status: local_status,
519                content: local_content,
520                entity: local_entity,
521            };
522            Err(datadog::Error::ResponseError(local_error))
523        }
524    }
525
526    /// Retrieve a list of all deployments for fleet automation.
527    /// Use the `page_size` and `page_offset` parameters to paginate results.
528    pub async fn list_fleet_deployments(
529        &self,
530        params: ListFleetDeploymentsOptionalParams,
531    ) -> Result<
532        crate::datadogV2::model::FleetDeploymentsResponse,
533        datadog::Error<ListFleetDeploymentsError>,
534    > {
535        match self.list_fleet_deployments_with_http_info(params).await {
536            Ok(response_content) => {
537                if let Some(e) = response_content.entity {
538                    Ok(e)
539                } else {
540                    Err(datadog::Error::Serde(serde::de::Error::custom(
541                        "response content was None",
542                    )))
543                }
544            }
545            Err(err) => Err(err),
546        }
547    }
548
549    /// Retrieve a list of all deployments for fleet automation.
550    /// Use the `page_size` and `page_offset` parameters to paginate results.
551    pub async fn list_fleet_deployments_with_http_info(
552        &self,
553        params: ListFleetDeploymentsOptionalParams,
554    ) -> Result<
555        datadog::ResponseContent<crate::datadogV2::model::FleetDeploymentsResponse>,
556        datadog::Error<ListFleetDeploymentsError>,
557    > {
558        let local_configuration = &self.config;
559        let operation_id = "v2.list_fleet_deployments";
560        if local_configuration.is_unstable_operation_enabled(operation_id) {
561            warn!("Using unstable operation {operation_id}");
562        } else {
563            let local_error = datadog::UnstableOperationDisabledError {
564                msg: "Operation 'v2.list_fleet_deployments' is not enabled".to_string(),
565            };
566            return Err(datadog::Error::UnstableOperationDisabledError(local_error));
567        }
568
569        // unbox and build optional parameters
570        let page_size = params.page_size;
571        let page_offset = params.page_offset;
572
573        let local_client = &self.client;
574
575        let local_uri_str = format!(
576            "{}/api/unstable/fleet/deployments",
577            local_configuration.get_operation_host(operation_id)
578        );
579        let mut local_req_builder =
580            local_client.request(reqwest::Method::GET, local_uri_str.as_str());
581
582        if let Some(ref local_query_param) = page_size {
583            local_req_builder =
584                local_req_builder.query(&[("page_size", &local_query_param.to_string())]);
585        };
586        if let Some(ref local_query_param) = page_offset {
587            local_req_builder =
588                local_req_builder.query(&[("page_offset", &local_query_param.to_string())]);
589        };
590
591        // build headers
592        let mut headers = HeaderMap::new();
593        headers.insert("Accept", HeaderValue::from_static("application/json"));
594
595        // build user agent
596        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
597            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
598            Err(e) => {
599                log::warn!("Failed to parse user agent header: {e}, falling back to default");
600                headers.insert(
601                    reqwest::header::USER_AGENT,
602                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
603                )
604            }
605        };
606
607        // build auth
608        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
609            headers.insert(
610                "DD-API-KEY",
611                HeaderValue::from_str(local_key.key.as_str())
612                    .expect("failed to parse DD-API-KEY header"),
613            );
614        };
615        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
616            headers.insert(
617                "DD-APPLICATION-KEY",
618                HeaderValue::from_str(local_key.key.as_str())
619                    .expect("failed to parse DD-APPLICATION-KEY header"),
620            );
621        };
622
623        local_req_builder = local_req_builder.headers(headers);
624        let local_req = local_req_builder.build()?;
625        log::debug!("request content: {:?}", local_req.body());
626        let local_resp = local_client.execute(local_req).await?;
627
628        let local_status = local_resp.status();
629        let local_content = local_resp.text().await?;
630        log::debug!("response content: {}", local_content);
631
632        if !local_status.is_client_error() && !local_status.is_server_error() {
633            match serde_json::from_str::<crate::datadogV2::model::FleetDeploymentsResponse>(
634                &local_content,
635            ) {
636                Ok(e) => {
637                    return Ok(datadog::ResponseContent {
638                        status: local_status,
639                        content: local_content,
640                        entity: Some(e),
641                    })
642                }
643                Err(e) => return Err(datadog::Error::Serde(e)),
644            };
645        } else {
646            let local_entity: Option<ListFleetDeploymentsError> =
647                serde_json::from_str(&local_content).ok();
648            let local_error = datadog::ResponseContent {
649                status: local_status,
650                content: local_content,
651                entity: local_entity,
652            };
653            Err(datadog::Error::ResponseError(local_error))
654        }
655    }
656}