Skip to main content

qcs_api_client_openapi/apis/
default_api.rs

1// Copyright 2022 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*
16 * Rigetti QCS API
17 *
18 * # Introduction  This is the documentation for the Rigetti QCS HTTP API.  You can find out more about Rigetti at [https://rigetti.com](https://rigetti.com), and also interact with QCS via the web at [https://qcs.rigetti.com](https://qcs.rigetti.com).  This API is documented in **OpenAPI format** and so is compatible with the dozens of language-specific client generators available [here](https://github.com/OpenAPITools/openapi-generator) and elsewhere on the web.  # Principles  This API follows REST design principles where appropriate, and otherwise an HTTP RPC paradigm. We adhere to the Google [API Improvement Proposals](https://google.aip.dev/general) where reasonable to provide a consistent, intuitive developer experience. HTTP response codes match their specifications, and error messages fit a common format.  # Authentication  All access to the QCS API requires OAuth2 authentication provided by Okta. You can request access [here](https://www.rigetti.com/get-quantum). Once you have a user account, you can download your access token from QCS [here](https://qcs.rigetti.com/auth/token).   That access token is valid for 24 hours after issuance. The value of `access_token` within the JSON file is the token used for authentication (don't use the entire JSON file).  Authenticate requests using the `Authorization` header and a `Bearer` prefix:  ``` curl --header \"Authorization: Bearer eyJraW...Iow\" ```  # Quantum Processor Access  Access to the quantum processors themselves is not yet provided directly by this HTTP API, but is instead performed over ZeroMQ/[rpcq](https://github.com/rigetti/rpcq). Until that changes, we suggest using [pyquil](https://github.com/rigetti/pyquil) to build and execute quantum programs via the Legacy API.  # Legacy API  Our legacy HTTP API remains accessible at https://forest-server.qcs.rigetti.com, and it shares a source of truth with this API's services. You can use either service with the same user account and means of authentication. We strongly recommend using the API documented here, as the legacy API is on the path to deprecation.
19 *
20 * The version of the OpenAPI document: 2020-07-31
21 * Contact: support@rigetti.com
22 * Generated by: https://openapi-generator.tech
23 */
24
25use 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/// Serialize command-line arguments for [`get_health`]
40#[cfg(feature = "clap")]
41#[derive(Debug, clap::Args)]
42pub struct GetHealthClapParams {}
43
44#[cfg(feature = "clap")]
45impl GetHealthClapParams {
46    pub async fn execute(
47        self,
48        configuration: &configuration::Configuration,
49    ) -> Result<models::Health, miette::Error> {
50        get_health(configuration).await.into_diagnostic()
51    }
52}
53
54/// Serialize command-line arguments for [`health_check`]
55#[cfg(feature = "clap")]
56#[derive(Debug, clap::Args)]
57pub struct HealthCheckClapParams {}
58
59#[cfg(feature = "clap")]
60impl HealthCheckClapParams {
61    pub async fn execute(
62        self,
63        configuration: &configuration::Configuration,
64    ) -> Result<(), miette::Error> {
65        health_check(configuration).await.into_diagnostic()
66    }
67}
68
69/// Serialize command-line arguments for [`health_check_deprecated`]
70#[cfg(feature = "clap")]
71#[derive(Debug, clap::Args)]
72pub struct HealthCheckDeprecatedClapParams {}
73
74#[cfg(feature = "clap")]
75impl HealthCheckDeprecatedClapParams {
76    pub async fn execute(
77        self,
78        configuration: &configuration::Configuration,
79    ) -> Result<serde_json::Value, miette::Error> {
80        health_check_deprecated(configuration)
81            .await
82            .into_diagnostic()
83    }
84}
85
86/// struct for typed errors of method [`get_health`]
87#[derive(Debug, Clone, Serialize, Deserialize)]
88#[serde(untagged)]
89pub enum GetHealthError {
90    UnknownValue(serde_json::Value),
91}
92
93/// struct for typed errors of method [`health_check`]
94#[derive(Debug, Clone, Serialize, Deserialize)]
95#[serde(untagged)]
96pub enum HealthCheckError {
97    UnknownValue(serde_json::Value),
98}
99
100/// struct for typed errors of method [`health_check_deprecated`]
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(untagged)]
103pub enum HealthCheckDeprecatedError {
104    Status422(models::ValidationError),
105    UnknownValue(serde_json::Value),
106}
107
108async fn get_health_inner(
109    configuration: &configuration::Configuration,
110    backoff: &mut ExponentialBackoff,
111) -> Result<models::Health, Error<GetHealthError>> {
112    let local_var_configuration = configuration;
113
114    let local_var_client = &local_var_configuration.client;
115
116    let local_var_uri_str = format!("{}/", local_var_configuration.qcs_config.api_url());
117    let mut local_var_req_builder =
118        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
119
120    #[cfg(feature = "tracing")]
121    {
122        // Ignore parsing errors if the URL is invalid for some reason.
123        // If it is invalid, it will turn up as an error later when actually making the request.
124        let local_var_do_tracing = local_var_uri_str
125            .parse::<::url::Url>()
126            .ok()
127            .is_none_or(|url| {
128                configuration
129                    .qcs_config
130                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
131            });
132
133        if local_var_do_tracing {
134            ::tracing::debug!(
135                url=%local_var_uri_str,
136                method="GET",
137                "making get_health request",
138            );
139        }
140    }
141
142    // Use the QCS Bearer token if a client OAuthSession is present,
143    // but do not require one when the security schema says it is optional.
144    {
145        use qcs_api_client_common::configuration::TokenError;
146
147        #[allow(
148            clippy::nonminimal_bool,
149            clippy::eq_op,
150            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
151        )]
152        let is_jwt_bearer_optional: bool = false;
153
154        let token = local_var_configuration
155            .qcs_config
156            .get_bearer_access_token()
157            .await;
158
159        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
160            // the client is configured without any OAuthSession, but this call does not require one.
161            #[cfg(feature = "tracing")]
162            tracing::debug!(
163                "No client credentials found, but this call does not require authentication."
164            );
165        } else {
166            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
167        }
168    }
169
170    let local_var_req = local_var_req_builder.build()?;
171    let local_var_resp = local_var_client.execute(local_var_req).await?;
172
173    let local_var_status = local_var_resp.status();
174    let local_var_raw_content_type = local_var_resp
175        .headers()
176        .get("content-type")
177        .and_then(|v| v.to_str().ok())
178        .unwrap_or("application/octet-stream")
179        .to_string();
180    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
181
182    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
183        let local_var_content = local_var_resp.text().await?;
184        match local_var_content_type {
185            ContentType::Json => serde_path_to_error::deserialize(
186                &mut serde_json::Deserializer::from_str(&local_var_content),
187            )
188            .map_err(Error::from),
189            ContentType::Text => Err(Error::InvalidContentType {
190                content_type: local_var_raw_content_type,
191                return_type: "models::Health",
192            }),
193            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
194                content_type: unknown_type,
195                return_type: "models::Health",
196            }),
197        }
198    } else {
199        let local_var_retry_delay =
200            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
201        let local_var_content = local_var_resp.text().await?;
202        let local_var_entity: Option<GetHealthError> =
203            serde_json::from_str(&local_var_content).ok();
204        let local_var_error = ResponseContent {
205            status: local_var_status,
206            content: local_var_content,
207            entity: local_var_entity,
208            retry_delay: local_var_retry_delay,
209        };
210        Err(Error::ResponseError(local_var_error))
211    }
212}
213
214/// Retrieve the health status of the API
215pub async fn get_health(
216    configuration: &configuration::Configuration,
217) -> Result<models::Health, Error<GetHealthError>> {
218    let mut backoff = configuration.backoff.clone();
219    let mut refreshed_credentials = false;
220    let method = reqwest::Method::GET;
221    loop {
222        let result = get_health_inner(configuration, &mut backoff).await;
223
224        match result {
225            Ok(result) => return Ok(result),
226            Err(Error::ResponseError(response)) => {
227                if !refreshed_credentials
228                    && matches!(
229                        response.status,
230                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
231                    )
232                {
233                    configuration.qcs_config.refresh().await?;
234                    refreshed_credentials = true;
235                    continue;
236                } else if let Some(duration) = response.retry_delay {
237                    tokio::time::sleep(duration).await;
238                    continue;
239                }
240
241                return Err(Error::ResponseError(response));
242            }
243            Err(Error::Reqwest(error)) => {
244                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
245                    tokio::time::sleep(duration).await;
246                    continue;
247                }
248
249                return Err(Error::Reqwest(error));
250            }
251            Err(Error::Io(error)) => {
252                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
253                    tokio::time::sleep(duration).await;
254                    continue;
255                }
256
257                return Err(Error::Io(error));
258            }
259            Err(error) => return Err(error),
260        }
261    }
262}
263async fn health_check_inner(
264    configuration: &configuration::Configuration,
265    backoff: &mut ExponentialBackoff,
266) -> Result<(), Error<HealthCheckError>> {
267    let local_var_configuration = configuration;
268
269    let local_var_client = &local_var_configuration.client;
270
271    let local_var_uri_str = format!(
272        "{}/v1/healthcheck",
273        local_var_configuration.qcs_config.api_url()
274    );
275    let mut local_var_req_builder =
276        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
277
278    #[cfg(feature = "tracing")]
279    {
280        // Ignore parsing errors if the URL is invalid for some reason.
281        // If it is invalid, it will turn up as an error later when actually making the request.
282        let local_var_do_tracing = local_var_uri_str
283            .parse::<::url::Url>()
284            .ok()
285            .is_none_or(|url| {
286                configuration
287                    .qcs_config
288                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
289            });
290
291        if local_var_do_tracing {
292            ::tracing::debug!(
293                url=%local_var_uri_str,
294                method="GET",
295                "making health_check request",
296            );
297        }
298    }
299
300    // Use the QCS Bearer token if a client OAuthSession is present,
301    // but do not require one when the security schema says it is optional.
302    {
303        use qcs_api_client_common::configuration::TokenError;
304
305        #[allow(
306            clippy::nonminimal_bool,
307            clippy::eq_op,
308            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
309        )]
310        let is_jwt_bearer_optional: bool = false;
311
312        let token = local_var_configuration
313            .qcs_config
314            .get_bearer_access_token()
315            .await;
316
317        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
318            // the client is configured without any OAuthSession, but this call does not require one.
319            #[cfg(feature = "tracing")]
320            tracing::debug!(
321                "No client credentials found, but this call does not require authentication."
322            );
323        } else {
324            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
325        }
326    }
327
328    let local_var_req = local_var_req_builder.build()?;
329    let local_var_resp = local_var_client.execute(local_var_req).await?;
330
331    let local_var_status = local_var_resp.status();
332
333    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
334        Ok(())
335    } else {
336        let local_var_retry_delay =
337            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
338        let local_var_content = local_var_resp.text().await?;
339        let local_var_entity: Option<HealthCheckError> =
340            serde_json::from_str(&local_var_content).ok();
341        let local_var_error = ResponseContent {
342            status: local_var_status,
343            content: local_var_content,
344            entity: local_var_entity,
345            retry_delay: local_var_retry_delay,
346        };
347        Err(Error::ResponseError(local_var_error))
348    }
349}
350
351/// Check the health of the service.
352pub async fn health_check(
353    configuration: &configuration::Configuration,
354) -> Result<(), Error<HealthCheckError>> {
355    let mut backoff = configuration.backoff.clone();
356    let mut refreshed_credentials = false;
357    let method = reqwest::Method::GET;
358    loop {
359        let result = health_check_inner(configuration, &mut backoff).await;
360
361        match result {
362            Ok(result) => return Ok(result),
363            Err(Error::ResponseError(response)) => {
364                if !refreshed_credentials
365                    && matches!(
366                        response.status,
367                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
368                    )
369                {
370                    configuration.qcs_config.refresh().await?;
371                    refreshed_credentials = true;
372                    continue;
373                } else if let Some(duration) = response.retry_delay {
374                    tokio::time::sleep(duration).await;
375                    continue;
376                }
377
378                return Err(Error::ResponseError(response));
379            }
380            Err(Error::Reqwest(error)) => {
381                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
382                    tokio::time::sleep(duration).await;
383                    continue;
384                }
385
386                return Err(Error::Reqwest(error));
387            }
388            Err(Error::Io(error)) => {
389                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
390                    tokio::time::sleep(duration).await;
391                    continue;
392                }
393
394                return Err(Error::Io(error));
395            }
396            Err(error) => return Err(error),
397        }
398    }
399}
400async fn health_check_deprecated_inner(
401    configuration: &configuration::Configuration,
402    backoff: &mut ExponentialBackoff,
403) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
404    let local_var_configuration = configuration;
405
406    let local_var_client = &local_var_configuration.client;
407
408    let local_var_uri_str = format!("{}/v1/", local_var_configuration.qcs_config.api_url());
409    let mut local_var_req_builder =
410        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
411
412    #[cfg(feature = "tracing")]
413    {
414        // Ignore parsing errors if the URL is invalid for some reason.
415        // If it is invalid, it will turn up as an error later when actually making the request.
416        let local_var_do_tracing = local_var_uri_str
417            .parse::<::url::Url>()
418            .ok()
419            .is_none_or(|url| {
420                configuration
421                    .qcs_config
422                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
423            });
424
425        if local_var_do_tracing {
426            ::tracing::debug!(
427                url=%local_var_uri_str,
428                method="GET",
429                "making health_check_deprecated request",
430            );
431        }
432    }
433
434    // Use the QCS Bearer token if a client OAuthSession is present,
435    // but do not require one when the security schema says it is optional.
436    {
437        use qcs_api_client_common::configuration::TokenError;
438
439        #[allow(
440            clippy::nonminimal_bool,
441            clippy::eq_op,
442            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
443        )]
444        let is_jwt_bearer_optional: bool = false;
445
446        let token = local_var_configuration
447            .qcs_config
448            .get_bearer_access_token()
449            .await;
450
451        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
452            // the client is configured without any OAuthSession, but this call does not require one.
453            #[cfg(feature = "tracing")]
454            tracing::debug!(
455                "No client credentials found, but this call does not require authentication."
456            );
457        } else {
458            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
459        }
460    }
461
462    let local_var_req = local_var_req_builder.build()?;
463    let local_var_resp = local_var_client.execute(local_var_req).await?;
464
465    let local_var_status = local_var_resp.status();
466    let local_var_raw_content_type = local_var_resp
467        .headers()
468        .get("content-type")
469        .and_then(|v| v.to_str().ok())
470        .unwrap_or("application/octet-stream")
471        .to_string();
472    let local_var_content_type = super::ContentType::from(local_var_raw_content_type.as_str());
473
474    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
475        let local_var_content = local_var_resp.text().await?;
476        match local_var_content_type {
477            ContentType::Json => serde_path_to_error::deserialize(
478                &mut serde_json::Deserializer::from_str(&local_var_content),
479            )
480            .map_err(Error::from),
481            ContentType::Text => Err(Error::InvalidContentType {
482                content_type: local_var_raw_content_type,
483                return_type: "serde_json::Value",
484            }),
485            ContentType::Unsupported(unknown_type) => Err(Error::InvalidContentType {
486                content_type: unknown_type,
487                return_type: "serde_json::Value",
488            }),
489        }
490    } else {
491        let local_var_retry_delay =
492            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
493        let local_var_content = local_var_resp.text().await?;
494        let local_var_entity: Option<HealthCheckDeprecatedError> =
495            serde_json::from_str(&local_var_content).ok();
496        let local_var_error = ResponseContent {
497            status: local_var_status,
498            content: local_var_content,
499            entity: local_var_entity,
500            retry_delay: local_var_retry_delay,
501        };
502        Err(Error::ResponseError(local_var_error))
503    }
504}
505
506/// Endpoint to return a status 200 for load balancer health checks
507#[deprecated]
508pub async fn health_check_deprecated(
509    configuration: &configuration::Configuration,
510) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
511    let mut backoff = configuration.backoff.clone();
512    let mut refreshed_credentials = false;
513    let method = reqwest::Method::GET;
514    loop {
515        let result = health_check_deprecated_inner(configuration, &mut backoff).await;
516
517        match result {
518            Ok(result) => return Ok(result),
519            Err(Error::ResponseError(response)) => {
520                if !refreshed_credentials
521                    && matches!(
522                        response.status,
523                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
524                    )
525                {
526                    configuration.qcs_config.refresh().await?;
527                    refreshed_credentials = true;
528                    continue;
529                } else if let Some(duration) = response.retry_delay {
530                    tokio::time::sleep(duration).await;
531                    continue;
532                }
533
534                return Err(Error::ResponseError(response));
535            }
536            Err(Error::Reqwest(error)) => {
537                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
538                    tokio::time::sleep(duration).await;
539                    continue;
540                }
541
542                return Err(Error::Reqwest(error));
543            }
544            Err(Error::Io(error)) => {
545                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
546                    tokio::time::sleep(duration).await;
547                    continue;
548                }
549
550                return Err(Error::Io(error));
551            }
552            Err(error) => return Err(error),
553        }
554    }
555}