diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 42168cb0f..095006c0c 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -51339,6 +51339,49 @@ components: $ref: '#/components/schemas/ServiceDefinitionData' type: array type: object + ServiceList: + properties: + data: + $ref: '#/components/schemas/ServiceListData' + type: object + ServiceListData: + properties: + attributes: + $ref: '#/components/schemas/ServiceListDataAttributes' + id: + type: string + type: + $ref: '#/components/schemas/ServiceListDataType' + required: + - type + type: object + ServiceListDataAttributes: + properties: + metadata: + items: + $ref: '#/components/schemas/ServiceListDataAttributesMetadataItems' + type: array + services: + items: + type: string + type: array + type: object + ServiceListDataAttributesMetadataItems: + properties: + isTraced: + type: boolean + isUsm: + type: boolean + type: object + ServiceListDataType: + default: services_list + description: Services list resource type. + enum: + - services_list + example: services_list + type: string + x-enum-varnames: + - SERVICES_LIST ServiceNowBasicAuth: description: The definition of the `ServiceNowBasicAuth` object. properties: @@ -61601,6 +61644,26 @@ paths: permissions: - apm_retention_filter_write - apm_pipelines_write + /api/v2/apm/services: + get: + operationId: GetServiceList + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/ServiceList' + description: OK + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - apm_read + summary: Get service list + tags: + - APM /api/v2/app-builder/apps: delete: description: Delete multiple apps in a single request from a list of app IDs. @@ -69334,9 +69397,6 @@ paths: operator: OR permissions: - incident_read - x-unstable: '**Note**: This endpoint is in Preview. - - If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' post: description: Create an impact for an incident. operationId: CreateIncidentImpact @@ -69380,9 +69440,6 @@ paths: operator: OR permissions: - incident_write - x-unstable: '**Note**: This endpoint is in Preview. - - If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' /api/v2/incidents/{incident_id}/impacts/{impact_id}: delete: description: Delete an incident impact. @@ -69413,9 +69470,6 @@ paths: operator: OR permissions: - incident_write - x-unstable: '**Note**: This endpoint is in Preview. - - If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' /api/v2/incidents/{incident_id}/relationships/integrations: get: description: Get all integration metadata for an incident. @@ -88586,6 +88640,9 @@ servers: tags: - description: Configure your API endpoints through the Datadog API. name: API Management +- description: Observe, troubleshoot, and improve cloud-scale applications with all + telemetry in context + name: APM - description: Manage configuration of [APM retention filters](https://app.datadoghq.com/apm/traces/retention-filters) for your organization. You need an API and application key with Admin rights to interact with this endpoint. See [retention filters](https://docs.datadoghq.com/tracing/trace_pipeline/trace_retention/#retention-filters) diff --git a/examples/v2_apm_GetServiceList.rs b/examples/v2_apm_GetServiceList.rs new file mode 100644 index 000000000..8f56375c9 --- /dev/null +++ b/examples/v2_apm_GetServiceList.rs @@ -0,0 +1,15 @@ +// Get service list returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_apm::APMAPI; + +#[tokio::main] +async fn main() { + let configuration = datadog::Configuration::new(); + let api = APMAPI::with_config(configuration); + let resp = api.get_service_list().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 f343078c3..270c6c2a0 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -188,14 +188,12 @@ impl Default for Configuration { ("v2.update_deployment_gate".to_owned(), false), ("v2.update_deployment_rule".to_owned(), false), ("v2.create_incident".to_owned(), false), - ("v2.create_incident_impact".to_owned(), false), ("v2.create_incident_integration".to_owned(), false), ("v2.create_incident_notification_rule".to_owned(), false), ("v2.create_incident_notification_template".to_owned(), false), ("v2.create_incident_todo".to_owned(), false), ("v2.create_incident_type".to_owned(), false), ("v2.delete_incident".to_owned(), false), - ("v2.delete_incident_impact".to_owned(), false), ("v2.delete_incident_integration".to_owned(), false), ("v2.delete_incident_notification_rule".to_owned(), false), ("v2.delete_incident_notification_template".to_owned(), false), @@ -208,7 +206,6 @@ impl Default for Configuration { ("v2.get_incident_todo".to_owned(), false), ("v2.get_incident_type".to_owned(), false), ("v2.list_incident_attachments".to_owned(), false), - ("v2.list_incident_impacts".to_owned(), false), ("v2.list_incident_integrations".to_owned(), false), ("v2.list_incident_notification_rules".to_owned(), false), ("v2.list_incident_notification_templates".to_owned(), false), diff --git a/src/datadogV2/api/api_apm.rs b/src/datadogV2/api/api_apm.rs new file mode 100644 index 000000000..72988588b --- /dev/null +++ b/src/datadogV2/api/api_apm.rs @@ -0,0 +1,179 @@ +// 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 crate::datadog; +use reqwest::header::{HeaderMap, HeaderValue}; +use serde::{Deserialize, Serialize}; + +/// GetServiceListError is a struct for typed errors of method [`APMAPI::get_service_list`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetServiceListError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// Observe, troubleshoot, and improve cloud-scale applications with all telemetry in context +#[derive(Debug, Clone)] +pub struct APMAPI { + config: datadog::Configuration, + client: reqwest_middleware::ClientWithMiddleware, +} + +impl Default for APMAPI { + fn default() -> Self { + Self::with_config(datadog::Configuration::default()) + } +} + +impl APMAPI { + pub fn new() -> Self { + Self::default() + } + pub fn with_config(config: datadog::Configuration) -> Self { + let mut reqwest_client_builder = reqwest::Client::builder(); + + if let Some(proxy_url) = &config.proxy_url { + let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL"); + reqwest_client_builder = reqwest_client_builder.proxy(proxy); + } + + let mut middleware_client_builder = + reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + + let client = middleware_client_builder.build(); + + Self { config, client } + } + + pub fn with_client_and_config( + config: datadog::Configuration, + client: reqwest_middleware::ClientWithMiddleware, + ) -> Self { + Self { config, client } + } + + pub async fn get_service_list( + &self, + ) -> Result> { + match self.get_service_list_with_http_info().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), + } + } + + pub async fn get_service_list_with_http_info( + &self, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_service_list"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/apm/services", + local_configuration.get_operation_host(operation_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + // 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/api/api_incidents.rs b/src/datadogV2/api/api_incidents.rs index 0fea1bd71..63919f46d 100644 --- a/src/datadogV2/api/api_incidents.rs +++ b/src/datadogV2/api/api_incidents.rs @@ -901,14 +901,6 @@ impl IncidentsAPI { > { let local_configuration = &self.config; let operation_id = "v2.create_incident_impact"; - if local_configuration.is_unstable_operation_enabled(operation_id) { - warn!("Using unstable operation {operation_id}"); - } else { - let local_error = datadog::UnstableOperationDisabledError { - msg: "Operation 'v2.create_incident_impact' is not enabled".to_string(), - }; - return Err(datadog::Error::UnstableOperationDisabledError(local_error)); - } // unbox and build optional parameters let include = params.include; @@ -1995,14 +1987,6 @@ impl IncidentsAPI { ) -> Result, datadog::Error> { let local_configuration = &self.config; let operation_id = "v2.delete_incident_impact"; - if local_configuration.is_unstable_operation_enabled(operation_id) { - warn!("Using unstable operation {operation_id}"); - } else { - let local_error = datadog::UnstableOperationDisabledError { - msg: "Operation 'v2.delete_incident_impact' is not enabled".to_string(), - }; - return Err(datadog::Error::UnstableOperationDisabledError(local_error)); - } let local_client = &self.client; @@ -3537,14 +3521,6 @@ impl IncidentsAPI { > { let local_configuration = &self.config; let operation_id = "v2.list_incident_impacts"; - if local_configuration.is_unstable_operation_enabled(operation_id) { - warn!("Using unstable operation {operation_id}"); - } else { - let local_error = datadog::UnstableOperationDisabledError { - msg: "Operation 'v2.list_incident_impacts' is not enabled".to_string(), - }; - return Err(datadog::Error::UnstableOperationDisabledError(local_error)); - } // unbox and build optional parameters let include = params.include; diff --git a/src/datadogV2/api/mod.rs b/src/datadogV2/api/mod.rs index 5ea26b017..4d3e9cb7e 100644 --- a/src/datadogV2/api/mod.rs +++ b/src/datadogV2/api/mod.rs @@ -6,6 +6,7 @@ pub mod api_action_connection; pub mod api_actions_datastores; pub mod api_agentless_scanning; pub mod api_api_management; +pub mod api_apm; pub mod api_apm_retention_filters; pub mod api_app_builder; pub mod api_application_security; diff --git a/src/datadogV2/mod.rs b/src/datadogV2/mod.rs index 4c3054ef5..3d7767d4f 100644 --- a/src/datadogV2/mod.rs +++ b/src/datadogV2/mod.rs @@ -7,6 +7,7 @@ pub use self::api::api_action_connection; pub use self::api::api_actions_datastores; pub use self::api::api_agentless_scanning; pub use self::api::api_api_management; +pub use self::api::api_apm; pub use self::api::api_apm_retention_filters; pub use self::api::api_app_builder; pub use self::api::api_application_security; diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index 80b8d5033..c7941c9ed 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -900,6 +900,16 @@ pub mod model_retention_filter_update_data; pub use self::model_retention_filter_update_data::RetentionFilterUpdateData; pub mod model_retention_filter_update_attributes; pub use self::model_retention_filter_update_attributes::RetentionFilterUpdateAttributes; +pub mod model_service_list; +pub use self::model_service_list::ServiceList; +pub mod model_service_list_data; +pub use self::model_service_list_data::ServiceListData; +pub mod model_service_list_data_attributes; +pub use self::model_service_list_data_attributes::ServiceListDataAttributes; +pub mod model_service_list_data_attributes_metadata_items; +pub use self::model_service_list_data_attributes_metadata_items::ServiceListDataAttributesMetadataItems; +pub mod model_service_list_data_type; +pub use self::model_service_list_data_type::ServiceListDataType; pub mod model_delete_apps_request; pub use self::model_delete_apps_request::DeleteAppsRequest; pub mod model_delete_apps_request_data_items; diff --git a/src/datadogV2/model/model_service_list.rs b/src/datadogV2/model/model_service_list.rs new file mode 100644 index 000000000..c97c6e78b --- /dev/null +++ b/src/datadogV2/model/model_service_list.rs @@ -0,0 +1,103 @@ +// 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}; + +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ServiceList { + #[serde(rename = "data")] + pub data: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ServiceList { + pub fn new() -> ServiceList { + ServiceList { + data: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data(mut self, value: crate::datadogV2::model::ServiceListData) -> 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 ServiceList { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for ServiceList { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ServiceListVisitor; + impl<'a> Visitor<'a> for ServiceListVisitor { + type Value = ServiceList; + + 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 = 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 = ServiceList { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ServiceListVisitor) + } +} diff --git a/src/datadogV2/model/model_service_list_data.rs b/src/datadogV2/model/model_service_list_data.rs new file mode 100644 index 000000000..1697a66d1 --- /dev/null +++ b/src/datadogV2/model/model_service_list_data.rs @@ -0,0 +1,132 @@ +// 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}; + +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ServiceListData { + #[serde(rename = "attributes")] + pub attributes: Option, + #[serde(rename = "id")] + pub id: Option, + /// Services list resource type. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::ServiceListDataType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ServiceListData { + pub fn new(type_: crate::datadogV2::model::ServiceListDataType) -> ServiceListData { + ServiceListData { + attributes: None, + id: None, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn attributes(mut self, value: crate::datadogV2::model::ServiceListDataAttributes) -> Self { + self.attributes = Some(value); + self + } + + pub fn id(mut self, value: String) -> Self { + self.id = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for ServiceListData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ServiceListDataVisitor; + impl<'a> Visitor<'a> for ServiceListDataVisitor { + type Value = ServiceListData; + + 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 = + None; + let mut id: Option = None; + let mut type_: 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() { + "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" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::ServiceListDataType::UnparsedObject(_type_) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = ServiceListData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ServiceListDataVisitor) + } +} diff --git a/src/datadogV2/model/model_service_list_data_attributes.rs b/src/datadogV2/model/model_service_list_data_attributes.rs new file mode 100644 index 000000000..0dd102dfc --- /dev/null +++ b/src/datadogV2/model/model_service_list_data_attributes.rs @@ -0,0 +1,124 @@ +// 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}; + +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ServiceListDataAttributes { + #[serde(rename = "metadata")] + pub metadata: Option>, + #[serde(rename = "services")] + pub services: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ServiceListDataAttributes { + pub fn new() -> ServiceListDataAttributes { + ServiceListDataAttributes { + metadata: None, + services: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn metadata( + mut self, + value: Vec, + ) -> Self { + self.metadata = Some(value); + self + } + + pub fn services(mut self, value: Vec) -> Self { + self.services = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for ServiceListDataAttributes { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for ServiceListDataAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ServiceListDataAttributesVisitor; + impl<'a> Visitor<'a> for ServiceListDataAttributesVisitor { + type Value = ServiceListDataAttributes; + + 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 metadata: Option< + Vec, + > = None; + let mut services: 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() { + "metadata" => { + if v.is_null() { + continue; + } + metadata = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "services" => { + if v.is_null() { + continue; + } + services = 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 = ServiceListDataAttributes { + metadata, + services, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ServiceListDataAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_service_list_data_attributes_metadata_items.rs b/src/datadogV2/model/model_service_list_data_attributes_metadata_items.rs new file mode 100644 index 000000000..898c97955 --- /dev/null +++ b/src/datadogV2/model/model_service_list_data_attributes_metadata_items.rs @@ -0,0 +1,119 @@ +// 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}; + +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct ServiceListDataAttributesMetadataItems { + #[serde(rename = "isTraced")] + pub is_traced: Option, + #[serde(rename = "isUsm")] + pub is_usm: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl ServiceListDataAttributesMetadataItems { + pub fn new() -> ServiceListDataAttributesMetadataItems { + ServiceListDataAttributesMetadataItems { + is_traced: None, + is_usm: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn is_traced(mut self, value: bool) -> Self { + self.is_traced = Some(value); + self + } + + pub fn is_usm(mut self, value: bool) -> Self { + self.is_usm = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for ServiceListDataAttributesMetadataItems { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for ServiceListDataAttributesMetadataItems { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ServiceListDataAttributesMetadataItemsVisitor; + impl<'a> Visitor<'a> for ServiceListDataAttributesMetadataItemsVisitor { + type Value = ServiceListDataAttributesMetadataItems; + + 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 is_traced: Option = None; + let mut is_usm: 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() { + "isTraced" => { + if v.is_null() { + continue; + } + is_traced = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "isUsm" => { + if v.is_null() { + continue; + } + is_usm = 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 = ServiceListDataAttributesMetadataItems { + is_traced, + is_usm, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(ServiceListDataAttributesMetadataItemsVisitor) + } +} diff --git a/src/datadogV2/model/model_service_list_data_type.rs b/src/datadogV2/model/model_service_list_data_type.rs new file mode 100644 index 000000000..a1cae6d5d --- /dev/null +++ b/src/datadogV2/model/model_service_list_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 ServiceListDataType { + SERVICES_LIST, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for ServiceListDataType { + fn to_string(&self) -> String { + match self { + Self::SERVICES_LIST => String::from("services_list"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for ServiceListDataType { + 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 ServiceListDataType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "services_list" => Self::SERVICES_LIST, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/tests/scenarios/features/v2/apm.feature b/tests/scenarios/features/v2/apm.feature new file mode 100644 index 000000000..e35bd4d47 --- /dev/null +++ b/tests/scenarios/features/v2/apm.feature @@ -0,0 +1,13 @@ +@endpoint(apm) @endpoint(apm-v2) +Feature: APM + Observe, troubleshoot, and improve cloud-scale applications with all + telemetry in context + + @generated @skip @team:DataDog/apm-aoe + Scenario: Get service list returns "OK" response + Given a valid "apiKeyAuth" key in the system + And a valid "appKeyAuth" key in the system + And an instance of "APM" API + And new "GetServiceList" request + When the request is sent + Then the response status is 200 OK diff --git a/tests/scenarios/features/v2/incidents.feature b/tests/scenarios/features/v2/incidents.feature index 74ae96596..12ab3e2f5 100644 --- a/tests/scenarios/features/v2/incidents.feature +++ b/tests/scenarios/features/v2/incidents.feature @@ -806,16 +806,14 @@ Feature: Incidents @generated @skip @team:DataDog/incident-app Scenario: List an incident's impacts returns "Bad Request" response - Given operation "ListIncidentImpacts" enabled - And new "ListIncidentImpacts" request + Given new "ListIncidentImpacts" request And request contains "incident_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 400 Bad Request @generated @skip @team:DataDog/incident-app Scenario: List an incident's impacts returns "Not Found" response - Given operation "ListIncidentImpacts" enabled - And new "ListIncidentImpacts" request + Given new "ListIncidentImpacts" request And request contains "incident_id" parameter from "REPLACE.ME" When the request is sent Then the response status is 404 Not Found diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 8aec373cd..e0f0b98d0 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -516,6 +516,12 @@ "type": "idempotent" } }, + "GetServiceList": { + "tag": "APM", + "undo": { + "type": "safe" + } + }, "DeleteApps": { "tag": "App Builder", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 3a3bea8e3..d6614cc7d 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -58,6 +58,7 @@ pub struct ApiInstances { pub v2_api_spans_metrics: Option, pub v2_api_apm_retention_filters: Option, + pub v2_api_apm: Option, pub v2_api_app_builder: Option, pub v2_api_audit: Option, pub v2_api_authn_mappings: Option, @@ -541,6 +542,13 @@ pub fn initialize_api_instance(world: &mut DatadogWorld, api: String) { world.http_client.as_ref().unwrap().clone() )); } + "APM" => { + world.api_instances.v2_api_apm = + Some(datadogV2::api_apm::APMAPI::with_client_and_config( + world.config.clone(), + world.http_client.as_ref().unwrap().clone(), + )); + } "AppBuilder" => { world.api_instances.v2_api_app_builder = Some( datadogV2::api_app_builder::AppBuilderAPI::with_client_and_config( @@ -2122,6 +2130,9 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.UpdateApmRetentionFilter".into(), test_v2_update_apm_retention_filter, ); + world + .function_mappings + .insert("v2.GetServiceList".into(), test_v2_get_service_list); world .function_mappings .insert("v2.DeleteApps".into(), test_v2_delete_apps); @@ -14140,6 +14151,30 @@ fn test_v2_update_apm_retention_filter( world.response.code = response.status.as_u16(); } +fn test_v2_get_service_list(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_apm + .as_ref() + .expect("api instance not found"); + let response = match block_on(api.get_service_list_with_http_info()) { + 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_delete_apps(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances