From 394095c666b74dfac26e163903ad9ccae6ddbf03 Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Fri, 22 May 2026 20:41:01 +0000 Subject: [PATCH] Regenerate client from commit fb6bd0f of spec repo --- .generator/schemas/v2/openapi.yaml | 101 ++++++++++++++ ...st-management_ListCostTagMetadataMonths.rs | 18 +++ src/datadog/configuration.rs | 1 + .../api/api_cloud_cost_management.rs | 132 ++++++++++++++++++ src/datadogV2/model/mod.rs | 6 + .../model/model_cost_tag_metadata_month.rs | 113 +++++++++++++++ .../model_cost_tag_metadata_month_type.rs | 48 +++++++ ...model_cost_tag_metadata_months_response.rs | 94 +++++++++++++ .../features/v2/cloud_cost_management.feature | 16 +++ tests/scenarios/features/v2/undo.json | 6 + tests/scenarios/function_mappings.rs | 34 +++++ 11 files changed, 569 insertions(+) create mode 100644 examples/v2_cloud-cost-management_ListCostTagMetadataMonths.rs create mode 100644 src/datadogV2/model/model_cost_tag_metadata_month.rs create mode 100644 src/datadogV2/model/model_cost_tag_metadata_month_type.rs create mode 100644 src/datadogV2/model/model_cost_tag_metadata_months_response.rs diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 3bd4dc490..c5944e124 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -18525,6 +18525,45 @@ components: x-enum-varnames: - "TRUE" - "FALSE" + CostTagMetadataMonth: + description: A month that has Cloud Cost Management tag metadata available for a given provider. + properties: + id: + description: The month, in `YYYY-MM` format. + example: "2026-04" + type: string + type: + $ref: "#/components/schemas/CostTagMetadataMonthType" + required: + - id + - type + type: object + CostTagMetadataMonthType: + default: cost_tag_metadata_month + description: Type of the Cloud Cost Management tag metadata month resource. + enum: + - cost_tag_metadata_month + example: cost_tag_metadata_month + type: string + x-enum-varnames: + - COST_TAG_METADATA_MONTH + CostTagMetadataMonthsResponse: + description: List of months that have Cloud Cost Management tag metadata for the requested provider, ordered most-recent first and capped at 36 months. + example: + data: + - id: "2026-04" + type: cost_tag_metadata_month + - id: "2026-03" + type: cost_tag_metadata_month + properties: + data: + description: List of months that have tag metadata available. + items: + $ref: "#/components/schemas/CostTagMetadataMonth" + type: array + required: + - data + type: object CostTagType: default: cost_tag description: Type of the Cloud Cost Management tag resource. @@ -109019,6 +109058,68 @@ paths: x-unstable: |- **Note**: This endpoint is in preview and is subject to change. If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/). + /api/v2/cost/tag_metadata/months: + get: + description: |- + List months that have Cloud Cost Management tag metadata for a given provider, + ordered most-recent first. The response is capped at 36 months. + operationId: ListCostTagMetadataMonths + parameters: + - description: |- + Provider to scope the query to. Use the value of the `providername` tag in CCM + (for example, `aws`, `azure`, `gcp`, `Oracle`, `Confluent Cloud`, `Snowflake`). + For costs uploaded through the Custom Costs API, use `custom`. + Values are case-sensitive. + example: aws + in: query + name: filter[provider] + required: true + schema: + type: string + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + - id: "2026-04" + type: cost_tag_metadata_month + - id: "2026-03" + type: cost_tag_metadata_month + schema: + $ref: "#/components/schemas/CostTagMetadataMonthsResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - cloud_cost_management_read + summary: List Cloud Cost Management tag metadata months + tags: + - Cloud Cost Management + "x-permission": + operator: OR + permissions: + - cloud_cost_management_read + x-unstable: |- + **Note**: This endpoint is in preview and is subject to change. + If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/). /api/v2/cost/tag_metadata/orchestrators: get: description: List container orchestrators (for example, `kubernetes`, `ecs`) detected in Cloud Cost Management data for the requested period. diff --git a/examples/v2_cloud-cost-management_ListCostTagMetadataMonths.rs b/examples/v2_cloud-cost-management_ListCostTagMetadataMonths.rs new file mode 100644 index 000000000..c61712504 --- /dev/null +++ b/examples/v2_cloud-cost-management_ListCostTagMetadataMonths.rs @@ -0,0 +1,18 @@ +// List Cloud Cost Management tag metadata months returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_cloud_cost_management::CloudCostManagementAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.ListCostTagMetadataMonths", true); + let api = CloudCostManagementAPI::with_config(configuration); + let resp = api + .list_cost_tag_metadata_months("filter[provider]".to_string()) + .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 6994cfb84..db6a7c804 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -374,6 +374,7 @@ impl Default for Configuration { ("v2.list_cost_tag_key_sources".to_owned(), false), ("v2.list_cost_tag_metadata".to_owned(), false), ("v2.list_cost_tag_metadata_metrics".to_owned(), false), + ("v2.list_cost_tag_metadata_months".to_owned(), false), ("v2.list_cost_tag_metadata_orchestrators".to_owned(), false), ("v2.search_cost_recommendations".to_owned(), false), ("v2.create_dashboard_secure_embed".to_owned(), false), diff --git a/src/datadogV2/api/api_cloud_cost_management.rs b/src/datadogV2/api/api_cloud_cost_management.rs index 02449cd05..555456f55 100644 --- a/src/datadogV2/api/api_cloud_cost_management.rs +++ b/src/datadogV2/api/api_cloud_cost_management.rs @@ -875,6 +875,14 @@ pub enum ListCostTagMetadataMetricsError { UnknownValue(serde_json::Value), } +/// ListCostTagMetadataMonthsError is a struct for typed errors of method [`CloudCostManagementAPI::list_cost_tag_metadata_months`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ListCostTagMetadataMonthsError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// ListCostTagMetadataOrchestratorsError is a struct for typed errors of method [`CloudCostManagementAPI::list_cost_tag_metadata_orchestrators`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -6163,6 +6171,130 @@ impl CloudCostManagementAPI { } } + /// List months that have Cloud Cost Management tag metadata for a given provider, + /// ordered most-recent first. The response is capped at 36 months. + pub async fn list_cost_tag_metadata_months( + &self, + filter_provider: String, + ) -> Result< + crate::datadogV2::model::CostTagMetadataMonthsResponse, + datadog::Error, + > { + match self + .list_cost_tag_metadata_months_with_http_info(filter_provider) + .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), + } + } + + /// List months that have Cloud Cost Management tag metadata for a given provider, + /// ordered most-recent first. The response is capped at 36 months. + pub async fn list_cost_tag_metadata_months_with_http_info( + &self, + filter_provider: String, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.list_cost_tag_metadata_months"; + 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_cost_tag_metadata_months' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/cost/tag_metadata/months", + local_configuration.get_operation_host(operation_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + local_req_builder = + local_req_builder.query(&[("filter[provider]", &filter_provider.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)) + } + } + /// List container orchestrators (for example, `kubernetes`, `ecs`) detected in Cloud Cost Management data for the requested period. pub async fn list_cost_tag_metadata_orchestrators( &self, diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index 4f61da0e3..283298993 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -2992,6 +2992,12 @@ pub mod model_cost_metric; pub use self::model_cost_metric::CostMetric; pub mod model_cost_metric_type; pub use self::model_cost_metric_type::CostMetricType; +pub mod model_cost_tag_metadata_months_response; +pub use self::model_cost_tag_metadata_months_response::CostTagMetadataMonthsResponse; +pub mod model_cost_tag_metadata_month; +pub use self::model_cost_tag_metadata_month::CostTagMetadataMonth; +pub mod model_cost_tag_metadata_month_type; +pub use self::model_cost_tag_metadata_month_type::CostTagMetadataMonthType; pub mod model_cost_orchestrators_response; pub use self::model_cost_orchestrators_response::CostOrchestratorsResponse; pub mod model_cost_orchestrator; diff --git a/src/datadogV2/model/model_cost_tag_metadata_month.rs b/src/datadogV2/model/model_cost_tag_metadata_month.rs new file mode 100644 index 000000000..afff20d30 --- /dev/null +++ b/src/datadogV2/model/model_cost_tag_metadata_month.rs @@ -0,0 +1,113 @@ +// 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}; + +/// A month that has Cloud Cost Management tag metadata available for a given provider. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CostTagMetadataMonth { + /// The month, in `YYYY-MM` format. + #[serde(rename = "id")] + pub id: String, + /// Type of the Cloud Cost Management tag metadata month resource. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::CostTagMetadataMonthType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CostTagMetadataMonth { + pub fn new( + id: String, + type_: crate::datadogV2::model::CostTagMetadataMonthType, + ) -> CostTagMetadataMonth { + CostTagMetadataMonth { + id, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for CostTagMetadataMonth { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CostTagMetadataMonthVisitor; + impl<'a> Visitor<'a> for CostTagMetadataMonthVisitor { + type Value = CostTagMetadataMonth; + + 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 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() { + "id" => { + 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::CostTagMetadataMonthType::UnparsedObject(_type_) => { + _unparsed = true; + }, + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = CostTagMetadataMonth { + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CostTagMetadataMonthVisitor) + } +} diff --git a/src/datadogV2/model/model_cost_tag_metadata_month_type.rs b/src/datadogV2/model/model_cost_tag_metadata_month_type.rs new file mode 100644 index 000000000..17be4bf38 --- /dev/null +++ b/src/datadogV2/model/model_cost_tag_metadata_month_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 CostTagMetadataMonthType { + COST_TAG_METADATA_MONTH, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for CostTagMetadataMonthType { + fn to_string(&self) -> String { + match self { + Self::COST_TAG_METADATA_MONTH => String::from("cost_tag_metadata_month"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for CostTagMetadataMonthType { + 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 CostTagMetadataMonthType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "cost_tag_metadata_month" => Self::COST_TAG_METADATA_MONTH, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_cost_tag_metadata_months_response.rs b/src/datadogV2/model/model_cost_tag_metadata_months_response.rs new file mode 100644 index 000000000..381255ab8 --- /dev/null +++ b/src/datadogV2/model/model_cost_tag_metadata_months_response.rs @@ -0,0 +1,94 @@ +// 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 months that have Cloud Cost Management tag metadata for the requested provider, ordered most-recent first and capped at 36 months. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CostTagMetadataMonthsResponse { + /// List of months that have tag metadata available. + #[serde(rename = "data")] + pub data: Vec, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CostTagMetadataMonthsResponse { + pub fn new( + data: Vec, + ) -> CostTagMetadataMonthsResponse { + CostTagMetadataMonthsResponse { + data, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for CostTagMetadataMonthsResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CostTagMetadataMonthsResponseVisitor; + impl<'a> Visitor<'a> for CostTagMetadataMonthsResponseVisitor { + type Value = CostTagMetadataMonthsResponse; + + 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" => { + 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 data = data.ok_or_else(|| M::Error::missing_field("data"))?; + + let content = CostTagMetadataMonthsResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CostTagMetadataMonthsResponseVisitor) + } +} diff --git a/tests/scenarios/features/v2/cloud_cost_management.feature b/tests/scenarios/features/v2/cloud_cost_management.feature index 17779e459..b41928f4c 100644 --- a/tests/scenarios/features/v2/cloud_cost_management.feature +++ b/tests/scenarios/features/v2/cloud_cost_management.feature @@ -606,6 +606,22 @@ Feature: Cloud Cost Management When the request is sent Then the response status is 200 OK + @generated @skip @team:DataDog/cloud-cost-management + Scenario: List Cloud Cost Management tag metadata months returns "Bad Request" response + Given operation "ListCostTagMetadataMonths" enabled + And new "ListCostTagMetadataMonths" request + And request contains "filter[provider]" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/cloud-cost-management + Scenario: List Cloud Cost Management tag metadata months returns "OK" response + Given operation "ListCostTagMetadataMonths" enabled + And new "ListCostTagMetadataMonths" request + And request contains "filter[provider]" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + @generated @skip @team:DataDog/cloud-cost-management Scenario: List Cloud Cost Management tag sources returns "Bad Request" response Given operation "ListCostTagKeySources" enabled diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index c22b14729..7e0e3ceeb 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -1898,6 +1898,12 @@ "type": "safe" } }, + "ListCostTagMetadataMonths": { + "tag": "Cloud Cost Management", + "undo": { + "type": "safe" + } + }, "ListCostTagMetadataOrchestrators": { "tag": "Cloud Cost Management", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 39ddb24b1..ed3ad6c7f 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -3826,6 +3826,10 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.ListCostTagMetadataMetrics".into(), test_v2_list_cost_tag_metadata_metrics, ); + world.function_mappings.insert( + "v2.ListCostTagMetadataMonths".into(), + test_v2_list_cost_tag_metadata_months, + ); world.function_mappings.insert( "v2.ListCostTagMetadataOrchestrators".into(), test_v2_list_cost_tag_metadata_orchestrators, @@ -29058,6 +29062,36 @@ fn test_v2_list_cost_tag_metadata_metrics( world.response.code = response.status.as_u16(); } +fn test_v2_list_cost_tag_metadata_months( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_cloud_cost_management + .as_ref() + .expect("api instance not found"); + let filter_provider = + serde_json::from_value(_parameters.get("filter[provider]").unwrap().clone()).unwrap(); + let response = match block_on(api.list_cost_tag_metadata_months_with_http_info(filter_provider)) + { + 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_list_cost_tag_metadata_orchestrators( world: &mut DatadogWorld, _parameters: &HashMap,