diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index c441901f4..13d9a8960 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -121499,6 +121499,249 @@ components: $ref: "#/components/schemas/UsageDataObject" type: array type: object + UsageQuotaBulkResultAttributes: + description: Attributes of a usage quota bulk write result. On success, all fields except `error` are present. On failure, only `error` is present and the other fields are omitted. + properties: + enforced: + description: Whether usage above the limit is actively blocked instead of only tracked or alerted on. Omitted if this item failed to write. + example: true + type: boolean + error: + description: An error message describing why this item failed to write. Omitted if this item was written successfully. + example: usage_limit is out of range + type: string + org_public_id: + description: The public ID of the organization that owns the quota. Omitted if this item failed to write. + example: abcdef12345 + type: string + scope: + $ref: "#/components/schemas/UsageQuotaResponseScope" + usage_limit: + description: The quota limit in the usage units defined by the quota namespace. May be fractional for quotas configured before public writes required whole units. Omitted if this item failed to write. + example: 100000 + format: double + type: number + type: object + UsageQuotaBulkResultData: + description: The result of writing one usage quota in a bulk create-or-update request. + properties: + attributes: + $ref: "#/components/schemas/UsageQuotaBulkResultAttributes" + id: + description: An opaque usage quota identifier. Clients must pass this value back verbatim in update and delete requests and must not infer any structure from it. + example: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: string + type: + $ref: "#/components/schemas/UsageQuotaType" + required: + - id + - type + - attributes + type: object + UsageQuotaBulkResultDataList: + description: The results of writing each usage quota in a bulk create-or-update request, in the same order as the request. + items: + $ref: "#/components/schemas/UsageQuotaBulkResultData" + type: array + UsageQuotaCreateAttributes: + description: Attributes for creating or updating a usage quota by scope. + properties: + enforced: + description: Whether to actively block usage above the limit instead of only tracking or alerting on it. + example: true + type: boolean + scope: + $ref: "#/components/schemas/UsageQuotaRequestScope" + usage_limit: + description: The quota limit to set in the usage units defined by the quota namespace. For an organization-wide quota (scope omitted), the limit must be greater than the usage already recorded in the current period. + example: 100000 + format: int64 + minimum: 0 + type: integer + required: + - usage_limit + - enforced + type: object + UsageQuotaCreateData: + description: A usage quota resource to create or update by scope. + properties: + attributes: + $ref: "#/components/schemas/UsageQuotaCreateAttributes" + type: + $ref: "#/components/schemas/UsageQuotaType" + required: + - type + - attributes + type: object + UsageQuotaCreateDataList: + description: A bulk list of usage quota resources to create or update by scope. + items: + $ref: "#/components/schemas/UsageQuotaCreateData" + minItems: 1 + type: array + UsageQuotaRequestScope: + additionalProperties: + example: jane@example.com + type: string + description: A namespace-specific key and value identifying what the quota applies to within an organization. The object must contain exactly one entry. Use `"*"` as the value for the default quota applied to entities without a specific quota, or omit the scope for an organization-wide quota. A specific value must identify an existing user handle in the caller's organization when `include_descendants` is false. When `include_descendants` is true, the handle must exist in the caller's organization or in at least one targeted descendant organization; the quota is then applied only to the organizations where that handle exists, and the request fails only if the handle exists in none of them. + example: + user_handle: jane@example.com + maxProperties: 1 + minProperties: 1 + type: object + UsageQuotaResponse: + description: Response containing a usage quota. + properties: + data: + $ref: "#/components/schemas/UsageQuotaResponseData" + required: + - data + type: object + UsageQuotaResponseAttributes: + description: Attributes of a usage quota. + properties: + enforced: + description: Whether usage above the limit is actively blocked instead of only tracked or alerted on. + example: true + type: boolean + org_public_id: + description: The public ID of the organization that owns the quota. + example: abcdef12345 + type: string + scope: + $ref: "#/components/schemas/UsageQuotaResponseScope" + usage_limit: + description: The quota limit in the usage units defined by the quota namespace. May be fractional for quotas configured before public writes required whole units. + example: 100000 + format: double + type: number + required: + - org_public_id + - usage_limit + - enforced + type: object + UsageQuotaResponseData: + description: A usage quota resource. + properties: + attributes: + $ref: "#/components/schemas/UsageQuotaResponseAttributes" + id: + description: An opaque usage quota identifier. Clients must pass this value back verbatim in update and delete requests and must not infer any structure from it. + example: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: string + type: + $ref: "#/components/schemas/UsageQuotaType" + required: + - id + - type + - attributes + type: object + UsageQuotaResponseDataList: + description: A list of usage quota resources. + items: + $ref: "#/components/schemas/UsageQuotaResponseData" + type: array + UsageQuotaResponseScope: + additionalProperties: + example: jane@example.com + type: string + description: A namespace-specific key and value identifying what the quota applies to within an organization. The object contains exactly one entry. A value of `"*"` identifies the default quota applied to entities without a specific quota. This field is omitted for an organization-wide quota. + example: + user_handle: jane@example.com + maxProperties: 1 + minProperties: 1 + type: object + UsageQuotaType: + description: The JSON:API resource type for a usage quota. + enum: + - quotas + example: quotas + type: string + x-enum-varnames: + - QUOTAS + UsageQuotaUpdateAttributes: + description: Attributes to update on a usage quota. Omitting a property leaves its current value unchanged. + properties: + enforced: + description: Whether to actively block usage above the limit. Omit this field to leave the current enforcement setting unchanged. + example: false + nullable: true + type: boolean + usage_limit: + description: The new quota limit in the usage units defined by the quota namespace. For an organization-wide quota (empty scope), the limit must be greater than the usage already recorded in the current period. Omit this field to leave the current limit unchanged. + example: 120000 + format: int64 + minimum: 0 + nullable: true + type: integer + type: object + UsageQuotaUpdateData: + description: A usage quota resource to update. + properties: + attributes: + $ref: "#/components/schemas/UsageQuotaUpdateAttributes" + id: + description: The opaque usage quota identifier, which must match the identifier in the request path. + example: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: string + type: + $ref: "#/components/schemas/UsageQuotaType" + required: + - id + - type + - attributes + type: object + UsageQuotaUpdateRequest: + description: Request containing the usage quota resource to update. + properties: + data: + $ref: "#/components/schemas/UsageQuotaUpdateData" + required: + - data + type: object + UsageQuotasBulkResponse: + description: Response containing the result of a bulk usage quota create-or-update request. Returned with a `200` status regardless of whether individual items succeeded or failed; check each item's `error` attribute to determine its outcome. + properties: + data: + $ref: "#/components/schemas/UsageQuotaBulkResultDataList" + required: + - data + type: object + UsageQuotasCreateRequest: + description: A JSON:API bulk request containing an array of usage quota resources rather than a single resource. + properties: + data: + $ref: "#/components/schemas/UsageQuotaCreateDataList" + required: + - data + type: object + UsageQuotasListResponse: + description: Response containing a paginated list of usage quotas. + properties: + data: + $ref: "#/components/schemas/UsageQuotaResponseDataList" + meta: + $ref: "#/components/schemas/UsageQuotasResponseMeta" + required: + - data + - meta + type: object + UsageQuotasResponseMeta: + description: Pagination metadata for a usage quota list response. + properties: + page: + $ref: "#/components/schemas/UsageQuotasResponseMetaPage" + required: + - page + type: object + UsageQuotasResponseMetaPage: + description: Cursor pagination fields for a usage quota list response. + properties: + next_cursor: + description: An opaque cursor for retrieving the next page. Omitted when there are no more results. + example: eyJvZmZzZXQiOjEwMH0= + type: string + type: object UsageSummaryAvailableFieldsAttributes: description: |- The lists of field names returned by `GET /api/v1/usage/summary` at each @@ -218399,6 +218642,356 @@ paths: permissions: - usage_read - billing_read + /api/v2/usage/quotas/{quota_namespace}: + get: + description: |- + Lists usage quotas for the caller's organization in a quota namespace. You can optionally include descendant organizations in the same datacenter as the caller. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + operationId: ListQuotas + parameters: + - description: The product-specific namespace whose usage quotas are being managed. + in: path + name: quota_namespace + required: true + schema: + example: ai_credits + type: string + - description: Whether to include quotas configured on descendant organizations in the caller's organization hierarchy. Only descendants in the same datacenter are supported. + in: query + name: include_descendants + required: false + schema: + default: false + type: boolean + - description: An opaque cursor from a previous response's `meta.page.next_cursor` used to retrieve the next page. + in: query + name: page[cursor] + required: false + schema: + type: string + - description: The number of usage quotas to return per page. + in: query + name: page[limit] + required: false + schema: + default: 100 + format: int64 + maximum: 1000 + minimum: 1 + type: integer + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + - attributes: + enforced: true + org_public_id: abcdef12345 + scope: + user_handle: jane@example.com + usage_limit: 100000 + id: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: quotas + meta: + page: + next_cursor: eyJvZmZzZXQiOjEwMH0= + schema: + $ref: "#/components/schemas/UsageQuotasListResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - user_access_manage + - billing_edit + - org_management + summary: List usage quotas + tags: + - Usage Metering + x-pagination: + cursorParam: page[cursor] + cursorPath: meta.page.next_cursor + limitParam: page[limit] + resultsPath: data + "x-permission": + operator: AND + permissions: + - user_access_manage + - billing_edit + - org_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/). + post: + description: |- + Creates or updates one or more usage quotas by scope. If a quota already exists for a supplied scope, it is updated; otherwise, a new quota is created. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + operationId: CreateQuotas + parameters: + - description: The product-specific namespace whose usage quotas are being managed. + in: path + name: quota_namespace + required: true + schema: + example: ai_credits + type: string + - description: Whether to write every item in the request to the caller's organization and all of its descendant organizations, instead of only the caller's organization. Only descendants in the same datacenter are supported. For a user-handle scope, the quota is applied only to the caller's organization and to descendant organizations where that user handle exists; the item fails only if the handle exists in none of them. + in: query + name: include_descendants + required: false + schema: + default: false + type: boolean + requestBody: + content: + application/json: + examples: + default: + summary: Create or update quotas for the caller's organization. + value: + data: + - attributes: + enforced: true + scope: + user_handle: jane@example.com + usage_limit: 100000 + type: quotas + - attributes: + enforced: false + scope: + user_handle: "*" + usage_limit: 250000 + type: quotas + schema: + $ref: "#/components/schemas/UsageQuotasCreateRequest" + description: The usage quotas to create or update. + required: true + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + - attributes: + enforced: true + org_public_id: abcdef12345 + scope: + user_handle: jane@example.com + usage_limit: 100000 + id: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: quotas + - attributes: + error: usage_limit is out of range + id: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTp1c2VyQGV4YW1wbGUuY29t" + type: quotas + schema: + $ref: "#/components/schemas/UsageQuotasBulkResponse" + description: OK. The response includes each item's result; see each item's `error` attribute for any that failed to write. + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + "500": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Internal Server Error. Every item in the batch failed to write. + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - user_access_manage + - billing_edit + - org_management + summary: Create or update usage quotas + tags: + - Usage Metering + "x-permission": + operator: AND + permissions: + - user_access_manage + - billing_edit + - org_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/usage/quotas/{quota_namespace}/{id}: + delete: + description: |- + Deletes a usage quota by its opaque identifier. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + operationId: DeleteQuota + parameters: + - description: The product-specific namespace whose usage quotas are being managed. + in: path + name: quota_namespace + required: true + schema: + example: ai_credits + type: string + - description: The opaque quota identifier returned by a previous list or create request. Clients must pass this value verbatim. + in: path + name: id + required: true + schema: + example: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: string + responses: + "204": + description: No Content + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Not Found + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - user_access_manage + - billing_edit + - org_management + summary: Delete a usage quota + tags: + - Usage Metering + "x-permission": + operator: AND + permissions: + - user_access_manage + - billing_edit + - org_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/). + patch: + description: |- + Updates the supplied fields on a usage quota and leaves omitted fields unchanged. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + operationId: UpdateQuota + parameters: + - description: The product-specific namespace whose usage quotas are being managed. + in: path + name: quota_namespace + required: true + schema: + example: ai_credits + type: string + - description: The opaque quota identifier returned by a previous list or create request. Clients must pass this value verbatim. + in: path + name: id + required: true + schema: + example: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: string + requestBody: + content: + application/json: + examples: + default: + value: + data: + attributes: + enforced: false + usage_limit: 120000 + id: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: quotas + schema: + $ref: "#/components/schemas/UsageQuotaUpdateRequest" + description: The usage quota fields to update. Omitting an attribute leaves its current value unchanged. + required: true + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + attributes: + enforced: false + org_public_id: abcdef12345 + scope: + user_handle: jane@example.com + usage_limit: 120000 + id: "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f" + type: quotas + schema: + $ref: "#/components/schemas/UsageQuotaResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Bad Request. Returned if the request is malformed, or if the `id` in the request body does not match the `id` in the request path. + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/JSONAPIErrorResponse" + description: Not Found + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - user_access_manage + - billing_edit + - org_management + summary: Update a usage quota + tags: + - Usage Metering + "x-permission": + operator: AND + permissions: + - user_access_manage + - billing_edit + - org_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/usage/summary/available_fields: get: description: |- diff --git a/examples/v2_usage-metering_CreateQuotas.rs b/examples/v2_usage-metering_CreateQuotas.rs new file mode 100644 index 000000000..15db945b2 --- /dev/null +++ b/examples/v2_usage-metering_CreateQuotas.rs @@ -0,0 +1,37 @@ +// Create or update usage quotas returns "OK. The response includes each item's +// result; see each item's `error` attribute for any that failed to write." +// response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_usage_metering::CreateQuotasOptionalParams; +use datadog_api_client::datadogV2::api_usage_metering::UsageMeteringAPI; +use datadog_api_client::datadogV2::model::UsageQuotaCreateAttributes; +use datadog_api_client::datadogV2::model::UsageQuotaCreateData; +use datadog_api_client::datadogV2::model::UsageQuotaType; +use datadog_api_client::datadogV2::model::UsageQuotasCreateRequest; +use std::collections::BTreeMap; + +#[tokio::main] +async fn main() { + let body = UsageQuotasCreateRequest::new(vec![UsageQuotaCreateData::new( + UsageQuotaCreateAttributes::new(true, 100000).scope(BTreeMap::from([( + "user_handle".to_string(), + "jane@example.com".to_string(), + )])), + UsageQuotaType::QUOTAS, + )]); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.CreateQuotas", true); + let api = UsageMeteringAPI::with_config(configuration); + let resp = api + .create_quotas( + "ai_credits".to_string(), + body, + CreateQuotasOptionalParams::default(), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_usage-metering_DeleteQuota.rs b/examples/v2_usage-metering_DeleteQuota.rs new file mode 100644 index 000000000..ebabd3f71 --- /dev/null +++ b/examples/v2_usage-metering_DeleteQuota.rs @@ -0,0 +1,21 @@ +// Delete a usage quota returns "No Content" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_usage_metering::UsageMeteringAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.DeleteQuota", true); + let api = UsageMeteringAPI::with_config(configuration); + let resp = api + .delete_quota( + "ai_credits".to_string(), + "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f".to_string(), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_usage-metering_ListQuotas.rs b/examples/v2_usage-metering_ListQuotas.rs new file mode 100644 index 000000000..fdb8047fc --- /dev/null +++ b/examples/v2_usage-metering_ListQuotas.rs @@ -0,0 +1,22 @@ +// List usage quotas returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_usage_metering::ListQuotasOptionalParams; +use datadog_api_client::datadogV2::api_usage_metering::UsageMeteringAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.ListQuotas", true); + let api = UsageMeteringAPI::with_config(configuration); + let resp = api + .list_quotas( + "ai_credits".to_string(), + ListQuotasOptionalParams::default(), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_usage-metering_ListQuotas_918754421.rs b/examples/v2_usage-metering_ListQuotas_918754421.rs new file mode 100644 index 000000000..085f34479 --- /dev/null +++ b/examples/v2_usage-metering_ListQuotas_918754421.rs @@ -0,0 +1,25 @@ +// List usage quotas returns "OK" response with pagination +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_usage_metering::ListQuotasOptionalParams; +use datadog_api_client::datadogV2::api_usage_metering::UsageMeteringAPI; +use futures_util::pin_mut; +use futures_util::stream::StreamExt; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.ListQuotas", true); + let api = UsageMeteringAPI::with_config(configuration); + let response = api.list_quotas_with_pagination( + "ai_credits".to_string(), + ListQuotasOptionalParams::default(), + ); + pin_mut!(response); + while let Some(resp) = response.next().await { + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } + } +} diff --git a/examples/v2_usage-metering_UpdateQuota.rs b/examples/v2_usage-metering_UpdateQuota.rs new file mode 100644 index 000000000..ddb0b96b7 --- /dev/null +++ b/examples/v2_usage-metering_UpdateQuota.rs @@ -0,0 +1,33 @@ +// Update a usage quota returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_usage_metering::UsageMeteringAPI; +use datadog_api_client::datadogV2::model::UsageQuotaType; +use datadog_api_client::datadogV2::model::UsageQuotaUpdateAttributes; +use datadog_api_client::datadogV2::model::UsageQuotaUpdateData; +use datadog_api_client::datadogV2::model::UsageQuotaUpdateRequest; + +#[tokio::main] +async fn main() { + let body = UsageQuotaUpdateRequest::new(UsageQuotaUpdateData::new( + UsageQuotaUpdateAttributes::new() + .enforced(Some(false)) + .usage_limit(Some(120000)), + "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f".to_string(), + UsageQuotaType::QUOTAS, + )); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.UpdateQuota", true); + let api = UsageMeteringAPI::with_config(configuration); + let resp = api + .update_quota( + "ai_credits".to_string(), + "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f".to_string(), + body, + ) + .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 ed9e26965..f330e7a75 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -510,6 +510,10 @@ impl Default for Configuration { ("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_quotas".to_owned(), false), + ("v2.delete_quota".to_owned(), false), + ("v2.list_quotas".to_owned(), false), + ("v2.update_quota".to_owned(), false), ("v2.create_ownership_feedback".to_owned(), false), ("v2.get_ownership_evidence".to_owned(), false), ("v2.get_ownership_inference".to_owned(), false), diff --git a/src/datadogV2/api/api_usage_metering.rs b/src/datadogV2/api/api_usage_metering.rs index c3192d4ec..0d66d1e8e 100644 --- a/src/datadogV2/api/api_usage_metering.rs +++ b/src/datadogV2/api/api_usage_metering.rs @@ -2,8 +2,32 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2019-Present Datadog, Inc. use crate::datadog; +use async_stream::try_stream; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; +use futures_core::stream::Stream; +use log::warn; use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; +use std::io::Write; + +/// CreateQuotasOptionalParams is a struct for passing parameters to the method [`UsageMeteringAPI::create_quotas`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct CreateQuotasOptionalParams { + /// Whether to write every item in the request to the caller's organization and all of its descendant organizations, instead of only the caller's organization. Only descendants in the same datacenter are supported. For a user-handle scope, the quota is applied only to the caller's organization and to descendant organizations where that user handle exists; the item fails only if the handle exists in none of them. + pub include_descendants: Option, +} + +impl CreateQuotasOptionalParams { + /// Whether to write every item in the request to the caller's organization and all of its descendant organizations, instead of only the caller's organization. Only descendants in the same datacenter are supported. For a user-handle scope, the quota is applied only to the caller's organization and to descendant organizations where that user handle exists; the item fails only if the handle exists in none of them. + pub fn include_descendants(mut self, value: bool) -> Self { + self.include_descendants = Some(value); + self + } +} /// GetBillingDimensionMappingOptionalParams is a struct for passing parameters to the method [`UsageMeteringAPI::get_billing_dimension_mapping`] #[non_exhaustive] @@ -324,6 +348,54 @@ impl GetUsageObservabilityPipelinesOptionalParams { } } +/// ListQuotasOptionalParams is a struct for passing parameters to the method [`UsageMeteringAPI::list_quotas`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct ListQuotasOptionalParams { + /// Whether to include quotas configured on descendant organizations in the caller's organization hierarchy. Only descendants in the same datacenter are supported. + pub include_descendants: Option, + /// An opaque cursor from a previous response's `meta.page.next_cursor` used to retrieve the next page. + pub page_cursor: Option, + /// The number of usage quotas to return per page. + pub page_limit: Option, +} + +impl ListQuotasOptionalParams { + /// Whether to include quotas configured on descendant organizations in the caller's organization hierarchy. Only descendants in the same datacenter are supported. + pub fn include_descendants(mut self, value: bool) -> Self { + self.include_descendants = Some(value); + self + } + /// An opaque cursor from a previous response's `meta.page.next_cursor` used to retrieve the next page. + pub fn page_cursor(mut self, value: String) -> Self { + self.page_cursor = Some(value); + self + } + /// The number of usage quotas to return per page. + pub fn page_limit(mut self, value: i64) -> Self { + self.page_limit = Some(value); + self + } +} + +/// CreateQuotasError is a struct for typed errors of method [`UsageMeteringAPI::create_quotas`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateQuotasError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// DeleteQuotaError is a struct for typed errors of method [`UsageMeteringAPI::delete_quota`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DeleteQuotaError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// GetActiveBillingDimensionsError is a struct for typed errors of method [`UsageMeteringAPI::get_active_billing_dimensions`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -428,6 +500,24 @@ pub enum GetUsageSummaryAvailableFieldsError { UnknownValue(serde_json::Value), } +/// ListQuotasError is a struct for typed errors of method [`UsageMeteringAPI::list_quotas`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ListQuotasError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// UpdateQuotaError is a struct for typed errors of method [`UsageMeteringAPI::update_quota`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UpdateQuotaError { + JSONAPIErrorResponse(crate::datadogV2::model::JSONAPIErrorResponse), + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// The usage metering API allows you to get hourly, daily, and /// monthly usage across multiple facets of Datadog. /// This API is available to all Pro and Enterprise customers. @@ -511,6 +601,280 @@ impl UsageMeteringAPI { Self { config, client } } + /// Creates or updates one or more usage quotas by scope. If a quota already exists for a supplied scope, it is updated; otherwise, a new quota is created. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn create_quotas( + &self, + quota_namespace: String, + body: crate::datadogV2::model::UsageQuotasCreateRequest, + params: CreateQuotasOptionalParams, + ) -> Result> + { + match self + .create_quotas_with_http_info(quota_namespace, body, params) + .await + { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + /// Creates or updates one or more usage quotas by scope. If a quota already exists for a supplied scope, it is updated; otherwise, a new quota is created. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn create_quotas_with_http_info( + &self, + quota_namespace: String, + body: crate::datadogV2::model::UsageQuotasCreateRequest, + params: CreateQuotasOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let local_operation_id = "v2.create_quotas"; + if local_configuration.is_unstable_operation_enabled(local_operation_id) { + warn!("Using unstable operation {local_operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.create_quotas' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + // unbox and build optional parameters + let include_descendants = params.include_descendants; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/usage/quotas/{quota_namespace}", + local_configuration.get_operation_host(local_operation_id), + quota_namespace = datadog::urlencode(quota_namespace) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::POST, local_uri_str.as_str()); + + if let Some(ref local_query_param) = include_descendants { + local_req_builder = + local_req_builder.query(&[("include_descendants", &local_query_param.to_string())]); + }; + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + 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"), + ); + }; + + // build body parameters + let output = Vec::new(); + let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter); + if body.serialize(&mut ser).is_ok() { + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + #[cfg(feature = "zstd")] + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + + 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)) + } + } + + /// Deletes a usage quota by its opaque identifier. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn delete_quota( + &self, + quota_namespace: String, + id: String, + ) -> Result<(), datadog::Error> { + match self.delete_quota_with_http_info(quota_namespace, id).await { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Deletes a usage quota by its opaque identifier. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn delete_quota_with_http_info( + &self, + quota_namespace: String, + id: String, + ) -> Result, datadog::Error> { + let local_configuration = &self.config; + let local_operation_id = "v2.delete_quota"; + if local_configuration.is_unstable_operation_enabled(local_operation_id) { + warn!("Using unstable operation {local_operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.delete_quota' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/usage/quotas/{quota_namespace}/{id}", + local_configuration.get_operation_host(local_operation_id), + quota_namespace = datadog::urlencode(quota_namespace), + id = datadog::urlencode(id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + + // 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() { + Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: None, + }) + } 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)) + } + } + /// Get active billing dimensions for cost attribution. Cost data for a given month becomes available no later than the 19th of the following month. pub async fn get_active_billing_dimensions( &self, @@ -2385,4 +2749,344 @@ impl UsageMeteringAPI { Err(datadog::Error::ResponseError(local_error)) } } + + /// Lists usage quotas for the caller's organization in a quota namespace. You can optionally include descendant organizations in the same datacenter as the caller. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn list_quotas( + &self, + quota_namespace: String, + params: ListQuotasOptionalParams, + ) -> Result> + { + match self + .list_quotas_with_http_info(quota_namespace, params) + .await + { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + pub fn list_quotas_with_pagination( + &self, + quota_namespace: String, + mut params: ListQuotasOptionalParams, + ) -> impl Stream< + Item = Result< + crate::datadogV2::model::UsageQuotaResponseData, + datadog::Error, + >, + > + '_ { + try_stream! { + let mut page_size: i64 = 100; + if params.page_limit.is_none() { + params.page_limit = Some(page_size); + } else { + page_size = params.page_limit.unwrap().clone(); + } + loop { + let resp = self.list_quotas( quota_namespace.clone(),params.clone()).await?; + + let r = resp.data; + let count = r.len(); + for team in r { + yield team; + } + if count == 0 { + break; + } + let Some(next_cursor) = resp.meta.page.next_cursor else { break }; + + params.page_cursor = Some(next_cursor); + } + } + } + + /// Lists usage quotas for the caller's organization in a quota namespace. You can optionally include descendant organizations in the same datacenter as the caller. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn list_quotas_with_http_info( + &self, + quota_namespace: String, + params: ListQuotasOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let local_operation_id = "v2.list_quotas"; + if local_configuration.is_unstable_operation_enabled(local_operation_id) { + warn!("Using unstable operation {local_operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.list_quotas' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + // unbox and build optional parameters + let include_descendants = params.include_descendants; + let page_cursor = params.page_cursor; + let page_limit = params.page_limit; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/usage/quotas/{quota_namespace}", + local_configuration.get_operation_host(local_operation_id), + quota_namespace = datadog::urlencode(quota_namespace) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + if let Some(ref local_query_param) = include_descendants { + local_req_builder = + local_req_builder.query(&[("include_descendants", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = page_cursor { + local_req_builder = + local_req_builder.query(&[("page[cursor]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = page_limit { + local_req_builder = + local_req_builder.query(&[("page[limit]", &local_query_param.to_string())]); + }; + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + + /// Updates the supplied fields on a usage quota and leaves omitted fields unchanged. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn update_quota( + &self, + quota_namespace: String, + id: String, + body: crate::datadogV2::model::UsageQuotaUpdateRequest, + ) -> Result> { + match self + .update_quota_with_http_info(quota_namespace, id, body) + .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), + } + } + + /// Updates the supplied fields on a usage quota and leaves omitted fields unchanged. The quota must belong to the caller's organization or one of its descendants, and its opaque identifier must belong to the requested quota namespace. Requires the `user_access_manage`, `billing_edit`, and `org_management` permissions. + pub async fn update_quota_with_http_info( + &self, + quota_namespace: String, + id: String, + body: crate::datadogV2::model::UsageQuotaUpdateRequest, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let local_operation_id = "v2.update_quota"; + if local_configuration.is_unstable_operation_enabled(local_operation_id) { + warn!("Using unstable operation {local_operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.update_quota' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/usage/quotas/{quota_namespace}/{id}", + local_configuration.get_operation_host(local_operation_id), + quota_namespace = datadog::urlencode(quota_namespace), + id = datadog::urlencode(id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::PATCH, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Content-Type", HeaderValue::from_static("application/json")); + 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"), + ); + }; + + // build body parameters + let output = Vec::new(); + let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter); + if body.serialize(&mut ser).is_ok() { + if let Some(content_encoding) = headers.get("Content-Encoding") { + match content_encoding.to_str().unwrap_or_default() { + "gzip" => { + let mut enc = GzEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + "deflate" => { + let mut enc = ZlibEncoder::new(Vec::new(), Compression::default()); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + #[cfg(feature = "zstd")] + "zstd1" => { + let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap(); + let _ = enc.write_all(ser.into_inner().as_slice()); + match enc.finish() { + Ok(buf) => { + local_req_builder = local_req_builder.body(buf); + } + Err(e) => return Err(datadog::Error::Io(e)), + } + } + _ => { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + } else { + local_req_builder = local_req_builder.body(ser.into_inner()); + } + } + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } } diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index 2fd0329d7..c6e0256bc 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -14990,6 +14990,38 @@ pub mod model_projected_cost_attributes; pub use self::model_projected_cost_attributes::ProjectedCostAttributes; pub mod model_projected_cost_type; pub use self::model_projected_cost_type::ProjectedCostType; +pub mod model_usage_quotas_list_response; +pub use self::model_usage_quotas_list_response::UsageQuotasListResponse; +pub mod model_usage_quota_response_data; +pub use self::model_usage_quota_response_data::UsageQuotaResponseData; +pub mod model_usage_quota_response_attributes; +pub use self::model_usage_quota_response_attributes::UsageQuotaResponseAttributes; +pub mod model_usage_quota_type; +pub use self::model_usage_quota_type::UsageQuotaType; +pub mod model_usage_quotas_response_meta; +pub use self::model_usage_quotas_response_meta::UsageQuotasResponseMeta; +pub mod model_usage_quotas_response_meta_page; +pub use self::model_usage_quotas_response_meta_page::UsageQuotasResponseMetaPage; +pub mod model_usage_quotas_create_request; +pub use self::model_usage_quotas_create_request::UsageQuotasCreateRequest; +pub mod model_usage_quota_create_data; +pub use self::model_usage_quota_create_data::UsageQuotaCreateData; +pub mod model_usage_quota_create_attributes; +pub use self::model_usage_quota_create_attributes::UsageQuotaCreateAttributes; +pub mod model_usage_quotas_bulk_response; +pub use self::model_usage_quotas_bulk_response::UsageQuotasBulkResponse; +pub mod model_usage_quota_bulk_result_data; +pub use self::model_usage_quota_bulk_result_data::UsageQuotaBulkResultData; +pub mod model_usage_quota_bulk_result_attributes; +pub use self::model_usage_quota_bulk_result_attributes::UsageQuotaBulkResultAttributes; +pub mod model_usage_quota_update_request; +pub use self::model_usage_quota_update_request::UsageQuotaUpdateRequest; +pub mod model_usage_quota_update_data; +pub use self::model_usage_quota_update_data::UsageQuotaUpdateData; +pub mod model_usage_quota_update_attributes; +pub use self::model_usage_quota_update_attributes::UsageQuotaUpdateAttributes; +pub mod model_usage_quota_response; +pub use self::model_usage_quota_response::UsageQuotaResponse; pub mod model_usage_summary_available_fields_response; pub use self::model_usage_summary_available_fields_response::UsageSummaryAvailableFieldsResponse; pub mod model_usage_summary_available_fields_body; diff --git a/src/datadogV2/model/model_usage_quota_bulk_result_attributes.rs b/src/datadogV2/model/model_usage_quota_bulk_result_attributes.rs new file mode 100644 index 000000000..c32562fd0 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_bulk_result_attributes.rs @@ -0,0 +1,175 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes of a usage quota bulk write result. On success, all fields except `error` are present. On failure, only `error` is present and the other fields are omitted. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaBulkResultAttributes { + /// Whether usage above the limit is actively blocked instead of only tracked or alerted on. Omitted if this item failed to write. + #[serde(rename = "enforced")] + pub enforced: Option, + /// An error message describing why this item failed to write. Omitted if this item was written successfully. + #[serde(rename = "error")] + pub error: Option, + /// The public ID of the organization that owns the quota. Omitted if this item failed to write. + #[serde(rename = "org_public_id")] + pub org_public_id: Option, + /// A namespace-specific key and value identifying what the quota applies to within an organization. The object contains exactly one entry. A value of `"*"` identifies the default quota applied to entities without a specific quota. This field is omitted for an organization-wide quota. + #[serde(rename = "scope")] + pub scope: Option>, + /// The quota limit in the usage units defined by the quota namespace. May be fractional for quotas configured before public writes required whole units. Omitted if this item failed to write. + #[serde(rename = "usage_limit")] + pub usage_limit: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaBulkResultAttributes { + pub fn new() -> UsageQuotaBulkResultAttributes { + UsageQuotaBulkResultAttributes { + enforced: None, + error: None, + org_public_id: None, + scope: None, + usage_limit: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn enforced(mut self, value: bool) -> Self { + self.enforced = Some(value); + self + } + + pub fn error(mut self, value: String) -> Self { + self.error = Some(value); + self + } + + pub fn org_public_id(mut self, value: String) -> Self { + self.org_public_id = Some(value); + self + } + + pub fn scope(mut self, value: std::collections::BTreeMap) -> Self { + self.scope = Some(value); + self + } + + pub fn usage_limit(mut self, value: f64) -> Self { + self.usage_limit = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for UsageQuotaBulkResultAttributes { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for UsageQuotaBulkResultAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaBulkResultAttributesVisitor; + impl<'a> Visitor<'a> for UsageQuotaBulkResultAttributesVisitor { + type Value = UsageQuotaBulkResultAttributes; + + 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 enforced: Option = None; + let mut error: Option = None; + let mut org_public_id: Option = None; + let mut scope: Option> = None; + let mut usage_limit: 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() { + "enforced" => { + if v.is_null() { + continue; + } + enforced = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "error" => { + if v.is_null() { + continue; + } + error = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "org_public_id" => { + if v.is_null() { + continue; + } + org_public_id = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "scope" => { + if v.is_null() { + continue; + } + scope = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "usage_limit" => { + if v.is_null() || v.as_str() == Some("") { + continue; + } + usage_limit = + 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 = UsageQuotaBulkResultAttributes { + enforced, + error, + org_public_id, + scope, + usage_limit, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaBulkResultAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_bulk_result_data.rs b/src/datadogV2/model/model_usage_quota_bulk_result_data.rs new file mode 100644 index 000000000..082e72508 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_bulk_result_data.rs @@ -0,0 +1,128 @@ +// 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}; + +/// The result of writing one usage quota in a bulk create-or-update request. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaBulkResultData { + /// Attributes of a usage quota bulk write result. On success, all fields except `error` are present. On failure, only `error` is present and the other fields are omitted. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::UsageQuotaBulkResultAttributes, + /// An opaque usage quota identifier. Clients must pass this value back verbatim in update and delete requests and must not infer any structure from it. + #[serde(rename = "id")] + pub id: String, + /// The JSON:API resource type for a usage quota. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::UsageQuotaType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaBulkResultData { + pub fn new( + attributes: crate::datadogV2::model::UsageQuotaBulkResultAttributes, + id: String, + type_: crate::datadogV2::model::UsageQuotaType, + ) -> UsageQuotaBulkResultData { + UsageQuotaBulkResultData { + attributes, + 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 UsageQuotaBulkResultData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaBulkResultDataVisitor; + impl<'a> Visitor<'a> for UsageQuotaBulkResultDataVisitor { + type Value = UsageQuotaBulkResultData; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut attributes: Option< + crate::datadogV2::model::UsageQuotaBulkResultAttributes, + > = 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" => { + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "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::UsageQuotaType::UnparsedObject( + _type_, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = UsageQuotaBulkResultData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaBulkResultDataVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_create_attributes.rs b/src/datadogV2/model/model_usage_quota_create_attributes.rs new file mode 100644 index 000000000..417f5a396 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_create_attributes.rs @@ -0,0 +1,121 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes for creating or updating a usage quota by scope. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaCreateAttributes { + /// Whether to actively block usage above the limit instead of only tracking or alerting on it. + #[serde(rename = "enforced")] + pub enforced: bool, + /// A namespace-specific key and value identifying what the quota applies to within an organization. The object must contain exactly one entry. Use `"*"` as the value for the default quota applied to entities without a specific quota, or omit the scope for an organization-wide quota. A specific value must identify an existing user handle in the caller's organization when `include_descendants` is false. When `include_descendants` is true, the handle must exist in the caller's organization or in at least one targeted descendant organization; the quota is then applied only to the organizations where that handle exists, and the request fails only if the handle exists in none of them. + #[serde(rename = "scope")] + pub scope: Option>, + /// The quota limit to set in the usage units defined by the quota namespace. For an organization-wide quota (scope omitted), the limit must be greater than the usage already recorded in the current period. + #[serde(rename = "usage_limit")] + pub usage_limit: i64, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaCreateAttributes { + pub fn new(enforced: bool, usage_limit: i64) -> UsageQuotaCreateAttributes { + UsageQuotaCreateAttributes { + enforced, + scope: None, + usage_limit, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn scope(mut self, value: std::collections::BTreeMap) -> Self { + self.scope = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for UsageQuotaCreateAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaCreateAttributesVisitor; + impl<'a> Visitor<'a> for UsageQuotaCreateAttributesVisitor { + type Value = UsageQuotaCreateAttributes; + + 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 enforced: Option = None; + let mut scope: Option> = None; + let mut usage_limit: 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() { + "enforced" => { + enforced = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "scope" => { + if v.is_null() { + continue; + } + scope = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "usage_limit" => { + usage_limit = + 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 enforced = enforced.ok_or_else(|| M::Error::missing_field("enforced"))?; + let usage_limit = + usage_limit.ok_or_else(|| M::Error::missing_field("usage_limit"))?; + + let content = UsageQuotaCreateAttributes { + enforced, + scope, + usage_limit, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaCreateAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_create_data.rs b/src/datadogV2/model/model_usage_quota_create_data.rs new file mode 100644 index 000000000..ceb966bec --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_create_data.rs @@ -0,0 +1,116 @@ +// 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 usage quota resource to create or update by scope. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaCreateData { + /// Attributes for creating or updating a usage quota by scope. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::UsageQuotaCreateAttributes, + /// The JSON:API resource type for a usage quota. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::UsageQuotaType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaCreateData { + pub fn new( + attributes: crate::datadogV2::model::UsageQuotaCreateAttributes, + type_: crate::datadogV2::model::UsageQuotaType, + ) -> UsageQuotaCreateData { + UsageQuotaCreateData { + attributes, + 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 UsageQuotaCreateData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaCreateDataVisitor; + impl<'a> Visitor<'a> for UsageQuotaCreateDataVisitor { + type Value = UsageQuotaCreateData; + + 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 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" => { + attributes = 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::UsageQuotaType::UnparsedObject( + _type_, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = UsageQuotaCreateData { + attributes, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaCreateDataVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_response.rs b/src/datadogV2/model/model_usage_quota_response.rs new file mode 100644 index 000000000..f5f3ee83c --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_response.rs @@ -0,0 +1,92 @@ +// 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}; + +/// Response containing a usage quota. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaResponse { + /// A usage quota resource. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::UsageQuotaResponseData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaResponse { + pub fn new(data: crate::datadogV2::model::UsageQuotaResponseData) -> UsageQuotaResponse { + UsageQuotaResponse { + 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 UsageQuotaResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaResponseVisitor; + impl<'a> Visitor<'a> for UsageQuotaResponseVisitor { + type Value = UsageQuotaResponse; + + 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 = UsageQuotaResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_response_attributes.rs b/src/datadogV2/model/model_usage_quota_response_attributes.rs new file mode 100644 index 000000000..5af354901 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_response_attributes.rs @@ -0,0 +1,137 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes of a usage quota. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaResponseAttributes { + /// Whether usage above the limit is actively blocked instead of only tracked or alerted on. + #[serde(rename = "enforced")] + pub enforced: bool, + /// The public ID of the organization that owns the quota. + #[serde(rename = "org_public_id")] + pub org_public_id: String, + /// A namespace-specific key and value identifying what the quota applies to within an organization. The object contains exactly one entry. A value of `"*"` identifies the default quota applied to entities without a specific quota. This field is omitted for an organization-wide quota. + #[serde(rename = "scope")] + pub scope: Option>, + /// The quota limit in the usage units defined by the quota namespace. May be fractional for quotas configured before public writes required whole units. + #[serde(rename = "usage_limit")] + pub usage_limit: f64, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaResponseAttributes { + pub fn new( + enforced: bool, + org_public_id: String, + usage_limit: f64, + ) -> UsageQuotaResponseAttributes { + UsageQuotaResponseAttributes { + enforced, + org_public_id, + scope: None, + usage_limit, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn scope(mut self, value: std::collections::BTreeMap) -> Self { + self.scope = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for UsageQuotaResponseAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaResponseAttributesVisitor; + impl<'a> Visitor<'a> for UsageQuotaResponseAttributesVisitor { + type Value = UsageQuotaResponseAttributes; + + 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 enforced: Option = None; + let mut org_public_id: Option = None; + let mut scope: Option> = None; + let mut usage_limit: 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() { + "enforced" => { + enforced = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "org_public_id" => { + org_public_id = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "scope" => { + if v.is_null() { + continue; + } + scope = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "usage_limit" => { + usage_limit = + 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 enforced = enforced.ok_or_else(|| M::Error::missing_field("enforced"))?; + let org_public_id = + org_public_id.ok_or_else(|| M::Error::missing_field("org_public_id"))?; + let usage_limit = + usage_limit.ok_or_else(|| M::Error::missing_field("usage_limit"))?; + + let content = UsageQuotaResponseAttributes { + enforced, + org_public_id, + scope, + usage_limit, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaResponseAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_response_data.rs b/src/datadogV2/model/model_usage_quota_response_data.rs new file mode 100644 index 000000000..c089ed0f2 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_response_data.rs @@ -0,0 +1,127 @@ +// 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 usage quota resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaResponseData { + /// Attributes of a usage quota. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::UsageQuotaResponseAttributes, + /// An opaque usage quota identifier. Clients must pass this value back verbatim in update and delete requests and must not infer any structure from it. + #[serde(rename = "id")] + pub id: String, + /// The JSON:API resource type for a usage quota. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::UsageQuotaType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaResponseData { + pub fn new( + attributes: crate::datadogV2::model::UsageQuotaResponseAttributes, + id: String, + type_: crate::datadogV2::model::UsageQuotaType, + ) -> UsageQuotaResponseData { + UsageQuotaResponseData { + attributes, + 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 UsageQuotaResponseData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaResponseDataVisitor; + impl<'a> Visitor<'a> for UsageQuotaResponseDataVisitor { + type Value = UsageQuotaResponseData; + + 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" => { + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "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::UsageQuotaType::UnparsedObject( + _type_, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = UsageQuotaResponseData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaResponseDataVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_type.rs b/src/datadogV2/model/model_usage_quota_type.rs new file mode 100644 index 000000000..009a643a1 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_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 UsageQuotaType { + QUOTAS, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for UsageQuotaType { + fn to_string(&self) -> String { + match self { + Self::QUOTAS => String::from("quotas"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for UsageQuotaType { + 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 UsageQuotaType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "quotas" => Self::QUOTAS, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_usage_quota_update_attributes.rs b/src/datadogV2/model/model_usage_quota_update_attributes.rs new file mode 100644 index 000000000..587dea2e0 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_update_attributes.rs @@ -0,0 +1,125 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes to update on a usage quota. Omitting a property leaves its current value unchanged. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaUpdateAttributes { + /// Whether to actively block usage above the limit. Omit this field to leave the current enforcement setting unchanged. + #[serde( + rename = "enforced", + default, + with = "::serde_with::rust::double_option" + )] + pub enforced: Option>, + /// The new quota limit in the usage units defined by the quota namespace. For an organization-wide quota (empty scope), the limit must be greater than the usage already recorded in the current period. Omit this field to leave the current limit unchanged. + #[serde( + rename = "usage_limit", + default, + with = "::serde_with::rust::double_option" + )] + pub usage_limit: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaUpdateAttributes { + pub fn new() -> UsageQuotaUpdateAttributes { + UsageQuotaUpdateAttributes { + enforced: None, + usage_limit: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn enforced(mut self, value: Option) -> Self { + self.enforced = Some(value); + self + } + + pub fn usage_limit(mut self, value: Option) -> Self { + self.usage_limit = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for UsageQuotaUpdateAttributes { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for UsageQuotaUpdateAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaUpdateAttributesVisitor; + impl<'a> Visitor<'a> for UsageQuotaUpdateAttributesVisitor { + type Value = UsageQuotaUpdateAttributes; + + 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 enforced: Option> = None; + let mut usage_limit: 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() { + "enforced" => { + enforced = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "usage_limit" => { + usage_limit = + 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 = UsageQuotaUpdateAttributes { + enforced, + usage_limit, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaUpdateAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_update_data.rs b/src/datadogV2/model/model_usage_quota_update_data.rs new file mode 100644 index 000000000..52064bb60 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_update_data.rs @@ -0,0 +1,127 @@ +// 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 usage quota resource to update. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaUpdateData { + /// Attributes to update on a usage quota. Omitting a property leaves its current value unchanged. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::UsageQuotaUpdateAttributes, + /// The opaque usage quota identifier, which must match the identifier in the request path. + #[serde(rename = "id")] + pub id: String, + /// The JSON:API resource type for a usage quota. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::UsageQuotaType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaUpdateData { + pub fn new( + attributes: crate::datadogV2::model::UsageQuotaUpdateAttributes, + id: String, + type_: crate::datadogV2::model::UsageQuotaType, + ) -> UsageQuotaUpdateData { + UsageQuotaUpdateData { + attributes, + 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 UsageQuotaUpdateData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaUpdateDataVisitor; + impl<'a> Visitor<'a> for UsageQuotaUpdateDataVisitor { + type Value = UsageQuotaUpdateData; + + 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" => { + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "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::UsageQuotaType::UnparsedObject( + _type_, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = UsageQuotaUpdateData { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaUpdateDataVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quota_update_request.rs b/src/datadogV2/model/model_usage_quota_update_request.rs new file mode 100644 index 000000000..4867b7838 --- /dev/null +++ b/src/datadogV2/model/model_usage_quota_update_request.rs @@ -0,0 +1,92 @@ +// 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}; + +/// Request containing the usage quota resource to update. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotaUpdateRequest { + /// A usage quota resource to update. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::UsageQuotaUpdateData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotaUpdateRequest { + pub fn new(data: crate::datadogV2::model::UsageQuotaUpdateData) -> UsageQuotaUpdateRequest { + UsageQuotaUpdateRequest { + 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 UsageQuotaUpdateRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotaUpdateRequestVisitor; + impl<'a> Visitor<'a> for UsageQuotaUpdateRequestVisitor { + type Value = UsageQuotaUpdateRequest; + + 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 = UsageQuotaUpdateRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotaUpdateRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quotas_bulk_response.rs b/src/datadogV2/model/model_usage_quotas_bulk_response.rs new file mode 100644 index 000000000..c35ef7446 --- /dev/null +++ b/src/datadogV2/model/model_usage_quotas_bulk_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}; + +/// Response containing the result of a bulk usage quota create-or-update request. Returned with a `200` status regardless of whether individual items succeeded or failed; check each item's `error` attribute to determine its outcome. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotasBulkResponse { + /// The results of writing each usage quota in a bulk create-or-update request, in the same order as the request. + #[serde(rename = "data")] + pub data: Vec, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotasBulkResponse { + pub fn new( + data: Vec, + ) -> UsageQuotasBulkResponse { + UsageQuotasBulkResponse { + 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 UsageQuotasBulkResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotasBulkResponseVisitor; + impl<'a> Visitor<'a> for UsageQuotasBulkResponseVisitor { + type Value = UsageQuotasBulkResponse; + + 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 = UsageQuotasBulkResponse { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotasBulkResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quotas_create_request.rs b/src/datadogV2/model/model_usage_quotas_create_request.rs new file mode 100644 index 000000000..6eacd8175 --- /dev/null +++ b/src/datadogV2/model/model_usage_quotas_create_request.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}; + +/// A JSON:API bulk request containing an array of usage quota resources rather than a single resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotasCreateRequest { + /// A bulk list of usage quota resources to create or update by scope. + #[serde(rename = "data")] + pub data: Vec, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotasCreateRequest { + pub fn new( + data: Vec, + ) -> UsageQuotasCreateRequest { + UsageQuotasCreateRequest { + 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 UsageQuotasCreateRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotasCreateRequestVisitor; + impl<'a> Visitor<'a> for UsageQuotasCreateRequestVisitor { + type Value = UsageQuotasCreateRequest; + + 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 = UsageQuotasCreateRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotasCreateRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quotas_list_response.rs b/src/datadogV2/model/model_usage_quotas_list_response.rs new file mode 100644 index 000000000..d896a9851 --- /dev/null +++ b/src/datadogV2/model/model_usage_quotas_list_response.rs @@ -0,0 +1,105 @@ +// 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}; + +/// Response containing a paginated list of usage quotas. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotasListResponse { + /// A list of usage quota resources. + #[serde(rename = "data")] + pub data: Vec, + /// Pagination metadata for a usage quota list response. + #[serde(rename = "meta")] + pub meta: crate::datadogV2::model::UsageQuotasResponseMeta, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotasListResponse { + pub fn new( + data: Vec, + meta: crate::datadogV2::model::UsageQuotasResponseMeta, + ) -> UsageQuotasListResponse { + UsageQuotasListResponse { + data, + meta, + 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 UsageQuotasListResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotasListResponseVisitor; + impl<'a> Visitor<'a> for UsageQuotasListResponseVisitor { + type Value = UsageQuotasListResponse; + + 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 meta: 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)?); + } + "meta" => { + meta = 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 meta = meta.ok_or_else(|| M::Error::missing_field("meta"))?; + + let content = UsageQuotasListResponse { + data, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotasListResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quotas_response_meta.rs b/src/datadogV2/model/model_usage_quotas_response_meta.rs new file mode 100644 index 000000000..52c6263cc --- /dev/null +++ b/src/datadogV2/model/model_usage_quotas_response_meta.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}; + +/// Pagination metadata for a usage quota list response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotasResponseMeta { + /// Cursor pagination fields for a usage quota list response. + #[serde(rename = "page")] + pub page: crate::datadogV2::model::UsageQuotasResponseMetaPage, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotasResponseMeta { + pub fn new( + page: crate::datadogV2::model::UsageQuotasResponseMetaPage, + ) -> UsageQuotasResponseMeta { + UsageQuotasResponseMeta { + page, + 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 UsageQuotasResponseMeta { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotasResponseMetaVisitor; + impl<'a> Visitor<'a> for UsageQuotasResponseMetaVisitor { + type Value = UsageQuotasResponseMeta; + + 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 page: 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() { + "page" => { + page = 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 page = page.ok_or_else(|| M::Error::missing_field("page"))?; + + let content = UsageQuotasResponseMeta { + page, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotasResponseMetaVisitor) + } +} diff --git a/src/datadogV2/model/model_usage_quotas_response_meta_page.rs b/src/datadogV2/model/model_usage_quotas_response_meta_page.rs new file mode 100644 index 000000000..038e552a9 --- /dev/null +++ b/src/datadogV2/model/model_usage_quotas_response_meta_page.rs @@ -0,0 +1,106 @@ +// 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}; + +/// Cursor pagination fields for a usage quota list response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct UsageQuotasResponseMetaPage { + /// An opaque cursor for retrieving the next page. Omitted when there are no more results. + #[serde(rename = "next_cursor")] + pub next_cursor: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl UsageQuotasResponseMetaPage { + pub fn new() -> UsageQuotasResponseMetaPage { + UsageQuotasResponseMetaPage { + next_cursor: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn next_cursor(mut self, value: String) -> Self { + self.next_cursor = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for UsageQuotasResponseMetaPage { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for UsageQuotasResponseMetaPage { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct UsageQuotasResponseMetaPageVisitor; + impl<'a> Visitor<'a> for UsageQuotasResponseMetaPageVisitor { + type Value = UsageQuotasResponseMetaPage; + + 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 next_cursor: 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() { + "next_cursor" => { + if v.is_null() { + continue; + } + next_cursor = + 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 = UsageQuotasResponseMetaPage { + next_cursor, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(UsageQuotasResponseMetaPageVisitor) + } +} diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 16e0df0b3..a7960e38c 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -10158,6 +10158,30 @@ "type": "safe" } }, + "ListQuotas": { + "tag": "Usage Metering", + "undo": { + "type": "safe" + } + }, + "CreateQuotas": { + "tag": "Usage Metering", + "undo": { + "type": "idempotent" + } + }, + "DeleteQuota": { + "tag": "Usage Metering", + "undo": { + "type": "idempotent" + } + }, + "UpdateQuota": { + "tag": "Usage Metering", + "undo": { + "type": "idempotent" + } + }, "GetUsageSummaryAvailableFields": { "tag": "Usage Metering", "undo": { diff --git a/tests/scenarios/features/v2/usage_metering.feature b/tests/scenarios/features/v2/usage_metering.feature index ee6989892..0dc681d2e 100644 --- a/tests/scenarios/features/v2/usage_metering.feature +++ b/tests/scenarios/features/v2/usage_metering.feature @@ -14,6 +14,42 @@ Feature: Usage Metering And a valid "appKeyAuth" key in the system And an instance of "UsageMetering" API + @generated @skip @team:DataDog/billing-hub + Scenario: Create or update usage quotas returns "Bad Request" response + Given operation "CreateQuotas" enabled + And new "CreateQuotas" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"enforced": true, "scope": {"user_handle": "jane@example.com"}, "usage_limit": 100000}, "type": "quotas"}]} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/billing-hub + Scenario: Create or update usage quotas returns "OK. The response includes each item's result; see each item's `error` attribute for any that failed to write." response + Given operation "CreateQuotas" enabled + And new "CreateQuotas" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"enforced": true, "scope": {"user_handle": "jane@example.com"}, "usage_limit": 100000}, "type": "quotas"}]} + When the request is sent + Then the response status is 200 OK. The response includes each item's result; see each item's `error` attribute for any that failed to write. + + @generated @skip @team:DataDog/billing-hub + Scenario: Delete a usage quota returns "No Content" response + Given operation "DeleteQuota" enabled + And new "DeleteQuota" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And request contains "id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 204 No Content + + @generated @skip @team:DataDog/billing-hub + Scenario: Delete a usage quota returns "Not Found" response + Given operation "DeleteQuota" enabled + And new "DeleteQuota" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And request contains "id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + @replay-only @team:DataDog/billing-hub Scenario: Get Monthly Cost Attribution returns "Bad Request" response Given new "GetMonthlyCostAttribution" request @@ -242,3 +278,57 @@ Feature: Usage Metering And request contains "start_month" parameter with value "{{ timeISO('now') }}" When the request is sent Then the response status is 200 OK + + @generated @skip @team:DataDog/billing-hub + Scenario: List usage quotas returns "Bad Request" response + Given operation "ListQuotas" enabled + And new "ListQuotas" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/billing-hub + Scenario: List usage quotas returns "OK" response + Given operation "ListQuotas" enabled + And new "ListQuotas" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/billing-hub @with-pagination + Scenario: List usage quotas returns "OK" response with pagination + Given operation "ListQuotas" enabled + And new "ListQuotas" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + When the request with pagination is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/billing-hub + Scenario: Update a usage quota returns "Bad Request. Returned if the request is malformed, or if the `id` in the request body does not match the `id` in the request path." response + Given operation "UpdateQuota" enabled + And new "UpdateQuota" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And request contains "id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"enforced": false, "usage_limit": 120000}, "id": "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f", "type": "quotas"}} + When the request is sent + Then the response status is 400 Bad Request. Returned if the request is malformed, or if the `id` in the request body does not match the `id` in the request path. + + @generated @skip @team:DataDog/billing-hub + Scenario: Update a usage quota returns "Not Found" response + Given operation "UpdateQuota" enabled + And new "UpdateQuota" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And request contains "id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"enforced": false, "usage_limit": 120000}, "id": "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f", "type": "quotas"}} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/billing-hub + Scenario: Update a usage quota returns "OK" response + Given operation "UpdateQuota" enabled + And new "UpdateQuota" request + And request contains "quota_namespace" parameter from "REPLACE.ME" + And request contains "id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"enforced": false, "usage_limit": 120000}, "id": "MjAfYWlfY3JlZGl0c1911c2VyX2hhbmRsZTpfX0FMTF9f", "type": "quotas"}} + When the request is sent + Then the response status is 200 OK diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index b02ffb24f..64e680097 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -4595,6 +4595,22 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { world .function_mappings .insert("v2.GetProjectedCost".into(), test_v2_get_projected_cost); + world + .function_mappings + .insert("v2.ListQuotas".into(), test_v2_list_quotas); + world.function_mappings.insert( + "v2.ListQuotasWithPagination".into(), + test_v2_list_quotas_with_pagination, + ); + world + .function_mappings + .insert("v2.CreateQuotas".into(), test_v2_create_quotas); + world + .function_mappings + .insert("v2.DeleteQuota".into(), test_v2_delete_quota); + world + .function_mappings + .insert("v2.UpdateQuota".into(), test_v2_update_quota); world.function_mappings.insert( "v2.GetUsageSummaryAvailableFields".into(), test_v2_get_usage_summary_available_fields, @@ -34897,6 +34913,183 @@ fn test_v2_get_projected_cost(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_usage_metering + .as_ref() + .expect("api instance not found"); + let quota_namespace = + serde_json::from_value(_parameters.get("quota_namespace").unwrap().clone()).unwrap(); + let include_descendants = _parameters + .get("include_descendants") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_cursor = _parameters + .get("page[cursor]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_limit = _parameters + .get("page[limit]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_usage_metering::ListQuotasOptionalParams::default(); + params.include_descendants = include_descendants; + params.page_cursor = page_cursor; + params.page_limit = page_limit; + let response = match block_on(api.list_quotas_with_http_info(quota_namespace, params)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} +fn test_v2_list_quotas_with_pagination( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_usage_metering + .as_ref() + .expect("api instance not found"); + let quota_namespace = + serde_json::from_value(_parameters.get("quota_namespace").unwrap().clone()).unwrap(); + let include_descendants = _parameters + .get("include_descendants") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_cursor = _parameters + .get("page[cursor]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_limit = _parameters + .get("page[limit]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_usage_metering::ListQuotasOptionalParams::default(); + params.include_descendants = include_descendants; + params.page_cursor = page_cursor; + params.page_limit = page_limit; + let response = api.list_quotas_with_pagination(quota_namespace, params); + let mut result = Vec::new(); + + block_on(async { + pin_mut!(response); + + while let Some(resp) = response.next().await { + match resp { + Ok(response) => { + result.push(response); + } + Err(error) => { + return match error { + Error::ResponseError(e) => { + 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(result).unwrap(); + world.response.code = 200; +} + +fn test_v2_create_quotas(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_usage_metering + .as_ref() + .expect("api instance not found"); + let quota_namespace = + serde_json::from_value(_parameters.get("quota_namespace").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let include_descendants = _parameters + .get("include_descendants") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_usage_metering::CreateQuotasOptionalParams::default(); + params.include_descendants = include_descendants; + let response = match block_on(api.create_quotas_with_http_info(quota_namespace, body, params)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + +fn test_v2_delete_quota(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_usage_metering + .as_ref() + .expect("api instance not found"); + let quota_namespace = + serde_json::from_value(_parameters.get("quota_namespace").unwrap().clone()).unwrap(); + let id = serde_json::from_value(_parameters.get("id").unwrap().clone()).unwrap(); + let response = match block_on(api.delete_quota_with_http_info(quota_namespace, id)) { + 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_update_quota(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_usage_metering + .as_ref() + .expect("api instance not found"); + let quota_namespace = + serde_json::from_value(_parameters.get("quota_namespace").unwrap().clone()).unwrap(); + let id = serde_json::from_value(_parameters.get("id").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = match block_on(api.update_quota_with_http_info(quota_namespace, id, body)) { + 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_get_usage_summary_available_fields( world: &mut DatadogWorld, _parameters: &HashMap,