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