qcs_api_client_openapi/apis/
engagements_api.rs1use super::{configuration, ContentType, Error};
26use crate::{apis::ResponseContent, models};
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")]
36#[allow(unused, reason = "not used in all templates, but required in some")]
37use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
38
39#[cfg(feature = "clap")]
41#[derive(Debug, clap::Args)]
42pub struct CreateEngagementClapParams {
43 pub create_engagement_request: JsonMaybeStdin<crate::models::CreateEngagementRequest>,
44 #[arg(long)]
46 pub x_qcs_account_id: Option<String>,
47 #[arg(long)]
49 pub x_qcs_account_type: Option<models::AccountType>,
50}
51
52#[cfg(feature = "clap")]
53impl CreateEngagementClapParams {
54 pub async fn execute(
55 self,
56 configuration: &configuration::Configuration,
57 ) -> Result<models::EngagementWithCredentials, miette::Error> {
58 let request = self.create_engagement_request.into_inner().into_inner();
59
60 create_engagement(
61 configuration,
62 request,
63 self.x_qcs_account_id.as_deref(),
64 self.x_qcs_account_type,
65 )
66 .await
67 .into_diagnostic()
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73#[serde(untagged)]
74pub enum CreateEngagementError {
75 Status400(models::Error),
76 Status404(models::Error),
77 Status422(models::Error),
78 Status503(),
79 UnknownValue(serde_json::Value),
80}
81
82async fn create_engagement_inner(
83 configuration: &configuration::Configuration,
84 backoff: &mut ExponentialBackoff,
85 create_engagement_request: crate::models::CreateEngagementRequest,
86 x_qcs_account_id: Option<&str>,
87 x_qcs_account_type: Option<models::AccountType>,
88) -> Result<models::EngagementWithCredentials, Error<CreateEngagementError>> {
89 let local_var_configuration = configuration;
90 let p_body_create_engagement_request = create_engagement_request;
92 let p_header_x_qcs_account_id = x_qcs_account_id;
93 let p_header_x_qcs_account_type = x_qcs_account_type;
94
95 let local_var_client = &local_var_configuration.client;
96
97 let local_var_uri_str = format!(
98 "{}/v1/engagements",
99 local_var_configuration.qcs_config.api_url()
100 );
101 let mut local_var_req_builder =
102 local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
103
104 #[cfg(feature = "tracing")]
105 {
106 let local_var_do_tracing = local_var_uri_str
109 .parse::<::url::Url>()
110 .ok()
111 .is_none_or(|url| {
112 configuration
113 .qcs_config
114 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
115 });
116
117 if local_var_do_tracing {
118 ::tracing::debug!(
119 url=%local_var_uri_str,
120 method="POST",
121 "making create_engagement request",
122 );
123 }
124 }
125
126 if let Some(local_var_param_value) = p_header_x_qcs_account_id {
127 local_var_req_builder =
128 local_var_req_builder.header("x-qcs-account-id", local_var_param_value.to_string());
129 }
130 if let Some(local_var_param_value) = p_header_x_qcs_account_type {
131 local_var_req_builder =
132 local_var_req_builder.header("x-qcs-account-type", local_var_param_value.to_string());
133 }
134
135 {
138 use qcs_api_client_common::configuration::TokenError;
139
140 #[allow(
141 clippy::nonminimal_bool,
142 clippy::eq_op,
143 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
144 )]
145 let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
146
147 let token = local_var_configuration
148 .qcs_config
149 .get_bearer_access_token()
150 .await;
151
152 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
153 #[cfg(feature = "tracing")]
155 tracing::debug!(
156 "No client credentials found, but this call does not require authentication."
157 );
158 } else {
159 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
160 }
161 }
162
163 local_var_req_builder = local_var_req_builder.json(&p_body_create_engagement_request);
164
165 let local_var_req = local_var_req_builder.build()?;
166 let local_var_resp = local_var_client.execute(local_var_req).await?;
167
168 let local_var_status = local_var_resp.status();
169 let local_var_raw_content_type = local_var_resp
170 .headers()
171 .get("content-type")
172 .and_then(|v| v.to_str().ok())
173 .unwrap_or("application/octet-stream")
174 .to_string();
175 let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
176
177 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
178 let local_var_content = local_var_resp.text().await?;
179 match local_var_content_type {
180 ContentType::Json => serde_path_to_error::deserialize(
181 &mut serde_json::Deserializer::from_str(&local_var_content),
182 )
183 .map_err(Error::from),
184 ContentType::Text => Err(Error::InvalidContentType {
185 content_type: local_var_raw_content_type,
186 return_type: "models::EngagementWithCredentials",
187 }),
188 ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
189 content_type: unknown_type,
190 return_type: "models::EngagementWithCredentials",
191 }),
192 }
193 } else {
194 let local_var_retry_delay =
195 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
196 let local_var_content = local_var_resp.text().await?;
197 let local_var_entity: Option<CreateEngagementError> =
198 serde_json::from_str(&local_var_content).ok();
199 let local_var_error = ResponseContent {
200 status: local_var_status,
201 content: local_var_content,
202 entity: local_var_entity,
203 retry_delay: local_var_retry_delay,
204 };
205 Err(Error::ResponseError(local_var_error))
206 }
207}
208
209pub async fn create_engagement(
211 configuration: &configuration::Configuration,
212 create_engagement_request: crate::models::CreateEngagementRequest,
213 x_qcs_account_id: Option<&str>,
214 x_qcs_account_type: Option<models::AccountType>,
215) -> Result<models::EngagementWithCredentials, Error<CreateEngagementError>> {
216 let mut backoff = configuration.backoff.clone();
217 let mut refreshed_credentials = false;
218 let method = reqwest::Method::POST;
219 loop {
220 let result = create_engagement_inner(
221 configuration,
222 &mut backoff,
223 create_engagement_request.clone(),
224 x_qcs_account_id.clone(),
225 x_qcs_account_type.clone(),
226 )
227 .await;
228
229 match result {
230 Ok(result) => return Ok(result),
231 Err(Error::ResponseError(response)) => {
232 if !refreshed_credentials
233 && matches!(
234 response.status,
235 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
236 )
237 {
238 configuration.qcs_config.refresh().await?;
239 refreshed_credentials = true;
240 continue;
241 } else if let Some(duration) = response.retry_delay {
242 tokio::time::sleep(duration).await;
243 continue;
244 }
245
246 return Err(Error::ResponseError(response));
247 }
248 Err(Error::Reqwest(error)) => {
249 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
250 tokio::time::sleep(duration).await;
251 continue;
252 }
253
254 return Err(Error::Reqwest(error));
255 }
256 Err(Error::Io(error)) => {
257 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
258 tokio::time::sleep(duration).await;
259 continue;
260 }
261
262 return Err(Error::Io(error));
263 }
264 Err(error) => return Err(error),
265 }
266 }
267}