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