diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 329c0e696..9cf7a6300 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -61011,6 +61011,35 @@ paths: tags: - Error Tracking /api/v2/error-tracking/issues/{issue_id}/assignee: + delete: + description: Remove the assignee of an issue by `issue_id`. + operationId: DeleteIssueAssignee + parameters: + - $ref: '#/components/parameters/IssueIDPathParameter' + responses: + '204': + description: No Content + '400': + $ref: '#/components/responses/BadRequestResponse' + '401': + $ref: '#/components/responses/UnauthorizedResponse' + '403': + $ref: '#/components/responses/ForbiddenResponse' + '404': + $ref: '#/components/responses/NotFoundResponse' + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - error_tracking_read + - error_tracking_write + - cases_read + - cases_write + summary: Remove the assignee of an issue + tags: + - Error Tracking put: description: Update the assignee of an issue by `issue_id`. operationId: UpdateIssueAssignee diff --git a/examples/v2_error-tracking_DeleteIssueAssignee.rs b/examples/v2_error-tracking_DeleteIssueAssignee.rs new file mode 100644 index 000000000..531fa4e87 --- /dev/null +++ b/examples/v2_error-tracking_DeleteIssueAssignee.rs @@ -0,0 +1,17 @@ +// Remove the assignee of an issue returns "No Content" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_error_tracking::ErrorTrackingAPI; + +#[tokio::main] +async fn main() { + // there is a valid "issue" in the system + let issue_id = std::env::var("ISSUE_ID").unwrap(); + let configuration = datadog::Configuration::new(); + let api = ErrorTrackingAPI::with_config(configuration); + let resp = api.delete_issue_assignee(issue_id.clone()).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadogV2/api/api_error_tracking.rs b/src/datadogV2/api/api_error_tracking.rs index d1ecd9320..8fbacd4d9 100644 --- a/src/datadogV2/api/api_error_tracking.rs +++ b/src/datadogV2/api/api_error_tracking.rs @@ -48,6 +48,14 @@ impl SearchIssuesOptionalParams { } } +/// DeleteIssueAssigneeError is a struct for typed errors of method [`ErrorTrackingAPI::delete_issue_assignee`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DeleteIssueAssigneeError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// GetIssueError is a struct for typed errors of method [`ErrorTrackingAPI::get_issue`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -145,6 +153,94 @@ impl ErrorTrackingAPI { Self { config, client } } + /// Remove the assignee of an issue by `issue_id`. + pub async fn delete_issue_assignee( + &self, + issue_id: String, + ) -> Result<(), datadog::Error> { + match self.delete_issue_assignee_with_http_info(issue_id).await { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Remove the assignee of an issue by `issue_id`. + pub async fn delete_issue_assignee_with_http_info( + &self, + issue_id: String, + ) -> Result, datadog::Error> { + let local_configuration = &self.config; + let operation_id = "v2.delete_issue_assignee"; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/error-tracking/issues/{issue_id}/assignee", + local_configuration.get_operation_host(operation_id), + issue_id = datadog::urlencode(issue_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::DELETE, local_uri_str.as_str()); + + // build headers + let mut headers = HeaderMap::new(); + headers.insert("Accept", HeaderValue::from_static("*/*")); + + // build user agent + match HeaderValue::from_str(local_configuration.user_agent.as_str()) { + Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent), + Err(e) => { + log::warn!("Failed to parse user agent header: {e}, falling back to default"); + headers.insert( + reqwest::header::USER_AGENT, + HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()), + ) + } + }; + + // build auth + if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") { + headers.insert( + "DD-API-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-API-KEY header"), + ); + }; + if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") { + headers.insert( + "DD-APPLICATION-KEY", + HeaderValue::from_str(local_key.key.as_str()) + .expect("failed to parse DD-APPLICATION-KEY header"), + ); + }; + + local_req_builder = local_req_builder.headers(headers); + let local_req = local_req_builder.build()?; + log::debug!("request content: {:?}", local_req.body()); + let local_resp = local_client.execute(local_req).await?; + + let local_status = local_resp.status(); + let local_content = local_resp.text().await?; + log::debug!("response content: {}", local_content); + + if !local_status.is_client_error() && !local_status.is_server_error() { + Ok(datadog::ResponseContent { + status: local_status, + content: local_content, + entity: None, + }) + } else { + let local_entity: Option = + serde_json::from_str(&local_content).ok(); + let local_error = datadog::ResponseContent { + status: local_status, + content: local_content, + entity: local_entity, + }; + Err(datadog::Error::ResponseError(local_error)) + } + } + /// Retrieve the full details for a specific error tracking issue, including attributes and relationships. pub async fn get_issue( &self, diff --git a/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.frozen b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.frozen new file mode 100644 index 000000000..1c36c01bc --- /dev/null +++ b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.frozen @@ -0,0 +1 @@ +2025-10-17T14:43:40.022Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.json b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.json new file mode 100644 index 000000000..14c50b2cf --- /dev/null +++ b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-No-Content-response.json @@ -0,0 +1,63 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"from\":1759416220000,\"query\":\"service:synthetics-browser\",\"to\":1760712220000,\"track\":\"rum\"},\"type\":\"search_request\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/error-tracking/issues/search" + }, + "response": { + "body": { + "string": "{\"data\":[{\"id\":\"d3ab59c6-84ee-11f0-87bb-da7ad0900002\",\"type\":\"error_tracking_search_result\",\"attributes\":{\"impacted_sessions\":4316,\"total_count\":8640},\"relationships\":{\"issue\":{\"data\":{\"id\":\"d3ab59c6-84ee-11f0-87bb-da7ad0900002\",\"type\":\"issue\"}}}},{\"id\":\"a5bb2896-a4d0-11f0-bd76-da7ad0900002\",\"type\":\"error_tracking_search_result\",\"attributes\":{\"impacted_sessions\":280,\"total_count\":272},\"relationships\":{\"issue\":{\"data\":{\"id\":\"a5bb2896-a4d0-11f0-bd76-da7ad0900002\",\"type\":\"issue\"}}}},{\"id\":\"e2a89d14-6f07-11f0-8a88-da7ad0900002\",\"type\":\"error_tracking_search_result\",\"attributes\":{\"impacted_sessions\":1,\"total_count\":4},\"relationships\":{\"issue\":{\"data\":{\"id\":\"e2a89d14-6f07-11f0-8a88-da7ad0900002\",\"type\":\"issue\"}}}},{\"id\":\"5f8ebd5c-6dd9-11f0-8a28-da7ad0900002\",\"type\":\"error_tracking_search_result\",\"attributes\":{\"impacted_sessions\":1,\"total_count\":1},\"relationships\":{\"issue\":{\"data\":{\"id\":\"5f8ebd5c-6dd9-11f0-8a28-da7ad0900002\",\"type\":\"issue\"}}}},{\"id\":\"e2a89134-6f07-11f0-8d36-da7ad0900002\",\"type\":\"error_tracking_search_result\",\"attributes\":{\"impacted_sessions\":1,\"total_count\":1},\"relationships\":{\"issue\":{\"data\":{\"id\":\"e2a89134-6f07-11f0-8d36-da7ad0900002\",\"type\":\"issue\"}}}}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Fri, 17 Oct 2025 14:43:40 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "*/*" + ] + }, + "method": "delete", + "uri": "https://api.datadoghq.com/api/v2/error-tracking/issues/d3ab59c6-84ee-11f0-87bb-da7ad0900002/assignee" + }, + "response": { + "body": { + "string": "", + "encoding": null + }, + "headers": {}, + "status": { + "code": 204, + "message": "No Content" + } + }, + "recorded_at": "Fri, 17 Oct 2025 14:43:40 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.frozen b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.frozen new file mode 100644 index 000000000..ed269c62a --- /dev/null +++ b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.frozen @@ -0,0 +1 @@ +2025-10-17T14:43:41.755Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.json b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.json new file mode 100644 index 000000000..72bac11bd --- /dev/null +++ b/tests/scenarios/cassettes/v2/error_tracking/Remove-the-assignee-of-an-issue-returns-Not-Found-response.json @@ -0,0 +1,33 @@ +{ + "http_interactions": [ + { + "request": { + "body": "", + "headers": { + "Accept": [ + "*/*" + ] + }, + "method": "delete", + "uri": "https://api.datadoghq.com/api/v2/error-tracking/issues/67d80aa3-36ff-44b9-a694-c501a7591737/assignee" + }, + "response": { + "body": { + "string": "{\"errors\":[{\"status\":\"404\",\"title\":\"Not Found\",\"detail\":\"issue not found\"}]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 404, + "message": "Not Found" + } + }, + "recorded_at": "Fri, 17 Oct 2025 14:43:41 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/features/v2/error_tracking.feature b/tests/scenarios/features/v2/error_tracking.feature index 97f8ceeed..253c3b24b 100644 --- a/tests/scenarios/features/v2/error_tracking.feature +++ b/tests/scenarios/features/v2/error_tracking.feature @@ -32,6 +32,28 @@ Feature: Error Tracking Then the response status is 200 OK And the response "data.id" is equal to "{{ issue.id }}" + @generated @skip @team:DataDog/error-tracking + Scenario: Remove the assignee of an issue returns "Bad Request" response + Given new "DeleteIssueAssignee" request + And request contains "issue_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/error-tracking + Scenario: Remove the assignee of an issue returns "No Content" response + Given new "DeleteIssueAssignee" request + And there is a valid "issue" in the system + And request contains "issue_id" parameter from "issue.id" + When the request is sent + Then the response status is 204 No Content + + @team:DataDog/error-tracking + Scenario: Remove the assignee of an issue returns "Not Found" response + Given new "DeleteIssueAssignee" request + And request contains "issue_id" parameter with value "67d80aa3-36ff-44b9-a694-c501a7591737" + When the request is sent + Then the response status is 404 Not Found + @team:DataDog/error-tracking Scenario: Search error tracking issues returns "Bad Request" response Given new "SearchIssues" request diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index f804a3dce..6c74e264b 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -1319,6 +1319,12 @@ "type": "safe" } }, + "DeleteIssueAssignee": { + "tag": "Error Tracking", + "undo": { + "type": "idempotent" + } + }, "UpdateIssueAssignee": { "tag": "Error Tracking", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 76fa07b94..dedc2950b 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -2838,6 +2838,10 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { world .function_mappings .insert("v2.GetIssue".into(), test_v2_get_issue); + world.function_mappings.insert( + "v2.DeleteIssueAssignee".into(), + test_v2_delete_issue_assignee, + ); world.function_mappings.insert( "v2.UpdateIssueAssignee".into(), test_v2_update_issue_assignee, @@ -21008,6 +21012,31 @@ fn test_v2_get_issue(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_error_tracking + .as_ref() + .expect("api instance not found"); + let issue_id = serde_json::from_value(_parameters.get("issue_id").unwrap().clone()).unwrap(); + let response = match block_on(api.delete_issue_assignee_with_http_info(issue_id)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + fn test_v2_update_issue_assignee(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances