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")]
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<crate::models::AccountType>,
50}
51
52#[cfg(feature = "clap")]
53impl CreateEngagementClapParams {
54 pub async fn execute(
55 self,
56 configuration: &configuration::Configuration,
57 ) -> Result<crate::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(crate::models::Error),
76 Status404(crate::models::Error),
77 Status422(crate::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<crate::models::AccountType>,
88) -> Result<crate::models::EngagementWithCredentials, Error<CreateEngagementError>> {
89 let local_var_configuration = configuration;
90
91 let local_var_client = &local_var_configuration.client;
92
93 let local_var_uri_str = format!(
94 "{}/v1/engagements",
95 local_var_configuration.qcs_config.api_url()
96 );
97 let mut local_var_req_builder =
98 local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
99
100 #[cfg(feature = "tracing")]
101 {
102 let local_var_do_tracing = local_var_uri_str
105 .parse::<::url::Url>()
106 .ok()
107 .is_none_or(|url| {
108 configuration
109 .qcs_config
110 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
111 });
112
113 if local_var_do_tracing {
114 ::tracing::debug!(
115 url=%local_var_uri_str,
116 method="POST",
117 "making create_engagement request",
118 );
119 }
120 }
121
122 if let Some(local_var_param_value) = x_qcs_account_id {
123 local_var_req_builder =
124 local_var_req_builder.header("x-qcs-account-id", local_var_param_value.to_string());
125 }
126 if let Some(local_var_param_value) = x_qcs_account_type {
127 local_var_req_builder =
128 local_var_req_builder.header("x-qcs-account-type", local_var_param_value.to_string());
129 }
130
131 {
134 use qcs_api_client_common::configuration::TokenError;
135
136 #[allow(
137 clippy::nonminimal_bool,
138 clippy::eq_op,
139 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
140 )]
141 let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
142
143 let token = local_var_configuration
144 .qcs_config
145 .get_bearer_access_token()
146 .await;
147
148 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
149 #[cfg(feature = "tracing")]
151 tracing::debug!(
152 "No client credentials found, but this call does not require authentication."
153 );
154 } else {
155 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
156 }
157 }
158
159 local_var_req_builder = local_var_req_builder.json(&create_engagement_request);
160
161 let local_var_req = local_var_req_builder.build()?;
162 let local_var_resp = local_var_client.execute(local_var_req).await?;
163
164 let local_var_status = local_var_resp.status();
165
166 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
167 let local_var_content = local_var_resp.text().await?;
168 serde_json::from_str(&local_var_content).map_err(Error::from)
169 } else {
170 let local_var_retry_delay =
171 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
172 let local_var_content = local_var_resp.text().await?;
173 let local_var_entity: Option<CreateEngagementError> =
174 serde_json::from_str(&local_var_content).ok();
175 let local_var_error = ResponseContent {
176 status: local_var_status,
177 content: local_var_content,
178 entity: local_var_entity,
179 retry_delay: local_var_retry_delay,
180 };
181 Err(Error::ResponseError(local_var_error))
182 }
183}
184
185pub async fn create_engagement(
187 configuration: &configuration::Configuration,
188 create_engagement_request: crate::models::CreateEngagementRequest,
189 x_qcs_account_id: Option<&str>,
190 x_qcs_account_type: Option<crate::models::AccountType>,
191) -> Result<crate::models::EngagementWithCredentials, Error<CreateEngagementError>> {
192 let mut backoff = configuration.backoff.clone();
193 let mut refreshed_credentials = false;
194 let method = reqwest::Method::POST;
195 loop {
196 let result = create_engagement_inner(
197 configuration,
198 &mut backoff,
199 create_engagement_request.clone(),
200 x_qcs_account_id.clone(),
201 x_qcs_account_type.clone(),
202 )
203 .await;
204
205 match result {
206 Ok(result) => return Ok(result),
207 Err(Error::ResponseError(response)) => {
208 if !refreshed_credentials
209 && matches!(
210 response.status,
211 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
212 )
213 {
214 configuration.qcs_config.refresh().await?;
215 refreshed_credentials = true;
216 continue;
217 } else if let Some(duration) = response.retry_delay {
218 tokio::time::sleep(duration).await;
219 continue;
220 }
221
222 return Err(Error::ResponseError(response));
223 }
224 Err(Error::Reqwest(error)) => {
225 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
226 tokio::time::sleep(duration).await;
227 continue;
228 }
229
230 return Err(Error::Reqwest(error));
231 }
232 Err(Error::Io(error)) => {
233 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
234 tokio::time::sleep(duration).await;
235 continue;
236 }
237
238 return Err(Error::Io(error));
239 }
240 Err(error) => return Err(error),
241 }
242 }
243}