diff --git a/.apigentools-info b/.apigentools-info index b9d3e8836..19b2ee8da 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.6.6", - "regenerated": "2024-12-02 19:29:50.308380", - "spec_repo_commit": "7511c5f0" + "regenerated": "2024-12-03 10:17:25.430966", + "spec_repo_commit": "3f8bbb67" }, "v2": { "apigentools_version": "1.6.6", - "regenerated": "2024-12-02 19:29:50.327733", - "spec_repo_commit": "7511c5f0" + "regenerated": "2024-12-03 10:17:25.450174", + "spec_repo_commit": "3f8bbb67" } } } \ No newline at end of file diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 66bdf713c..ed720de0d 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -566,6 +566,13 @@ components: example: 10 format: int64 type: integer + ProductName: + description: Name of the product to be deleted, either `logs` or `rum`. + in: path + name: product + required: true + schema: + type: string ProjectIDPathParameter: description: Project UUID example: e555e290-ed65-49bd-ae18-8acbfcf18db7 @@ -581,6 +588,13 @@ components: required: true schema: type: string + RequestId: + description: ID of the deletion request. + in: path + name: id + required: true + schema: + type: string ResourceID: description: 'Identifier, formatted as `type:id`. Supported types: `connection`, `dashboard`, `notebook`, `security-rule`, `slo`.' @@ -4197,6 +4211,14 @@ components: - name - expression type: object + CancelDataDeletionResponseBody: + description: The response from the cancel data deletion request endpoint. + properties: + data: + $ref: '#/components/schemas/DataDeletionResponseItem' + meta: + $ref: '#/components/schemas/DataDeletionResponseMeta' + type: object Case: description: A case properties: @@ -6372,6 +6394,66 @@ components: type: string x-enum-varnames: - COST_BY_ORG + CreateDataDeletionRequestBody: + description: Object needed to create a data deletion request. + properties: + data: + $ref: '#/components/schemas/CreateDataDeletionRequestBodyData' + required: + - data + type: object + CreateDataDeletionRequestBodyAttributes: + description: Attributes for creating a data deletion request. + properties: + from: + description: Start of requested time window, milliseconds since Unix epoch. + example: 1672527600000 + format: int64 + type: integer + indexes: + description: List of indexes for the search. If not provided, the search + is performed in all indexes. + example: + - index-1 + - index-2 + items: + description: Individual index. + type: string + type: array + query: + additionalProperties: + type: string + description: Query for creating a data deletion request. + example: + host: abc + service: xyz + type: object + to: + description: End of requested time window, milliseconds since Unix epoch. + example: 1704063600000 + format: int64 + type: integer + required: + - query + - from + - to + type: object + CreateDataDeletionRequestBodyData: + description: Data needed to create a data deletion request. + properties: + attributes: + $ref: '#/components/schemas/CreateDataDeletionRequestBodyAttributes' + required: + - attributes + type: object + CreateDataDeletionResponseBody: + description: The response from the create data deletion request endpoint. + properties: + data: + $ref: '#/components/schemas/DataDeletionResponseItem' + meta: + $ref: '#/components/schemas/DataDeletionResponseMeta' + type: object CreateOpenAPIResponse: description: Response for `CreateOpenAPI` operation. properties: @@ -7663,6 +7745,140 @@ components: - INTEGRATION_SCREENBOARD - INTEGRATION_TIMEBOARD - HOST_TIMEBOARD + DataDeletionResponseItem: + description: The created data deletion request information. + properties: + attributes: + $ref: '#/components/schemas/DataDeletionResponseItemAttributes' + id: + description: The ID of the created data deletion request. + example: '1' + type: string + type: + description: The type of the request created. + example: deletion_request + type: string + required: + - id + - type + - attributes + type: object + DataDeletionResponseItemAttributes: + description: Deletion attribute for data deletion response. + properties: + created_at: + description: Creation time of the deletion request. + example: '2024-01-01T00:00:00.000000Z' + type: string + created_by: + description: User who created the deletion request. + example: test.user@datadoghq.com + type: string + from_time: + description: Start of requested time window, milliseconds since Unix epoch. + example: 1672527600000 + format: int64 + type: integer + indexes: + description: List of indexes for the search. If not provided, the search + is performed in all indexes. + example: + - index-1 + - index-2 + items: + description: Individual index. + type: string + type: array + is_created: + description: Whether the deletion request is fully created or not. + example: true + type: boolean + org_id: + description: Organization ID. + example: 321813 + format: int64 + type: integer + product: + description: Product name. + example: logs + type: string + query: + description: Query for creating a data deletion request. + example: service:xyz host:abc + type: string + starting_at: + description: Starting time of the process to delete the requested data. + example: '2024-01-01T02:00:00.000000Z' + type: string + status: + description: Status of the deletion request. + example: pending + type: string + to_time: + description: End of requested time window, milliseconds since Unix epoch. + example: 1704063600000 + format: int64 + type: integer + total_unrestricted: + description: Total number of elements to be deleted. Only the data accessible + to the current user that matches the query and timeframe provided will + be deleted. + example: 100 + format: int64 + type: integer + updated_at: + description: Update time of the deletion request. + example: '2024-01-01T00:00:00.000000Z' + type: string + required: + - created_at + - created_by + - from_time + - is_created + - org_id + - product + - query + - starting_at + - status + - to_time + - total_unrestricted + - updated_at + type: object + DataDeletionResponseMeta: + description: The metadata of the data deletion response. + properties: + count_product: + additionalProperties: + format: int64 + type: integer + description: The total deletion requests created by product. + example: + logs: 8 + rum: 7 + type: object + count_status: + additionalProperties: + format: int64 + type: integer + description: The total deletion requests created by status. + example: + completed: 10 + pending: 5 + type: object + next_page: + description: The next page when searching deletion requests created in the + current organization. + example: cGFnZTI= + type: string + product: + description: The product of the deletion request. + example: logs + type: string + request_status: + description: The status of the executed request. + example: canceled + type: string + type: object DataScalarColumn: description: A column containing the numerical results for a formula or query. properties: @@ -10649,6 +10865,17 @@ components: type: string x-enum-varnames: - GCP_SERVICE_ACCOUNT + GetDataDeletionsResponseBody: + description: The response from the get data deletion requests endpoint. + properties: + data: + description: The list of data deletion requests that matches the query. + items: + $ref: '#/components/schemas/DataDeletionResponseItem' + type: array + meta: + $ref: '#/components/schemas/DataDeletionResponseMeta' + type: object GetDeviceAttributes: description: The device attributes properties: @@ -30912,6 +31139,172 @@ paths: tags: - Dashboard Lists x-codegen-request-body-name: body + /api/v2/deletion/data/{product}: + post: + description: Creates a data deletion request by providing a query and a time + frame targeting the proper data. + operationId: CreateDataDeletionRequest + parameters: + - $ref: '#/components/parameters/ProductName' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDataDeletionRequestBody' + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CreateDataDeletionResponseBody' + description: OK + '400': + $ref: '#/components/responses/BadRequestResponse' + '403': + $ref: '#/components/responses/ForbiddenResponse' + '412': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Precondition failed error + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + '500': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Internal server error + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Creates a data deletion request + tags: + - Data Deletion + x-permission: + operator: OR + permissions: + - rum_delete_data + - logs_delete_data + /api/v2/deletion/requests: + get: + description: Gets a list of data deletion requests based on several filter parameters. + operationId: GetDataDeletionRequests + parameters: + - description: The next page of the previous search. If the next_page parameter + is included, the rest of the query elements are ignored. + example: cGFnZTI= + in: query + name: next_page + required: false + schema: + type: string + - description: Retrieve only the requests related to the given product. + example: logs + in: query + name: product + required: false + schema: + type: string + - description: Retrieve only the requests that matches the given query. + example: service:xyz host:abc + in: query + name: query + required: false + schema: + type: string + - description: Retrieve only the requests with the given status. + example: pending + in: query + name: status + required: false + schema: + type: string + - description: Sets the page size of the search. + example: '50' + in: query + name: page_size + required: false + schema: + default: 50 + format: int64 + maximum: 50 + minimum: 1 + type: integer + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/GetDataDeletionsResponseBody' + description: OK + '400': + $ref: '#/components/responses/BadRequestResponse' + '403': + $ref: '#/components/responses/ForbiddenResponse' + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + '500': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Internal server error + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Gets a list of data deletion requests + tags: + - Data Deletion + x-permission: + operator: OR + permissions: + - rum_delete_data + - logs_delete_data + /api/v2/deletion/requests/{id}/cancel: + put: + description: Cancels a data deletion request by providing its ID. + operationId: CancelDataDeletionRequest + parameters: + - $ref: '#/components/parameters/RequestId' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/CancelDataDeletionResponseBody' + description: OK + '400': + $ref: '#/components/responses/BadRequestResponse' + '403': + $ref: '#/components/responses/ForbiddenResponse' + '412': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Precondition failed error + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + '500': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Internal server error + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Cancels a data deletion request + tags: + - Data Deletion + x-permission: + operator: OR + permissions: + - rum_delete_data + - logs_delete_data /api/v2/domain_allowlist: get: description: Get the domain allowlist for an organization. @@ -44061,6 +44454,10 @@ tags: organization.' name: Dashboard Lists +- description: The Data Deletion API allows the user to target and delete data from + the allowed products. It's currently enabled for Logs and RUM and depends on `logs_delete_data` + and `rum_delete_data` permissions respectively. + name: Data Deletion - description: 'Configure your Datadog Email Domain Allowlist directly through the Datadog API. diff --git a/examples/v2_data-deletion_CancelDataDeletionRequest.rs b/examples/v2_data-deletion_CancelDataDeletionRequest.rs new file mode 100644 index 000000000..fc883042a --- /dev/null +++ b/examples/v2_data-deletion_CancelDataDeletionRequest.rs @@ -0,0 +1,19 @@ +// Cancels a data deletion request returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_data_deletion::DataDeletionAPI; + +#[tokio::main] +async fn main() { + // there is a valid "deletion_request" in the system + let deletion_request_data_id = std::env::var("DELETION_REQUEST_DATA_ID").unwrap(); + let configuration = datadog::Configuration::new(); + let api = DataDeletionAPI::with_config(configuration); + let resp = api + .cancel_data_deletion_request(deletion_request_data_id.clone()) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_data-deletion_CreateDataDeletionRequest.rs b/examples/v2_data-deletion_CreateDataDeletionRequest.rs new file mode 100644 index 000000000..483bf04a4 --- /dev/null +++ b/examples/v2_data-deletion_CreateDataDeletionRequest.rs @@ -0,0 +1,32 @@ +// Creates a data deletion request returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_data_deletion::DataDeletionAPI; +use datadog_api_client::datadogV2::model::CreateDataDeletionRequestBody; +use datadog_api_client::datadogV2::model::CreateDataDeletionRequestBodyAttributes; +use datadog_api_client::datadogV2::model::CreateDataDeletionRequestBodyData; +use std::collections::BTreeMap; + +#[tokio::main] +async fn main() { + let body = CreateDataDeletionRequestBody::new(CreateDataDeletionRequestBodyData::new( + CreateDataDeletionRequestBodyAttributes::new( + 1672527600000, + BTreeMap::from([ + ("host".to_string(), "abc".to_string()), + ("service".to_string(), "xyz".to_string()), + ]), + 1704063600000, + ) + .indexes(vec!["index-1".to_string(), "index-2".to_string()]), + )); + let configuration = datadog::Configuration::new(); + let api = DataDeletionAPI::with_config(configuration); + let resp = api + .create_data_deletion_request("logs".to_string(), body) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_data-deletion_GetDataDeletionRequests.rs b/examples/v2_data-deletion_GetDataDeletionRequests.rs new file mode 100644 index 000000000..86715d91b --- /dev/null +++ b/examples/v2_data-deletion_GetDataDeletionRequests.rs @@ -0,0 +1,18 @@ +// Gets a list of data deletion requests returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_data_deletion::DataDeletionAPI; +use datadog_api_client::datadogV2::api_data_deletion::GetDataDeletionRequestsOptionalParams; + +#[tokio::main] +async fn main() { + let configuration = datadog::Configuration::new(); + let api = DataDeletionAPI::with_config(configuration); + let resp = api + .get_data_deletion_requests(GetDataDeletionRequestsOptionalParams::default()) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadogV2/api/api_data_deletion.rs b/src/datadogV2/api/api_data_deletion.rs new file mode 100644 index 000000000..b27e66461 --- /dev/null +++ b/src/datadogV2/api/api_data_deletion.rs @@ -0,0 +1,550 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use crate::datadog; +use flate2::{ + write::{GzEncoder, ZlibEncoder}, + Compression, +}; +use reqwest::header::{HeaderMap, HeaderValue}; +use serde::{Deserialize, Serialize}; +use std::io::Write; + +/// GetDataDeletionRequestsOptionalParams is a struct for passing parameters to the method [`DataDeletionAPI::get_data_deletion_requests`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct GetDataDeletionRequestsOptionalParams { + /// The next page of the previous search. If the next_page parameter is included, the rest of the query elements are ignored. + pub next_page: Option, + /// Retrieve only the requests related to the given product. + pub product: Option, + /// Retrieve only the requests that matches the given query. + pub query: Option, + /// Retrieve only the requests with the given status. + pub status: Option, + /// Sets the page size of the search. + pub page_size: Option, +} + +impl GetDataDeletionRequestsOptionalParams { + /// The next page of the previous search. If the next_page parameter is included, the rest of the query elements are ignored. + pub fn next_page(mut self, value: String) -> Self { + self.next_page = Some(value); + self + } + /// Retrieve only the requests related to the given product. + pub fn product(mut self, value: String) -> Self { + self.product = Some(value); + self + } + /// Retrieve only the requests that matches the given query. + pub fn query(mut self, value: String) -> Self { + self.query = Some(value); + self + } + /// Retrieve only the requests with the given status. + pub fn status(mut self, value: String) -> Self { + self.status = Some(value); + self + } + /// Sets the page size of the search. + pub fn page_size(mut self, value: i64) -> Self { + self.page_size = Some(value); + self + } +} + +/// CancelDataDeletionRequestError is a struct for typed errors of method [`DataDeletionAPI::cancel_data_deletion_request`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CancelDataDeletionRequestError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// CreateDataDeletionRequestError is a struct for typed errors of method [`DataDeletionAPI::create_data_deletion_request`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateDataDeletionRequestError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// GetDataDeletionRequestsError is a struct for typed errors of method [`DataDeletionAPI::get_data_deletion_requests`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetDataDeletionRequestsError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// The Data Deletion API allows the user to target and delete data from the allowed products. It's currently enabled for Logs and RUM and depends on `logs_delete_data` and `rum_delete_data` permissions respectively. +#[derive(Debug, Clone)] +pub struct DataDeletionAPI { + config: datadog::Configuration, + client: reqwest_middleware::ClientWithMiddleware, +} + +impl Default for DataDeletionAPI { + fn default() -> Self { + Self::with_config(datadog::Configuration::default()) + } +} + +impl DataDeletionAPI { + pub fn new() -> Self { + Self::default() + } + pub fn with_config(config: datadog::Configuration) -> Self { + let mut reqwest_client_builder = reqwest::Client::builder(); + + if let Some(proxy_url) = &config.proxy_url { + let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL"); + reqwest_client_builder = reqwest_client_builder.proxy(proxy); + } + + let mut middleware_client_builder = + reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap()); + + if config.enable_retry { + struct RetryableStatus; + impl reqwest_retry::RetryableStrategy for RetryableStatus { + fn handle( + &self, + res: &Result, + ) -> Option { + match res { + Ok(success) => reqwest_retry::default_on_request_success(success), + Err(_) => None, + } + } + } + let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder() + .build_with_max_retries(config.max_retries); + + let retry_middleware = + reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy( + backoff_policy, + RetryableStatus, + ); + + middleware_client_builder = middleware_client_builder.with(retry_middleware); + } + + let client = middleware_client_builder.build(); + + Self { config, client } + } + + pub fn with_client_and_config( + config: datadog::Configuration, + client: reqwest_middleware::ClientWithMiddleware, + ) -> Self { + Self { config, client } + } + + /// Cancels a data deletion request by providing its ID. + pub async fn cancel_data_deletion_request( + &self, + id: String, + ) -> Result< + crate::datadogV2::model::CancelDataDeletionResponseBody, + datadog::Error, + > { + match self.cancel_data_deletion_request_with_http_info(id).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), + } + } + + /// Cancels a data deletion request by providing its ID. + pub async fn cancel_data_deletion_request_with_http_info( + &self, + id: String, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.cancel_data_deletion_request"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/deletion/requests/{id}/cancel", + local_configuration.get_operation_host(operation_id), + id = datadog::urlencode(id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::PUT, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = + serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + + /// Creates a data deletion request by providing a query and a time frame targeting the proper data. + pub async fn create_data_deletion_request( + &self, + product: String, + body: crate::datadogV2::model::CreateDataDeletionRequestBody, + ) -> Result< + crate::datadogV2::model::CreateDataDeletionResponseBody, + datadog::Error, + > { + match self + .create_data_deletion_request_with_http_info(product, 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), + } + } + + /// Creates a data deletion request by providing a query and a time frame targeting the proper data. + pub async fn create_data_deletion_request_with_http_info( + &self, + product: String, + body: crate::datadogV2::model::CreateDataDeletionRequestBody, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.create_data_deletion_request"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/deletion/data/{product}", + local_configuration.get_operation_host(operation_id), + product = datadog::urlencode(product) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::POST, 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)), + } + } + "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)) + } + } + + /// Gets a list of data deletion requests based on several filter parameters. + pub async fn get_data_deletion_requests( + &self, + params: GetDataDeletionRequestsOptionalParams, + ) -> Result< + crate::datadogV2::model::GetDataDeletionsResponseBody, + datadog::Error, + > { + match self.get_data_deletion_requests_with_http_info(params).await { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + /// Gets a list of data deletion requests based on several filter parameters. + pub async fn get_data_deletion_requests_with_http_info( + &self, + params: GetDataDeletionRequestsOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_data_deletion_requests"; + + // unbox and build optional parameters + let next_page = params.next_page; + let product = params.product; + let query = params.query; + let status = params.status; + let page_size = params.page_size; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/deletion/requests", + local_configuration.get_operation_host(operation_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + if let Some(ref local_query_param) = next_page { + local_req_builder = + local_req_builder.query(&[("next_page", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = product { + local_req_builder = + local_req_builder.query(&[("product", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = query { + local_req_builder = + local_req_builder.query(&[("query", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = status { + local_req_builder = + local_req_builder.query(&[("status", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = page_size { + local_req_builder = + local_req_builder.query(&[("page_size", &local_query_param.to_string())]); + }; + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::( + &local_content, + ) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = + serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } +} diff --git a/src/datadogV2/api/mod.rs b/src/datadogV2/api/mod.rs index 2904bc5b3..2eab40719 100644 --- a/src/datadogV2/api/mod.rs +++ b/src/datadogV2/api/mod.rs @@ -18,6 +18,7 @@ pub mod api_container_images; pub mod api_containers; pub mod api_csm_threats; pub mod api_dashboard_lists; +pub mod api_data_deletion; pub mod api_domain_allowlist; pub mod api_dora_metrics; pub mod api_downtimes; diff --git a/src/datadogV2/mod.rs b/src/datadogV2/mod.rs index 4034d7dcd..f57d3d8da 100644 --- a/src/datadogV2/mod.rs +++ b/src/datadogV2/mod.rs @@ -19,6 +19,7 @@ pub use self::api::api_container_images; pub use self::api::api_containers; pub use self::api::api_csm_threats; pub use self::api::api_dashboard_lists; +pub use self::api::api_data_deletion; pub use self::api::api_domain_allowlist; pub use self::api::api_dora_metrics; pub use self::api::api_downtimes; diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index ef49252d9..8de48df4f 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -894,6 +894,24 @@ pub mod model_dashboard_list_update_items_request; pub use self::model_dashboard_list_update_items_request::DashboardListUpdateItemsRequest; pub mod model_dashboard_list_update_items_response; pub use self::model_dashboard_list_update_items_response::DashboardListUpdateItemsResponse; +pub mod model_create_data_deletion_request_body; +pub use self::model_create_data_deletion_request_body::CreateDataDeletionRequestBody; +pub mod model_create_data_deletion_request_body_data; +pub use self::model_create_data_deletion_request_body_data::CreateDataDeletionRequestBodyData; +pub mod model_create_data_deletion_request_body_attributes; +pub use self::model_create_data_deletion_request_body_attributes::CreateDataDeletionRequestBodyAttributes; +pub mod model_create_data_deletion_response_body; +pub use self::model_create_data_deletion_response_body::CreateDataDeletionResponseBody; +pub mod model_data_deletion_response_item; +pub use self::model_data_deletion_response_item::DataDeletionResponseItem; +pub mod model_data_deletion_response_item_attributes; +pub use self::model_data_deletion_response_item_attributes::DataDeletionResponseItemAttributes; +pub mod model_data_deletion_response_meta; +pub use self::model_data_deletion_response_meta::DataDeletionResponseMeta; +pub mod model_get_data_deletions_response_body; +pub use self::model_get_data_deletions_response_body::GetDataDeletionsResponseBody; +pub mod model_cancel_data_deletion_response_body; +pub use self::model_cancel_data_deletion_response_body::CancelDataDeletionResponseBody; pub mod model_domain_allowlist_response; pub use self::model_domain_allowlist_response::DomainAllowlistResponse; pub mod model_domain_allowlist_response_data; diff --git a/src/datadogV2/model/model_cancel_data_deletion_response_body.rs b/src/datadogV2/model/model_cancel_data_deletion_response_body.rs new file mode 100644 index 000000000..3edbdae96 --- /dev/null +++ b/src/datadogV2/model/model_cancel_data_deletion_response_body.rs @@ -0,0 +1,122 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// The response from the cancel data deletion request endpoint. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CancelDataDeletionResponseBody { + /// The created data deletion request information. + #[serde(rename = "data")] + pub data: Option, + /// The metadata of the data deletion response. + #[serde(rename = "meta")] + pub meta: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CancelDataDeletionResponseBody { + pub fn new() -> CancelDataDeletionResponseBody { + CancelDataDeletionResponseBody { + data: None, + meta: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data(mut self, value: crate::datadogV2::model::DataDeletionResponseItem) -> Self { + self.data = Some(value); + self + } + + pub fn meta(mut self, value: crate::datadogV2::model::DataDeletionResponseMeta) -> Self { + self.meta = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for CancelDataDeletionResponseBody { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for CancelDataDeletionResponseBody { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CancelDataDeletionResponseBodyVisitor; + impl<'a> Visitor<'a> for CancelDataDeletionResponseBodyVisitor { + type Value = CancelDataDeletionResponseBody; + + 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" => { + if v.is_null() { + continue; + } + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "meta" => { + if v.is_null() { + continue; + } + 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 content = CancelDataDeletionResponseBody { + data, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CancelDataDeletionResponseBodyVisitor) + } +} diff --git a/src/datadogV2/model/model_create_data_deletion_request_body.rs b/src/datadogV2/model/model_create_data_deletion_request_body.rs new file mode 100644 index 000000000..f4b9088db --- /dev/null +++ b/src/datadogV2/model/model_create_data_deletion_request_body.rs @@ -0,0 +1,95 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Object needed to create a data deletion request. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateDataDeletionRequestBody { + /// Data needed to create a data deletion request. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::CreateDataDeletionRequestBodyData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateDataDeletionRequestBody { + pub fn new( + data: crate::datadogV2::model::CreateDataDeletionRequestBodyData, + ) -> CreateDataDeletionRequestBody { + CreateDataDeletionRequestBody { + 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 CreateDataDeletionRequestBody { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateDataDeletionRequestBodyVisitor; + impl<'a> Visitor<'a> for CreateDataDeletionRequestBodyVisitor { + type Value = CreateDataDeletionRequestBody; + + 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 = CreateDataDeletionRequestBody { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateDataDeletionRequestBodyVisitor) + } +} diff --git a/src/datadogV2/model/model_create_data_deletion_request_body_attributes.rs b/src/datadogV2/model/model_create_data_deletion_request_body_attributes.rs new file mode 100644 index 000000000..40b974cc6 --- /dev/null +++ b/src/datadogV2/model/model_create_data_deletion_request_body_attributes.rs @@ -0,0 +1,133 @@ +// 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 a data deletion request. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateDataDeletionRequestBodyAttributes { + /// Start of requested time window, milliseconds since Unix epoch. + #[serde(rename = "from")] + pub from: i64, + /// List of indexes for the search. If not provided, the search is performed in all indexes. + #[serde(rename = "indexes")] + pub indexes: Option>, + /// Query for creating a data deletion request. + #[serde(rename = "query")] + pub query: std::collections::BTreeMap, + /// End of requested time window, milliseconds since Unix epoch. + #[serde(rename = "to")] + pub to: i64, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateDataDeletionRequestBodyAttributes { + pub fn new( + from: i64, + query: std::collections::BTreeMap, + to: i64, + ) -> CreateDataDeletionRequestBodyAttributes { + CreateDataDeletionRequestBodyAttributes { + from, + indexes: None, + query, + to, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn indexes(mut self, value: Vec) -> Self { + self.indexes = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for CreateDataDeletionRequestBodyAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateDataDeletionRequestBodyAttributesVisitor; + impl<'a> Visitor<'a> for CreateDataDeletionRequestBodyAttributesVisitor { + type Value = CreateDataDeletionRequestBodyAttributes; + + 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 from: Option = None; + let mut indexes: Option> = None; + let mut query: Option> = None; + let mut to: 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() { + "from" => { + from = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "indexes" => { + if v.is_null() { + continue; + } + indexes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "query" => { + query = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "to" => { + to = 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 from = from.ok_or_else(|| M::Error::missing_field("from"))?; + let query = query.ok_or_else(|| M::Error::missing_field("query"))?; + let to = to.ok_or_else(|| M::Error::missing_field("to"))?; + + let content = CreateDataDeletionRequestBodyAttributes { + from, + indexes, + query, + to, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateDataDeletionRequestBodyAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_create_data_deletion_request_body_data.rs b/src/datadogV2/model/model_create_data_deletion_request_body_data.rs new file mode 100644 index 000000000..941ae9c83 --- /dev/null +++ b/src/datadogV2/model/model_create_data_deletion_request_body_data.rs @@ -0,0 +1,96 @@ +// 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}; + +/// Data needed to create a data deletion request. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateDataDeletionRequestBodyData { + /// Attributes for creating a data deletion request. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::CreateDataDeletionRequestBodyAttributes, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateDataDeletionRequestBodyData { + pub fn new( + attributes: crate::datadogV2::model::CreateDataDeletionRequestBodyAttributes, + ) -> CreateDataDeletionRequestBodyData { + CreateDataDeletionRequestBodyData { + attributes, + 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 CreateDataDeletionRequestBodyData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateDataDeletionRequestBodyDataVisitor; + impl<'a> Visitor<'a> for CreateDataDeletionRequestBodyDataVisitor { + type Value = CreateDataDeletionRequestBodyData; + + 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::CreateDataDeletionRequestBodyAttributes, + > = 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)?); + } + &_ => { + 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 content = CreateDataDeletionRequestBodyData { + attributes, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateDataDeletionRequestBodyDataVisitor) + } +} diff --git a/src/datadogV2/model/model_create_data_deletion_response_body.rs b/src/datadogV2/model/model_create_data_deletion_response_body.rs new file mode 100644 index 000000000..ebe7501bf --- /dev/null +++ b/src/datadogV2/model/model_create_data_deletion_response_body.rs @@ -0,0 +1,122 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// The response from the create data deletion request endpoint. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateDataDeletionResponseBody { + /// The created data deletion request information. + #[serde(rename = "data")] + pub data: Option, + /// The metadata of the data deletion response. + #[serde(rename = "meta")] + pub meta: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateDataDeletionResponseBody { + pub fn new() -> CreateDataDeletionResponseBody { + CreateDataDeletionResponseBody { + data: None, + meta: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data(mut self, value: crate::datadogV2::model::DataDeletionResponseItem) -> Self { + self.data = Some(value); + self + } + + pub fn meta(mut self, value: crate::datadogV2::model::DataDeletionResponseMeta) -> Self { + self.meta = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for CreateDataDeletionResponseBody { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for CreateDataDeletionResponseBody { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateDataDeletionResponseBodyVisitor; + impl<'a> Visitor<'a> for CreateDataDeletionResponseBodyVisitor { + type Value = CreateDataDeletionResponseBody; + + 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" => { + if v.is_null() { + continue; + } + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "meta" => { + if v.is_null() { + continue; + } + 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 content = CreateDataDeletionResponseBody { + data, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateDataDeletionResponseBodyVisitor) + } +} diff --git a/src/datadogV2/model/model_data_deletion_response_item.rs b/src/datadogV2/model/model_data_deletion_response_item.rs new file mode 100644 index 000000000..e10590a3b --- /dev/null +++ b/src/datadogV2/model/model_data_deletion_response_item.rs @@ -0,0 +1,118 @@ +// 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 created data deletion request information. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct DataDeletionResponseItem { + /// Deletion attribute for data deletion response. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::DataDeletionResponseItemAttributes, + /// The ID of the created data deletion request. + #[serde(rename = "id")] + pub id: String, + /// The type of the request created. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl DataDeletionResponseItem { + pub fn new( + attributes: crate::datadogV2::model::DataDeletionResponseItemAttributes, + id: String, + type_: String, + ) -> DataDeletionResponseItem { + DataDeletionResponseItem { + 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 DataDeletionResponseItem { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct DataDeletionResponseItemVisitor; + impl<'a> Visitor<'a> for DataDeletionResponseItemVisitor { + type Value = DataDeletionResponseItem; + + 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::DataDeletionResponseItemAttributes, + > = 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 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 = DataDeletionResponseItem { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(DataDeletionResponseItemVisitor) + } +} diff --git a/src/datadogV2/model/model_data_deletion_response_item_attributes.rs b/src/datadogV2/model/model_data_deletion_response_item_attributes.rs new file mode 100644 index 000000000..7dafef683 --- /dev/null +++ b/src/datadogV2/model/model_data_deletion_response_item_attributes.rs @@ -0,0 +1,236 @@ +// 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}; + +/// Deletion attribute for data deletion response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct DataDeletionResponseItemAttributes { + /// Creation time of the deletion request. + #[serde(rename = "created_at")] + pub created_at: String, + /// User who created the deletion request. + #[serde(rename = "created_by")] + pub created_by: String, + /// Start of requested time window, milliseconds since Unix epoch. + #[serde(rename = "from_time")] + pub from_time: i64, + /// List of indexes for the search. If not provided, the search is performed in all indexes. + #[serde(rename = "indexes")] + pub indexes: Option>, + /// Whether the deletion request is fully created or not. + #[serde(rename = "is_created")] + pub is_created: bool, + /// Organization ID. + #[serde(rename = "org_id")] + pub org_id: i64, + /// Product name. + #[serde(rename = "product")] + pub product: String, + /// Query for creating a data deletion request. + #[serde(rename = "query")] + pub query: String, + /// Starting time of the process to delete the requested data. + #[serde(rename = "starting_at")] + pub starting_at: String, + /// Status of the deletion request. + #[serde(rename = "status")] + pub status: String, + /// End of requested time window, milliseconds since Unix epoch. + #[serde(rename = "to_time")] + pub to_time: i64, + /// Total number of elements to be deleted. Only the data accessible to the current user that matches the query and timeframe provided will be deleted. + #[serde(rename = "total_unrestricted")] + pub total_unrestricted: i64, + /// Update time of the deletion request. + #[serde(rename = "updated_at")] + pub updated_at: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl DataDeletionResponseItemAttributes { + pub fn new( + created_at: String, + created_by: String, + from_time: i64, + is_created: bool, + org_id: i64, + product: String, + query: String, + starting_at: String, + status: String, + to_time: i64, + total_unrestricted: i64, + updated_at: String, + ) -> DataDeletionResponseItemAttributes { + DataDeletionResponseItemAttributes { + created_at, + created_by, + from_time, + indexes: None, + is_created, + org_id, + product, + query, + starting_at, + status, + to_time, + total_unrestricted, + updated_at, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn indexes(mut self, value: Vec) -> Self { + self.indexes = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for DataDeletionResponseItemAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct DataDeletionResponseItemAttributesVisitor; + impl<'a> Visitor<'a> for DataDeletionResponseItemAttributesVisitor { + type Value = DataDeletionResponseItemAttributes; + + 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 created_at: Option = None; + let mut created_by: Option = None; + let mut from_time: Option = None; + let mut indexes: Option> = None; + let mut is_created: Option = None; + let mut org_id: Option = None; + let mut product: Option = None; + let mut query: Option = None; + let mut starting_at: Option = None; + let mut status: Option = None; + let mut to_time: Option = None; + let mut total_unrestricted: Option = None; + let mut updated_at: 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() { + "created_at" => { + created_at = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "created_by" => { + created_by = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "from_time" => { + from_time = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "indexes" => { + if v.is_null() { + continue; + } + indexes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "is_created" => { + is_created = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "org_id" => { + org_id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "product" => { + product = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "query" => { + query = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "starting_at" => { + starting_at = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "status" => { + status = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "to_time" => { + to_time = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "total_unrestricted" => { + total_unrestricted = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "updated_at" => { + updated_at = 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 created_at = created_at.ok_or_else(|| M::Error::missing_field("created_at"))?; + let created_by = created_by.ok_or_else(|| M::Error::missing_field("created_by"))?; + let from_time = from_time.ok_or_else(|| M::Error::missing_field("from_time"))?; + let is_created = is_created.ok_or_else(|| M::Error::missing_field("is_created"))?; + let org_id = org_id.ok_or_else(|| M::Error::missing_field("org_id"))?; + let product = product.ok_or_else(|| M::Error::missing_field("product"))?; + let query = query.ok_or_else(|| M::Error::missing_field("query"))?; + let starting_at = + starting_at.ok_or_else(|| M::Error::missing_field("starting_at"))?; + let status = status.ok_or_else(|| M::Error::missing_field("status"))?; + let to_time = to_time.ok_or_else(|| M::Error::missing_field("to_time"))?; + let total_unrestricted = total_unrestricted + .ok_or_else(|| M::Error::missing_field("total_unrestricted"))?; + let updated_at = updated_at.ok_or_else(|| M::Error::missing_field("updated_at"))?; + + let content = DataDeletionResponseItemAttributes { + created_at, + created_by, + from_time, + indexes, + is_created, + org_id, + product, + query, + starting_at, + status, + to_time, + total_unrestricted, + updated_at, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(DataDeletionResponseItemAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_data_deletion_response_meta.rs b/src/datadogV2/model/model_data_deletion_response_meta.rs new file mode 100644 index 000000000..b6c165ea2 --- /dev/null +++ b/src/datadogV2/model/model_data_deletion_response_meta.rs @@ -0,0 +1,176 @@ +// 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 metadata of the data deletion response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct DataDeletionResponseMeta { + /// The total deletion requests created by product. + #[serde(rename = "count_product")] + pub count_product: Option>, + /// The total deletion requests created by status. + #[serde(rename = "count_status")] + pub count_status: Option>, + /// The next page when searching deletion requests created in the current organization. + #[serde(rename = "next_page")] + pub next_page: Option, + /// The product of the deletion request. + #[serde(rename = "product")] + pub product: Option, + /// The status of the executed request. + #[serde(rename = "request_status")] + pub request_status: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl DataDeletionResponseMeta { + pub fn new() -> DataDeletionResponseMeta { + DataDeletionResponseMeta { + count_product: None, + count_status: None, + next_page: None, + product: None, + request_status: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn count_product(mut self, value: std::collections::BTreeMap) -> Self { + self.count_product = Some(value); + self + } + + pub fn count_status(mut self, value: std::collections::BTreeMap) -> Self { + self.count_status = Some(value); + self + } + + pub fn next_page(mut self, value: String) -> Self { + self.next_page = Some(value); + self + } + + pub fn product(mut self, value: String) -> Self { + self.product = Some(value); + self + } + + pub fn request_status(mut self, value: String) -> Self { + self.request_status = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for DataDeletionResponseMeta { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for DataDeletionResponseMeta { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct DataDeletionResponseMetaVisitor; + impl<'a> Visitor<'a> for DataDeletionResponseMetaVisitor { + type Value = DataDeletionResponseMeta; + + 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 count_product: Option> = None; + let mut count_status: Option> = None; + let mut next_page: Option = None; + let mut product: Option = None; + let mut request_status: 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() { + "count_product" => { + if v.is_null() { + continue; + } + count_product = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "count_status" => { + if v.is_null() { + continue; + } + count_status = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "next_page" => { + if v.is_null() { + continue; + } + next_page = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "product" => { + if v.is_null() { + continue; + } + product = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "request_status" => { + if v.is_null() { + continue; + } + request_status = + 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 = DataDeletionResponseMeta { + count_product, + count_status, + next_page, + product, + request_status, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(DataDeletionResponseMetaVisitor) + } +} diff --git a/src/datadogV2/model/model_get_data_deletions_response_body.rs b/src/datadogV2/model/model_get_data_deletions_response_body.rs new file mode 100644 index 000000000..fbac8941f --- /dev/null +++ b/src/datadogV2/model/model_get_data_deletions_response_body.rs @@ -0,0 +1,122 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// The response from the get data deletion requests endpoint. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct GetDataDeletionsResponseBody { + /// The list of data deletion requests that matches the query. + #[serde(rename = "data")] + pub data: Option>, + /// The metadata of the data deletion response. + #[serde(rename = "meta")] + pub meta: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl GetDataDeletionsResponseBody { + pub fn new() -> GetDataDeletionsResponseBody { + GetDataDeletionsResponseBody { + data: None, + meta: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data(mut self, value: Vec) -> Self { + self.data = Some(value); + self + } + + pub fn meta(mut self, value: crate::datadogV2::model::DataDeletionResponseMeta) -> Self { + self.meta = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for GetDataDeletionsResponseBody { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for GetDataDeletionsResponseBody { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct GetDataDeletionsResponseBodyVisitor; + impl<'a> Visitor<'a> for GetDataDeletionsResponseBodyVisitor { + type Value = GetDataDeletionsResponseBody; + + 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" => { + if v.is_null() { + continue; + } + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "meta" => { + if v.is_null() { + continue; + } + 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 content = GetDataDeletionsResponseBody { + data, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(GetDataDeletionsResponseBodyVisitor) + } +} diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.frozen new file mode 100644 index 000000000..4390af597 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:56:51.182Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.json new file mode 100644 index 000000000..31a694c79 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Bad-Request-response.json @@ -0,0 +1,33 @@ +{ + "http_interactions": [ + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/id-1/cancel" + }, + "response": { + "body": { + "string": "{\"errors\":[{\"status\":\"400\",\"title\":\"Invalid Parameter\",\"detail\":\"invalid parameter \\\"id\\\" in \\\"path\\\"; expected type \\\"int\\\"\"}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 400, + "message": "Bad Request" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:56:51 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.frozen new file mode 100644 index 000000000..04ac8a541 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:57:02.769Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.json b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.json new file mode 100644 index 000000000..6b7f8b294 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-OK-response.json @@ -0,0 +1,95 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"from\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"query\":{\"host\":\"abc\",\"service\":\"xyz\"},\"to\":1704063600000}}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/deletion/data/logs" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"303\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:03.242841331Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"pending\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:03.242841331Z\"}},\"meta\":{\"product\":\"logs\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:02 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/303/cancel" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"303\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:03.242841Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:03.638067Z\"}},\"meta\":{\"product\":\"logs\",\"request_status\":\"canceled\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:02 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/303/cancel" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"303\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:03.242841Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:03.936325Z\"}},\"meta\":{\"product\":\"logs\",\"request_status\":\"canceled\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:02 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.frozen new file mode 100644 index 000000000..3bb79b73d --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:57:14.890Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.json b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.json new file mode 100644 index 000000000..f67dd6781 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Cancels-a-data-deletion-request-returns-Precondition-failed-error-response.json @@ -0,0 +1,33 @@ +{ + "http_interactions": [ + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/-1/cancel" + }, + "response": { + "body": { + "string": "{\"errors\":[{\"status\":\"412\",\"code\":\"INVALID_ID\",\"title\":\"INVALID_ID\",\"detail\":\"INVALID_ID\"}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 412, + "message": "Precondition Failed" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:14 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.frozen new file mode 100644 index 000000000..b74c2983a --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:59:09.810Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.json b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.json new file mode 100644 index 000000000..6f973063c --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-OK-response.json @@ -0,0 +1,67 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"from\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"query\":{\"host\":\"abc\",\"service\":\"xyz\"},\"to\":1704063600000}}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/deletion/data/logs" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"305\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:59:10.304195172Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"pending\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:59:10.304195172Z\"}},\"meta\":{\"product\":\"logs\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:59:09 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/305/cancel" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"305\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:59:10.304195Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:59:10.681676Z\"}},\"meta\":{\"product\":\"logs\",\"request_status\":\"canceled\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:59:09 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.frozen new file mode 100644 index 000000000..74ecbd427 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:59:22.532Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.json b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.json new file mode 100644 index 000000000..2fce23709 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Creates-a-data-deletion-request-returns-Precondition-failed-error-response.json @@ -0,0 +1,39 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"from\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"query\":{},\"to\":1704063600000}}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/deletion/data/logs" + }, + "response": { + "body": { + "string": "{\"errors\":[{\"status\":\"412\",\"code\":\"INVALID_BODY\",\"title\":\"INVALID_BODY\",\"detail\":\"INVALID_BODY\"}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 412, + "message": "Precondition Failed" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:59:22 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.frozen new file mode 100644 index 000000000..108d0eae3 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.frozen @@ -0,0 +1 @@ +2024-11-15T08:57:26.678Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.json b/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.json new file mode 100644 index 000000000..76057cb25 --- /dev/null +++ b/tests/scenarios/cassettes/v2/data_deletion/Gets-a-list-of-data-deletion-requests-returns-OK-response.json @@ -0,0 +1,95 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"from\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"query\":{\"host\":\"abc\",\"service\":\"xyz\"},\"to\":1704063600000}}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/deletion/data/logs" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"304\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:27.161919269Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"pending\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:27.161919269Z\"}},\"meta\":{\"product\":\"logs\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:26 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "get", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests" + }, + "response": { + "body": { + "string": "{\"data\":[{\"id\":\"304\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:27.161919Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"pending\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:27.161919Z\"}},{\"id\":\"303\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:03.242841Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:03.936325Z\"}},{\"id\":\"302\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:44:51.953197Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:44:54.901861Z\"}},{\"id\":\"301\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:44:12.92412Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:44:44.846759Z\"}},{\"id\":\"300\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:20:26.053712Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:20:34.545658Z\"}},{\"id\":\"299\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:12:17.70049Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:12:50.271468Z\"}},{\"id\":\"298\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:09:41.997486Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:09:45.322668Z\"}},{\"id\":\"297\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T07:51:10.059846Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T07:51:27.637588Z\"}},{\"id\":\"296\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T07:49:26.502631Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T07:49:28.431587Z\"}},{\"id\":\"295\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:57:14.713251Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:57:16.874262Z\"}},{\"id\":\"294\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:56:38.672296Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:56:39.220134Z\"}},{\"id\":\"293\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:56:21.931549Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:56:22.653515Z\"}},{\"id\":\"292\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:52:37.230638Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:52:41.82939Z\"}},{\"id\":\"291\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:51:34.464818Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:51:35.662615Z\"}},{\"id\":\"290\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T17:34:51.13924Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T17:34:52.585803Z\"}},{\"id\":\"289\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:54:28.587048Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:54:30.222141Z\"}},{\"id\":\"288\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:52:52.567007Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:52:54.810859Z\"}},{\"id\":\"287\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:49:54.011076Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:49:55.255357Z\"}},{\"id\":\"286\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:35:25.381857Z\",\"created_by\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:35:30.570834Z\"}},{\"id\":\"285\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:32:52.425512Z\",\"created_by\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:33:25.559245Z\"}},{\"id\":\"284\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:27:22.412357Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:27:28.763719Z\"}},{\"id\":\"283\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:26:56.006849Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:26:57.682661Z\"}},{\"id\":\"282\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:26:02.447468Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:26:05.009146Z\"}},{\"id\":\"281\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:24:58.627741Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:25:02.852354Z\"}},{\"id\":\"280\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:23:10.220638Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:23:42.451575Z\"}},{\"id\":\"279\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:22:34.323711Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:23:06.006296Z\"}},{\"id\":\"278\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:21:42.323606Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:21:49.622015Z\"}},{\"id\":\"277\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:19:07.723768Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:19:11.463512Z\"}},{\"id\":\"276\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-14T16:16:47.047428Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-14T16:17:18.723041Z\"}}],\"meta\":{\"count_status\":{\"canceled\":28,\"pending\":1},\"count_product\":{\"logs\":29}}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:26 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/deletion/requests/304/cancel" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"304\",\"type\":\"deletion_request\",\"attributes\":{\"created_at\":\"2024-11-15T08:57:27.161919Z\",\"created_by\":\"frog@datadoghq.com\",\"from_time\":1672527600000,\"indexes\":[\"index-1\",\"index-2\"],\"is_created\":false,\"org_id\":321813,\"product\":\"logs\",\"query\":\"host:abc service:xyz\",\"starting_at\":\"0001-01-01T00:00:00Z\",\"status\":\"canceled\",\"to_time\":1704063600000,\"total_unrestricted\":0,\"updated_at\":\"2024-11-15T08:57:27.931008Z\"}},\"meta\":{\"product\":\"logs\",\"request_status\":\"canceled\"}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 15 Nov 2024 08:57:26 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/features/v2/data_deletion.feature b/tests/scenarios/features/v2/data_deletion.feature new file mode 100644 index 000000000..84c5830ea --- /dev/null +++ b/tests/scenarios/features/v2/data_deletion.feature @@ -0,0 +1,76 @@ +@endpoint(data-deletion) @endpoint(data-deletion-v2) +Feature: Data Deletion + The Data Deletion API allows the user to target and delete data from the + allowed products. It's currently enabled for Logs and RUM and depends on + `logs_delete_data` and `rum_delete_data` permissions respectively. + + Background: + Given a valid "apiKeyAuth" key in the system + And a valid "appKeyAuth" key in the system + And an instance of "DataDeletion" API + + @team:DataDog/supportability-engineering + Scenario: Cancels a data deletion request returns "Bad Request" response + Given new "CancelDataDeletionRequest" request + And request contains "id" parameter with value "id-1" + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/supportability-engineering + Scenario: Cancels a data deletion request returns "OK" response + Given there is a valid "deletion_request" in the system + And new "CancelDataDeletionRequest" request + And request contains "id" parameter from "deletion_request.data.id" + When the request is sent + Then the response status is 200 OK + And the response "data.id" is equal to "{{ deletion_request.data.id }}" + And the response "data.type" is equal to "{{ deletion_request.data.type }}" + And the response "data.attributes.product" is equal to "{{ deletion_request.data.attributes.product }}" + And the response "data.attributes.status" is equal to "canceled" + + @team:DataDog/supportability-engineering + Scenario: Cancels a data deletion request returns "Precondition failed error" response + Given new "CancelDataDeletionRequest" request + And request contains "id" parameter with value "-1" + When the request is sent + Then the response status is 412 Precondition failed error + + @generated @skip @team:DataDog/supportability-engineering + Scenario: Creates a data deletion request returns "Bad Request" response + Given new "CreateDataDeletionRequest" request + And request contains "product" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"from": 1672527600000, "indexes": ["index-1", "index-2"], "query": {"host": "abc", "service": "xyz"}, "to": 1704063600000}}} + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/supportability-engineering + Scenario: Creates a data deletion request returns "OK" response + Given new "CreateDataDeletionRequest" request + And request contains "product" parameter with value "logs" + And body with value {"data": {"attributes": {"from": 1672527600000, "indexes": ["index-1", "index-2"], "query": {"host": "abc", "service": "xyz"}, "to": 1704063600000}}} + When the request is sent + Then the response status is 200 OK + And the response "data.type" is equal to "deletion_request" + And the response "data.attributes.product" is equal to "logs" + And the response "data.attributes.status" is equal to "pending" + + @team:DataDog/supportability-engineering + Scenario: Creates a data deletion request returns "Precondition failed error" response + Given new "CreateDataDeletionRequest" request + And request contains "product" parameter with value "logs" + And body with value {"data": {"attributes": {"from": 1672527600000, "indexes": ["index-1", "index-2"], "query": {}, "to": 1704063600000}}} + When the request is sent + Then the response status is 412 Precondition failed error + + @generated @skip @team:DataDog/supportability-engineering + Scenario: Gets a list of data deletion requests returns "Bad Request" response + Given new "GetDataDeletionRequests" request + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/supportability-engineering + Scenario: Gets a list of data deletion requests returns "OK" response + Given there is a valid "deletion_request" in the system + And new "GetDataDeletionRequests" request + When the request is sent + Then the response status is 200 OK diff --git a/tests/scenarios/features/v2/given.json b/tests/scenarios/features/v2/given.json index 41cd8e0f2..62f11ecc9 100644 --- a/tests/scenarios/features/v2/given.json +++ b/tests/scenarios/features/v2/given.json @@ -128,6 +128,22 @@ "tag": "Dashboard Lists", "operationId": "CreateDashboardListItems" }, + { + "parameters": [ + { + "name": "product", + "value": "\"logs\"" + }, + { + "name": "body", + "value": "{\n \"data\": {\n \"attributes\": {\n \"from\": 1672527600000,\n \"to\": 1704063600000,\n \"indexes\": [\"index-1\", \"index-2\"],\n \"query\": {\"host\": \"abc\", \"service\": \"xyz\"}\n }\n }\n}" + } + ], + "step": "there is a valid \"deletion_request\" in the system", + "key": "deletion_request", + "tag": "Data Deletion", + "operationId": "CreateDataDeletionRequest" + }, { "parameters": [ { diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 91f554953..608035022 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -541,6 +541,31 @@ "type": "safe" } }, + "CreateDataDeletionRequest": { + "tag": "Data Deletion", + "undo": { + "operationId": "CancelDataDeletionRequest", + "parameters": [ + { + "name": "id", + "source": "data.id" + } + ], + "type": "unsafe" + } + }, + "GetDataDeletionRequests": { + "tag": "Data Deletion", + "undo": { + "type": "safe" + } + }, + "CancelDataDeletionRequest": { + "tag": "Data Deletion", + "undo": { + "type": "idempotent" + } + }, "GetDomainAllowlist": { "tag": "Domain Allowlist", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 726a7fd33..c391d732f 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -68,6 +68,7 @@ pub struct ApiInstances { Option, pub v2_api_usage_metering: Option, pub v2_api_dashboard_lists: Option, + pub v2_api_data_deletion: Option, pub v2_api_domain_allowlist: Option, pub v2_api_dora_metrics: Option, pub v2_api_downtimes: Option, @@ -541,6 +542,14 @@ pub fn initialize_api_instance(world: &mut DatadogWorld, api: String) { world.http_client.as_ref().unwrap().clone() )); } + "DataDeletion" => { + world.api_instances.v2_api_data_deletion = Some( + datadogV2::api_data_deletion::DataDeletionAPI::with_client_and_config( + world.config.clone(), + world.http_client.as_ref().unwrap().clone(), + ), + ); + } "DomainAllowlist" => { world.api_instances.v2_api_domain_allowlist = Some( datadogV2::api_domain_allowlist::DomainAllowlistAPI::with_client_and_config( @@ -1959,6 +1968,18 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.UpdateDashboardListItems".into(), test_v2_update_dashboard_list_items, ); + world.function_mappings.insert( + "v2.CreateDataDeletionRequest".into(), + test_v2_create_data_deletion_request, + ); + world.function_mappings.insert( + "v2.GetDataDeletionRequests".into(), + test_v2_get_data_deletion_requests, + ); + world.function_mappings.insert( + "v2.CancelDataDeletionRequest".into(), + test_v2_cancel_data_deletion_request, + ); world .function_mappings .insert("v2.GetDomainAllowlist".into(), test_v2_get_domain_allowlist); @@ -13772,6 +13793,111 @@ fn test_v2_update_dashboard_list_items( world.response.code = response.status.as_u16(); } +fn test_v2_create_data_deletion_request( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_data_deletion + .as_ref() + .expect("api instance not found"); + let product = serde_json::from_value(_parameters.get("product").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = match block_on(api.create_data_deletion_request_with_http_info(product, 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_data_deletion_requests( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_data_deletion + .as_ref() + .expect("api instance not found"); + let next_page = _parameters + .get("next_page") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let product = _parameters + .get("product") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let query = _parameters + .get("query") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let status = _parameters + .get("status") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_size = _parameters + .get("page_size") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_data_deletion::GetDataDeletionRequestsOptionalParams::default(); + params.next_page = next_page; + params.product = product; + params.query = query; + params.status = status; + params.page_size = page_size; + let response = match block_on(api.get_data_deletion_requests_with_http_info(params)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + +fn test_v2_cancel_data_deletion_request( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_data_deletion + .as_ref() + .expect("api instance not found"); + let id = serde_json::from_value(_parameters.get("id").unwrap().clone()).unwrap(); + let response = match block_on(api.cancel_data_deletion_request_with_http_info(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_get_domain_allowlist(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances