qcs_api_client_openapi/apis/
engagements_api.rs1use super::{configuration, Error};
26use crate::apis::ResponseContent;
27use ::qcs_api_client_common::backoff::{
28 duration_from_io_error, duration_from_reqwest_error, duration_from_response, ExponentialBackoff,
29};
30#[cfg(feature = "tracing")]
31use qcs_api_client_common::configuration::tokens::TokenRefresher;
32use reqwest::StatusCode;
33use serde::{Deserialize, Serialize};
34
35#[cfg(feature = "clap")]
37#[derive(Debug, clap::Args)]
38pub struct CreateEngagementClapParams {
39 pub create_engagement_request:
40 crate::clap_utils::JsonMaybeStdin<crate::models::CreateEngagementRequest>,
41 #[arg(long)]
43 pub x_qcs_account_id: Option<String>,
44 #[arg(long)]
46 pub x_qcs_account_type: Option<crate::models::AccountType>,
47}
48
49#[cfg(feature = "clap")]
50impl CreateEngagementClapParams {
51 pub async fn execute(
52 self,
53 configuration: &configuration::Configuration,
54 ) -> Result<crate::models::EngagementWithCredentials, anyhow::Error> {
55 let request = self.create_engagement_request.into_inner().into_inner();
56
57 create_engagement(
58 configuration,
59 request,
60 self.x_qcs_account_id.as_deref(),
61 self.x_qcs_account_type,
62 )
63 .await
64 .map_err(Into::into)
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(untagged)]
71pub enum CreateEngagementError {
72 Status400(crate::models::Error),
73 Status404(crate::models::Error),
74 Status422(crate::models::Error),
75 Status503(),
76 UnknownValue(serde_json::Value),
77}
78
79async fn create_engagement_inner(
80 configuration: &configuration::Configuration,
81 backoff: &mut ExponentialBackoff,
82 create_engagement_request: crate::models::CreateEngagementRequest,
83 x_qcs_account_id: Option<&str>,
84 x_qcs_account_type: Option<crate::models::AccountType>,
85) -> Result<crate::models::EngagementWithCredentials, Error<CreateEngagementError>> {
86 let local_var_configuration = configuration;
87
88 let local_var_client = &local_var_configuration.client;
89
90 let local_var_uri_str = format!(
91 "{}/v1/engagements",
92 local_var_configuration.qcs_config.api_url()
93 );
94 let mut local_var_req_builder =
95 local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
96
97 #[cfg(feature = "tracing")]
98 {
99 let local_var_do_tracing = local_var_uri_str
102 .parse::<::url::Url>()
103 .ok()
104 .is_none_or(|url| {
105 configuration
106 .qcs_config
107 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
108 });
109
110 if local_var_do_tracing {
111 ::tracing::debug!(
112 url=%local_var_uri_str,
113 method="POST",
114 "making create_engagement request",
115 );
116 }
117 }
118
119 if let Some(local_var_param_value) = x_qcs_account_id {
120 local_var_req_builder =
121 local_var_req_builder.header("x-qcs-account-id", local_var_param_value.to_string());
122 }
123 if let Some(local_var_param_value) = x_qcs_account_type {
124 local_var_req_builder =
125 local_var_req_builder.header("x-qcs-account-type", local_var_param_value.to_string());
126 }
127
128 {
131 use qcs_api_client_common::configuration::TokenError;
132
133 #[allow(
134 clippy::nonminimal_bool,
135 clippy::eq_op,
136 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
137 )]
138 let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
139
140 let token = local_var_configuration
141 .qcs_config
142 .get_bearer_access_token()
143 .await;
144
145 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
146 #[cfg(feature = "tracing")]
148 tracing::debug!(
149 "No client credentials found, but this call does not require authentication."
150 );
151 } else {
152 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
153 }
154 }
155
156 local_var_req_builder = local_var_req_builder.json(&create_engagement_request);
157
158 let local_var_req = local_var_req_builder.build()?;
159 let local_var_resp = local_var_client.execute(local_var_req).await?;
160
161 let local_var_status = local_var_resp.status();
162
163 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
164 let local_var_content = local_var_resp.text().await?;
165 serde_json::from_str(&local_var_content).map_err(Error::from)
166 } else {
167 let local_var_retry_delay =
168 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
169 let local_var_content = local_var_resp.text().await?;
170 let local_var_entity: Option<CreateEngagementError> =
171 serde_json::from_str(&local_var_content).ok();
172 let local_var_error = ResponseContent {
173 status: local_var_status,
174 content: local_var_content,
175 entity: local_var_entity,
176 retry_delay: local_var_retry_delay,
177 };
178 Err(Error::ResponseError(local_var_error))
179 }
180}
181
182pub async fn create_engagement(
184 configuration: &configuration::Configuration,
185 create_engagement_request: crate::models::CreateEngagementRequest,
186 x_qcs_account_id: Option<&str>,
187 x_qcs_account_type: Option<crate::models::AccountType>,
188) -> Result<crate::models::EngagementWithCredentials, Error<CreateEngagementError>> {
189 let mut backoff = configuration.backoff.clone();
190 let mut refreshed_credentials = false;
191 let method = reqwest::Method::POST;
192 loop {
193 let result = create_engagement_inner(
194 configuration,
195 &mut backoff,
196 create_engagement_request.clone(),
197 x_qcs_account_id.clone(),
198 x_qcs_account_type.clone(),
199 )
200 .await;
201
202 match result {
203 Ok(result) => return Ok(result),
204 Err(Error::ResponseError(response)) => {
205 if !refreshed_credentials
206 && matches!(
207 response.status,
208 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
209 )
210 {
211 configuration.qcs_config.refresh().await?;
212 refreshed_credentials = true;
213 continue;
214 } else if let Some(duration) = response.retry_delay {
215 tokio::time::sleep(duration).await;
216 continue;
217 }
218
219 return Err(Error::ResponseError(response));
220 }
221 Err(Error::Reqwest(error)) => {
222 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
223 tokio::time::sleep(duration).await;
224 continue;
225 }
226
227 return Err(Error::Reqwest(error));
228 }
229 Err(Error::Io(error)) => {
230 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
231 tokio::time::sleep(duration).await;
232 continue;
233 }
234
235 return Err(Error::Io(error));
236 }
237 Err(error) => return Err(error),
238 }
239 }
240}