diff --git a/.apigentools-info b/.apigentools-info index 1c5c62fa9..8201d23d4 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.6.6", - "regenerated": "2025-05-27 17:12:16.501759", - "spec_repo_commit": "ed439f7c" + "regenerated": "2025-05-27 19:53:20.123557", + "spec_repo_commit": "7131a437" }, "v2": { "apigentools_version": "1.6.6", - "regenerated": "2025-05-27 17:12:16.518477", - "spec_repo_commit": "ed439f7c" + "regenerated": "2025-05-27 19:53:20.139397", + "spec_repo_commit": "7131a437" } } } \ No newline at end of file diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 5c41dee7d..58eefb059 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -2192,6 +2192,14 @@ components: type: string x-enum-varnames: - BILLING_DIMENSIONS + AddMemberTeamRequest: + description: Request to add a member team to super team's hierarchy + properties: + data: + $ref: '#/components/schemas/MemberTeam' + required: + - data + type: object Advisory: description: Advisory. properties: @@ -21003,6 +21011,28 @@ components: - ms_channel_name - redirect_url type: object + MemberTeam: + description: A member team + properties: + id: + description: The member team's identifier + example: aeadc05e-98a8-11ec-ac2c-da7ad0900001 + type: string + type: + $ref: '#/components/schemas/MemberTeamType' + required: + - id + - type + type: object + MemberTeamType: + default: member_teams + description: Member team type + enum: + - member_teams + example: member_teams + type: string + x-enum-varnames: + - MEMBER_TEAMS Metadata: description: The metadata related to this request. properties: @@ -59781,6 +59811,156 @@ paths: permissions: - teams_read - teams_manage + /api/v2/team/{super_team_id}/member_teams: + get: + description: Get all member teams. + operationId: ListMemberTeams + parameters: + - description: None + in: path + name: super_team_id + required: true + schema: + type: string + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/PageNumber' + - description: List of fields that need to be fetched. + explode: false + in: query + name: fields[team] + required: false + schema: + items: + $ref: '#/components/schemas/TeamsField' + type: array + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/TeamsResponse' + description: OK + '403': + $ref: '#/components/responses/ForbiddenResponse' + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: API error response. + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - teams_read + summary: Get all member teams + tags: + - Teams + x-pagination: + limitParam: page[size] + pageParam: page[number] + resultsPath: data + x-permission: + operator: OR + permissions: + - teams_read + x-unstable: '**Note**: This endpoint is in Preview. If you have any feedback, + + contact [Datadog support](https://docs.datadoghq.com/help/).' + post: + description: 'Add a member team. + + Adds the team given by the `id` in the body as a member team of the super + team.' + operationId: AddMemberTeam + parameters: + - description: None + in: path + name: super_team_id + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AddMemberTeamRequest' + required: true + responses: + '204': + description: Added + '403': + $ref: '#/components/responses/ForbiddenResponse' + '409': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: API error response. + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - teams_read + summary: Add a member team + tags: + - Teams + x-permission: + operator: OR + permissions: + - teams_read + x-unstable: '**Note**: This endpoint is in Preview. If you have any feedback, + + contact [Datadog support](https://docs.datadoghq.com/help/).' + /api/v2/team/{super_team_id}/member_teams/{member_team_id}: + delete: + description: Remove a super team's member team identified by `member_team_id`. + operationId: RemoveMemberTeam + parameters: + - description: None + in: path + name: super_team_id + required: true + schema: + type: string + - description: None + in: path + name: member_team_id + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ForbiddenResponse' + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: API error response. + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - teams_read + summary: Remove a member team + tags: + - Teams + x-permission: + operator: OR + permissions: + - teams_read + x-unstable: '**Note**: This endpoint is in Preview. If you have any feedback, + + contact [Datadog support](https://docs.datadoghq.com/help/).' /api/v2/team/{team_id}: delete: description: Remove a team using the team's `id`. diff --git a/examples/v2_teams_AddMemberTeam.rs b/examples/v2_teams_AddMemberTeam.rs new file mode 100644 index 000000000..776142110 --- /dev/null +++ b/examples/v2_teams_AddMemberTeam.rs @@ -0,0 +1,23 @@ +// Add a member team returns "Added" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_teams::TeamsAPI; +use datadog_api_client::datadogV2::model::AddMemberTeamRequest; +use datadog_api_client::datadogV2::model::MemberTeam; +use datadog_api_client::datadogV2::model::MemberTeamType; + +#[tokio::main] +async fn main() { + let body = AddMemberTeamRequest::new(MemberTeam::new( + "aeadc05e-98a8-11ec-ac2c-da7ad0900001".to_string(), + MemberTeamType::MEMBER_TEAMS, + )); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.AddMemberTeam", true); + let api = TeamsAPI::with_config(configuration); + let resp = api.add_member_team("super_team_id".to_string(), body).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_teams_ListMemberTeams.rs b/examples/v2_teams_ListMemberTeams.rs new file mode 100644 index 000000000..21f9c54a9 --- /dev/null +++ b/examples/v2_teams_ListMemberTeams.rs @@ -0,0 +1,22 @@ +// Get all member teams returns "OK" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_teams::ListMemberTeamsOptionalParams; +use datadog_api_client::datadogV2::api_teams::TeamsAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.ListMemberTeams", true); + let api = TeamsAPI::with_config(configuration); + let resp = api + .list_member_teams( + "super_team_id".to_string(), + ListMemberTeamsOptionalParams::default(), + ) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_teams_ListMemberTeams_1662850354.rs b/examples/v2_teams_ListMemberTeams_1662850354.rs new file mode 100644 index 000000000..3887a5c8c --- /dev/null +++ b/examples/v2_teams_ListMemberTeams_1662850354.rs @@ -0,0 +1,25 @@ +// Get all member teams returns "OK" response with pagination +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_teams::ListMemberTeamsOptionalParams; +use datadog_api_client::datadogV2::api_teams::TeamsAPI; +use futures_util::pin_mut; +use futures_util::stream::StreamExt; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.ListMemberTeams", true); + let api = TeamsAPI::with_config(configuration); + let response = api.list_member_teams_with_pagination( + "super_team_id".to_string(), + ListMemberTeamsOptionalParams::default(), + ); + pin_mut!(response); + while let Some(resp) = response.next().await { + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } + } +} diff --git a/examples/v2_teams_RemoveMemberTeam.rs b/examples/v2_teams_RemoveMemberTeam.rs new file mode 100644 index 000000000..8b8497c77 --- /dev/null +++ b/examples/v2_teams_RemoveMemberTeam.rs @@ -0,0 +1,18 @@ +// Remove a member team returns "No Content" response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_teams::TeamsAPI; + +#[tokio::main] +async fn main() { + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.RemoveMemberTeam", true); + let api = TeamsAPI::with_config(configuration); + let resp = api + .remove_member_team("super_team_id".to_string(), "member_team_id".to_string()) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadog/configuration.rs b/src/datadog/configuration.rs index b5f2823e3..c1e5684a8 100644 --- a/src/datadog/configuration.rs +++ b/src/datadog/configuration.rs @@ -202,6 +202,9 @@ impl Default for Configuration { ("v2.create_slo_report_job".to_owned(), false), ("v2.get_slo_report".to_owned(), false), ("v2.get_slo_report_job_status".to_owned(), false), + ("v2.add_member_team".to_owned(), false), + ("v2.list_member_teams".to_owned(), false), + ("v2.remove_member_team".to_owned(), false), ("v2.create_incident_team".to_owned(), false), ("v2.delete_incident_team".to_owned(), false), ("v2.get_incident_team".to_owned(), false), diff --git a/src/datadogV2/api/api_teams.rs b/src/datadogV2/api/api_teams.rs index 5358affd0..f6bdf5a55 100644 --- a/src/datadogV2/api/api_teams.rs +++ b/src/datadogV2/api/api_teams.rs @@ -8,6 +8,7 @@ use flate2::{ Compression, }; use futures_core::stream::Stream; +use log::warn; use reqwest::header::{HeaderMap, HeaderValue}; use serde::{Deserialize, Serialize}; use std::io::Write; @@ -49,6 +50,36 @@ impl GetTeamMembershipsOptionalParams { } } +/// ListMemberTeamsOptionalParams is a struct for passing parameters to the method [`TeamsAPI::list_member_teams`] +#[non_exhaustive] +#[derive(Clone, Default, Debug)] +pub struct ListMemberTeamsOptionalParams { + /// Size for a given page. The maximum allowed value is 100. + pub page_size: Option, + /// Specific page number to return. + pub page_number: Option, + /// List of fields that need to be fetched. + pub fields_team: Option>, +} + +impl ListMemberTeamsOptionalParams { + /// Size for a given page. The maximum allowed value is 100. + pub fn page_size(mut self, value: i64) -> Self { + self.page_size = Some(value); + self + } + /// Specific page number to return. + pub fn page_number(mut self, value: i64) -> Self { + self.page_number = Some(value); + self + } + /// List of fields that need to be fetched. + pub fn fields_team(mut self, value: Vec) -> Self { + self.fields_team = Some(value); + self + } +} + /// ListTeamsOptionalParams is a struct for passing parameters to the method [`TeamsAPI::list_teams`] #[non_exhaustive] #[derive(Clone, Default, Debug)] @@ -107,6 +138,14 @@ impl ListTeamsOptionalParams { } } +/// AddMemberTeamError is a struct for typed errors of method [`TeamsAPI::add_member_team`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum AddMemberTeamError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// CreateTeamError is a struct for typed errors of method [`TeamsAPI::create_team`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -203,6 +242,14 @@ pub enum GetUserMembershipsError { UnknownValue(serde_json::Value), } +/// ListMemberTeamsError is a struct for typed errors of method [`TeamsAPI::list_member_teams`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ListMemberTeamsError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// ListTeamsError is a struct for typed errors of method [`TeamsAPI::list_teams`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -211,6 +258,14 @@ pub enum ListTeamsError { UnknownValue(serde_json::Value), } +/// RemoveMemberTeamError is a struct for typed errors of method [`TeamsAPI::remove_member_team`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum RemoveMemberTeamError { + APIErrorResponse(crate::datadogV2::model::APIErrorResponse), + UnknownValue(serde_json::Value), +} + /// UpdateTeamError is a struct for typed errors of method [`TeamsAPI::update_team`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -308,6 +363,155 @@ impl TeamsAPI { Self { config, client } } + /// Add a member team. + /// Adds the team given by the `id` in the body as a member team of the super team. + pub async fn add_member_team( + &self, + super_team_id: String, + body: crate::datadogV2::model::AddMemberTeamRequest, + ) -> Result<(), datadog::Error> { + match self + .add_member_team_with_http_info(super_team_id, body) + .await + { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Add a member team. + /// Adds the team given by the `id` in the body as a member team of the super team. + pub async fn add_member_team_with_http_info( + &self, + super_team_id: String, + body: crate::datadogV2::model::AddMemberTeamRequest, + ) -> Result, datadog::Error> { + let local_configuration = &self.config; + let operation_id = "v2.add_member_team"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.add_member_team' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/team/{super_team_id}/member_teams", + local_configuration.get_operation_host(operation_id), + super_team_id = datadog::urlencode(super_team_id) + ); + 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("*/*")); + + // 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() { + 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)) + } + } + /// Create a new team. /// User IDs passed through the `users` relationship field are added to the team. pub async fn create_team( @@ -1742,6 +1946,183 @@ impl TeamsAPI { } } + /// Get all member teams. + pub async fn list_member_teams( + &self, + super_team_id: String, + params: ListMemberTeamsOptionalParams, + ) -> Result> { + match self + .list_member_teams_with_http_info(super_team_id, params) + .await + { + Ok(response_content) => { + if let Some(e) = response_content.entity { + Ok(e) + } else { + Err(datadog::Error::Serde(serde::de::Error::custom( + "response content was None", + ))) + } + } + Err(err) => Err(err), + } + } + + pub fn list_member_teams_with_pagination( + &self, + super_team_id: String, + mut params: ListMemberTeamsOptionalParams, + ) -> impl Stream< + Item = Result>, + > + '_ { + try_stream! { + let mut page_size: i64 = 10; + if params.page_size.is_none() { + params.page_size = Some(page_size); + } else { + page_size = params.page_size.unwrap().clone(); + } + if params.page_number.is_none() { + params.page_number = Some(0); + } + loop { + let resp = self.list_member_teams( super_team_id.clone(),params.clone()).await?; + let Some(data) = resp.data else { break }; + + let r = data; + let count = r.len(); + for team in r { + yield team; + } + + if count < page_size as usize { + break; + } + params.page_number = Some(params.page_number.unwrap() + 1); + } + } + } + + /// Get all member teams. + pub async fn list_member_teams_with_http_info( + &self, + super_team_id: String, + params: ListMemberTeamsOptionalParams, + ) -> Result< + datadog::ResponseContent, + datadog::Error, + > { + let local_configuration = &self.config; + let operation_id = "v2.list_member_teams"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.list_member_teams' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + // unbox and build optional parameters + let page_size = params.page_size; + let page_number = params.page_number; + let fields_team = params.fields_team; + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/team/{super_team_id}/member_teams", + local_configuration.get_operation_host(operation_id), + super_team_id = datadog::urlencode(super_team_id) + ); + let mut local_req_builder = + local_client.request(reqwest::Method::GET, local_uri_str.as_str()); + + if let Some(ref local_query_param) = page_size { + local_req_builder = + local_req_builder.query(&[("page[size]", &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) = fields_team { + local_req_builder = local_req_builder.query(&[( + "fields[team]", + &local + .iter() + .map(|p| p.to_string()) + .collect::>() + .join(",") + .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)) + } + } + /// Get all teams. /// Can be used to search for teams using the `filter[keyword]` and `filter[me]` query parameters. pub async fn list_teams( @@ -1925,6 +2306,108 @@ impl TeamsAPI { } } + /// Remove a super team's member team identified by `member_team_id`. + pub async fn remove_member_team( + &self, + super_team_id: String, + member_team_id: String, + ) -> Result<(), datadog::Error> { + match self + .remove_member_team_with_http_info(super_team_id, member_team_id) + .await + { + Ok(_) => Ok(()), + Err(err) => Err(err), + } + } + + /// Remove a super team's member team identified by `member_team_id`. + pub async fn remove_member_team_with_http_info( + &self, + super_team_id: String, + member_team_id: String, + ) -> Result, datadog::Error> { + let local_configuration = &self.config; + let operation_id = "v2.remove_member_team"; + if local_configuration.is_unstable_operation_enabled(operation_id) { + warn!("Using unstable operation {operation_id}"); + } else { + let local_error = datadog::UnstableOperationDisabledError { + msg: "Operation 'v2.remove_member_team' is not enabled".to_string(), + }; + return Err(datadog::Error::UnstableOperationDisabledError(local_error)); + } + + let local_client = &self.client; + + let local_uri_str = format!( + "{}/api/v2/team/{super_team_id}/member_teams/{member_team_id}", + local_configuration.get_operation_host(operation_id), + super_team_id = datadog::urlencode(super_team_id), + member_team_id = datadog::urlencode(member_team_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)) + } + } + /// Update a team using the team's `id`. /// If the `team_links` relationship is present, the associated links are updated to be in the order they appear in the array, and any existing team links not present are removed. pub async fn update_team( diff --git a/src/datadogV2/model/mod.rs b/src/datadogV2/model/mod.rs index f47e2b0ef..423cac271 100644 --- a/src/datadogV2/model/mod.rs +++ b/src/datadogV2/model/mod.rs @@ -4704,6 +4704,12 @@ pub mod model_team_create_relationships; pub use self::model_team_create_relationships::TeamCreateRelationships; pub mod model_team_response; pub use self::model_team_response::TeamResponse; +pub mod model_add_member_team_request; +pub use self::model_add_member_team_request::AddMemberTeamRequest; +pub mod model_member_team; +pub use self::model_member_team::MemberTeam; +pub mod model_member_team_type; +pub use self::model_member_team_type::MemberTeamType; pub mod model_team_update_request; pub use self::model_team_update_request::TeamUpdateRequest; pub mod model_team_update; diff --git a/src/datadogV2/model/model_add_member_team_request.rs b/src/datadogV2/model/model_add_member_team_request.rs new file mode 100644 index 000000000..867b31a76 --- /dev/null +++ b/src/datadogV2/model/model_add_member_team_request.rs @@ -0,0 +1,92 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. +use serde::de::{Error, MapAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_with::skip_serializing_none; +use std::fmt::{self, Formatter}; + +/// Request to add a member team to super team's hierarchy +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct AddMemberTeamRequest { + /// A member team + #[serde(rename = "data")] + pub data: crate::datadogV2::model::MemberTeam, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl AddMemberTeamRequest { + pub fn new(data: crate::datadogV2::model::MemberTeam) -> AddMemberTeamRequest { + AddMemberTeamRequest { + 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 AddMemberTeamRequest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct AddMemberTeamRequestVisitor; + impl<'a> Visitor<'a> for AddMemberTeamRequestVisitor { + type Value = AddMemberTeamRequest; + + 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 = AddMemberTeamRequest { + data, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(AddMemberTeamRequestVisitor) + } +} diff --git a/src/datadogV2/model/model_member_team.rs b/src/datadogV2/model/model_member_team.rs new file mode 100644 index 000000000..216987f24 --- /dev/null +++ b/src/datadogV2/model/model_member_team.rs @@ -0,0 +1,112 @@ +// 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 member team +#[non_exhaustive] +#[skip_serializing_none] +#[derive(Clone, Debug, PartialEq, Serialize)] +pub struct MemberTeam { + /// The member team's identifier + #[serde(rename = "id")] + pub id: String, + /// Member team type + #[serde(rename = "type")] + pub type_: crate::datadogV2::model::MemberTeamType, + #[serde(flatten)] + pub additional_properties: std::collections::BTreeMap, + #[serde(skip)] + #[serde(default)] + pub(crate) _unparsed: bool, +} + +impl MemberTeam { + pub fn new(id: String, type_: crate::datadogV2::model::MemberTeamType) -> MemberTeam { + MemberTeam { + 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 MemberTeam { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct MemberTeamVisitor; + impl<'a> Visitor<'a> for MemberTeamVisitor { + type Value = MemberTeam; + + 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 Some(ref _type_) = type_ { + match _type_ { + crate::datadogV2::model::MemberTeamType::UnparsedObject( + _type_, + ) => { + _unparsed = true; + } + _ => {} + } + } + } + &_ => { + 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 = MemberTeam { + id, + type_, + additional_properties, + _unparsed, + }; + + Ok(content) + } + } + + deserializer.deserialize_any(MemberTeamVisitor) + } +} diff --git a/src/datadogV2/model/model_member_team_type.rs b/src/datadogV2/model/model_member_team_type.rs new file mode 100644 index 000000000..6b19afcbb --- /dev/null +++ b/src/datadogV2/model/model_member_team_type.rs @@ -0,0 +1,48 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[non_exhaustive] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum MemberTeamType { + MEMBER_TEAMS, + UnparsedObject(crate::datadog::UnparsedObject), +} + +impl ToString for MemberTeamType { + fn to_string(&self) -> String { + match self { + Self::MEMBER_TEAMS => String::from("member_teams"), + Self::UnparsedObject(v) => v.value.to_string(), + } + } +} + +impl Serialize for MemberTeamType { + 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 MemberTeamType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: String = String::deserialize(deserializer)?; + Ok(match s.as_str() { + "member_teams" => Self::MEMBER_TEAMS, + _ => Self::UnparsedObject(crate::datadog::UnparsedObject { + value: serde_json::Value::String(s.into()), + }), + }) + } +} diff --git a/tests/scenarios/features/v2/teams.feature b/tests/scenarios/features/v2/teams.feature index 5d4069034..4cdf61f0f 100644 --- a/tests/scenarios/features/v2/teams.feature +++ b/tests/scenarios/features/v2/teams.feature @@ -9,6 +9,24 @@ Feature: Teams And a valid "appKeyAuth" key in the system And an instance of "Teams" API + @generated @skip @team:DataDog/core-app + Scenario: Add a member team returns "API error response." response + Given operation "AddMemberTeam" enabled + And new "AddMemberTeam" request + And request contains "super_team_id" parameter from "REPLACE.ME" + And body with value {"data": {"id": "aeadc05e-98a8-11ec-ac2c-da7ad0900001", "type": "member_teams"}} + When the request is sent + Then the response status is 409 API error response. + + @generated @skip @team:DataDog/core-app + Scenario: Add a member team returns "Added" response + Given operation "AddMemberTeam" enabled + And new "AddMemberTeam" request + And request contains "super_team_id" parameter from "REPLACE.ME" + And body with value {"data": {"id": "aeadc05e-98a8-11ec-ac2c-da7ad0900001", "type": "member_teams"}} + When the request is sent + Then the response status is 204 Added + @generated @skip @team:DataDog/core-app Scenario: Add a user to a team returns "API error response." response Given new "CreateTeamMembership" request @@ -112,6 +130,30 @@ Feature: Teams When the request is sent Then the response status is 200 OK + @generated @skip @team:DataDog/core-app + Scenario: Get all member teams returns "API error response." response + Given operation "ListMemberTeams" enabled + And new "ListMemberTeams" request + And request contains "super_team_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 API error response. + + @generated @skip @team:DataDog/core-app + Scenario: Get all member teams returns "OK" response + Given operation "ListMemberTeams" enabled + And new "ListMemberTeams" request + And request contains "super_team_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/core-app @with-pagination + Scenario: Get all member teams returns "OK" response with pagination + Given operation "ListMemberTeams" enabled + And new "ListMemberTeams" request + And request contains "super_team_id" parameter from "REPLACE.ME" + When the request with pagination is sent + Then the response status is 200 OK + @team:DataDog/core-app Scenario: Get all teams returns "OK" response Given new "ListTeams" request @@ -209,6 +251,24 @@ Feature: Teams Then the response status is 200 Represents a user's association to a team And the response "data" has length 0 + @generated @skip @team:DataDog/core-app + Scenario: Remove a member team returns "API error response." response + Given operation "RemoveMemberTeam" enabled + And new "RemoveMemberTeam" request + And request contains "super_team_id" parameter from "REPLACE.ME" + And request contains "member_team_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 API error response. + + @generated @skip @team:DataDog/core-app + Scenario: Remove a member team returns "No Content" response + Given operation "RemoveMemberTeam" enabled + And new "RemoveMemberTeam" request + And request contains "super_team_id" parameter from "REPLACE.ME" + And request contains "member_team_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 204 No Content + @team:DataDog/core-app Scenario: Remove a team link returns "API error response." response Given new "DeleteTeamLink" request diff --git a/tests/scenarios/features/v2/undo.json b/tests/scenarios/features/v2/undo.json index 69af02feb..67a1f9058 100644 --- a/tests/scenarios/features/v2/undo.json +++ b/tests/scenarios/features/v2/undo.json @@ -3204,6 +3204,25 @@ "type": "unsafe" } }, + "ListMemberTeams": { + "tag": "Teams", + "undo": { + "type": "safe" + } + }, + "AddMemberTeam": { + "tag": "Teams", + "undo": { + "operationId": "RemoveMemberTeam", + "type": "unsafe" + } + }, + "RemoveMemberTeam": { + "tag": "Teams", + "undo": { + "type": "idempotent" + } + }, "DeleteTeam": { "tag": "Teams", "undo": { diff --git a/tests/scenarios/function_mappings.rs b/tests/scenarios/function_mappings.rs index 2225068a5..f7e1de9de 100644 --- a/tests/scenarios/function_mappings.rs +++ b/tests/scenarios/function_mappings.rs @@ -3522,6 +3522,19 @@ pub fn collect_function_calls(world: &mut DatadogWorld) { world .function_mappings .insert("v2.CreateTeam".into(), test_v2_create_team); + world + .function_mappings + .insert("v2.ListMemberTeams".into(), test_v2_list_member_teams); + world.function_mappings.insert( + "v2.ListMemberTeamsWithPagination".into(), + test_v2_list_member_teams_with_pagination, + ); + world + .function_mappings + .insert("v2.AddMemberTeam".into(), test_v2_add_member_team); + world + .function_mappings + .insert("v2.RemoveMemberTeam".into(), test_v2_remove_member_team); world .function_mappings .insert("v2.DeleteTeam".into(), test_v2_delete_team); @@ -27054,6 +27067,152 @@ fn test_v2_create_team(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_teams + .as_ref() + .expect("api instance not found"); + let super_team_id = + serde_json::from_value(_parameters.get("super_team_id").unwrap().clone()).unwrap(); + let page_size = _parameters + .get("page[size]") + .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 fields_team = _parameters + .get("fields[team]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_teams::ListMemberTeamsOptionalParams::default(); + params.page_size = page_size; + params.page_number = page_number; + params.fields_team = fields_team; + let response = match block_on(api.list_member_teams_with_http_info(super_team_id, params)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} +fn test_v2_list_member_teams_with_pagination( + world: &mut DatadogWorld, + _parameters: &HashMap, +) { + let api = world + .api_instances + .v2_api_teams + .as_ref() + .expect("api instance not found"); + let super_team_id = + serde_json::from_value(_parameters.get("super_team_id").unwrap().clone()).unwrap(); + let page_size = _parameters + .get("page[size]") + .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 fields_team = _parameters + .get("fields[team]") + .and_then(|param| Some(serde_json::from_value(param.clone()).unwrap())); + let mut params = datadogV2::api_teams::ListMemberTeamsOptionalParams::default(); + params.page_size = page_size; + params.page_number = page_number; + params.fields_team = fields_team; + let response = api.list_member_teams_with_pagination(super_team_id, params); + let mut result = Vec::new(); + + block_on(async { + pin_mut!(response); + + while let Some(resp) = response.next().await { + match resp { + Ok(response) => { + result.push(response); + } + Err(error) => { + return match error { + Error::ResponseError(e) => { + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {}", error), + }; + } + } + } + }); + world.response.object = serde_json::to_value(result).unwrap(); + world.response.code = 200; +} + +fn test_v2_add_member_team(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_teams + .as_ref() + .expect("api instance not found"); + let super_team_id = + serde_json::from_value(_parameters.get("super_team_id").unwrap().clone()).unwrap(); + let body = serde_json::from_value(_parameters.get("body").unwrap().clone()).unwrap(); + let response = match block_on(api.add_member_team_with_http_info(super_team_id, body)) { + Ok(response) => response, + Err(error) => { + return match error { + Error::ResponseError(e) => { + world.response.code = e.status.as_u16(); + if let Some(entity) = e.entity { + world.response.object = serde_json::to_value(entity).unwrap(); + } + } + _ => panic!("error parsing response: {error}"), + }; + } + }; + world.response.object = serde_json::to_value(response.entity).unwrap(); + world.response.code = response.status.as_u16(); +} + +fn test_v2_remove_member_team(world: &mut DatadogWorld, _parameters: &HashMap) { + let api = world + .api_instances + .v2_api_teams + .as_ref() + .expect("api instance not found"); + let super_team_id = + serde_json::from_value(_parameters.get("super_team_id").unwrap().clone()).unwrap(); + let member_team_id = + serde_json::from_value(_parameters.get("member_team_id").unwrap().clone()).unwrap(); + let response = + match block_on(api.remove_member_team_with_http_info(super_team_id, member_team_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_delete_team(world: &mut DatadogWorld, _parameters: &HashMap) { let api = world .api_instances