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, 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::TokenRefresher;
32use reqwest::StatusCode;
33use serde::{Deserialize, Serialize};
34
35/// struct for typed errors of method [`get_health`]
36#[derive(Debug, Clone, Serialize, Deserialize)]
37#[serde(untagged)]
38pub enum GetHealthError {
39    UnknownValue(serde_json::Value),
40}
41
42/// struct for typed errors of method [`health_check`]
43#[derive(Debug, Clone, Serialize, Deserialize)]
44#[serde(untagged)]
45pub enum HealthCheckError {
46    UnknownValue(serde_json::Value),
47}
48
49/// struct for typed errors of method [`health_check_deprecated`]
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(untagged)]
52pub enum HealthCheckDeprecatedError {
53    Status422(crate::models::ValidationError),
54    UnknownValue(serde_json::Value),
55}
56
57async fn get_health_inner(
58    configuration: &configuration::Configuration,
59    backoff: &mut ExponentialBackoff,
60) -> Result<crate::models::Health, Error<GetHealthError>> {
61    let local_var_configuration = configuration;
62
63    let local_var_client = &local_var_configuration.client;
64
65    let local_var_uri_str = format!("{}/", local_var_configuration.qcs_config.api_url());
66    let mut local_var_req_builder =
67        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
68
69    #[cfg(feature = "tracing")]
70    {
71        // Ignore parsing errors if the URL is invalid for some reason.
72        // If it is invalid, it will turn up as an error later when actually making the request.
73        let local_var_do_tracing =
74            local_var_uri_str
75                .parse::<::url::Url>()
76                .ok()
77                .map_or(true, |url| {
78                    configuration
79                        .qcs_config
80                        .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
81                });
82
83        if local_var_do_tracing {
84            ::tracing::debug!(
85                url=%local_var_uri_str,
86                method="GET",
87                "making get_health request",
88            );
89        }
90    }
91
92    // Use the QCS Bearer token if a client OAuthSession is present,
93    // but do not require one when the security schema says it is optional.
94    {
95        use qcs_api_client_common::configuration::TokenError;
96
97        #[allow(
98            clippy::nonminimal_bool,
99            clippy::eq_op,
100            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
101        )]
102        let is_jwt_bearer_optional: bool = false;
103
104        let token = local_var_configuration
105            .qcs_config
106            .get_bearer_access_token()
107            .await;
108
109        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
110            // the client is configured without any OAuthSession, but this call does not require one.
111            #[cfg(feature = "tracing")]
112            tracing::debug!(
113                "No client credentials found, but this call does not require authentication."
114            );
115        } else {
116            local_var_req_builder = local_var_req_builder.bearer_auth(token?);
117        }
118    }
119
120    let local_var_req = local_var_req_builder.build()?;
121    let local_var_resp = local_var_client.execute(local_var_req).await?;
122
123    let local_var_status = local_var_resp.status();
124
125    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
126        let local_var_content = local_var_resp.text().await?;
127        serde_json::from_str(&local_var_content).map_err(Error::from)
128    } else {
129        let local_var_retry_delay =
130            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
131        let local_var_content = local_var_resp.text().await?;
132        let local_var_entity: Option<GetHealthError> =
133            serde_json::from_str(&local_var_content).ok();
134        let local_var_error = ResponseContent {
135            status: local_var_status,
136            content: local_var_content,
137            entity: local_var_entity,
138            retry_delay: local_var_retry_delay,
139        };
140        Err(Error::ResponseError(local_var_error))
141    }
142}
143
144/// Retrieve the health status of the API
145pub async fn get_health(
146    configuration: &configuration::Configuration,
147) -> Result<crate::models::Health, Error<GetHealthError>> {
148    let mut backoff = configuration.backoff.clone();
149    let mut refreshed_credentials = false;
150    let method = reqwest::Method::GET;
151    loop {
152        let result = get_health_inner(configuration, &mut backoff).await;
153
154        match result {
155            Ok(result) => return Ok(result),
156            Err(Error::ResponseError(response)) => {
157                if !refreshed_credentials
158                    && matches!(
159                        response.status,
160                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
161                    )
162                {
163                    configuration.qcs_config.refresh().await?;
164                    refreshed_credentials = true;
165                    continue;
166                } else if let Some(duration) = response.retry_delay {
167                    tokio::time::sleep(duration).await;
168                    continue;
169                }
170
171                return Err(Error::ResponseError(response));
172            }
173            Err(Error::Reqwest(error)) => {
174                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
175                    tokio::time::sleep(duration).await;
176                    continue;
177                }
178
179                return Err(Error::Reqwest(error));
180            }
181            Err(Error::Io(error)) => {
182                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
183                    tokio::time::sleep(duration).await;
184                    continue;
185                }
186
187                return Err(Error::Io(error));
188            }
189            Err(error) => return Err(error),
190        }
191    }
192}
193async fn health_check_inner(
194    configuration: &configuration::Configuration,
195    backoff: &mut ExponentialBackoff,
196) -> Result<(), Error<HealthCheckError>> {
197    let local_var_configuration = configuration;
198
199    let local_var_client = &local_var_configuration.client;
200
201    let local_var_uri_str = format!(
202        "{}/v1/healthcheck",
203        local_var_configuration.qcs_config.api_url()
204    );
205    let mut local_var_req_builder =
206        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
207
208    #[cfg(feature = "tracing")]
209    {
210        // Ignore parsing errors if the URL is invalid for some reason.
211        // If it is invalid, it will turn up as an error later when actually making the request.
212        let local_var_do_tracing =
213            local_var_uri_str
214                .parse::<::url::Url>()
215                .ok()
216                .map_or(true, |url| {
217                    configuration
218                        .qcs_config
219                        .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
220                });
221
222        if local_var_do_tracing {
223            ::tracing::debug!(
224                url=%local_var_uri_str,
225                method="GET",
226                "making health_check request",
227            );
228        }
229    }
230
231    // Use the QCS Bearer token if a client OAuthSession is present,
232    // but do not require one when the security schema says it is optional.
233    {
234        use qcs_api_client_common::configuration::TokenError;
235
236        #[allow(
237            clippy::nonminimal_bool,
238            clippy::eq_op,
239            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
240        )]
241        let is_jwt_bearer_optional: bool = false;
242
243        let token = local_var_configuration
244            .qcs_config
245            .get_bearer_access_token()
246            .await;
247
248        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
249            // the client is configured without any OAuthSession, but this call does not require one.
250            #[cfg(feature = "tracing")]
251            tracing::debug!(
252                "No client credentials found, but this call does not require authentication."
253            );
254        } else {
255            local_var_req_builder = local_var_req_builder.bearer_auth(token?);
256        }
257    }
258
259    let local_var_req = local_var_req_builder.build()?;
260    let local_var_resp = local_var_client.execute(local_var_req).await?;
261
262    let local_var_status = local_var_resp.status();
263
264    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
265        Ok(())
266    } else {
267        let local_var_retry_delay =
268            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
269        let local_var_content = local_var_resp.text().await?;
270        let local_var_entity: Option<HealthCheckError> =
271            serde_json::from_str(&local_var_content).ok();
272        let local_var_error = ResponseContent {
273            status: local_var_status,
274            content: local_var_content,
275            entity: local_var_entity,
276            retry_delay: local_var_retry_delay,
277        };
278        Err(Error::ResponseError(local_var_error))
279    }
280}
281
282/// Check the health of the service.
283pub async fn health_check(
284    configuration: &configuration::Configuration,
285) -> Result<(), Error<HealthCheckError>> {
286    let mut backoff = configuration.backoff.clone();
287    let mut refreshed_credentials = false;
288    let method = reqwest::Method::GET;
289    loop {
290        let result = health_check_inner(configuration, &mut backoff).await;
291
292        match result {
293            Ok(result) => return Ok(result),
294            Err(Error::ResponseError(response)) => {
295                if !refreshed_credentials
296                    && matches!(
297                        response.status,
298                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
299                    )
300                {
301                    configuration.qcs_config.refresh().await?;
302                    refreshed_credentials = true;
303                    continue;
304                } else if let Some(duration) = response.retry_delay {
305                    tokio::time::sleep(duration).await;
306                    continue;
307                }
308
309                return Err(Error::ResponseError(response));
310            }
311            Err(Error::Reqwest(error)) => {
312                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
313                    tokio::time::sleep(duration).await;
314                    continue;
315                }
316
317                return Err(Error::Reqwest(error));
318            }
319            Err(Error::Io(error)) => {
320                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
321                    tokio::time::sleep(duration).await;
322                    continue;
323                }
324
325                return Err(Error::Io(error));
326            }
327            Err(error) => return Err(error),
328        }
329    }
330}
331async fn health_check_deprecated_inner(
332    configuration: &configuration::Configuration,
333    backoff: &mut ExponentialBackoff,
334) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
335    let local_var_configuration = configuration;
336
337    let local_var_client = &local_var_configuration.client;
338
339    let local_var_uri_str = format!("{}/v1/", local_var_configuration.qcs_config.api_url());
340    let mut local_var_req_builder =
341        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
342
343    #[cfg(feature = "tracing")]
344    {
345        // Ignore parsing errors if the URL is invalid for some reason.
346        // If it is invalid, it will turn up as an error later when actually making the request.
347        let local_var_do_tracing =
348            local_var_uri_str
349                .parse::<::url::Url>()
350                .ok()
351                .map_or(true, |url| {
352                    configuration
353                        .qcs_config
354                        .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
355                });
356
357        if local_var_do_tracing {
358            ::tracing::debug!(
359                url=%local_var_uri_str,
360                method="GET",
361                "making health_check_deprecated request",
362            );
363        }
364    }
365
366    // Use the QCS Bearer token if a client OAuthSession is present,
367    // but do not require one when the security schema says it is optional.
368    {
369        use qcs_api_client_common::configuration::TokenError;
370
371        #[allow(
372            clippy::nonminimal_bool,
373            clippy::eq_op,
374            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
375        )]
376        let is_jwt_bearer_optional: bool = false;
377
378        let token = local_var_configuration
379            .qcs_config
380            .get_bearer_access_token()
381            .await;
382
383        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
384            // the client is configured without any OAuthSession, but this call does not require one.
385            #[cfg(feature = "tracing")]
386            tracing::debug!(
387                "No client credentials found, but this call does not require authentication."
388            );
389        } else {
390            local_var_req_builder = local_var_req_builder.bearer_auth(token?);
391        }
392    }
393
394    let local_var_req = local_var_req_builder.build()?;
395    let local_var_resp = local_var_client.execute(local_var_req).await?;
396
397    let local_var_status = local_var_resp.status();
398
399    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
400        let local_var_content = local_var_resp.text().await?;
401        serde_json::from_str(&local_var_content).map_err(Error::from)
402    } else {
403        let local_var_retry_delay =
404            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
405        let local_var_content = local_var_resp.text().await?;
406        let local_var_entity: Option<HealthCheckDeprecatedError> =
407            serde_json::from_str(&local_var_content).ok();
408        let local_var_error = ResponseContent {
409            status: local_var_status,
410            content: local_var_content,
411            entity: local_var_entity,
412            retry_delay: local_var_retry_delay,
413        };
414        Err(Error::ResponseError(local_var_error))
415    }
416}
417
418/// Endpoint to return a status 200 for load balancer health checks
419pub async fn health_check_deprecated(
420    configuration: &configuration::Configuration,
421) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
422    let mut backoff = configuration.backoff.clone();
423    let mut refreshed_credentials = false;
424    let method = reqwest::Method::GET;
425    loop {
426        let result = health_check_deprecated_inner(configuration, &mut backoff).await;
427
428        match result {
429            Ok(result) => return Ok(result),
430            Err(Error::ResponseError(response)) => {
431                if !refreshed_credentials
432                    && matches!(
433                        response.status,
434                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
435                    )
436                {
437                    configuration.qcs_config.refresh().await?;
438                    refreshed_credentials = true;
439                    continue;
440                } else if let Some(duration) = response.retry_delay {
441                    tokio::time::sleep(duration).await;
442                    continue;
443                }
444
445                return Err(Error::ResponseError(response));
446            }
447            Err(Error::Reqwest(error)) => {
448                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
449                    tokio::time::sleep(duration).await;
450                    continue;
451                }
452
453                return Err(Error::Reqwest(error));
454            }
455            Err(Error::Io(error)) => {
456                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
457                    tokio::time::sleep(duration).await;
458                    continue;
459                }
460
461                return Err(Error::Io(error));
462            }
463            Err(error) => return Err(error),
464        }
465    }
466}