diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index f45d9a1cc..fa9e4f021 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -15324,6 +15324,41 @@ components: id: $ref: "#/components/schemas/ApiID" type: object + CreateOrUpdateWidgetRequest: + description: Request body for creating or updating a widget. + properties: + data: + $ref: "#/components/schemas/CreateOrUpdateWidgetRequestData" + required: + - data + type: object + CreateOrUpdateWidgetRequestAttributes: + description: Attributes for creating or updating a widget. + properties: + definition: + $ref: "#/components/schemas/WidgetDefinition" + tags: + description: User-defined tags for organizing the widget. + items: + type: string + nullable: true + type: array + required: + - definition + type: object + CreateOrUpdateWidgetRequestData: + description: Data for creating or updating a widget. + properties: + attributes: + $ref: "#/components/schemas/CreateOrUpdateWidgetRequestAttributes" + type: + description: Widgets resource type. + example: widgets + type: string + required: + - type + - attributes + type: object CreatePageRequest: description: Full request to trigger an On-Call Page. example: @@ -45795,6 +45830,13 @@ components: description: The unique identifier for this component. Used in other parts of the pipeline to reference this component (for example, as the `input` to downstream components). example: splunk-hec-source type: string + store_hec_token: + default: false + description: |- + If `true`, the HEC token is stored in the event's metadata and made available to the Enrichment Table + processor and the `splunk_hec` destination for routing or enrichment based on the token. Defaults to `false`. + example: true + type: boolean tls: $ref: "#/components/schemas/ObservabilityPipelineTls" type: @@ -71675,6 +71717,136 @@ components: - FRIDAY - SATURDAY - SUNDAY + WidgetAttributes: + description: Attributes of a widget resource. + properties: + created_at: + description: ISO 8601 timestamp of when the widget was created. + example: "2024-01-15T00:00:00.000Z" + type: string + definition: + $ref: "#/components/schemas/WidgetDefinition" + is_favorited: + description: "Will be implemented soon. Currently always returns false." + example: false + type: boolean + modified_at: + description: ISO 8601 timestamp of when the widget was last modified. + example: "2024-01-15T00:00:00.000Z" + type: string + tags: + description: User-defined tags for organizing widgets. + example: + - "team:my-team" + items: + type: string + nullable: true + type: array + required: + - definition + - tags + - is_favorited + - created_at + - modified_at + type: object + WidgetData: + description: A widget resource object. + properties: + attributes: + $ref: "#/components/schemas/WidgetAttributes" + id: + description: The unique identifier of the widget. + example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + type: string + relationships: + $ref: "#/components/schemas/WidgetRelationships" + type: + description: Widgets resource type. + example: widgets + type: string + required: + - id + - type + - attributes + type: object + WidgetDefinition: + additionalProperties: {} + description: The definition of a widget, including its type and configuration. + properties: + title: + description: The display title of the widget. + example: My Widget + maxLength: 100 + minLength: 1 + type: string + type: + $ref: "#/components/schemas/WidgetType" + required: + - type + - title + type: object + WidgetExperienceType: + description: Widget experience types that differentiate between the products using the specific widget. + enum: + - ccm_reports + - logs_reports + - csv_reports + - product_analytics + example: ccm_reports + type: string + x-enum-varnames: + - CCM_REPORTS + - LOGS_REPORTS + - CSV_REPORTS + - PRODUCT_ANALYTICS + WidgetIncludedUser: + description: A user resource included in the response. + properties: + attributes: + $ref: "#/components/schemas/WidgetIncludedUserAttributes" + id: + description: The unique identifier of the user. + example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + type: string + type: + description: Users resource type. + example: users + type: string + required: + - id + - type + type: object + WidgetIncludedUserAttributes: + description: Attributes of an included user resource. + properties: + handle: + description: The email handle of the user. + example: "john.doe@example.com" + type: string + name: + description: The display name of the user. + example: "John Doe" + nullable: true + type: string + type: object + WidgetListResponse: + description: Response containing a list of widgets. + properties: + data: + description: List of widget resources. + items: + $ref: "#/components/schemas/WidgetData" + type: array + included: + description: Array of user resources related to the widgets. + items: + $ref: "#/components/schemas/WidgetIncludedUser" + type: array + meta: + $ref: "#/components/schemas/WidgetSearchMeta" + required: + - data + type: object WidgetLiveSpan: description: The available timeframes depend on the widget you are using. enum: @@ -71711,6 +71883,108 @@ components: - PAST_SIX_MONTHS - PAST_ONE_YEAR - ALERT + WidgetRelationshipData: + description: Relationship data referencing a user resource. + properties: + id: + description: The unique identifier of the user. + example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890" + type: string + type: + description: Users resource type. + example: users + type: string + required: + - id + - type + type: object + WidgetRelationshipItem: + description: A JSON:API relationship to a user. + properties: + data: + $ref: "#/components/schemas/WidgetRelationshipData" + type: object + WidgetRelationships: + description: Relationships of the widget resource. + properties: + created_by: + $ref: "#/components/schemas/WidgetRelationshipItem" + description: The user who created the widget. + modified_by: + $ref: "#/components/schemas/WidgetRelationshipItem" + description: The user who last modified the widget. + type: object + WidgetResponse: + description: Response containing a single widget. + properties: + data: + $ref: "#/components/schemas/WidgetData" + included: + description: Array of user resources related to the widget. + items: + $ref: "#/components/schemas/WidgetIncludedUser" + type: array + required: + - data + type: object + WidgetSearchMeta: + description: Metadata about the search results. + properties: + created_by_anyone_total: + description: Total number of widgets created by anyone. + format: int64 + type: integer + created_by_you_total: + description: Total number of widgets created by the current user. + format: int64 + type: integer + favorited_by_you_total: + description: Total number of widgets favorited by the current user. + format: int64 + type: integer + filtered_total: + description: Total number of widgets matching the current filter criteria. + format: int64 + type: integer + type: object + WidgetType: + description: |- + Widget types that are allowed to be stored as individual records. + This is not a complete list of dashboard and notebook widget types. + enum: + - bar_chart + - change + - cloud_cost_summary + - cohort + - funnel + - geomap + - list_stream + - query_table + - query_value + - retention_curve + - sankey + - sunburst + - timeseries + - toplist + - treemap + example: bar_chart + type: string + x-enum-varnames: + - BAR_CHART + - CHANGE + - CLOUD_COST_SUMMARY + - COHORT + - FUNNEL + - GEOMAP + - LIST_STREAM + - QUERY_TABLE + - QUERY_VALUE + - RETENTION_CURVE + - SANKEY + - SUNBURST + - TIMESERIES + - TOPLIST + - TREEMAP WorkflowData: description: Data related to the workflow. properties: @@ -109866,6 +110140,328 @@ paths: operator: OR permissions: - teams_read + /api/v2/widgets/{experience_type}: + get: + description: Search and list widgets for a given experience type. Supports filtering by widget type, creator, title, and tags, as well as sorting and pagination. + operationId: SearchWidgets + parameters: + - description: The experience type for the widget. + in: path + name: experience_type + required: true + schema: + $ref: "#/components/schemas/WidgetExperienceType" + - description: Filter widgets by widget type. + in: query + name: filter[widgetType] + schema: + $ref: "#/components/schemas/WidgetType" + - description: Filter widgets by the email handle of the creator. + in: query + name: filter[creatorHandle] + schema: + example: "john.doe@example.com" + type: string + - description: Filter to only widgets favorited by the current user. + in: query + name: filter[isFavorited] + schema: + type: boolean + - description: Filter widgets by title (substring match). + in: query + name: filter[title] + schema: + type: string + - description: Filter widgets by tags. Format as bracket-delimited CSV, e.g. `[tag1,tag2]`. + in: query + name: filter[tags] + schema: + type: string + - description: |- + Sort field for the results. Prefix with `-` for descending order. + Allowed values: `title`, `created_at`, `modified_at`. + in: query + name: sort + schema: + default: "-modified_at" + example: "-modified_at" + type: string + - description: Page number for pagination (0-indexed). + in: query + name: page[number] + schema: + default: 0 + minimum: 0 + type: integer + - description: Number of widgets per page. + in: query + name: page[size] + schema: + default: 50 + maximum: 100 + type: integer + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WidgetListResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Search widgets + tags: + - Widgets + x-permission: + operator: OR + permissions: + - cloud_cost_management_read + - generate_log_reports + - manage_log_reports + - product_analytics_saved_widgets_read + post: + description: Create a new widget for a given experience type. + operationId: CreateWidget + parameters: + - description: The experience type for the widget. + in: path + name: experience_type + required: true + schema: + $ref: "#/components/schemas/WidgetExperienceType" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/CreateOrUpdateWidgetRequest" + description: Widget request body. + required: true + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WidgetResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Create a widget + tags: + - Widgets + x-codegen-request-body-name: body + x-permission: + operator: OR + permissions: + - cloud_cost_management_write + - generate_log_reports + - manage_log_reports + - product_analytics_saved_widgets_write + /api/v2/widgets/{experience_type}/{uuid}: + delete: + description: Soft-delete a widget by its UUID for a given experience type. + operationId: DeleteWidget + parameters: + - description: The experience type for the widget. + in: path + name: experience_type + required: true + schema: + $ref: "#/components/schemas/WidgetExperienceType" + - description: The UUID of the widget. + in: path + name: uuid + required: true + schema: + format: uuid + type: string + responses: + "204": + description: No Content + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Delete a widget + tags: + - Widgets + x-permission: + operator: OR + permissions: + - cloud_cost_management_write + - generate_log_reports + - manage_log_reports + - product_analytics_saved_widgets_write + get: + description: Retrieve a widget by its UUID for a given experience type. + operationId: GetWidget + parameters: + - description: The experience type for the widget. + in: path + name: experience_type + required: true + schema: + $ref: "#/components/schemas/WidgetExperienceType" + - description: The UUID of the widget. + in: path + name: uuid + required: true + schema: + format: uuid + type: string + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WidgetResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Get a widget + tags: + - Widgets + x-permission: + operator: OR + permissions: + - cloud_cost_management_read + - generate_log_reports + - manage_log_reports + - product_analytics_saved_widgets_read + put: + description: Update a widget by its UUID for a given experience type. This performs a full replacement of the widget definition. + operationId: UpdateWidget + parameters: + - description: The experience type for the widget. + in: path + name: experience_type + required: true + schema: + $ref: "#/components/schemas/WidgetExperienceType" + - description: The UUID of the widget. + in: path + name: uuid + required: true + schema: + format: uuid + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/CreateOrUpdateWidgetRequest" + description: Widget request body. + required: true + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WidgetResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Update a widget + tags: + - Widgets + x-codegen-request-body-name: body + x-permission: + operator: OR + permissions: + - cloud_cost_management_write + - generate_log_reports + - manage_log_reports + - product_analytics_saved_widgets_write /api/v2/workflows: post: description: Create a new workflow, returning the workflow ID. This API requires a [registered application key](https://docs.datadoghq.com/api/latest/action-connection/#register-a-new-app-key). Alternatively, you can configure these permissions [in the UI](https://docs.datadoghq.com/account_management/api-app-keys/#actions-api-access). @@ -110716,6 +111312,11 @@ tags: externalDocs: url: https://docs.datadoghq.com/account_management/users name: Users + - description: |- + Create, read, update, and delete saved widgets. Widgets are reusable + visualization components stored independently from any dashboard or notebook, + partitioned by experience type and identified by a UUID. + name: Widgets - description: |- Datadog Workflow Automation allows you to automate your end-to-end processes by connecting Datadog with the rest of your tech stack. Build workflows to auto-remediate your alerts, streamline your incident and security processes, and reduce manual toil. Workflow Automation supports over 1,000+ OOTB actions, including AWS, JIRA, ServiceNow, GitHub, and OpenAI. Learn more in our Workflow Automation docs [here](https://docs.datadoghq.com/service_management/workflows/). externalDocs: diff --git a/examples/v2_widgets_CreateWidget.rs b/examples/v2_widgets_CreateWidget.rs new file mode 100644 index 000000000..d1acb95c7 --- /dev/null +++ b/examples/v2_widgets_CreateWidget.rs @@ -0,0 +1,31 @@ +// Create a widget returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_widgets::WidgetsAPI; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequest; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequestAttributes; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequestData; +use datadog_api_client::datadogV2::model::WidgetDefinition; +use datadog_api_client::datadogV2::model::WidgetExperienceType; +use datadog_api_client::datadogV2::model::WidgetType; + +#[tokio::main] +async fn main() { + let body = CreateOrUpdateWidgetRequest::new(CreateOrUpdateWidgetRequestData::new( + CreateOrUpdateWidgetRequestAttributes::new(WidgetDefinition::new( + "My Widget".to_string(), + WidgetType::BAR_CHART, + )) + .tags(Some(vec![])), + "widgets".to_string(), + )); + let configuration = datadog::Configuration::new(); + let api = WidgetsAPI::with_config(configuration); + let resp = api + .create_widget(WidgetExperienceType::CCM_REPORTS, body) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_widgets_DeleteWidget.rs b/examples/v2_widgets_DeleteWidget.rs new file mode 100644 index 000000000..aed5fbe3a --- /dev/null +++ b/examples/v2_widgets_DeleteWidget.rs @@ -0,0 +1,22 @@ +// Delete a widget returns "No Content" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_widgets::WidgetsAPI; +use datadog_api_client::datadogV2::model::WidgetExperienceType; +use uuid::Uuid; + +#[tokio::main] +async fn main() { + let configuration = datadog::Configuration::new(); + let api = WidgetsAPI::with_config(configuration); + let resp = api + .delete_widget( + WidgetExperienceType::CCM_REPORTS, + Uuid::parse_str("00000000-0000-0000-0000-000000000000").expect("invalid UUID"), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_widgets_GetWidget.rs b/examples/v2_widgets_GetWidget.rs new file mode 100644 index 000000000..0e5df5d4b --- /dev/null +++ b/examples/v2_widgets_GetWidget.rs @@ -0,0 +1,22 @@ +// Get a widget returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_widgets::WidgetsAPI; +use datadog_api_client::datadogV2::model::WidgetExperienceType; +use uuid::Uuid; + +#[tokio::main] +async fn main() { + let configuration = datadog::Configuration::new(); + let api = WidgetsAPI::with_config(configuration); + let resp = api + .get_widget( + WidgetExperienceType::CCM_REPORTS, + Uuid::parse_str("00000000-0000-0000-0000-000000000000").expect("invalid UUID"), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_widgets_SearchWidgets.rs b/examples/v2_widgets_SearchWidgets.rs new file mode 100644 index 000000000..ff6370764 --- /dev/null +++ b/examples/v2_widgets_SearchWidgets.rs @@ -0,0 +1,22 @@ +// Search widgets returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_widgets::SearchWidgetsOptionalParams; +use datadog_api_client::datadogV2::api_widgets::WidgetsAPI; +use datadog_api_client::datadogV2::model::WidgetExperienceType; + +#[tokio::main] +async fn main() { + let configuration = datadog::Configuration::new(); + let api = WidgetsAPI::with_config(configuration); + let resp = api + .search_widgets( + WidgetExperienceType::CCM_REPORTS, + SearchWidgetsOptionalParams::default(), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_widgets_UpdateWidget.rs b/examples/v2_widgets_UpdateWidget.rs new file mode 100644 index 000000000..3dbd9a092 --- /dev/null +++ b/examples/v2_widgets_UpdateWidget.rs @@ -0,0 +1,36 @@ +// Update a widget returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_widgets::WidgetsAPI; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequest; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequestAttributes; +use datadog_api_client::datadogV2::model::CreateOrUpdateWidgetRequestData; +use datadog_api_client::datadogV2::model::WidgetDefinition; +use datadog_api_client::datadogV2::model::WidgetExperienceType; +use datadog_api_client::datadogV2::model::WidgetType; +use uuid::Uuid; + +#[tokio::main] +async fn main() { + let body = CreateOrUpdateWidgetRequest::new(CreateOrUpdateWidgetRequestData::new( + CreateOrUpdateWidgetRequestAttributes::new(WidgetDefinition::new( + "My Widget".to_string(), + WidgetType::BAR_CHART, + )) + .tags(Some(vec![])), + "widgets".to_string(), + )); + let configuration = datadog::Configuration::new(); + let api = WidgetsAPI::with_config(configuration); + let resp = api + .update_widget( + WidgetExperienceType::CCM_REPORTS, + Uuid::parse_str("00000000-0000-0000-0000-000000000000").expect("invalid UUID"), + body, + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadogV2/api/api_widgets.rs b/src/datadogV2/api/api_widgets.rs new file mode 100644 index 000000000..87a981c55 --- /dev/null +++ b/src/datadogV2/api/api_widgets.rs @@ -0,0 +1,851 @@ +// 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; + +/// SearchWidgetsOptionalParams is a struct for passing parameters to the method [`WidgetsAPI::search_widgets`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct SearchWidgetsOptionalParams { + /// Filter widgets by widget type. + pub filter_widget_type: Option, + /// Filter widgets by the email handle of the creator. + pub filter_creator_handle: Option, + /// Filter to only widgets favorited by the current user. + pub filter_is_favorited: Option, + /// Filter widgets by title (substring match). + pub filter_title: Option, + /// Filter widgets by tags. Format as bracket-delimited CSV, e.g. `[tag1,tag2]`. + pub filter_tags: Option, + /// Sort field for the results. Prefix with `-` for descending order. + /// Allowed values: `title`, `created_at`, `modified_at`. + pub sort: Option, + /// Page number for pagination (0-indexed). + pub page_number: Option, + /// Number of widgets per page. + pub page_size: Option, +} + +impl SearchWidgetsOptionalParams { + /// Filter widgets by widget type. + pub fn filter_widget_type(mut self, value: crate::datadogV2::model::WidgetType) -> Self { + self.filter_widget_type = Some(value); + self + } + /// Filter widgets by the email handle of the creator. + pub fn filter_creator_handle(mut self, value: String) -> Self { + self.filter_creator_handle = Some(value); + self + } + /// Filter to only widgets favorited by the current user. + pub fn filter_is_favorited(mut self, value: bool) -> Self { + self.filter_is_favorited = Some(value); + self + } + /// Filter widgets by title (substring match). + pub fn filter_title(mut self, value: String) -> Self { + self.filter_title = Some(value); + self + } + /// Filter widgets by tags. Format as bracket-delimited CSV, e.g. `[tag1,tag2]`. + pub fn filter_tags(mut self, value: String) -> Self { + self.filter_tags = Some(value); + self + } + /// Sort field for the results. Prefix with `-` for descending order. + /// Allowed values: `title`, `created_at`, `modified_at`. + pub fn sort(mut self, value: String) -> Self { + self.sort = Some(value); + self + } + /// Page number for pagination (0-indexed). + pub fn page_number(mut self, value: i32) -> Self { + self.page_number = Some(value); + self + } + /// Number of widgets per page. + pub fn page_size(mut self, value: i32) -> Self { + self.page_size = Some(value); + self + } +} + +/// CreateWidgetError is a struct for typed errors of method [`WidgetsAPI::create_widget`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CreateWidgetError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// DeleteWidgetError is a struct for typed errors of method [`WidgetsAPI::delete_widget`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DeleteWidgetError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// GetWidgetError is a struct for typed errors of method [`WidgetsAPI::get_widget`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetWidgetError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// SearchWidgetsError is a struct for typed errors of method [`WidgetsAPI::search_widgets`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum SearchWidgetsError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// UpdateWidgetError is a struct for typed errors of method [`WidgetsAPI::update_widget`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UpdateWidgetError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + +/// Create, read, update, and delete saved widgets. Widgets are reusable +/// visualization components stored independently from any dashboard or notebook, +/// partitioned by experience type and identified by a UUID. +#[derive(Debug, Clone)] +pub struct WidgetsAPI { + config: datadog::Configuration, + client: reqwest_middleware::ClientWithMiddleware, +} + +impl Default for WidgetsAPI { + fn default() -> Self { + Self::with_config(datadog::Configuration::default()) + } +} + +impl WidgetsAPI { + 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 } + } + + /// Create a new widget for a given experience type. + pub async fn create_widget( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + body: crate::datadogV2::model::CreateOrUpdateWidgetRequest, + ) -> Result> { + match self + .create_widget_with_http_info(experience_type, 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), + } + } + + /// Create a new widget for a given experience type. + pub async fn create_widget_with_http_info( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + body: crate::datadogV2::model::CreateOrUpdateWidgetRequest, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.create_widget"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/widgets/{experience_type}", + local_configuration.get_operation_host(operation_id), + experience_type = datadog::urlencode(experience_type.to_string()) + ); + 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)) + } + } + + /// Soft-delete a widget by its UUID for a given experience type. + pub async fn delete_widget( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + ) -> Result<(), datadog::Error> { + match self + .delete_widget_with_http_info(experience_type, uuid) + .await + { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Soft-delete a widget by its UUID for a given experience type. + pub async fn delete_widget_with_http_info( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + ) -> Result, datadog::Error> { + let local_configuration = &self.config; + let operation_id = "v2.delete_widget"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/widgets/{experience_type}/{uuid}", + local_configuration.get_operation_host(operation_id), + experience_type = datadog::urlencode(experience_type.to_string()), + uuid = datadog::urlencode(uuid.to_string()) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: None, + }) + } else { + let local_entity: Option = serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + + /// Retrieve a widget by its UUID for a given experience type. + pub async fn get_widget( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + ) -> Result> { + match self.get_widget_with_http_info(experience_type, uuid).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), + } + } + + /// Retrieve a widget by its UUID for a given experience type. + pub async fn get_widget_with_http_info( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.get_widget"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/widgets/{experience_type}/{uuid}", + local_configuration.get_operation_host(operation_id), + experience_type = datadog::urlencode(experience_type.to_string()), + uuid = datadog::urlencode(uuid.to_string()) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("application/json")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + match serde_json::from_str::(&local_content) { + Ok(e) => { + return Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: Some(e), + }) + } + Err(e) => return Err(datadog::Error::Serde(e)), + }; + } else { + let local_entity: Option = serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + + /// Search and list widgets for a given experience type. Supports filtering by widget type, creator, title, and tags, as well as sorting and pagination. + pub async fn search_widgets( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + params: SearchWidgetsOptionalParams, + ) -> Result> + { + match self + .search_widgets_with_http_info(experience_type, 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), + } + } + + /// Search and list widgets for a given experience type. Supports filtering by widget type, creator, title, and tags, as well as sorting and pagination. + pub async fn search_widgets_with_http_info( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + params: SearchWidgetsOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.search_widgets"; + + // unbox and build optional parameters + let filter_widget_type = params.filter_widget_type; + let filter_creator_handle = params.filter_creator_handle; + let filter_is_favorited = params.filter_is_favorited; + let filter_title = params.filter_title; + let filter_tags = params.filter_tags; + let sort = params.sort; + let page_number = params.page_number; + let page_size = params.page_size; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/widgets/{experience_type}", + local_configuration.get_operation_host(operation_id), + experience_type = datadog::urlencode(experience_type.to_string()) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + if let Some(ref local_query_param) = filter_widget_type { + local_req_builder = + local_req_builder.query(&[("filter[widgetType]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = filter_creator_handle { + local_req_builder = local_req_builder + .query(&[("filter[creatorHandle]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = filter_is_favorited { + local_req_builder = + local_req_builder.query(&[("filter[isFavorited]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = filter_title { + local_req_builder = + local_req_builder.query(&[("filter[title]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = filter_tags { + local_req_builder = + local_req_builder.query(&[("filter[tags]", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = sort { + local_req_builder = + local_req_builder.query(&[("sort", &local_query_param.to_string())]); + }; + if let Some(ref local_query_param) = page_number { + local_req_builder = + local_req_builder.query(&[("page[number]", &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)) + } + } + + /// Update a widget by its UUID for a given experience type. This performs a full replacement of the widget definition. + pub async fn update_widget( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + body: crate::datadogV2::model::CreateOrUpdateWidgetRequest, + ) -> Result> { + match self + .update_widget_with_http_info(experience_type, uuid, 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), + } + } + + /// Update a widget by its UUID for a given experience type. This performs a full replacement of the widget definition. + pub async fn update_widget_with_http_info( + &self, + experience_type: crate::datadogV2::model::WidgetExperienceType, + uuid: uuid::Uuid, + body: crate::datadogV2::model::CreateOrUpdateWidgetRequest, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.update_widget"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/widgets/{experience_type}/{uuid}", + local_configuration.get_operation_host(operation_id), + experience_type = datadog::urlencode(experience_type.to_string()), + uuid = datadog::urlencode(uuid.to_string()) + ); + 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("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)) + } + } +} diff --git a/src/datadogV2/api/mod.rs b/src/datadogV2/api/mod.rs index c7bf9a616..7e8f3d0fe 100644 --- a/src/datadogV2/api/mod.rs +++ b/src/datadogV2/api/mod.rs @@ -105,4 +105,5 @@ pub mod api_teams; pub mod api_test_optimization; pub mod api_usage_metering; pub mod api_users; +pub mod api_widgets; pub mod api_workflow_automation; diff --git a/src/datadogV2/mod.rs b/src/datadogV2/mod.rs index 2f24ef070..83e5755e9 100644 --- a/src/datadogV2/mod.rs +++ b/src/datadogV2/mod.rs @@ -106,5 +106,6 @@ pub use self::api::api_teams; pub use self::api::api_test_optimization; pub use self::api::api_usage_metering; pub use self::api::api_users; +pub use self::api::api_widgets; pub use self::api::api_workflow_automation; pub mod model; diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index aa5165ee9..38d71b1ea 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -9148,6 +9148,38 @@ pub mod model_user_update_data; pub use self::model_user_update_data::UserUpdateData; pub mod model_user_update_attributes; pub use self::model_user_update_attributes::UserUpdateAttributes; +pub mod model_widget_experience_type; +pub use self::model_widget_experience_type::WidgetExperienceType; +pub mod model_widget_type; +pub use self::model_widget_type::WidgetType; +pub mod model_widget_list_response; +pub use self::model_widget_list_response::WidgetListResponse; +pub mod model_widget_data; +pub use self::model_widget_data::WidgetData; +pub mod model_widget_attributes; +pub use self::model_widget_attributes::WidgetAttributes; +pub mod model_widget_definition; +pub use self::model_widget_definition::WidgetDefinition; +pub mod model_widget_relationships; +pub use self::model_widget_relationships::WidgetRelationships; +pub mod model_widget_relationship_item; +pub use self::model_widget_relationship_item::WidgetRelationshipItem; +pub mod model_widget_relationship_data; +pub use self::model_widget_relationship_data::WidgetRelationshipData; +pub mod model_widget_included_user; +pub use self::model_widget_included_user::WidgetIncludedUser; +pub mod model_widget_included_user_attributes; +pub use self::model_widget_included_user_attributes::WidgetIncludedUserAttributes; +pub mod model_widget_search_meta; +pub use self::model_widget_search_meta::WidgetSearchMeta; +pub mod model_create_or_update_widget_request; +pub use self::model_create_or_update_widget_request::CreateOrUpdateWidgetRequest; +pub mod model_create_or_update_widget_request_data; +pub use self::model_create_or_update_widget_request_data::CreateOrUpdateWidgetRequestData; +pub mod model_create_or_update_widget_request_attributes; +pub use self::model_create_or_update_widget_request_attributes::CreateOrUpdateWidgetRequestAttributes; +pub mod model_widget_response; +pub use self::model_widget_response::WidgetResponse; pub mod model_create_workflow_request; pub use self::model_create_workflow_request::CreateWorkflowRequest; pub mod model_workflow_data; diff --git a/src/datadogV2/model/model_create_or_update_widget_request.rs b/src/datadogV2/model/model_create_or_update_widget_request.rs new file mode 100644 index 000000000..18ace249b --- /dev/null +++ b/src/datadogV2/model/model_create_or_update_widget_request.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}; + +/// Request body for creating or updating a widget. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateOrUpdateWidgetRequest { + /// Data for creating or updating a widget. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::CreateOrUpdateWidgetRequestData, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateOrUpdateWidgetRequest { + pub fn new( + data: crate::datadogV2::model::CreateOrUpdateWidgetRequestData, + ) -> CreateOrUpdateWidgetRequest { + CreateOrUpdateWidgetRequest { + 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 CreateOrUpdateWidgetRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateOrUpdateWidgetRequestVisitor; + impl<'a> Visitor<'a> for CreateOrUpdateWidgetRequestVisitor { + type Value = CreateOrUpdateWidgetRequest; + + 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 = CreateOrUpdateWidgetRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateOrUpdateWidgetRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_create_or_update_widget_request_attributes.rs b/src/datadogV2/model/model_create_or_update_widget_request_attributes.rs new file mode 100644 index 000000000..2daeda439 --- /dev/null +++ b/src/datadogV2/model/model_create_or_update_widget_request_attributes.rs @@ -0,0 +1,108 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes for creating or updating a widget. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateOrUpdateWidgetRequestAttributes { + /// The definition of a widget, including its type and configuration. + #[serde(rename = "definition")] + pub definition: crate::datadogV2::model::WidgetDefinition, + /// User-defined tags for organizing the widget. + #[serde(rename = "tags", default, with = "::serde_with::rust::double_option")] + pub tags: Option>>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateOrUpdateWidgetRequestAttributes { + pub fn new( + definition: crate::datadogV2::model::WidgetDefinition, + ) -> CreateOrUpdateWidgetRequestAttributes { + CreateOrUpdateWidgetRequestAttributes { + definition, + tags: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn tags(mut self, value: Option>) -> Self { + self.tags = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for CreateOrUpdateWidgetRequestAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateOrUpdateWidgetRequestAttributesVisitor; + impl<'a> Visitor<'a> for CreateOrUpdateWidgetRequestAttributesVisitor { + type Value = CreateOrUpdateWidgetRequestAttributes; + + 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 definition: Option = None; + let mut tags: 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() { + "definition" => { + definition = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "tags" => { + tags = 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 definition = definition.ok_or_else(|| M::Error::missing_field("definition"))?; + + let content = CreateOrUpdateWidgetRequestAttributes { + definition, + tags, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateOrUpdateWidgetRequestAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_create_or_update_widget_request_data.rs b/src/datadogV2/model/model_create_or_update_widget_request_data.rs new file mode 100644 index 000000000..553b270f6 --- /dev/null +++ b/src/datadogV2/model/model_create_or_update_widget_request_data.rs @@ -0,0 +1,107 @@ +// 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 for creating or updating a widget. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct CreateOrUpdateWidgetRequestData { + /// Attributes for creating or updating a widget. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::CreateOrUpdateWidgetRequestAttributes, + /// Widgets resource type. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl CreateOrUpdateWidgetRequestData { + pub fn new( + attributes: crate::datadogV2::model::CreateOrUpdateWidgetRequestAttributes, + type_: String, + ) -> CreateOrUpdateWidgetRequestData { + CreateOrUpdateWidgetRequestData { + attributes, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for CreateOrUpdateWidgetRequestData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct CreateOrUpdateWidgetRequestDataVisitor; + impl<'a> Visitor<'a> for CreateOrUpdateWidgetRequestDataVisitor { + type Value = CreateOrUpdateWidgetRequestData; + + 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::CreateOrUpdateWidgetRequestAttributes, + > = None; + let mut type_: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "attributes" => { + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let attributes = attributes.ok_or_else(|| M::Error::missing_field("attributes"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = CreateOrUpdateWidgetRequestData { + attributes, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(CreateOrUpdateWidgetRequestDataVisitor) + } +} diff --git a/src/datadogV2/model/model_observability_pipeline_splunk_hec_source.rs b/src/datadogV2/model/model_observability_pipeline_splunk_hec_source.rs index 941e331d1..97caaba56 100644 --- a/src/datadogV2/model/model_observability_pipeline_splunk_hec_source.rs +++ b/src/datadogV2/model/model_observability_pipeline_splunk_hec_source.rs @@ -19,6 +19,10 @@ pub struct ObservabilityPipelineSplunkHecSource { /// The unique identifier for this component. Used in other parts of the pipeline to reference this component (for example, as the `input` to downstream components). #[serde(rename = "id")] pub id: String, + /// If `true`, the HEC token is stored in the event's metadata and made available to the Enrichment Table + /// processor and the `splunk_hec` destination for routing or enrichment based on the token. Defaults to `false`. + #[serde(rename = "store_hec_token")] + pub store_hec_token: Option, /// Configuration for enabling TLS encryption between the pipeline component and external services. #[serde(rename = "tls")] pub tls: Option, @@ -40,6 +44,7 @@ impl ObservabilityPipelineSplunkHecSource { ObservabilityPipelineSplunkHecSource { address_key: None, id, + store_hec_token: None, tls: None, type_, additional_properties: std::collections::BTreeMap::new(), @@ -52,6 +57,11 @@ impl ObservabilityPipelineSplunkHecSource { self } + pub fn store_hec_token(mut self, value: bool) -> Self { + self.store_hec_token = Some(value); + self + } + pub fn tls(mut self, value: crate::datadogV2::model::ObservabilityPipelineTls) -> Self { self.tls = Some(value); self @@ -85,6 +95,7 @@ impl<'de> Deserialize<'de> for ObservabilityPipelineSplunkHecSource { { let mut address_key: Option = None; let mut id: Option = None; + let mut store_hec_token: Option = None; let mut tls: Option = None; let mut type_: Option< crate::datadogV2::model::ObservabilityPipelineSplunkHecSourceType, @@ -107,6 +118,13 @@ impl<'de> Deserialize<'de> for ObservabilityPipelineSplunkHecSource { "id" => { id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); } + "store_hec_token" => { + if v.is_null() { + continue; + } + store_hec_token = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } "tls" => { if v.is_null() { continue; @@ -137,6 +155,7 @@ impl<'de> Deserialize<'de> for ObservabilityPipelineSplunkHecSource { let content = ObservabilityPipelineSplunkHecSource { address_key, id, + store_hec_token, tls, type_, additional_properties, diff --git a/src/datadogV2/model/model_widget_attributes.rs b/src/datadogV2/model/model_widget_attributes.rs new file mode 100644 index 000000000..d3140ef9c --- /dev/null +++ b/src/datadogV2/model/model_widget_attributes.rs @@ -0,0 +1,143 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes of a widget resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetAttributes { + /// ISO 8601 timestamp of when the widget was created. + #[serde(rename = "created_at")] + pub created_at: String, + /// The definition of a widget, including its type and configuration. + #[serde(rename = "definition")] + pub definition: crate::datadogV2::model::WidgetDefinition, + /// Will be implemented soon. Currently always returns false. + #[serde(rename = "is_favorited")] + pub is_favorited: bool, + /// ISO 8601 timestamp of when the widget was last modified. + #[serde(rename = "modified_at")] + pub modified_at: String, + /// User-defined tags for organizing widgets. + #[serialize_always] + #[serde(rename = "tags")] + pub tags: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetAttributes { + pub fn new( + created_at: String, + definition: crate::datadogV2::model::WidgetDefinition, + is_favorited: bool, + modified_at: String, + tags: Option>, + ) -> WidgetAttributes { + WidgetAttributes { + created_at, + definition, + is_favorited, + modified_at, + tags, + 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 WidgetAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetAttributesVisitor; + impl<'a> Visitor<'a> for WidgetAttributesVisitor { + type Value = WidgetAttributes; + + 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 definition: Option = None; + let mut is_favorited: Option = None; + let mut modified_at: Option = None; + let mut tags: 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)?); + } + "definition" => { + definition = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "is_favorited" => { + is_favorited = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "modified_at" => { + modified_at = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "tags" => { + tags = 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 definition = definition.ok_or_else(|| M::Error::missing_field("definition"))?; + let is_favorited = + is_favorited.ok_or_else(|| M::Error::missing_field("is_favorited"))?; + let modified_at = + modified_at.ok_or_else(|| M::Error::missing_field("modified_at"))?; + let tags = tags.ok_or_else(|| M::Error::missing_field("tags"))?; + + let content = WidgetAttributes { + created_at, + definition, + is_favorited, + modified_at, + tags, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_data.rs b/src/datadogV2/model/model_widget_data.rs new file mode 100644 index 000000000..6d0ab8d09 --- /dev/null +++ b/src/datadogV2/model/model_widget_data.rs @@ -0,0 +1,134 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// A widget resource object. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetData { + /// Attributes of a widget resource. + #[serde(rename = "attributes")] + pub attributes: crate::datadogV2::model::WidgetAttributes, + /// The unique identifier of the widget. + #[serde(rename = "id")] + pub id: String, + /// Relationships of the widget resource. + #[serde(rename = "relationships")] + pub relationships: Option, + /// Widgets resource type. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetData { + pub fn new( + attributes: crate::datadogV2::model::WidgetAttributes, + id: String, + type_: String, + ) -> WidgetData { + WidgetData { + attributes, + id, + relationships: None, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn relationships(mut self, value: crate::datadogV2::model::WidgetRelationships) -> Self { + self.relationships = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for WidgetData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetDataVisitor; + impl<'a> Visitor<'a> for WidgetDataVisitor { + type Value = WidgetData; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut attributes: Option = None; + let mut id: Option = None; + let mut relationships: 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)?); + } + "relationships" => { + if v.is_null() { + continue; + } + relationships = + 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 = WidgetData { + attributes, + id, + relationships, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetDataVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_definition.rs b/src/datadogV2/model/model_widget_definition.rs new file mode 100644 index 000000000..b1bcc10df --- /dev/null +++ b/src/datadogV2/model/model_widget_definition.rs @@ -0,0 +1,111 @@ +// 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 definition of a widget, including its type and configuration. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetDefinition { + /// The display title of the widget. + #[serde(rename = "title")] + pub title: String, + /// Widget types that are allowed to be stored as individual records. + /// This is not a complete list of dashboard and notebook widget types. + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::WidgetType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetDefinition { + pub fn new(title: String, type_: crate::datadogV2::model::WidgetType) -> WidgetDefinition { + WidgetDefinition { + title, + 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 WidgetDefinition { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetDefinitionVisitor; + impl<'a> Visitor<'a> for WidgetDefinitionVisitor { + type Value = WidgetDefinition; + + 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 title: 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() { + "title" => { + title = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + if let Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::WidgetType::UnparsedObject(_type_) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let title = title.ok_or_else(|| M::Error::missing_field("title"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = WidgetDefinition { + title, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetDefinitionVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_experience_type.rs b/src/datadogV2/model/model_widget_experience_type.rs new file mode 100644 index 000000000..2be12bd52 --- /dev/null +++ b/src/datadogV2/model/model_widget_experience_type.rs @@ -0,0 +1,57 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum WidgetExperienceType { + CCM_REPORTS, + LOGS_REPORTS, + CSV_REPORTS, + PRODUCT_ANALYTICS, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for WidgetExperienceType { + fn to_string(&self) -> String { + match self { + Self::CCM_REPORTS => String::from("ccm_reports"), + Self::LOGS_REPORTS => String::from("logs_reports"), + Self::CSV_REPORTS => String::from("csv_reports"), + Self::PRODUCT_ANALYTICS => String::from("product_analytics"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for WidgetExperienceType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for WidgetExperienceType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "ccm_reports" => Self::CCM_REPORTS, + "logs_reports" => Self::LOGS_REPORTS, + "csv_reports" => Self::CSV_REPORTS, + "product_analytics" => Self::PRODUCT_ANALYTICS, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/src/datadogV2/model/model_widget_included_user.rs b/src/datadogV2/model/model_widget_included_user.rs new file mode 100644 index 000000000..92161f793 --- /dev/null +++ b/src/datadogV2/model/model_widget_included_user.rs @@ -0,0 +1,123 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// A user resource included in the response. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetIncludedUser { + /// Attributes of an included user resource. + #[serde(rename = "attributes")] + pub attributes: Option, + /// The unique identifier of the user. + #[serde(rename = "id")] + pub id: String, + /// Users resource type. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetIncludedUser { + pub fn new(id: String, type_: String) -> WidgetIncludedUser { + WidgetIncludedUser { + attributes: None, + id, + type_, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn attributes( + mut self, + value: crate::datadogV2::model::WidgetIncludedUserAttributes, + ) -> Self { + self.attributes = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for WidgetIncludedUser { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetIncludedUserVisitor; + impl<'a> Visitor<'a> for WidgetIncludedUserVisitor { + type Value = WidgetIncludedUser; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut attributes: Option = + None; + let mut id: Option = None; + let mut type_: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "attributes" => { + if v.is_null() { + continue; + } + attributes = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "id" => { + 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 id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = WidgetIncludedUser { + attributes, + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetIncludedUserVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_included_user_attributes.rs b/src/datadogV2/model/model_widget_included_user_attributes.rs new file mode 100644 index 000000000..e31da36a5 --- /dev/null +++ b/src/datadogV2/model/model_widget_included_user_attributes.rs @@ -0,0 +1,119 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Attributes of an included user resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetIncludedUserAttributes { + /// The email handle of the user. + #[serde(rename = "handle")] + pub handle: Option, + /// The display name of the user. + #[serde(rename = "name", default, with = "::serde_with::rust::double_option")] + pub name: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetIncludedUserAttributes { + pub fn new() -> WidgetIncludedUserAttributes { + WidgetIncludedUserAttributes { + handle: None, + name: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn handle(mut self, value: String) -> Self { + self.handle = Some(value); + self + } + + pub fn name(mut self, value: Option) -> Self { + self.name = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for WidgetIncludedUserAttributes { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for WidgetIncludedUserAttributes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetIncludedUserAttributesVisitor; + impl<'a> Visitor<'a> for WidgetIncludedUserAttributesVisitor { + type Value = WidgetIncludedUserAttributes; + + 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 handle: Option = None; + let mut name: 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() { + "handle" => { + if v.is_null() { + continue; + } + handle = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "name" => { + name = 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 = WidgetIncludedUserAttributes { + handle, + name, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetIncludedUserAttributesVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_list_response.rs b/src/datadogV2/model/model_widget_list_response.rs new file mode 100644 index 000000000..91c199a9b --- /dev/null +++ b/src/datadogV2/model/model_widget_list_response.rs @@ -0,0 +1,126 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Response containing a list of widgets. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetListResponse { + /// List of widget resources. + #[serde(rename = "data")] + pub data: Vec, + /// Array of user resources related to the widgets. + #[serde(rename = "included")] + pub included: Option>, + /// Metadata about the search results. + #[serde(rename = "meta")] + pub meta: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetListResponse { + pub fn new(data: Vec) -> WidgetListResponse { + WidgetListResponse { + data, + included: None, + meta: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn included(mut self, value: Vec) -> Self { + self.included = Some(value); + self + } + + pub fn meta(mut self, value: crate::datadogV2::model::WidgetSearchMeta) -> Self { + self.meta = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for WidgetListResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetListResponseVisitor; + impl<'a> Visitor<'a> for WidgetListResponseVisitor { + type Value = WidgetListResponse; + + 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 included: Option> = None; + let mut meta: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "data" => { + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "included" => { + if v.is_null() { + continue; + } + included = 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 data = data.ok_or_else(|| M::Error::missing_field("data"))?; + + let content = WidgetListResponse { + data, + included, + meta, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetListResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_relationship_data.rs b/src/datadogV2/model/model_widget_relationship_data.rs new file mode 100644 index 000000000..7818c6a05 --- /dev/null +++ b/src/datadogV2/model/model_widget_relationship_data.rs @@ -0,0 +1,102 @@ +// 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}; + +/// Relationship data referencing a user resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetRelationshipData { + /// The unique identifier of the user. + #[serde(rename = "id")] + pub id: String, + /// Users resource type. + #[serde(rename = "type")] + pub type_: String, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetRelationshipData { + pub fn new(id: String, type_: String) -> WidgetRelationshipData { + WidgetRelationshipData { + 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 WidgetRelationshipData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetRelationshipDataVisitor; + impl<'a> Visitor<'a> for WidgetRelationshipDataVisitor { + type Value = WidgetRelationshipData; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut id: Option = None; + let mut type_: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "id" => { + id = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "type" => { + type_ = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + let id = id.ok_or_else(|| M::Error::missing_field("id"))?; + let type_ = type_.ok_or_else(|| M::Error::missing_field("type_"))?; + + let content = WidgetRelationshipData { + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetRelationshipDataVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_relationship_item.rs b/src/datadogV2/model/model_widget_relationship_item.rs new file mode 100644 index 000000000..76ecfbf76 --- /dev/null +++ b/src/datadogV2/model/model_widget_relationship_item.rs @@ -0,0 +1,105 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// A JSON:API relationship to a user. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetRelationshipItem { + /// Relationship data referencing a user resource. + #[serde(rename = "data")] + pub data: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetRelationshipItem { + pub fn new() -> WidgetRelationshipItem { + WidgetRelationshipItem { + data: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn data(mut self, value: crate::datadogV2::model::WidgetRelationshipData) -> Self { + self.data = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for WidgetRelationshipItem { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for WidgetRelationshipItem { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetRelationshipItemVisitor; + impl<'a> Visitor<'a> for WidgetRelationshipItemVisitor { + type Value = WidgetRelationshipItem; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut data: Option = None; + let mut additional_properties: std::collections::BTreeMap< + String, + serde_json::Value, + > = std::collections::BTreeMap::new(); + let mut _unparsed = false; + + while let Some((k, v)) = map.next_entry::()? { + match k.as_str() { + "data" => { + if v.is_null() { + continue; + } + data = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + &_ => { + if let Ok(value) = serde_json::from_value(v.clone()) { + additional_properties.insert(k, value); + } + } + } + } + + let content = WidgetRelationshipItem { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetRelationshipItemVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_relationships.rs b/src/datadogV2/model/model_widget_relationships.rs new file mode 100644 index 000000000..3b1ba61fb --- /dev/null +++ b/src/datadogV2/model/model_widget_relationships.rs @@ -0,0 +1,123 @@ +// 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}; + +/// Relationships of the widget resource. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetRelationships { + /// A JSON:API relationship to a user. + #[serde(rename = "created_by")] + pub created_by: Option, + /// A JSON:API relationship to a user. + #[serde(rename = "modified_by")] + pub modified_by: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetRelationships { + pub fn new() -> WidgetRelationships { + WidgetRelationships { + created_by: None, + modified_by: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn created_by(mut self, value: crate::datadogV2::model::WidgetRelationshipItem) -> Self { + self.created_by = Some(value); + self + } + + pub fn modified_by(mut self, value: crate::datadogV2::model::WidgetRelationshipItem) -> Self { + self.modified_by = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for WidgetRelationships { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for WidgetRelationships { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetRelationshipsVisitor; + impl<'a> Visitor<'a> for WidgetRelationshipsVisitor { + type Value = WidgetRelationships; + + 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_by: Option = None; + let mut modified_by: 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_by" => { + if v.is_null() { + continue; + } + created_by = Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "modified_by" => { + if v.is_null() { + continue; + } + modified_by = + 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 = WidgetRelationships { + created_by, + modified_by, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetRelationshipsVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_response.rs b/src/datadogV2/model/model_widget_response.rs new file mode 100644 index 000000000..ec2d32549 --- /dev/null +++ b/src/datadogV2/model/model_widget_response.rs @@ -0,0 +1,109 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Response containing a single widget. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetResponse { + /// A widget resource object. + #[serde(rename = "data")] + pub data: crate::datadogV2::model::WidgetData, + /// Array of user resources related to the widget. + #[serde(rename = "included")] + pub included: Option>, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetResponse { + pub fn new(data: crate::datadogV2::model::WidgetData) -> WidgetResponse { + WidgetResponse { + data, + included: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn included(mut self, value: Vec) -> Self { + self.included = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl<'de> Deserialize<'de> for WidgetResponse { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetResponseVisitor; + impl<'a> Visitor<'a> for WidgetResponseVisitor { + type Value = WidgetResponse; + + 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 included: 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)?); + } + "included" => { + if v.is_null() { + continue; + } + included = 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 = WidgetResponse { + data, + included, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetResponseVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_search_meta.rs b/src/datadogV2/model/model_widget_search_meta.rs new file mode 100644 index 000000000..462e5678c --- /dev/null +++ b/src/datadogV2/model/model_widget_search_meta.rs @@ -0,0 +1,160 @@ +// 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}; + +/// Metadata about the search results. +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct WidgetSearchMeta { + /// Total number of widgets created by anyone. + #[serde(rename = "created_by_anyone_total")] + pub created_by_anyone_total: Option, + /// Total number of widgets created by the current user. + #[serde(rename = "created_by_you_total")] + pub created_by_you_total: Option, + /// Total number of widgets favorited by the current user. + #[serde(rename = "favorited_by_you_total")] + pub favorited_by_you_total: Option, + /// Total number of widgets matching the current filter criteria. + #[serde(rename = "filtered_total")] + pub filtered_total: Option, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl WidgetSearchMeta { + pub fn new() -> WidgetSearchMeta { + WidgetSearchMeta { + created_by_anyone_total: None, + created_by_you_total: None, + favorited_by_you_total: None, + filtered_total: None, + additional_properties: std::collections::BTreeMap::new(), + _unparsed: false, + } + } + + pub fn created_by_anyone_total(mut self, value: i64) -> Self { + self.created_by_anyone_total = Some(value); + self + } + + pub fn created_by_you_total(mut self, value: i64) -> Self { + self.created_by_you_total = Some(value); + self + } + + pub fn favorited_by_you_total(mut self, value: i64) -> Self { + self.favorited_by_you_total = Some(value); + self + } + + pub fn filtered_total(mut self, value: i64) -> Self { + self.filtered_total = Some(value); + self + } + + pub fn additional_properties( + mut self, + value: std::collections::BTreeMap, + ) -> Self { + self.additional_properties = value; + self + } +} + +impl Default for WidgetSearchMeta { + fn default() -> Self { + Self::new() + } +} + +impl<'de> Deserialize<'de> for WidgetSearchMeta { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct WidgetSearchMetaVisitor; + impl<'a> Visitor<'a> for WidgetSearchMetaVisitor { + type Value = WidgetSearchMeta; + + 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_by_anyone_total: Option = None; + let mut created_by_you_total: Option = None; + let mut favorited_by_you_total: Option = None; + let mut filtered_total: 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_by_anyone_total" => { + if v.is_null() { + continue; + } + created_by_anyone_total = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "created_by_you_total" => { + if v.is_null() { + continue; + } + created_by_you_total = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "favorited_by_you_total" => { + if v.is_null() { + continue; + } + favorited_by_you_total = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "filtered_total" => { + if v.is_null() { + continue; + } + filtered_total = + 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 = WidgetSearchMeta { + created_by_anyone_total, + created_by_you_total, + favorited_by_you_total, + filtered_total, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(WidgetSearchMetaVisitor) + } +} diff --git a/src/datadogV2/model/model_widget_type.rs b/src/datadogV2/model/model_widget_type.rs new file mode 100644 index 000000000..3b024e43d --- /dev/null +++ b/src/datadogV2/model/model_widget_type.rs @@ -0,0 +1,90 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum WidgetType { + BAR_CHART, + CHANGE, + CLOUD_COST_SUMMARY, + COHORT, + FUNNEL, + GEOMAP, + LIST_STREAM, + QUERY_TABLE, + QUERY_VALUE, + RETENTION_CURVE, + SANKEY, + SUNBURST, + TIMESERIES, + TOPLIST, + TREEMAP, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for WidgetType { + fn to_string(&self) -> String { + match self { + Self::BAR_CHART => String::from("bar_chart"), + Self::CHANGE => String::from("change"), + Self::CLOUD_COST_SUMMARY => String::from("cloud_cost_summary"), + Self::COHORT => String::from("cohort"), + Self::FUNNEL => String::from("funnel"), + Self::GEOMAP => String::from("geomap"), + Self::LIST_STREAM => String::from("list_stream"), + Self::QUERY_TABLE => String::from("query_table"), + Self::QUERY_VALUE => String::from("query_value"), + Self::RETENTION_CURVE => String::from("retention_curve"), + Self::SANKEY => String::from("sankey"), + Self::SUNBURST => String::from("sunburst"), + Self::TIMESERIES => String::from("timeseries"), + Self::TOPLIST => String::from("toplist"), + Self::TREEMAP => String::from("treemap"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for WidgetType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + Self::UnparsedObject(v) => v.serialize(serializer), + _ => serializer.serialize_str(self.to_string().as_str()), + } + } +} + +impl<'de> Deserialize<'de> for WidgetType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "bar_chart" => Self::BAR_CHART, + "change" => Self::CHANGE, + "cloud_cost_summary" => Self::CLOUD_COST_SUMMARY, + "cohort" => Self::COHORT, + "funnel" => Self::FUNNEL, + "geomap" => Self::GEOMAP, + "list_stream" => Self::LIST_STREAM, + "query_table" => Self::QUERY_TABLE, + "query_value" => Self::QUERY_VALUE, + "retention_curve" => Self::RETENTION_CURVE, + "sankey" => Self::SANKEY, + "sunburst" => Self::SUNBURST, + "timeseries" => Self::TIMESERIES, + "toplist" => Self::TOPLIST, + "treemap" => Self::TREEMAP, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 67596e358..c19cdf545 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -6356,6 +6356,47 @@ "type": "safe" } }, + "SearchWidgets": { + "tag": "Widgets", + "undo": { + "type": "safe" + } + }, + "CreateWidget": { + "tag": "Widgets", + "undo": { + "operationId": "DeleteWidget", + "parameters": [ + { + "name": "experience_type", + "source": "experience_type" + }, + { + "name": "uuid", + "source": "data.id" + } + ], + "type": "unsafe" + } + }, + "DeleteWidget": { + "tag": "Widgets", + "undo": { + "type": "idempotent" + } + }, + "GetWidget": { + "tag": "Widgets", + "undo": { + "type": "safe" + } + }, + "UpdateWidget": { + "tag": "Widgets", + "undo": { + "type": "safe" + } + }, "CreateWorkflow": { "tag": "Workflow Automation", "undo": { diff --git a/tests/scenarios/features/v2/widgets.feature b/tests/scenarios/features/v2/widgets.feature new file mode 100644 index 000000000..54b015711 --- /dev/null +++ b/tests/scenarios/features/v2/widgets.feature @@ -0,0 +1,115 @@ +@endpoint(widgets) @endpoint(widgets-v2) +Feature: Widgets + Create, read, update, and delete saved widgets. Widgets are reusable + visualization components stored independently from any dashboard or + notebook, partitioned by experience type and identified by a UUID. + + Background: + Given a valid "apiKeyAuth" key in the system + And a valid "appKeyAuth" key in the system + And an instance of "Widgets" API + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Create a widget returns "Bad Request" response + Given new "CreateWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"definition": {"title": "My Widget", "type": "bar_chart"}, "tags": []}, "type": "widgets"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Create a widget returns "OK" response + Given new "CreateWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"definition": {"title": "My Widget", "type": "bar_chart"}, "tags": []}, "type": "widgets"}} + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Delete a widget returns "Bad Request" response + Given new "DeleteWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Delete a widget returns "No Content" response + Given new "DeleteWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 204 No Content + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Delete a widget returns "Not Found" response + Given new "DeleteWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Get a widget returns "Bad Request" response + Given new "GetWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Get a widget returns "Not Found" response + Given new "GetWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Get a widget returns "OK" response + Given new "GetWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Search widgets returns "Bad Request" response + Given new "SearchWidgets" request + And request contains "experience_type" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Search widgets returns "OK" response + Given new "SearchWidgets" request + And request contains "experience_type" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Update a widget returns "Bad Request" response + Given new "UpdateWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"definition": {"title": "My Widget", "type": "bar_chart"}, "tags": []}, "type": "widgets"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Update a widget returns "Not Found" response + Given new "UpdateWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"definition": {"title": "My Widget", "type": "bar_chart"}, "tags": []}, "type": "widgets"}} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/reporting-and-sharing + Scenario: Update a widget returns "OK" response + Given new "UpdateWidget" request + And request contains "experience_type" parameter from "REPLACE.ME" + And request contains "uuid" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"definition": {"title": "My Widget", "type": "bar_chart"}, "tags": []}, "type": "widgets"}} + When the request is sent + Then the response status is 200 OK diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index e185a12f4..931c10ac6 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -183,6 +183,7 @@ pub struct ApiInstances { pub v2_api_teams: Option, pub v2_api_incident_teams: Option, pub v2_api_users: Option, + pub v2_api_widgets: Option, pub v2_api_workflow_automation: Option, } @@ -1164,6 +1165,13 @@ pub fn initialize_api_instance(world: &mut DatadogWorld, api: String) { ), ); } + "Widgets" => { + world.api_instances.v2_api_widgets = + Some(datadogV2::api_widgets::WidgetsAPI::with_client_and_config( + world.config.clone(), + world.http_client.as_ref().unwrap().clone(), + )); + } "WorkflowAutomation" => { world.api_instances.v2_api_workflow_automation = Some( datadogV2::api_workflow_automation::WorkflowAutomationAPI::with_client_and_config( @@ -5481,6 +5489,21 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { "v2.ListUserPermissions".into(), test_v2_list_user_permissions, ); + world + .function_mappings + .insert("v2.SearchWidgets".into(), test_v2_search_widgets); + world + .function_mappings + .insert("v2.CreateWidget".into(), test_v2_create_widget); + world + .function_mappings + .insert("v2.DeleteWidget".into(), test_v2_delete_widget); + world + .function_mappings + .insert("v2.GetWidget".into(), test_v2_get_widget); + world + .function_mappings + .insert("v2.UpdateWidget".into(), test_v2_update_widget); world .function_mappings .insert("v2.CreateWorkflow".into(), test_v2_create_workflow); @@ -42758,6 +42781,174 @@ fn test_v2_list_user_permissions(world: &mut DatadogWorld, _parameters: &HashMap world.response.code = response.status.as_u16(); } +fn test_v2_search_widgets(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_widgets + .as_ref() + .expect("api instance not found"); + let experience_type = + serde_json::from_value(_parameters.get("experience_type").unwrap().clone()).unwrap(); + let filter_widget_type = _parameters + .get("filter[widgetType]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let filter_creator_handle = _parameters + .get("filter[creatorHandle]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let filter_is_favorited = _parameters + .get("filter[isFavorited]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let filter_title = _parameters + .get("filter[title]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let filter_tags = _parameters + .get("filter[tags]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let sort = _parameters + .get("sort") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let page_number = _parameters + .get("page[number]") + .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_widgets::SearchWidgetsOptionalParams::default(); + params.filter_widget_type = filter_widget_type; + params.filter_creator_handle = filter_creator_handle; + params.filter_is_favorited = filter_is_favorited; + params.filter_title = filter_title; + params.filter_tags = filter_tags; + params.sort = sort; + params.page_number = page_number; + params.page_size = page_size; + let response = match block_on(api.search_widgets_with_http_info(experience_type, 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_create_widget(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_widgets + .as_ref() + .expect("api instance not found"); + let experience_type = + serde_json::from_value(_parameters.get("experience_type").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = match block_on(api.create_widget_with_http_info(experience_type, 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_delete_widget(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_widgets + .as_ref() + .expect("api instance not found"); + let experience_type = + serde_json::from_value(_parameters.get("experience_type").unwrap().clone()).unwrap(); + let uuid = serde_json::from_value(_parameters.get("uuid").unwrap().clone()).unwrap(); + let response = match block_on(api.delete_widget_with_http_info(experience_type, uuid)) { + 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_widget(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_widgets + .as_ref() + .expect("api instance not found"); + let experience_type = + serde_json::from_value(_parameters.get("experience_type").unwrap().clone()).unwrap(); + let uuid = serde_json::from_value(_parameters.get("uuid").unwrap().clone()).unwrap(); + let response = match block_on(api.get_widget_with_http_info(experience_type, uuid)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + +fn test_v2_update_widget(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_widgets + .as_ref() + .expect("api instance not found"); + let experience_type = + serde_json::from_value(_parameters.get("experience_type").unwrap().clone()).unwrap(); + let uuid = serde_json::from_value(_parameters.get("uuid").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = match block_on(api.update_widget_with_http_info(experience_type, uuid, 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_create_workflow(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances