1use super::{ContentType, Error, configuration};
26use crate::{apis::ResponseContent, models};
27use ::qcs_api_client_common::backoff::{
28 BackoffBuilder, ExponentialBackoff, duration_from_io_error, duration_from_reqwest_error,
29 duration_from_response,
30};
31#[cfg(feature = "tracing")]
32use qcs_api_client_common::configuration::tokens::TokenRefresher;
33use qcs_dependencies_client::reqwest::{self, StatusCode};
34use serde::{Deserialize, Serialize};
35
36#[cfg(feature = "clap")]
37#[allow(unused, reason = "not used in all templates, but required in some")]
38use ::{miette::IntoDiagnostic as _, qcs_api_client_common::clap_utils::JsonMaybeStdin};
39
40#[cfg(feature = "clap")]
42#[derive(Debug, clap::Args)]
43pub struct GetDefaultEndpointClapParams {
44 #[arg(long)]
45 pub quantum_processor_id: String,
46}
47
48#[cfg(feature = "clap")]
49impl GetDefaultEndpointClapParams {
50 pub async fn execute(
51 self,
52 configuration: &configuration::Configuration,
53 ) -> Result<models::Endpoint, miette::Error> {
54 get_default_endpoint(configuration, self.quantum_processor_id.as_str())
55 .await
56 .into_diagnostic()
57 }
58}
59
60#[cfg(feature = "clap")]
62#[derive(Debug, clap::Args)]
63pub struct GetEndpointClapParams {
64 #[arg(long)]
65 pub endpoint_id: String,
66}
67
68#[cfg(feature = "clap")]
69impl GetEndpointClapParams {
70 pub async fn execute(
71 self,
72 configuration: &configuration::Configuration,
73 ) -> Result<models::Endpoint, miette::Error> {
74 get_endpoint(configuration, self.endpoint_id.as_str())
75 .await
76 .into_diagnostic()
77 }
78}
79
80#[cfg(feature = "clap")]
82#[derive(Debug, clap::Args)]
83pub struct GetEndpointAccessorsClapParams {
84 #[arg(long)]
85 pub endpoint_id: String,
86}
87
88#[cfg(feature = "clap")]
89impl GetEndpointAccessorsClapParams {
90 pub async fn execute(
91 self,
92 configuration: &configuration::Configuration,
93 ) -> Result<models::ListQuantumProcessorAccessorsResponse, miette::Error> {
94 get_endpoint_accessors(configuration, self.endpoint_id.as_str())
95 .await
96 .into_diagnostic()
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(untagged)]
103pub enum GetDefaultEndpointError {
104 Status422(models::ValidationError),
105 DefaultResponse(models::Error),
106 UnknownValue(serde_json::Value),
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111#[serde(untagged)]
112pub enum GetEndpointError {
113 Status422(models::ValidationError),
114 DefaultResponse(models::Error),
115 UnknownValue(serde_json::Value),
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120#[serde(untagged)]
121pub enum GetEndpointAccessorsError {
122 Status422(models::ValidationError),
123 DefaultResponse(models::Error),
124 UnknownValue(serde_json::Value),
125}
126
127async fn get_default_endpoint_inner(
128 configuration: &configuration::Configuration,
129 backoff: &mut ExponentialBackoff,
130 quantum_processor_id: &str,
131) -> Result<models::Endpoint, Error<GetDefaultEndpointError>> {
132 let local_var_configuration = configuration;
133 let p_path_quantum_processor_id = quantum_processor_id;
135
136 let local_var_client = &local_var_configuration.client;
137
138 let local_var_uri_str = format!(
139 "{}/v1/quantumProcessors/{quantumProcessorId}/endpoints:getDefault",
140 local_var_configuration.qcs_config.api_url(),
141 quantumProcessorId = crate::apis::urlencode(p_path_quantum_processor_id)
142 );
143 let mut local_var_req_builder =
144 local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
145
146 #[cfg(feature = "tracing")]
147 {
148 let local_var_do_tracing = local_var_uri_str
151 .parse::<::url::Url>()
152 .ok()
153 .is_none_or(|url| {
154 configuration
155 .qcs_config
156 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
157 });
158
159 if local_var_do_tracing {
160 ::tracing::debug!(
161 url=%local_var_uri_str,
162 method="GET",
163 "making get_default_endpoint request",
164 );
165 }
166 }
167
168 {
171 use qcs_api_client_common::configuration::TokenError;
172
173 #[allow(
174 clippy::nonminimal_bool,
175 clippy::eq_op,
176 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
177 )]
178 let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
179
180 let token = local_var_configuration
181 .qcs_config
182 .get_bearer_access_token()
183 .await;
184
185 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
186 #[cfg(feature = "tracing")]
188 tracing::debug!(
189 "No client credentials found, but this call does not require authentication."
190 );
191 } else {
192 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
193 }
194 }
195
196 let local_var_req = local_var_req_builder.build()?;
197 let local_var_resp = local_var_client.execute(local_var_req).await?;
198
199 let local_var_status = local_var_resp.status();
200 let local_var_raw_content_type = local_var_resp
201 .headers()
202 .get("content-type")
203 .and_then(|v| v.to_str().ok())
204 .unwrap_or("application/octet-stream")
205 .to_string();
206 let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
207
208 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
209 let local_var_content = local_var_resp.text().await?;
210 match local_var_content_type {
211 ContentType::Json => serde_path_to_error::deserialize(
212 &mut serde_json::Deserializer::from_str(&local_var_content),
213 )
214 .map_err(Error::from),
215 ContentType::Text => Err(Error::InvalidContentType {
216 content_type: local_var_raw_content_type,
217 return_type: "models::Endpoint",
218 }),
219 ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
220 content_type: unknown_type,
221 return_type: "models::Endpoint",
222 }),
223 }
224 } else {
225 let local_var_retry_delay =
226 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
227 let local_var_content = local_var_resp.text().await?;
228 let local_var_entity: Option<GetDefaultEndpointError> =
229 serde_json::from_str(&local_var_content).ok();
230 let local_var_error = ResponseContent {
231 status: local_var_status,
232 content: local_var_content,
233 entity: local_var_entity,
234 retry_delay: local_var_retry_delay,
235 };
236 Err(Error::ResponseError(local_var_error))
237 }
238}
239
240pub async fn get_default_endpoint(
242 configuration: &configuration::Configuration,
243 quantum_processor_id: &str,
244) -> Result<models::Endpoint, Error<GetDefaultEndpointError>> {
245 let mut backoff = configuration.backoff.build();
246 let mut refreshed_credentials = false;
247 let method = reqwest::Method::GET;
248 loop {
249 let result =
250 get_default_endpoint_inner(configuration, &mut backoff, quantum_processor_id.clone())
251 .await;
252
253 match result {
254 Ok(result) => return Ok(result),
255 Err(Error::ResponseError(response)) => {
256 if !refreshed_credentials
257 && matches!(
258 response.status,
259 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
260 )
261 {
262 match configuration.qcs_config.refresh().await {
264 Ok(_) => {
265 refreshed_credentials = true;
266 continue;
267 }
268 Err(::qcs_api_client_common::configuration::TokenError::Write {
269 error,
270 oauth_session: _,
271 }) => {
272 #[cfg(feature = "tracing")]
275 tracing::warn!(
276 "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
277 error
278 );
279 refreshed_credentials = true;
280 continue;
281 }
282 Err(e) => return Err(e.into()),
283 }
284 } else if let Some(duration) = response.retry_delay {
285 tokio::time::sleep(duration).await;
286 continue;
287 }
288
289 return Err(Error::ResponseError(response));
290 }
291 Err(Error::Reqwest(error)) => {
292 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
293 tokio::time::sleep(duration).await;
294 continue;
295 }
296
297 return Err(Error::Reqwest(error));
298 }
299 Err(Error::Io(error)) => {
300 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
301 tokio::time::sleep(duration).await;
302 continue;
303 }
304
305 return Err(Error::Io(error));
306 }
307 Err(error) => return Err(error),
308 }
309 }
310}
311async fn get_endpoint_inner(
312 configuration: &configuration::Configuration,
313 backoff: &mut ExponentialBackoff,
314 endpoint_id: &str,
315) -> Result<models::Endpoint, Error<GetEndpointError>> {
316 let local_var_configuration = configuration;
317 let p_path_endpoint_id = endpoint_id;
319
320 let local_var_client = &local_var_configuration.client;
321
322 let local_var_uri_str = format!(
323 "{}/v1/endpoints/{endpointId}",
324 local_var_configuration.qcs_config.api_url(),
325 endpointId = crate::apis::urlencode(p_path_endpoint_id)
326 );
327 let mut local_var_req_builder =
328 local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
329
330 #[cfg(feature = "tracing")]
331 {
332 let local_var_do_tracing = local_var_uri_str
335 .parse::<::url::Url>()
336 .ok()
337 .is_none_or(|url| {
338 configuration
339 .qcs_config
340 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
341 });
342
343 if local_var_do_tracing {
344 ::tracing::debug!(
345 url=%local_var_uri_str,
346 method="GET",
347 "making get_endpoint request",
348 );
349 }
350 }
351
352 {
355 use qcs_api_client_common::configuration::TokenError;
356
357 #[allow(
358 clippy::nonminimal_bool,
359 clippy::eq_op,
360 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
361 )]
362 let is_jwt_bearer_optional: bool = false || "JWTBearer" == "JWTBearerOptional";
363
364 let token = local_var_configuration
365 .qcs_config
366 .get_bearer_access_token()
367 .await;
368
369 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
370 #[cfg(feature = "tracing")]
372 tracing::debug!(
373 "No client credentials found, but this call does not require authentication."
374 );
375 } else {
376 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
377 }
378 }
379
380 let local_var_req = local_var_req_builder.build()?;
381 let local_var_resp = local_var_client.execute(local_var_req).await?;
382
383 let local_var_status = local_var_resp.status();
384 let local_var_raw_content_type = local_var_resp
385 .headers()
386 .get("content-type")
387 .and_then(|v| v.to_str().ok())
388 .unwrap_or("application/octet-stream")
389 .to_string();
390 let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
391
392 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
393 let local_var_content = local_var_resp.text().await?;
394 match local_var_content_type {
395 ContentType::Json => serde_path_to_error::deserialize(
396 &mut serde_json::Deserializer::from_str(&local_var_content),
397 )
398 .map_err(Error::from),
399 ContentType::Text => Err(Error::InvalidContentType {
400 content_type: local_var_raw_content_type,
401 return_type: "models::Endpoint",
402 }),
403 ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
404 content_type: unknown_type,
405 return_type: "models::Endpoint",
406 }),
407 }
408 } else {
409 let local_var_retry_delay =
410 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
411 let local_var_content = local_var_resp.text().await?;
412 let local_var_entity: Option<GetEndpointError> =
413 serde_json::from_str(&local_var_content).ok();
414 let local_var_error = ResponseContent {
415 status: local_var_status,
416 content: local_var_content,
417 entity: local_var_entity,
418 retry_delay: local_var_retry_delay,
419 };
420 Err(Error::ResponseError(local_var_error))
421 }
422}
423
424pub async fn get_endpoint(
425 configuration: &configuration::Configuration,
426 endpoint_id: &str,
427) -> Result<models::Endpoint, Error<GetEndpointError>> {
428 let mut backoff = configuration.backoff.build();
429 let mut refreshed_credentials = false;
430 let method = reqwest::Method::GET;
431 loop {
432 let result = get_endpoint_inner(configuration, &mut backoff, endpoint_id.clone()).await;
433
434 match result {
435 Ok(result) => return Ok(result),
436 Err(Error::ResponseError(response)) => {
437 if !refreshed_credentials
438 && matches!(
439 response.status,
440 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
441 )
442 {
443 match configuration.qcs_config.refresh().await {
445 Ok(_) => {
446 refreshed_credentials = true;
447 continue;
448 }
449 Err(::qcs_api_client_common::configuration::TokenError::Write {
450 error,
451 oauth_session: _,
452 }) => {
453 #[cfg(feature = "tracing")]
456 tracing::warn!(
457 "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
458 error
459 );
460 refreshed_credentials = true;
461 continue;
462 }
463 Err(e) => return Err(e.into()),
464 }
465 } else if let Some(duration) = response.retry_delay {
466 tokio::time::sleep(duration).await;
467 continue;
468 }
469
470 return Err(Error::ResponseError(response));
471 }
472 Err(Error::Reqwest(error)) => {
473 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
474 tokio::time::sleep(duration).await;
475 continue;
476 }
477
478 return Err(Error::Reqwest(error));
479 }
480 Err(Error::Io(error)) => {
481 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
482 tokio::time::sleep(duration).await;
483 continue;
484 }
485
486 return Err(Error::Io(error));
487 }
488 Err(error) => return Err(error),
489 }
490 }
491}
492async fn get_endpoint_accessors_inner(
493 configuration: &configuration::Configuration,
494 backoff: &mut ExponentialBackoff,
495 endpoint_id: &str,
496) -> Result<models::ListQuantumProcessorAccessorsResponse, Error<GetEndpointAccessorsError>> {
497 let local_var_configuration = configuration;
498 let p_path_endpoint_id = endpoint_id;
500
501 let local_var_client = &local_var_configuration.client;
502
503 let local_var_uri_str = format!(
504 "{}/v1/endpoints/{endpoint_id}/accessors",
505 local_var_configuration.qcs_config.api_url(),
506 endpoint_id = crate::apis::urlencode(p_path_endpoint_id)
507 );
508 let mut local_var_req_builder =
509 local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
510
511 #[cfg(feature = "tracing")]
512 {
513 let local_var_do_tracing = local_var_uri_str
516 .parse::<::url::Url>()
517 .ok()
518 .is_none_or(|url| {
519 configuration
520 .qcs_config
521 .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
522 });
523
524 if local_var_do_tracing {
525 ::tracing::debug!(
526 url=%local_var_uri_str,
527 method="GET",
528 "making get_endpoint_accessors request",
529 );
530 }
531 }
532
533 {
536 use qcs_api_client_common::configuration::TokenError;
537
538 #[allow(
539 clippy::nonminimal_bool,
540 clippy::eq_op,
541 reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
542 )]
543 let is_jwt_bearer_optional: bool = false || "JWTBearerOptional" == "JWTBearerOptional";
544
545 let token = local_var_configuration
546 .qcs_config
547 .get_bearer_access_token()
548 .await;
549
550 if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
551 #[cfg(feature = "tracing")]
553 tracing::debug!(
554 "No client credentials found, but this call does not require authentication."
555 );
556 } else {
557 local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
558 }
559 }
560
561 let local_var_req = local_var_req_builder.build()?;
562 let local_var_resp = local_var_client.execute(local_var_req).await?;
563
564 let local_var_status = local_var_resp.status();
565 let local_var_raw_content_type = local_var_resp
566 .headers()
567 .get("content-type")
568 .and_then(|v| v.to_str().ok())
569 .unwrap_or("application/octet-stream")
570 .to_string();
571 let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
572
573 if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
574 let local_var_content = local_var_resp.text().await?;
575 match local_var_content_type {
576 ContentType::Json => serde_path_to_error::deserialize(
577 &mut serde_json::Deserializer::from_str(&local_var_content),
578 )
579 .map_err(Error::from),
580 ContentType::Text => Err(Error::InvalidContentType {
581 content_type: local_var_raw_content_type,
582 return_type: "models::ListQuantumProcessorAccessorsResponse",
583 }),
584 ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
585 content_type: unknown_type,
586 return_type: "models::ListQuantumProcessorAccessorsResponse",
587 }),
588 }
589 } else {
590 let local_var_retry_delay =
591 duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
592 let local_var_content = local_var_resp.text().await?;
593 let local_var_entity: Option<GetEndpointAccessorsError> =
594 serde_json::from_str(&local_var_content).ok();
595 let local_var_error = ResponseContent {
596 status: local_var_status,
597 content: local_var_content,
598 entity: local_var_entity,
599 retry_delay: local_var_retry_delay,
600 };
601 Err(Error::ResponseError(local_var_error))
602 }
603}
604
605pub async fn get_endpoint_accessors(
606 configuration: &configuration::Configuration,
607 endpoint_id: &str,
608) -> Result<models::ListQuantumProcessorAccessorsResponse, Error<GetEndpointAccessorsError>> {
609 let mut backoff = configuration.backoff.build();
610 let mut refreshed_credentials = false;
611 let method = reqwest::Method::GET;
612 loop {
613 let result =
614 get_endpoint_accessors_inner(configuration, &mut backoff, endpoint_id.clone()).await;
615
616 match result {
617 Ok(result) => return Ok(result),
618 Err(Error::ResponseError(response)) => {
619 if !refreshed_credentials
620 && matches!(
621 response.status,
622 StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
623 )
624 {
625 match configuration.qcs_config.refresh().await {
627 Ok(_) => {
628 refreshed_credentials = true;
629 continue;
630 }
631 Err(::qcs_api_client_common::configuration::TokenError::Write {
632 error,
633 oauth_session: _,
634 }) => {
635 #[cfg(feature = "tracing")]
638 tracing::warn!(
639 "Token refresh succeeded but failed to persist: {}. Continuing with in-memory token.",
640 error
641 );
642 refreshed_credentials = true;
643 continue;
644 }
645 Err(e) => return Err(e.into()),
646 }
647 } else if let Some(duration) = response.retry_delay {
648 tokio::time::sleep(duration).await;
649 continue;
650 }
651
652 return Err(Error::ResponseError(response));
653 }
654 Err(Error::Reqwest(error)) => {
655 if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
656 tokio::time::sleep(duration).await;
657 continue;
658 }
659
660 return Err(Error::Reqwest(error));
661 }
662 Err(Error::Io(error)) => {
663 if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
664 tokio::time::sleep(duration).await;
665 continue;
666 }
667
668 return Err(Error::Io(error));
669 }
670 Err(error) => return Err(error),
671 }
672 }
673}