From d1241e2f1419310e02afeb58bfddf30d41631c06 Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Mon, 22 Jun 2026 14:31:29 +0000 Subject: [PATCH] Regenerate client from commit 27b019f of spec repo --- .generator/schemas/v2/openapi.yaml | 250 ++++++++++++++++++ docs/datadog_api_client.v2.model.rst | 63 +++++ .../DeleteCustomForecast.py | 14 + .../UpsertCustomForecast.py | 44 +++ src/datadog_api_client/configuration.py | 2 + .../v2/api/cloud_cost_management_api.py | 79 ++++++ .../v2/model/custom_forecast_entry.py | 52 ++++ .../model/custom_forecast_entry_tag_filter.py | 39 +++ .../v2/model/custom_forecast_response.py | 40 +++ .../v2/model/custom_forecast_response_data.py | 58 ++++ ...ustom_forecast_response_data_attributes.py | 79 ++++++ .../v2/model/custom_forecast_type.py | 35 +++ .../model/custom_forecast_upsert_request.py | 40 +++ .../custom_forecast_upsert_request_data.py | 67 +++++ ...forecast_upsert_request_data_attributes.py | 47 ++++ src/datadog_api_client/v2/models/__init__.py | 20 ++ .../v2/features/cloud_cost_management.feature | 48 ++++ tests/v2/features/undo.json | 12 + 18 files changed, 989 insertions(+) create mode 100644 examples/v2/cloud-cost-management/DeleteCustomForecast.py create mode 100644 examples/v2/cloud-cost-management/UpsertCustomForecast.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_entry.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_entry_tag_filter.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_response.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_response_data.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_response_data_attributes.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_type.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_upsert_request.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_upsert_request_data.py create mode 100644 src/datadog_api_client/v2/model/custom_forecast_upsert_request_data_attributes.py diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 99b25f0ac8..7696e4a9b6 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -27149,6 +27149,156 @@ components: $ref: "#/components/schemas/CustomDestinationResponseDefinition" type: array type: object + CustomForecastEntry: + description: A monthly entry of a custom budget forecast. + properties: + amount: + description: Forecast amount for the month. + example: 400 + format: double + type: number + month: + description: Month the custom forecast entry applies to, in `YYYYMM` format. + example: 202501 + format: int64 + type: integer + tag_filters: + description: Tag filters that scope this custom forecast entry to specific resources. + items: + $ref: "#/components/schemas/CustomForecastEntryTagFilter" + type: array + required: + - month + - amount + - tag_filters + type: object + CustomForecastEntryTagFilter: + description: A tag filter that scopes a custom forecast entry to specific resource tags. + properties: + tag_key: + description: The tag key to filter on. + example: service + type: string + tag_value: + description: The tag value to filter on. + example: ec2 + type: string + required: + - tag_key + - tag_value + type: object + CustomForecastResponse: + description: Response object containing the custom forecast for a budget. + properties: + data: + $ref: "#/components/schemas/CustomForecastResponseData" + required: + - data + type: object + CustomForecastResponseData: + description: Custom forecast resource wrapper in a response. + properties: + attributes: + $ref: "#/components/schemas/CustomForecastResponseDataAttributes" + id: + description: The unique identifier of the custom forecast. + example: 11111111-1111-1111-1111-111111111111 + type: string + type: + $ref: "#/components/schemas/CustomForecastType" + required: + - id + - type + - attributes + type: object + CustomForecastResponseDataAttributes: + description: Attributes of a custom forecast. + properties: + budget_uid: + description: The UUID of the budget that this custom forecast belongs to. + example: 00000000-0000-0000-0000-000000000001 + type: string + created_at: + description: Timestamp the custom forecast was created, in Unix milliseconds. + example: 1738258683590 + format: int64 + type: integer + created_by: + description: The id of the user that created the custom forecast. + example: 00000000-0a0a-0a0a-aaa0-00000000000a + type: string + entries: + description: Monthly custom forecast entries. + items: + $ref: "#/components/schemas/CustomForecastEntry" + type: array + updated_at: + description: Timestamp the custom forecast was last updated, in Unix milliseconds. + example: 1738258683590 + format: int64 + type: integer + updated_by: + description: The id of the user that last updated the custom forecast. + example: 00000000-0a0a-0a0a-aaa0-00000000000a + type: string + required: + - budget_uid + - created_at + - updated_at + - created_by + - updated_by + - entries + type: object + CustomForecastType: + default: custom_forecast + description: The type of the custom forecast resource. Must be `custom_forecast`. + enum: + - custom_forecast + example: custom_forecast + type: string + x-enum-varnames: + - CUSTOM_FORECAST + CustomForecastUpsertRequest: + description: Request body to upsert (create or replace) the custom forecast for a budget. + properties: + data: + $ref: "#/components/schemas/CustomForecastUpsertRequestData" + required: + - data + type: object + CustomForecastUpsertRequestData: + description: Custom forecast resource wrapper in an upsert request. + properties: + attributes: + $ref: "#/components/schemas/CustomForecastUpsertRequestDataAttributes" + id: + description: Unused on upsert; the resource is keyed by `budget_uid`. Send an empty string. + example: "" + type: string + type: + $ref: "#/components/schemas/CustomForecastType" + required: + - type + - attributes + type: object + CustomForecastUpsertRequestDataAttributes: + description: Attributes of a custom forecast upsert request. + properties: + budget_uid: + description: The UUID of the budget that this custom forecast belongs to. + example: 00000000-0000-0000-0000-000000000001 + type: string + entries: + description: |- + Monthly custom forecast entries. An empty list deletes any existing + custom forecast for the budget. + items: + $ref: "#/components/schemas/CustomForecastEntry" + type: array + required: + - budget_uid + - entries + type: object CustomFrameworkControl: description: Framework Control. properties: @@ -123849,6 +123999,82 @@ paths: summary: Validate CSV budget tags: - Cloud Cost Management + /api/v2/cost/budget/custom-forecast: + put: + description: |- + Create or replace the custom forecast for an existing budget. + Pass an empty `entries` list to delete the custom forecast for the budget. + operationId: UpsertCustomForecast + requestBody: + content: + application/json: + examples: + default: + value: + data: + attributes: + budget_uid: 00000000-0000-0000-0000-000000000001 + entries: + - amount: 400 + month: 202501 + tag_filters: + - tag_key: service + tag_value: ec2 + - amount: 450 + month: 202502 + tag_filters: + - tag_key: service + tag_value: ec2 + id: "" + type: custom_forecast + schema: + $ref: "#/components/schemas/CustomForecastUpsertRequest" + required: true + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + attributes: + budget_uid: 00000000-0000-0000-0000-000000000001 + created_at: 1738258683590 + created_by: 00000000-0a0a-0a0a-aaa0-00000000000a + entries: + - amount: 400 + month: 202501 + tag_filters: + - tag_key: service + tag_value: ec2 + - amount: 450 + month: 202502 + tag_filters: + - tag_key: service + tag_value: ec2 + updated_at: 1738258683590 + updated_by: 00000000-0a0a-0a0a-aaa0-00000000000a + id: 11111111-1111-1111-1111-111111111111 + type: custom_forecast + schema: + $ref: "#/components/schemas/CustomForecastResponse" + description: OK + "400": + $ref: "#/components/responses/BadRequestResponse" + "404": + $ref: "#/components/responses/NotFoundResponse" + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Create or replace a budget's custom forecast + tags: + - Cloud Cost Management + 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/budget/validate: post: description: Validate a budget configuration without creating or modifying it @@ -123971,6 +124197,30 @@ paths: summary: Get budget tags: - Cloud Cost Management + /api/v2/cost/budget/{budget_id}/custom-forecast: + delete: + description: Delete the custom forecast for a budget. + operationId: DeleteCustomForecast + parameters: + - $ref: "#/components/parameters/BudgetID" + responses: + "204": + description: No Content + "400": + $ref: "#/components/responses/BadRequestResponse" + "404": + $ref: "#/components/responses/NotFoundResponse" + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Delete a budget's custom forecast + tags: + - Cloud Cost Management + 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/budgets: get: description: List budgets. diff --git a/docs/datadog_api_client.v2.model.rst b/docs/datadog_api_client.v2.model.rst index 14023429c7..2a2fc00289 100644 --- a/docs/datadog_api_client.v2.model.rst +++ b/docs/datadog_api_client.v2.model.rst @@ -10532,6 +10532,69 @@ datadog\_api\_client.v2.model.custom\_destinations\_response module :members: :show-inheritance: +datadog\_api\_client.v2.model.custom\_forecast\_entry module +------------------------------------------------------------ + +.. automodule:: datadog_api_client.v2.model.custom_forecast_entry + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_entry\_tag\_filter module +------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_entry_tag_filter + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_response module +--------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_response + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_response\_data module +--------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_response_data + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_response\_data\_attributes module +--------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_response_data_attributes + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_type module +----------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_type + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_upsert\_request module +---------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_upsert_request + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_upsert\_request\_data module +---------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_upsert_request_data + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.custom\_forecast\_upsert\_request\_data\_attributes module +---------------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.custom_forecast_upsert_request_data_attributes + :members: + :show-inheritance: + datadog\_api\_client.v2.model.custom\_framework\_control module --------------------------------------------------------------- diff --git a/examples/v2/cloud-cost-management/DeleteCustomForecast.py b/examples/v2/cloud-cost-management/DeleteCustomForecast.py new file mode 100644 index 0000000000..78f274b448 --- /dev/null +++ b/examples/v2/cloud-cost-management/DeleteCustomForecast.py @@ -0,0 +1,14 @@ +""" +Delete a budget's custom forecast returns "No Content" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.cloud_cost_management_api import CloudCostManagementApi + +configuration = Configuration() +configuration.unstable_operations["delete_custom_forecast"] = True +with ApiClient(configuration) as api_client: + api_instance = CloudCostManagementApi(api_client) + api_instance.delete_custom_forecast( + budget_id="budget_id", + ) diff --git a/examples/v2/cloud-cost-management/UpsertCustomForecast.py b/examples/v2/cloud-cost-management/UpsertCustomForecast.py new file mode 100644 index 0000000000..b58407f1ac --- /dev/null +++ b/examples/v2/cloud-cost-management/UpsertCustomForecast.py @@ -0,0 +1,44 @@ +""" +Create or replace a budget's custom forecast returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.cloud_cost_management_api import CloudCostManagementApi +from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry +from datadog_api_client.v2.model.custom_forecast_entry_tag_filter import CustomForecastEntryTagFilter +from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType +from datadog_api_client.v2.model.custom_forecast_upsert_request import CustomForecastUpsertRequest +from datadog_api_client.v2.model.custom_forecast_upsert_request_data import CustomForecastUpsertRequestData +from datadog_api_client.v2.model.custom_forecast_upsert_request_data_attributes import ( + CustomForecastUpsertRequestDataAttributes, +) + +body = CustomForecastUpsertRequest( + data=CustomForecastUpsertRequestData( + attributes=CustomForecastUpsertRequestDataAttributes( + budget_uid="00000000-0000-0000-0000-000000000001", + entries=[ + CustomForecastEntry( + amount=400.0, + month=202501, + tag_filters=[ + CustomForecastEntryTagFilter( + tag_key="service", + tag_value="ec2", + ), + ], + ), + ], + ), + id="", + type=CustomForecastType.CUSTOM_FORECAST, + ), +) + +configuration = Configuration() +configuration.unstable_operations["upsert_custom_forecast"] = True +with ApiClient(configuration) as api_client: + api_instance = CloudCostManagementApi(api_client) + response = api_instance.upsert_custom_forecast(body=body) + + print(response) diff --git a/src/datadog_api_client/configuration.py b/src/datadog_api_client/configuration.py index 0694277a12..d556ecd680 100644 --- a/src/datadog_api_client/configuration.py +++ b/src/datadog_api_client/configuration.py @@ -475,6 +475,7 @@ def __init__( "v2.get_code_coverage_branch_summary": False, "v2.get_code_coverage_commit_summary": False, "v2.get_rule_based_view": False, + "v2.delete_custom_forecast": False, "v2.get_commitments_commitment_list": False, "v2.get_commitments_coverage_scalar": False, "v2.get_commitments_coverage_timeseries": False, @@ -492,6 +493,7 @@ def __init__( "v2.list_cost_tag_metadata_months": False, "v2.list_cost_tag_metadata_orchestrators": False, "v2.search_cost_recommendations": False, + "v2.upsert_custom_forecast": False, "v2.create_ownership_feedback": False, "v2.get_ownership_evidence": False, "v2.get_ownership_inference": False, diff --git a/src/datadog_api_client/v2/api/cloud_cost_management_api.py b/src/datadog_api_client/v2/api/cloud_cost_management_api.py index f2d35f381a..7543d36d50 100644 --- a/src/datadog_api_client/v2/api/cloud_cost_management_api.py +++ b/src/datadog_api_client/v2/api/cloud_cost_management_api.py @@ -29,6 +29,8 @@ from datadog_api_client.v2.model.azure_uc_config_patch_request import AzureUCConfigPatchRequest from datadog_api_client.v2.model.budget_with_entries import BudgetWithEntries from datadog_api_client.v2.model.validation_response import ValidationResponse +from datadog_api_client.v2.model.custom_forecast_response import CustomForecastResponse +from datadog_api_client.v2.model.custom_forecast_upsert_request import CustomForecastUpsertRequest from datadog_api_client.v2.model.budget_validation_response import BudgetValidationResponse from datadog_api_client.v2.model.budget_validation_request import BudgetValidationRequest from datadog_api_client.v2.model.budget_array import BudgetArray @@ -358,6 +360,29 @@ def __init__(self, api_client=None): api_client=api_client, ) + self._delete_custom_forecast_endpoint = _Endpoint( + settings={ + "response_type": None, + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/cost/budget/{budget_id}/custom-forecast", + "operation_id": "delete_custom_forecast", + "http_method": "DELETE", + "version": "v2", + }, + params_map={ + "budget_id": { + "required": True, + "openapi_types": (str,), + "attribute": "budget_id", + "location": "path", + }, + }, + headers_map={ + "accept": ["*/*"], + }, + api_client=api_client, + ) + self._delete_tag_pipelines_ruleset_endpoint = _Endpoint( settings={ "response_type": None, @@ -1847,6 +1872,26 @@ def __init__(self, api_client=None): api_client=api_client, ) + self._upsert_custom_forecast_endpoint = _Endpoint( + settings={ + "response_type": (CustomForecastResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/cost/budget/custom-forecast", + "operation_id": "upsert_custom_forecast", + "http_method": "PUT", + "version": "v2", + }, + params_map={ + "body": { + "required": True, + "openapi_types": (CustomForecastUpsertRequest,), + "location": "body", + }, + }, + headers_map={"accept": ["application/json"], "content_type": ["application/json"]}, + api_client=api_client, + ) + self._validate_budget_endpoint = _Endpoint( settings={ "response_type": (BudgetValidationResponse,), @@ -2123,6 +2168,23 @@ def delete_custom_costs_file( return self._delete_custom_costs_file_endpoint.call_with_http_info(**kwargs) + def delete_custom_forecast( + self, + budget_id: str, + ) -> None: + """Delete a budget's custom forecast. + + Delete the custom forecast for a budget. + + :param budget_id: Budget id. + :type budget_id: str + :rtype: None + """ + kwargs: Dict[str, Any] = {} + kwargs["budget_id"] = budget_id + + return self._delete_custom_forecast_endpoint.call_with_http_info(**kwargs) + def delete_tag_pipelines_ruleset( self, ruleset_id: str, @@ -3405,6 +3467,23 @@ def upsert_cost_tag_description_by_key( return self._upsert_cost_tag_description_by_key_endpoint.call_with_http_info(**kwargs) + def upsert_custom_forecast( + self, + body: CustomForecastUpsertRequest, + ) -> CustomForecastResponse: + """Create or replace a budget's custom forecast. + + Create or replace the custom forecast for an existing budget. + Pass an empty ``entries`` list to delete the custom forecast for the budget. + + :type body: CustomForecastUpsertRequest + :rtype: CustomForecastResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["body"] = body + + return self._upsert_custom_forecast_endpoint.call_with_http_info(**kwargs) + def validate_budget( self, body: BudgetValidationRequest, diff --git a/src/datadog_api_client/v2/model/custom_forecast_entry.py b/src/datadog_api_client/v2/model/custom_forecast_entry.py new file mode 100644 index 0000000000..b55ed5b795 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_entry.py @@ -0,0 +1,52 @@ +# 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. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_entry_tag_filter import CustomForecastEntryTagFilter + + +class CustomForecastEntry(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_entry_tag_filter import CustomForecastEntryTagFilter + + return { + "amount": (float,), + "month": (int,), + "tag_filters": ([CustomForecastEntryTagFilter],), + } + + attribute_map = { + "amount": "amount", + "month": "month", + "tag_filters": "tag_filters", + } + + def __init__(self_, amount: float, month: int, tag_filters: List[CustomForecastEntryTagFilter], **kwargs): + """ + A monthly entry of a custom budget forecast. + + :param amount: Forecast amount for the month. + :type amount: float + + :param month: Month the custom forecast entry applies to, in ``YYYYMM`` format. + :type month: int + + :param tag_filters: Tag filters that scope this custom forecast entry to specific resources. + :type tag_filters: [CustomForecastEntryTagFilter] + """ + super().__init__(kwargs) + + self_.amount = amount + self_.month = month + self_.tag_filters = tag_filters diff --git a/src/datadog_api_client/v2/model/custom_forecast_entry_tag_filter.py b/src/datadog_api_client/v2/model/custom_forecast_entry_tag_filter.py new file mode 100644 index 0000000000..83270a1fd5 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_entry_tag_filter.py @@ -0,0 +1,39 @@ +# 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. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +class CustomForecastEntryTagFilter(ModelNormal): + @cached_property + def openapi_types(_): + return { + "tag_key": (str,), + "tag_value": (str,), + } + + attribute_map = { + "tag_key": "tag_key", + "tag_value": "tag_value", + } + + def __init__(self_, tag_key: str, tag_value: str, **kwargs): + """ + A tag filter that scopes a custom forecast entry to specific resource tags. + + :param tag_key: The tag key to filter on. + :type tag_key: str + + :param tag_value: The tag value to filter on. + :type tag_value: str + """ + super().__init__(kwargs) + + self_.tag_key = tag_key + self_.tag_value = tag_value diff --git a/src/datadog_api_client/v2/model/custom_forecast_response.py b/src/datadog_api_client/v2/model/custom_forecast_response.py new file mode 100644 index 0000000000..6bf8c681fd --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_response.py @@ -0,0 +1,40 @@ +# 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. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_response_data import CustomForecastResponseData + + +class CustomForecastResponse(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_response_data import CustomForecastResponseData + + return { + "data": (CustomForecastResponseData,), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: CustomForecastResponseData, **kwargs): + """ + Response object containing the custom forecast for a budget. + + :param data: Custom forecast resource wrapper in a response. + :type data: CustomForecastResponseData + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/custom_forecast_response_data.py b/src/datadog_api_client/v2/model/custom_forecast_response_data.py new file mode 100644 index 0000000000..c53bcacab7 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_response_data.py @@ -0,0 +1,58 @@ +# 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. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_response_data_attributes import ( + CustomForecastResponseDataAttributes, + ) + from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType + + +class CustomForecastResponseData(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_response_data_attributes import ( + CustomForecastResponseDataAttributes, + ) + from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType + + return { + "attributes": (CustomForecastResponseDataAttributes,), + "id": (str,), + "type": (CustomForecastType,), + } + + attribute_map = { + "attributes": "attributes", + "id": "id", + "type": "type", + } + + def __init__(self_, attributes: CustomForecastResponseDataAttributes, id: str, type: CustomForecastType, **kwargs): + """ + Custom forecast resource wrapper in a response. + + :param attributes: Attributes of a custom forecast. + :type attributes: CustomForecastResponseDataAttributes + + :param id: The unique identifier of the custom forecast. + :type id: str + + :param type: The type of the custom forecast resource. Must be ``custom_forecast``. + :type type: CustomForecastType + """ + super().__init__(kwargs) + + self_.attributes = attributes + self_.id = id + self_.type = type diff --git a/src/datadog_api_client/v2/model/custom_forecast_response_data_attributes.py b/src/datadog_api_client/v2/model/custom_forecast_response_data_attributes.py new file mode 100644 index 0000000000..b244c82551 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_response_data_attributes.py @@ -0,0 +1,79 @@ +# 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. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry + + +class CustomForecastResponseDataAttributes(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry + + return { + "budget_uid": (str,), + "created_at": (int,), + "created_by": (str,), + "entries": ([CustomForecastEntry],), + "updated_at": (int,), + "updated_by": (str,), + } + + attribute_map = { + "budget_uid": "budget_uid", + "created_at": "created_at", + "created_by": "created_by", + "entries": "entries", + "updated_at": "updated_at", + "updated_by": "updated_by", + } + + def __init__( + self_, + budget_uid: str, + created_at: int, + created_by: str, + entries: List[CustomForecastEntry], + updated_at: int, + updated_by: str, + **kwargs, + ): + """ + Attributes of a custom forecast. + + :param budget_uid: The UUID of the budget that this custom forecast belongs to. + :type budget_uid: str + + :param created_at: Timestamp the custom forecast was created, in Unix milliseconds. + :type created_at: int + + :param created_by: The id of the user that created the custom forecast. + :type created_by: str + + :param entries: Monthly custom forecast entries. + :type entries: [CustomForecastEntry] + + :param updated_at: Timestamp the custom forecast was last updated, in Unix milliseconds. + :type updated_at: int + + :param updated_by: The id of the user that last updated the custom forecast. + :type updated_by: str + """ + super().__init__(kwargs) + + self_.budget_uid = budget_uid + self_.created_at = created_at + self_.created_by = created_by + self_.entries = entries + self_.updated_at = updated_at + self_.updated_by = updated_by diff --git a/src/datadog_api_client/v2/model/custom_forecast_type.py b/src/datadog_api_client/v2/model/custom_forecast_type.py new file mode 100644 index 0000000000..3786034890 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_type.py @@ -0,0 +1,35 @@ +# 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. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class CustomForecastType(ModelSimple): + """ + The type of the custom forecast resource. Must be `custom_forecast`. + + :param value: If omitted defaults to "custom_forecast". Must be one of ["custom_forecast"]. + :type value: str + """ + + allowed_values = { + "custom_forecast", + } + CUSTOM_FORECAST: ClassVar["CustomForecastType"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +CustomForecastType.CUSTOM_FORECAST = CustomForecastType("custom_forecast") diff --git a/src/datadog_api_client/v2/model/custom_forecast_upsert_request.py b/src/datadog_api_client/v2/model/custom_forecast_upsert_request.py new file mode 100644 index 0000000000..6fa1644702 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_upsert_request.py @@ -0,0 +1,40 @@ +# 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. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_upsert_request_data import CustomForecastUpsertRequestData + + +class CustomForecastUpsertRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_upsert_request_data import CustomForecastUpsertRequestData + + return { + "data": (CustomForecastUpsertRequestData,), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: CustomForecastUpsertRequestData, **kwargs): + """ + Request body to upsert (create or replace) the custom forecast for a budget. + + :param data: Custom forecast resource wrapper in an upsert request. + :type data: CustomForecastUpsertRequestData + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data.py b/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data.py new file mode 100644 index 0000000000..070a17c82b --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data.py @@ -0,0 +1,67 @@ +# 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. +from __future__ import annotations + +from typing import Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + unset, + UnsetType, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_upsert_request_data_attributes import ( + CustomForecastUpsertRequestDataAttributes, + ) + from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType + + +class CustomForecastUpsertRequestData(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_upsert_request_data_attributes import ( + CustomForecastUpsertRequestDataAttributes, + ) + from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType + + return { + "attributes": (CustomForecastUpsertRequestDataAttributes,), + "id": (str,), + "type": (CustomForecastType,), + } + + attribute_map = { + "attributes": "attributes", + "id": "id", + "type": "type", + } + + def __init__( + self_, + attributes: CustomForecastUpsertRequestDataAttributes, + type: CustomForecastType, + id: Union[str, UnsetType] = unset, + **kwargs, + ): + """ + Custom forecast resource wrapper in an upsert request. + + :param attributes: Attributes of a custom forecast upsert request. + :type attributes: CustomForecastUpsertRequestDataAttributes + + :param id: Unused on upsert; the resource is keyed by ``budget_uid``. Send an empty string. + :type id: str, optional + + :param type: The type of the custom forecast resource. Must be ``custom_forecast``. + :type type: CustomForecastType + """ + if id is not unset: + kwargs["id"] = id + super().__init__(kwargs) + + self_.attributes = attributes + self_.type = type diff --git a/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data_attributes.py b/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data_attributes.py new file mode 100644 index 0000000000..647683bb39 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_forecast_upsert_request_data_attributes.py @@ -0,0 +1,47 @@ +# 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. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry + + +class CustomForecastUpsertRequestDataAttributes(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry + + return { + "budget_uid": (str,), + "entries": ([CustomForecastEntry],), + } + + attribute_map = { + "budget_uid": "budget_uid", + "entries": "entries", + } + + def __init__(self_, budget_uid: str, entries: List[CustomForecastEntry], **kwargs): + """ + Attributes of a custom forecast upsert request. + + :param budget_uid: The UUID of the budget that this custom forecast belongs to. + :type budget_uid: str + + :param entries: Monthly custom forecast entries. An empty list deletes any existing + custom forecast for the budget. + :type entries: [CustomForecastEntry] + """ + super().__init__(kwargs) + + self_.budget_uid = budget_uid + self_.entries = entries diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py index 9413425cce..764478810b 100644 --- a/src/datadog_api_client/v2/models/__init__.py +++ b/src/datadog_api_client/v2/models/__init__.py @@ -2020,6 +2020,17 @@ CustomDestinationUpdateRequestDefinition, ) from datadog_api_client.v2.model.custom_destinations_response import CustomDestinationsResponse +from datadog_api_client.v2.model.custom_forecast_entry import CustomForecastEntry +from datadog_api_client.v2.model.custom_forecast_entry_tag_filter import CustomForecastEntryTagFilter +from datadog_api_client.v2.model.custom_forecast_response import CustomForecastResponse +from datadog_api_client.v2.model.custom_forecast_response_data import CustomForecastResponseData +from datadog_api_client.v2.model.custom_forecast_response_data_attributes import CustomForecastResponseDataAttributes +from datadog_api_client.v2.model.custom_forecast_type import CustomForecastType +from datadog_api_client.v2.model.custom_forecast_upsert_request import CustomForecastUpsertRequest +from datadog_api_client.v2.model.custom_forecast_upsert_request_data import CustomForecastUpsertRequestData +from datadog_api_client.v2.model.custom_forecast_upsert_request_data_attributes import ( + CustomForecastUpsertRequestDataAttributes, +) from datadog_api_client.v2.model.custom_framework_control import CustomFrameworkControl from datadog_api_client.v2.model.custom_framework_data import CustomFrameworkData from datadog_api_client.v2.model.custom_framework_data_attributes import CustomFrameworkDataAttributes @@ -10894,6 +10905,15 @@ "CustomDestinationUpdateRequestAttributes", "CustomDestinationUpdateRequestDefinition", "CustomDestinationsResponse", + "CustomForecastEntry", + "CustomForecastEntryTagFilter", + "CustomForecastResponse", + "CustomForecastResponseData", + "CustomForecastResponseDataAttributes", + "CustomForecastType", + "CustomForecastUpsertRequest", + "CustomForecastUpsertRequestData", + "CustomForecastUpsertRequestDataAttributes", "CustomFrameworkControl", "CustomFrameworkData", "CustomFrameworkDataAttributes", diff --git a/tests/v2/features/cloud_cost_management.feature b/tests/v2/features/cloud_cost_management.feature index 535fe88d7c..d9434ef407 100644 --- a/tests/v2/features/cloud_cost_management.feature +++ b/tests/v2/features/cloud_cost_management.feature @@ -67,6 +67,30 @@ Feature: Cloud Cost Management And the response "data.type" is equal to "arbitrary_rule" And the response "data.attributes.rule_name" is equal to "example-arbitrary-cost-rule" + @generated @skip @team:DataDog/cloud-cost-management + Scenario: Create or replace a budget's custom forecast returns "Bad Request" response + Given operation "UpsertCustomForecast" enabled + And new "UpsertCustomForecast" request + And body with value {"data": {"attributes": {"budget_uid": "00000000-0000-0000-0000-000000000001", "entries": [{"amount": 400, "month": 202501, "tag_filters": [{"tag_key": "service", "tag_value": "ec2"}]}]}, "id": "", "type": "custom_forecast"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/cloud-cost-management + Scenario: Create or replace a budget's custom forecast returns "Not Found" response + Given operation "UpsertCustomForecast" enabled + And new "UpsertCustomForecast" request + And body with value {"data": {"attributes": {"budget_uid": "00000000-0000-0000-0000-000000000001", "entries": [{"amount": 400, "month": 202501, "tag_filters": [{"tag_key": "service", "tag_value": "ec2"}]}]}, "id": "", "type": "custom_forecast"}} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/cloud-cost-management + Scenario: Create or replace a budget's custom forecast returns "OK" response + Given operation "UpsertCustomForecast" enabled + And new "UpsertCustomForecast" request + And body with value {"data": {"attributes": {"budget_uid": "00000000-0000-0000-0000-000000000001", "entries": [{"amount": 400, "month": 202501, "tag_filters": [{"tag_key": "service", "tag_value": "ec2"}]}]}, "id": "", "type": "custom_forecast"}} + When the request is sent + Then the response status is 200 OK + @generated @skip @team:DataDog/cloud-cost-management Scenario: Create or update a budget returns "Bad Request" response Given new "UpsertBudget" request @@ -211,6 +235,30 @@ Feature: Cloud Cost Management When the request is sent Then the response status is 400 Bad Request + @generated @skip @team:DataDog/cloud-cost-management + Scenario: Delete a budget's custom forecast returns "Bad Request" response + Given operation "DeleteCustomForecast" enabled + And new "DeleteCustomForecast" request + And request contains "budget_id" 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: Delete a budget's custom forecast returns "No Content" response + Given operation "DeleteCustomForecast" enabled + And new "DeleteCustomForecast" request + And request contains "budget_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 204 No Content + + @generated @skip @team:DataDog/cloud-cost-management + Scenario: Delete a budget's custom forecast returns "Not Found" response + Given operation "DeleteCustomForecast" enabled + And new "DeleteCustomForecast" request + And request contains "budget_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + @generated @skip @team:DataDog/cloud-cost-management Scenario: Delete budget returns "No Content" response Given new "DeleteBudget" request diff --git a/tests/v2/features/undo.json b/tests/v2/features/undo.json index a5c43f6c0f..00f6525933 100644 --- a/tests/v2/features/undo.json +++ b/tests/v2/features/undo.json @@ -1755,6 +1755,12 @@ "type": "safe" } }, + "UpsertCustomForecast": { + "tag": "Cloud Cost Management", + "undo": { + "type": "idempotent" + } + }, "ValidateBudget": { "tag": "Cloud Cost Management", "undo": { @@ -1773,6 +1779,12 @@ "type": "safe" } }, + "DeleteCustomForecast": { + "tag": "Cloud Cost Management", + "undo": { + "type": "idempotent" + } + }, "ListBudgets": { "tag": "Cloud Cost Management", "undo": {