diff --git a/.generated-info b/.generated-info index ec07df810..5277337dd 100644 --- a/.generated-info +++ b/.generated-info @@ -1,4 +1,4 @@ { - "spec_repo_commit": "df31e44", - "generated": "2025-07-28 19:59:31.744" + "spec_repo_commit": "2f91666", + "generated": "2025-07-29 21:59:14.839" } diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index c26c8055f..b4dff0ae8 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -12939,6 +12939,42 @@ components: description: The type of the resource. The value should always be device. type: string type: object + DnsMetricKey: + description: The metric key for DNS metrics. + enum: + - dns_total_requests + - dns_failures + - dns_successful_responses + - dns_failed_responses + - dns_timeouts + - dns_responses.nxdomain + - dns_responses.servfail + - dns_responses.other + - dns_success_latency_percentile + - dns_failure_latency_percentile + type: string + x-enum-descriptions: + - The total number of DNS requests made by the client. + - The total number of timeouts and errors in DNS requests. + - The total number of successful DNS responses. + - The total number of failed DNS responses. + - The total number of DNS timeouts. + - The total number of DNS responses with the NXDOMAIN error code. + - The total number of DNS responses with the SERVFAIL error code. + - The total number of DNS responses with other error codes. + - The latency percentile for successful DNS responses. + - The latency percentile for failed DNS responses. + x-enum-varnames: + - DNS_TOTAL_REQUESTS + - DNS_FAILURES + - DNS_SUCCESSFUL_RESPONSES + - DNS_FAILED_RESPONSES + - DNS_TIMEOUTS + - DNS_RESPONSES_NXDOMAIN + - DNS_RESPONSES_SERVFAIL + - DNS_RESPONSES_OTHER + - DNS_SUCCESS_LATENCY_PERCENTILE + - DNS_FAILURE_LATENCY_PERCENTILE DomainAllowlist: description: The email domain allowlist for an org. properties: @@ -38433,6 +38469,100 @@ components: type: string x-enum-varnames: - AGGREGATED_CONNECTION + SingleAggregatedDnsResponseArray: + description: List of aggregated DNS flows. + example: + data: + - attributes: + group_bys: + - key: client_service + value: example-service + - key: network.dns_query + value: example.com + metrics: + - key: dns_total_requests + value: 100 + - key: dns_failures + value: 7 + - key: dns_successful_responses + value: 93 + - key: dns_failed_responses + value: 5 + - key: dns_timeouts + value: 2 + - key: dns_responses.nxdomain + value: 1 + - key: dns_responses.servfail + value: 1 + - key: dns_responses.other + value: 3 + - key: dns_success_latency_percentile + value: 50 + - key: dns_failure_latency_percentile + value: 75 + id: client_service:example-service,network.dns_query:example.com + type: aggregated_dns + properties: + data: + description: Array of aggregated DNS objects. + items: + $ref: '#/components/schemas/SingleAggregatedDnsResponseData' + type: array + type: object + SingleAggregatedDnsResponseData: + description: Object describing an aggregated DNS flow. + properties: + attributes: + $ref: '#/components/schemas/SingleAggregatedDnsResponseDataAttributes' + id: + description: A unique identifier for the aggregated DNS traffic based on + the group by values. + type: string + type: + $ref: '#/components/schemas/SingleAggregatedDnsResponseDataType' + type: object + SingleAggregatedDnsResponseDataAttributes: + description: Attributes for an aggregated DNS flow. + properties: + group_bys: + description: The key, value pairs for each group by. + items: + $ref: '#/components/schemas/SingleAggregatedDnsResponseDataAttributesGroupByItems' + type: array + metrics: + description: Metrics associated with an aggregated DNS flow. + items: + $ref: '#/components/schemas/SingleAggregatedDnsResponseDataAttributesMetricsItems' + type: array + type: object + SingleAggregatedDnsResponseDataAttributesGroupByItems: + description: Attributes associated with a group by + properties: + key: + description: The group by key. + type: string + value: + description: The group by value. + type: string + type: object + SingleAggregatedDnsResponseDataAttributesMetricsItems: + description: Metrics associated with an aggregated DNS flow. + properties: + key: + $ref: '#/components/schemas/DnsMetricKey' + value: + description: The metric value. + format: int64 + type: integer + type: object + SingleAggregatedDnsResponseDataType: + default: aggregated_dns + description: Aggregated DNS resource type. + enum: + - aggregated_dns + type: string + x-enum-varnames: + - AGGREGATED_DNS SlackIntegrationMetadata: description: Incident integration metadata for the Slack integration. properties: @@ -55093,7 +55223,7 @@ paths: schema: type: string - description: The number of connections to be returned. The maximum value is - 7500. + 7500. The default is 100. in: query name: limit schema: @@ -55119,6 +55249,69 @@ paths: x-unstable: '**Note**: This endpoint is in Preview. If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' + /api/v2/network/dns/aggregate: + get: + description: Get all aggregated DNS traffic. + operationId: GetAggregatedDns + parameters: + - description: Unix timestamp (number of seconds since epoch) of the start of + the query window. If not provided, the start of the query window is 15 minutes + before the `to` timestamp. If neither `from` nor `to` are provided, the + query window is `[now - 15m, now]`. + in: query + name: from + schema: + format: int64 + type: integer + - description: Unix timestamp (number of seconds since epoch) of the end of + the query window. If not provided, the end of the query window is the current + time. If neither `from` nor `to` are provided, the query window is `[now + - 15m, now]`. + in: query + name: to + schema: + format: int64 + type: integer + - description: Comma-separated list of fields to group DNS traffic by. The server + side defaults to `network.dns_query` if unspecified. `server_ungrouped` + may be used if groups are not desired. The maximum number of group_by(s) + is 10. + in: query + name: group_by + schema: + type: string + - description: Comma-separated list of tags to filter DNS traffic by. + in: query + name: tags + schema: + type: string + - description: The number of aggregated DNS entries to be returned. The maximum + value is 7500. The default is 100. + in: query + name: limit + schema: + default: 100 + format: int32 + maximum: 7500 + minimum: 1 + type: integer + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/SingleAggregatedDnsResponseArray' + description: OK + '400': + $ref: '#/components/responses/BadRequestResponse' + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + summary: Get all aggregated DNS traffic + tags: + - Cloud Network Monitoring + x-unstable: '**Note**: This endpoint is in Preview. If you have any feedback, + + contact [Datadog support](https://docs.datadoghq.com/help/).' /api/v2/on-call/escalation-policies: post: description: Create a new On-Call escalation policy @@ -65906,7 +66099,8 @@ tags: documentation](https://docs.datadoghq.com/cloud_cost_management/). name: Cloud Cost Management - description: The Cloud Network Monitoring API allows you to fetch aggregated connections - and their attributes. See the [Cloud Network Monitoring page](https://docs.datadoghq.com/network_monitoring/cloud_network_monitoring/) + and DNS traffic with their attributes. See the [Cloud Network Monitoring page](https://docs.datadoghq.com/network_monitoring/cloud_network_monitoring/) + and [DNS Monitoring page](https://docs.datadoghq.com/network_monitoring/dns/) for more information. name: Cloud Network Monitoring - description: Manage your Datadog Cloudflare integration directly through the Datadog diff --git a/examples/v2_cloud-network-monitoring_GetAggregatedDns.rs b/examples/v2_cloud-network-monitoring_GetAggregatedDns.rs new file mode 100644 index 000000000..34b95e8e9 --- /dev/null +++ b/examples/v2_cloud-network-monitoring_GetAggregatedDns.rs @@ -0,0 +1,19 @@ +// Get all aggregated DNS traffic returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_cloud_network_monitoring::CloudNetworkMonitoringAPI; +use datadog_api_client::datadogV2::api_cloud_network_monitoring::GetAggregatedDnsOptionalParams; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.GetAggregatedDns", true); + let api = CloudNetworkMonitoringAPI::with_config(configuration); + let resp = api + .get_aggregated_dns(GetAggregatedDnsOptionalParams::default()) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs index f555f02d6..02acc9120 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -186,6 +186,7 @@ impl Default for Configuration { ), ("v2.validate_monitor_user_template".to_owned(), false), ("v2.get_aggregated_connections".to_owned(), false), + ("v2.get_aggregated_dns".to_owned(), false), ("v2.create_pipeline".to_owned(), false), ("v2.delete_pipeline".to_owned(), false), ("v2.get_pipeline".to_owned(), false), diff --git a/src/datadogV2/api/api_cloud_network_monitoring.rs b/src/datadogV2/api/api_cloud_network_monitoring.rs index 8d034d065..37b2a16ad 100644 --- a/src/datadogV2/api/api_cloud_network_monitoring.rs +++ b/src/datadogV2/api/api_cloud_network_monitoring.rs @@ -18,7 +18,7 @@ pub struct GetAggregatedConnectionsOptionalParams { pub group_by: Option, /// Comma-separated list of tags to filter connections by. pub tags: Option, - /// The number of connections to be returned. The maximum value is 7500. + /// The number of connections to be returned. The maximum value is 7500. The default is 100. pub limit: Option, } @@ -43,7 +43,51 @@ impl GetAggregatedConnectionsOptionalParams { self.tags = Some(value); self } - /// The number of connections to be returned. The maximum value is 7500. + /// The number of connections to be returned. The maximum value is 7500. The default is 100. + pub fn limit(mut self, value: i32) -> Self { + self.limit = Some(value); + self + } +} + +/// GetAggregatedDnsOptionalParams is a struct for passing parameters to the method [`CloudNetworkMonitoringAPI::get_aggregated_dns`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct GetAggregatedDnsOptionalParams { + /// Unix timestamp (number of seconds since epoch) of the start of the query window. If not provided, the start of the query window is 15 minutes before the `to` timestamp. If neither `from` nor `to` are provided, the query window is `[now - 15m, now]`. + pub from: Option, + /// Unix timestamp (number of seconds since epoch) of the end of the query window. If not provided, the end of the query window is the current time. If neither `from` nor `to` are provided, the query window is `[now - 15m, now]`. + pub to: Option, + /// Comma-separated list of fields to group DNS traffic by. The server side defaults to `network.dns_query` if unspecified. `server_ungrouped` may be used if groups are not desired. The maximum number of group_by(s) is 10. + pub group_by: Option, + /// Comma-separated list of tags to filter DNS traffic by. + pub tags: Option, + /// The number of aggregated DNS entries to be returned. The maximum value is 7500. The default is 100. + pub limit: Option, +} + +impl GetAggregatedDnsOptionalParams { + /// Unix timestamp (number of seconds since epoch) of the start of the query window. If not provided, the start of the query window is 15 minutes before the `to` timestamp. If neither `from` nor `to` are provided, the query window is `[now - 15m, now]`. + pub fn from(mut self, value: i64) -> Self { + self.from = Some(value); + self + } + /// Unix timestamp (number of seconds since epoch) of the end of the query window. If not provided, the end of the query window is the current time. If neither `from` nor `to` are provided, the query window is `[now - 15m, now]`. + pub fn to(mut self, value: i64) -> Self { + self.to = Some(value); + self + } + /// Comma-separated list of fields to group DNS traffic by. The server side defaults to `network.dns_query` if unspecified. `server_ungrouped` may be used if groups are not desired. The maximum number of group_by(s) is 10. + pub fn group_by(mut self, value: String) -> Self { + self.group_by = Some(value); + self + } + /// Comma-separated list of tags to filter DNS traffic by. + pub fn tags(mut self, value: String) -> Self { + self.tags = Some(value); + self + } + /// The number of aggregated DNS entries to be returned. The maximum value is 7500. The default is 100. pub fn limit(mut self, value: i32) -> Self { self.limit = Some(value); self @@ -58,7 +102,15 @@ pub enum GetAggregatedConnectionsError { UnknownValue(serde_json::Value), } -/// The Cloud Network Monitoring API allows you to fetch aggregated connections and their attributes. See the [Cloud Network Monitoring page]() for more information. +/// GetAggregatedDnsError is a struct for typed errors of method [`CloudNetworkMonitoringAPI::get_aggregated_dns`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetAggregatedDnsError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// The Cloud Network Monitoring API allows you to fetch aggregated connections and DNS traffic with their attributes. See the [Cloud Network Monitoring page]() and [DNS Monitoring page]() for more information. #[derive(Debug, Clone)] pub struct CloudNetworkMonitoringAPI { config: datadog::Configuration, @@ -266,4 +318,147 @@ impl CloudNetworkMonitoringAPI { Err(datadog::Error::ResponseError(local_error)) } } + + /// Get all aggregated DNS traffic. + pub async fn get_aggregated_dns( + &self, + params: GetAggregatedDnsOptionalParams, + ) -> Result< + crate::datadogV2::model::SingleAggregatedDnsResponseArray, + datadog::Error, + > { + match self.get_aggregated_dns_with_http_info(params).await { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + /// Get all aggregated DNS traffic. + pub async fn get_aggregated_dns_with_http_info( + &self, + params: GetAggregatedDnsOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_aggregated_dns"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.get_aggregated_dns' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + // unbox and build optional parameters + let from = params.from; + let to = params.to; + let group_by = params.group_by; + let tags = params.tags; + let limit = params.limit; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/network/dns/aggregate", + local_configuration.get_operation_host(operation_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + if let Some(ref local_query_param) = from { + local_req_builder = + local_req_builder.query(&[("from", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = to { + local_req_builder = local_req_builder.query(&[("to", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = group_by { + local_req_builder = + local_req_builder.query(&[("group_by", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = tags { + local_req_builder = + local_req_builder.query(&[("tags", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = limit { + local_req_builder = + local_req_builder.query(&[("limit", &local_query_param.to_string())]); + }; + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = + serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } } diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index d2d2ead3d..d76c8d330 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -2794,6 +2794,20 @@ pub mod model_single_aggregated_connection_response_data_attributes; pub use self::model_single_aggregated_connection_response_data_attributes::SingleAggregatedConnectionResponseDataAttributes; pub mod model_single_aggregated_connection_response_data_type; pub use self::model_single_aggregated_connection_response_data_type::SingleAggregatedConnectionResponseDataType; +pub mod model_single_aggregated_dns_response_array; +pub use self::model_single_aggregated_dns_response_array::SingleAggregatedDnsResponseArray; +pub mod model_single_aggregated_dns_response_data; +pub use self::model_single_aggregated_dns_response_data::SingleAggregatedDnsResponseData; +pub mod model_single_aggregated_dns_response_data_attributes; +pub use self::model_single_aggregated_dns_response_data_attributes::SingleAggregatedDnsResponseDataAttributes; +pub mod model_single_aggregated_dns_response_data_attributes_group_by_items; +pub use self::model_single_aggregated_dns_response_data_attributes_group_by_items::SingleAggregatedDnsResponseDataAttributesGroupByItems; +pub mod model_single_aggregated_dns_response_data_attributes_metrics_items; +pub use self::model_single_aggregated_dns_response_data_attributes_metrics_items::SingleAggregatedDnsResponseDataAttributesMetricsItems; +pub mod model_dns_metric_key; +pub use self::model_dns_metric_key::DnsMetricKey; +pub mod model_single_aggregated_dns_response_data_type; +pub use self::model_single_aggregated_dns_response_data_type::SingleAggregatedDnsResponseDataType; pub mod model_escalation_policy_create_request; pub use self::model_escalation_policy_create_request::EscalationPolicyCreateRequest; pub mod model_escalation_policy_create_request_data; diff --git a/src/datadogV2/model/model_dns_metric_key.rs b/src/datadogV2/model/model_dns_metric_key.rs new file mode 100644 index 000000000..67d9a61ff --- /dev/null +++ b/src/datadogV2/model/model_dns_metric_key.rs @@ -0,0 +1,75 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum DnsMetricKey { + DNS_TOTAL_REQUESTS, + DNS_FAILURES, + DNS_SUCCESSFUL_RESPONSES, + DNS_FAILED_RESPONSES, + DNS_TIMEOUTS, + DNS_RESPONSES_NXDOMAIN, + DNS_RESPONSES_SERVFAIL, + DNS_RESPONSES_OTHER, + DNS_SUCCESS_LATENCY_PERCENTILE, + DNS_FAILURE_LATENCY_PERCENTILE, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for DnsMetricKey { + fn to_string(&self) -> String { + match self { + Self::DNS_TOTAL_REQUESTS => String::from("dns_total_requests"), + Self::DNS_FAILURES => String::from("dns_failures"), + Self::DNS_SUCCESSFUL_RESPONSES => String::from("dns_successful_responses"), + Self::DNS_FAILED_RESPONSES => String::from("dns_failed_responses"), + Self::DNS_TIMEOUTS => String::from("dns_timeouts"), + Self::DNS_RESPONSES_NXDOMAIN => String::from("dns_responses.nxdomain"), + Self::DNS_RESPONSES_SERVFAIL => String::from("dns_responses.servfail"), + Self::DNS_RESPONSES_OTHER => String::from("dns_responses.other"), + Self::DNS_SUCCESS_LATENCY_PERCENTILE => String::from("dns_success_latency_percentile"), + Self::DNS_FAILURE_LATENCY_PERCENTILE => String::from("dns_failure_latency_percentile"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for DnsMetricKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for DnsMetricKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "dns_total_requests" => Self::DNS_TOTAL_REQUESTS, + "dns_failures" => Self::DNS_FAILURES, + "dns_successful_responses" => Self::DNS_SUCCESSFUL_RESPONSES, + "dns_failed_responses" => Self::DNS_FAILED_RESPONSES, + "dns_timeouts" => Self::DNS_TIMEOUTS, + "dns_responses.nxdomain" => Self::DNS_RESPONSES_NXDOMAIN, + "dns_responses.servfail" => Self::DNS_RESPONSES_SERVFAIL, + "dns_responses.other" => Self::DNS_RESPONSES_OTHER, + "dns_success_latency_percentile" => Self::DNS_SUCCESS_LATENCY_PERCENTILE, + "dns_failure_latency_percentile" => Self::DNS_FAILURE_LATENCY_PERCENTILE, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_array.rs b/src/datadogV2/model/model_single_aggregated_dns_response_array.rs new file mode 100644 index 000000000..bccb31f91 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_array.rs @@ -0,0 +1,110 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// List of aggregated DNS flows. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SingleAggregatedDnsResponseArray { + /// Array of aggregated DNS objects. + #[serde(rename = "data")] + pub data: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SingleAggregatedDnsResponseArray { + pub fn new() -> SingleAggregatedDnsResponseArray { + SingleAggregatedDnsResponseArray { + data: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data( + mut self, + value: Vec, + ) -> Self { + self.data = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for SingleAggregatedDnsResponseArray { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseArray { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SingleAggregatedDnsResponseArrayVisitor; + impl<'a> Visitor<'a> for SingleAggregatedDnsResponseArrayVisitor { + type Value = SingleAggregatedDnsResponseArray; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut data: Option< + Vec, + > = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "data" => { + if v.is_null() { + continue; + } + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = SingleAggregatedDnsResponseArray { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SingleAggregatedDnsResponseArrayVisitor) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_data.rs b/src/datadogV2/model/model_single_aggregated_dns_response_data.rs new file mode 100644 index 000000000..d4e8ea079 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_data.rs @@ -0,0 +1,157 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Object describing an aggregated DNS flow. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SingleAggregatedDnsResponseData { + /// Attributes for an aggregated DNS flow. + #[serde(rename = "attributes")] + pub attributes: Option, + /// A unique identifier for the aggregated DNS traffic based on the group by values. + #[serde(rename = "id")] + pub id: Option, + /// Aggregated DNS resource type. + #[serde(rename = "type")] + pub type_: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SingleAggregatedDnsResponseData { + pub fn new() -> SingleAggregatedDnsResponseData { + SingleAggregatedDnsResponseData { + attributes: None, + id: None, + type_: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn attributes( + mut self, + value: crate::datadogV2::model::SingleAggregatedDnsResponseDataAttributes, + ) -> Self { + self.attributes = Some(value); + self + } + + pub fn id(mut self, value: String) -> Self { + self.id = Some(value); + self + } + + pub fn type_( + mut self, + value: crate::datadogV2::model::SingleAggregatedDnsResponseDataType, + ) -> Self { + self.type_ = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for SingleAggregatedDnsResponseData { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SingleAggregatedDnsResponseDataVisitor; + impl<'a> Visitor<'a> for SingleAggregatedDnsResponseDataVisitor { + type Value = SingleAggregatedDnsResponseData; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut attributes: Option< + crate::datadogV2::model::SingleAggregatedDnsResponseDataAttributes, + > = None; + let mut id: Option = None; + let mut type_: Option< + crate::datadogV2::model::SingleAggregatedDnsResponseDataType, + > = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "attributes" => { + if v.is_null() { + continue; + } + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "id" => { + if v.is_null() { + continue; + } + id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + if v.is_null() { + continue; + } + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::SingleAggregatedDnsResponseDataType::UnparsedObject(_type_) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = SingleAggregatedDnsResponseData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SingleAggregatedDnsResponseDataVisitor) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes.rs b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes.rs new file mode 100644 index 000000000..5dfc88f19 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes.rs @@ -0,0 +1,130 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes for an aggregated DNS flow. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SingleAggregatedDnsResponseDataAttributes { + /// The key, value pairs for each group by. + #[serde(rename = "group_bys")] + pub group_bys: + Option>, + /// Metrics associated with an aggregated DNS flow. + #[serde(rename = "metrics")] + pub metrics: + Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SingleAggregatedDnsResponseDataAttributes { + pub fn new() -> SingleAggregatedDnsResponseDataAttributes { + SingleAggregatedDnsResponseDataAttributes { + group_bys: None, + metrics: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn group_bys( + mut self, + value: Vec, + ) -> Self { + self.group_bys = Some(value); + self + } + + pub fn metrics( + mut self, + value: Vec, + ) -> Self { + self.metrics = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for SingleAggregatedDnsResponseDataAttributes { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseDataAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SingleAggregatedDnsResponseDataAttributesVisitor; + impl<'a> Visitor<'a> for SingleAggregatedDnsResponseDataAttributesVisitor { + type Value = SingleAggregatedDnsResponseDataAttributes; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut group_bys: Option> = None; + let mut metrics: Option> = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "group_bys" => { + if v.is_null() { + continue; + } + group_bys = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "metrics" => { + if v.is_null() { + continue; + } + metrics = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = SingleAggregatedDnsResponseDataAttributes { + group_bys, + metrics, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SingleAggregatedDnsResponseDataAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_group_by_items.rs b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_group_by_items.rs new file mode 100644 index 000000000..b5d4ebab8 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_group_by_items.rs @@ -0,0 +1,122 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes associated with a group by +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SingleAggregatedDnsResponseDataAttributesGroupByItems { + /// The group by key. + #[serde(rename = "key")] + pub key: Option, + /// The group by value. + #[serde(rename = "value")] + pub value: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SingleAggregatedDnsResponseDataAttributesGroupByItems { + pub fn new() -> SingleAggregatedDnsResponseDataAttributesGroupByItems { + SingleAggregatedDnsResponseDataAttributesGroupByItems { + key: None, + value: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn key(mut self, value: String) -> Self { + self.key = Some(value); + self + } + + pub fn value(mut self, value: String) -> Self { + self.value = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for SingleAggregatedDnsResponseDataAttributesGroupByItems { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseDataAttributesGroupByItems { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SingleAggregatedDnsResponseDataAttributesGroupByItemsVisitor; + impl<'a> Visitor<'a> for SingleAggregatedDnsResponseDataAttributesGroupByItemsVisitor { + type Value = SingleAggregatedDnsResponseDataAttributesGroupByItems; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut key: Option = None; + let mut value: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "key" => { + if v.is_null() { + continue; + } + key = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "value" => { + if v.is_null() { + continue; + } + value = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = SingleAggregatedDnsResponseDataAttributesGroupByItems { + key, + value, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SingleAggregatedDnsResponseDataAttributesGroupByItemsVisitor) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_metrics_items.rs b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_metrics_items.rs new file mode 100644 index 000000000..e555dc6e5 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_data_attributes_metrics_items.rs @@ -0,0 +1,130 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Metrics associated with an aggregated DNS flow. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct SingleAggregatedDnsResponseDataAttributesMetricsItems { + /// The metric key for DNS metrics. + #[serde(rename = "key")] + pub key: Option, + /// The metric value. + #[serde(rename = "value")] + pub value: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl SingleAggregatedDnsResponseDataAttributesMetricsItems { + pub fn new() -> SingleAggregatedDnsResponseDataAttributesMetricsItems { + SingleAggregatedDnsResponseDataAttributesMetricsItems { + key: None, + value: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn key(mut self, value: crate::datadogV2::model::DnsMetricKey) -> Self { + self.key = Some(value); + self + } + + pub fn value(mut self, value: i64) -> Self { + self.value = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for SingleAggregatedDnsResponseDataAttributesMetricsItems { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseDataAttributesMetricsItems { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct SingleAggregatedDnsResponseDataAttributesMetricsItemsVisitor; + impl<'a> Visitor<'a> for SingleAggregatedDnsResponseDataAttributesMetricsItemsVisitor { + type Value = SingleAggregatedDnsResponseDataAttributesMetricsItems; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut key: Option = None; + let mut value: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "key" => { + if v.is_null() { + continue; + } + key = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _key) = key { + match _key { + crate::datadogV2::model::DnsMetricKey::UnparsedObject(_key) => { + _unparsed = true; + } + _ => {} + } + } + } + "value" => { + if v.is_null() { + continue; + } + value = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = SingleAggregatedDnsResponseDataAttributesMetricsItems { + key, + value, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(SingleAggregatedDnsResponseDataAttributesMetricsItemsVisitor) + } +} diff --git a/src/datadogV2/model/model_single_aggregated_dns_response_data_type.rs b/src/datadogV2/model/model_single_aggregated_dns_response_data_type.rs new file mode 100644 index 000000000..f4c35f758 --- /dev/null +++ b/src/datadogV2/model/model_single_aggregated_dns_response_data_type.rs @@ -0,0 +1,48 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum SingleAggregatedDnsResponseDataType { + AGGREGATED_DNS, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for SingleAggregatedDnsResponseDataType { + fn to_string(&self) -> String { + match self { + Self::AGGREGATED_DNS => String::from("aggregated_dns"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for SingleAggregatedDnsResponseDataType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for SingleAggregatedDnsResponseDataType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "aggregated_dns" => Self::AGGREGATED_DNS, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.frozen new file mode 100644 index 000000000..93894bd9f --- /dev/null +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.frozen @@ -0,0 +1 @@ +2025-07-25T20:54:53.474Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.json new file mode 100644 index 000000000..1178d3a76 --- /dev/null +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-Bad-Request-response.json @@ -0,0 +1,33 @@ +{ + "http_interactions": [ + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "get", + "uri": "https://api.datadoghq.com/api/v2/network/dns/aggregate?group_by=server_ungrouped%2Cserver_service" + }, + "response": { + "body": { + "string": "{\"errors\":[{\"status\":\"400\",\"title\":\"Cannot combine server_ungrouped with other server groupings or network.dns_query\"}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 400, + "message": "Bad Request" + } + }, + "recorded_at": "Fri, 25 Jul 2025 20:54:53 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.frozen new file mode 100644 index 000000000..5d59f9b39 --- /dev/null +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.frozen @@ -0,0 +1 @@ +2025-07-25T20:54:53.819Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.json b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.json new file mode 100644 index 000000000..590a83514 --- /dev/null +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-DNS-traffic-returns-OK-response.json @@ -0,0 +1,33 @@ +{ + "http_interactions": [ + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "get", + "uri": "https://api.datadoghq.com/api/v2/network/dns/aggregate" + }, + "response": { + "body": { + "string": "{\"data\":[]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 25 Jul 2025 20:54:53 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.frozen index ca4c2f607..e555d1467 100644 --- a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.frozen +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.frozen @@ -1 +1 @@ -2025-03-31T18:18:50.770Z \ No newline at end of file +2025-07-25T20:54:53.978Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.json index fd85051a0..e4ad1252c 100644 --- a/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.json +++ b/tests/scenarios/cassettes/v2/cloud_network_monitoring/Get-all-aggregated-connections-returns-Bad-Request-response.json @@ -9,11 +9,11 @@ ] }, "method": "get", - "uri": "https://api.datadoghq.com/api/v2/network/connections/aggregate?limit=6000" + "uri": "https://api.datadoghq.com/api/v2/network/connections/aggregate?limit=8000" }, "response": { "body": { - "string": "{\"errors\":[{\"status\":\"400\",\"title\":\"Invalid limit\"}]}", + "string": "{\"errors\":[{\"status\":\"400\",\"title\":\"Invalid limit\",\"detail\":\"Limit must meet requirements listed in https://docs.datadoghq.com/api/latest/cloud-network-monitoring/\"}]}", "encoding": null }, "headers": { @@ -26,7 +26,7 @@ "message": "Bad Request" } }, - "recorded_at": "Mon, 31 Mar 2025 18:18:50 GMT" + "recorded_at": "Fri, 25 Jul 2025 20:54:53 GMT" } ], "recorded_with": "VCR 6.0.0" diff --git a/tests/scenarios/features/v2/cloud_network_monitoring.feature b/tests/scenarios/features/v2/cloud_network_monitoring.feature index 11e44ca18..feabf8845 100644 --- a/tests/scenarios/features/v2/cloud_network_monitoring.feature +++ b/tests/scenarios/features/v2/cloud_network_monitoring.feature @@ -1,29 +1,50 @@ @endpoint(cloud-network-monitoring) @endpoint(cloud-network-monitoring-v2) Feature: Cloud Network Monitoring The Cloud Network Monitoring API allows you to fetch aggregated - connections and their attributes. See the [Cloud Network Monitoring page]( - https://docs.datadoghq.com/network_monitoring/cloud_network_monitoring/) - for more information. + connections and DNS traffic with their attributes. See the [Cloud Network + Monitoring page](https://docs.datadoghq.com/network_monitoring/cloud_netwo + rk_monitoring/) and [DNS Monitoring + page](https://docs.datadoghq.com/network_monitoring/dns/) for more + information. Background: Given a valid "apiKeyAuth" key in the system And a valid "appKeyAuth" key in the system And an instance of "CloudNetworkMonitoring" API - And operation "GetAggregatedConnections" enabled - And new "GetAggregatedConnections" request @team:Datadog/networks Scenario: Get aggregated connections returns "OK" response + Given operation "GetAggregatedConnections" enabled + And new "GetAggregatedConnections" request + When the request is sent + Then the response status is 200 OK + + @team:Datadog/networks + Scenario: Get all aggregated DNS traffic returns "Bad Request" response + Given operation "GetAggregatedDns" enabled + And new "GetAggregatedDns" request + And request contains "group_by" parameter with value "server_ungrouped,server_service" + When the request is sent + Then the response status is 400 Bad Request + + @team:Datadog/networks + Scenario: Get all aggregated DNS traffic returns "OK" response + Given operation "GetAggregatedDns" enabled + And new "GetAggregatedDns" request When the request is sent Then the response status is 200 OK @skip-python @skip-ruby @team:Datadog/networks Scenario: Get all aggregated connections returns "Bad Request" response - Given request contains "limit" parameter with value 6000 + Given operation "GetAggregatedConnections" enabled + And new "GetAggregatedConnections" request + And request contains "limit" parameter with value 8000 When the request is sent Then the response status is 400 Bad Request @generated @skip @team:Datadog/networks Scenario: Get all aggregated connections returns "OK" response + Given operation "GetAggregatedConnections" enabled + And new "GetAggregatedConnections" request When the request is sent Then the response status is 200 OK diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index a1fe13fed..f278c5774 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -2078,6 +2078,12 @@ "type": "safe" } }, + "GetAggregatedDns": { + "tag": "Cloud Network Monitoring", + "undo": { + "type": "safe" + } + }, "CreateOnCallEscalationPolicy": { "tag": "On-Call", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 7d328ca53..4ebcdbf5d 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -3116,6 +3116,9 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.GetAggregatedConnections".into(), test_v2_get_aggregated_connections, ); + world + .function_mappings + .insert("v2.GetAggregatedDns".into(), test_v2_get_aggregated_dns); world.function_mappings.insert( "v2.CreateOnCallEscalationPolicy".into(), test_v2_create_on_call_escalation_policy, @@ -23593,6 +23596,52 @@ fn test_v2_get_aggregated_connections( world.response.code = response.status.as_u16(); } +fn test_v2_get_aggregated_dns(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_cloud_network_monitoring + .as_ref() + .expect("api instance not found"); + let from = _parameters + .get("from") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let to = _parameters + .get("to") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let group_by = _parameters + .get("group_by") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let tags = _parameters + .get("tags") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let limit = _parameters + .get("limit") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = + datadogV2::api_cloud_network_monitoring::GetAggregatedDnsOptionalParams::default(); + params.from = from; + params.to = to; + params.group_by = group_by; + params.tags = tags; + params.limit = limit; + let response = match block_on(api.get_aggregated_dns_with_http_info(params)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + fn test_v2_create_on_call_escalation_policy( world: &mut DatadogWorld, _parameters: &HashMap,