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#[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<crate::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(crate::models::ValidationError),
105    UnknownValue(serde_json::Value),
106}
107
108async fn get_health_inner(
109    configuration: &configuration::Configuration,
110    backoff: &mut ExponentialBackoff,
111) -> Result<crate::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
175    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
176        let local_var_content = local_var_resp.text().await?;
177        serde_json::from_str(&local_var_content).map_err(Error::from)
178    } else {
179        let local_var_retry_delay =
180            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
181        let local_var_content = local_var_resp.text().await?;
182        let local_var_entity: Option<GetHealthError> =
183            serde_json::from_str(&local_var_content).ok();
184        let local_var_error = ResponseContent {
185            status: local_var_status,
186            content: local_var_content,
187            entity: local_var_entity,
188            retry_delay: local_var_retry_delay,
189        };
190        Err(Error::ResponseError(local_var_error))
191    }
192}
193
194/// Retrieve the health status of the API
195pub async fn get_health(
196    configuration: &configuration::Configuration,
197) -> Result<crate::models::Health, Error<GetHealthError>> {
198    let mut backoff = configuration.backoff.clone();
199    let mut refreshed_credentials = false;
200    let method = reqwest::Method::GET;
201    loop {
202        let result = get_health_inner(configuration, &mut backoff).await;
203
204        match result {
205            Ok(result) => return Ok(result),
206            Err(Error::ResponseError(response)) => {
207                if !refreshed_credentials
208                    && matches!(
209                        response.status,
210                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
211                    )
212                {
213                    configuration.qcs_config.refresh().await?;
214                    refreshed_credentials = true;
215                    continue;
216                } else if let Some(duration) = response.retry_delay {
217                    tokio::time::sleep(duration).await;
218                    continue;
219                }
220
221                return Err(Error::ResponseError(response));
222            }
223            Err(Error::Reqwest(error)) => {
224                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
225                    tokio::time::sleep(duration).await;
226                    continue;
227                }
228
229                return Err(Error::Reqwest(error));
230            }
231            Err(Error::Io(error)) => {
232                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
233                    tokio::time::sleep(duration).await;
234                    continue;
235                }
236
237                return Err(Error::Io(error));
238            }
239            Err(error) => return Err(error),
240        }
241    }
242}
243async fn health_check_inner(
244    configuration: &configuration::Configuration,
245    backoff: &mut ExponentialBackoff,
246) -> Result<(), Error<HealthCheckError>> {
247    let local_var_configuration = configuration;
248
249    let local_var_client = &local_var_configuration.client;
250
251    let local_var_uri_str = format!(
252        "{}/v1/healthcheck",
253        local_var_configuration.qcs_config.api_url()
254    );
255    let mut local_var_req_builder =
256        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
257
258    #[cfg(feature = "tracing")]
259    {
260        // Ignore parsing errors if the URL is invalid for some reason.
261        // If it is invalid, it will turn up as an error later when actually making the request.
262        let local_var_do_tracing = local_var_uri_str
263            .parse::<::url::Url>()
264            .ok()
265            .is_none_or(|url| {
266                configuration
267                    .qcs_config
268                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
269            });
270
271        if local_var_do_tracing {
272            ::tracing::debug!(
273                url=%local_var_uri_str,
274                method="GET",
275                "making health_check request",
276            );
277        }
278    }
279
280    // Use the QCS Bearer token if a client OAuthSession is present,
281    // but do not require one when the security schema says it is optional.
282    {
283        use qcs_api_client_common::configuration::TokenError;
284
285        #[allow(
286            clippy::nonminimal_bool,
287            clippy::eq_op,
288            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
289        )]
290        let is_jwt_bearer_optional: bool = false;
291
292        let token = local_var_configuration
293            .qcs_config
294            .get_bearer_access_token()
295            .await;
296
297        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
298            // the client is configured without any OAuthSession, but this call does not require one.
299            #[cfg(feature = "tracing")]
300            tracing::debug!(
301                "No client credentials found, but this call does not require authentication."
302            );
303        } else {
304            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
305        }
306    }
307
308    let local_var_req = local_var_req_builder.build()?;
309    let local_var_resp = local_var_client.execute(local_var_req).await?;
310
311    let local_var_status = local_var_resp.status();
312
313    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
314        Ok(())
315    } else {
316        let local_var_retry_delay =
317            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
318        let local_var_content = local_var_resp.text().await?;
319        let local_var_entity: Option<HealthCheckError> =
320            serde_json::from_str(&local_var_content).ok();
321        let local_var_error = ResponseContent {
322            status: local_var_status,
323            content: local_var_content,
324            entity: local_var_entity,
325            retry_delay: local_var_retry_delay,
326        };
327        Err(Error::ResponseError(local_var_error))
328    }
329}
330
331/// Check the health of the service.
332pub async fn health_check(
333    configuration: &configuration::Configuration,
334) -> Result<(), Error<HealthCheckError>> {
335    let mut backoff = configuration.backoff.clone();
336    let mut refreshed_credentials = false;
337    let method = reqwest::Method::GET;
338    loop {
339        let result = health_check_inner(configuration, &mut backoff).await;
340
341        match result {
342            Ok(result) => return Ok(result),
343            Err(Error::ResponseError(response)) => {
344                if !refreshed_credentials
345                    && matches!(
346                        response.status,
347                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
348                    )
349                {
350                    configuration.qcs_config.refresh().await?;
351                    refreshed_credentials = true;
352                    continue;
353                } else if let Some(duration) = response.retry_delay {
354                    tokio::time::sleep(duration).await;
355                    continue;
356                }
357
358                return Err(Error::ResponseError(response));
359            }
360            Err(Error::Reqwest(error)) => {
361                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
362                    tokio::time::sleep(duration).await;
363                    continue;
364                }
365
366                return Err(Error::Reqwest(error));
367            }
368            Err(Error::Io(error)) => {
369                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
370                    tokio::time::sleep(duration).await;
371                    continue;
372                }
373
374                return Err(Error::Io(error));
375            }
376            Err(error) => return Err(error),
377        }
378    }
379}
380async fn health_check_deprecated_inner(
381    configuration: &configuration::Configuration,
382    backoff: &mut ExponentialBackoff,
383) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
384    let local_var_configuration = configuration;
385
386    let local_var_client = &local_var_configuration.client;
387
388    let local_var_uri_str = format!("{}/v1/", local_var_configuration.qcs_config.api_url());
389    let mut local_var_req_builder =
390        local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
391
392    #[cfg(feature = "tracing")]
393    {
394        // Ignore parsing errors if the URL is invalid for some reason.
395        // If it is invalid, it will turn up as an error later when actually making the request.
396        let local_var_do_tracing = local_var_uri_str
397            .parse::<::url::Url>()
398            .ok()
399            .is_none_or(|url| {
400                configuration
401                    .qcs_config
402                    .should_trace(&::urlpattern::UrlPatternMatchInput::Url(url))
403            });
404
405        if local_var_do_tracing {
406            ::tracing::debug!(
407                url=%local_var_uri_str,
408                method="GET",
409                "making health_check_deprecated request",
410            );
411        }
412    }
413
414    // Use the QCS Bearer token if a client OAuthSession is present,
415    // but do not require one when the security schema says it is optional.
416    {
417        use qcs_api_client_common::configuration::TokenError;
418
419        #[allow(
420            clippy::nonminimal_bool,
421            clippy::eq_op,
422            reason = "Logic must be done at runtime since it cannot be handled by the mustache template engine."
423        )]
424        let is_jwt_bearer_optional: bool = false;
425
426        let token = local_var_configuration
427            .qcs_config
428            .get_bearer_access_token()
429            .await;
430
431        if is_jwt_bearer_optional && matches!(token, Err(TokenError::NoCredentials)) {
432            // the client is configured without any OAuthSession, but this call does not require one.
433            #[cfg(feature = "tracing")]
434            tracing::debug!(
435                "No client credentials found, but this call does not require authentication."
436            );
437        } else {
438            local_var_req_builder = local_var_req_builder.bearer_auth(token?.secret());
439        }
440    }
441
442    let local_var_req = local_var_req_builder.build()?;
443    let local_var_resp = local_var_client.execute(local_var_req).await?;
444
445    let local_var_status = local_var_resp.status();
446
447    if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
448        let local_var_content = local_var_resp.text().await?;
449        serde_json::from_str(&local_var_content).map_err(Error::from)
450    } else {
451        let local_var_retry_delay =
452            duration_from_response(local_var_resp.status(), local_var_resp.headers(), backoff);
453        let local_var_content = local_var_resp.text().await?;
454        let local_var_entity: Option<HealthCheckDeprecatedError> =
455            serde_json::from_str(&local_var_content).ok();
456        let local_var_error = ResponseContent {
457            status: local_var_status,
458            content: local_var_content,
459            entity: local_var_entity,
460            retry_delay: local_var_retry_delay,
461        };
462        Err(Error::ResponseError(local_var_error))
463    }
464}
465
466/// Endpoint to return a status 200 for load balancer health checks
467pub async fn health_check_deprecated(
468    configuration: &configuration::Configuration,
469) -> Result<serde_json::Value, Error<HealthCheckDeprecatedError>> {
470    let mut backoff = configuration.backoff.clone();
471    let mut refreshed_credentials = false;
472    let method = reqwest::Method::GET;
473    loop {
474        let result = health_check_deprecated_inner(configuration, &mut backoff).await;
475
476        match result {
477            Ok(result) => return Ok(result),
478            Err(Error::ResponseError(response)) => {
479                if !refreshed_credentials
480                    && matches!(
481                        response.status,
482                        StatusCode::FORBIDDEN | StatusCode::UNAUTHORIZED
483                    )
484                {
485                    configuration.qcs_config.refresh().await?;
486                    refreshed_credentials = true;
487                    continue;
488                } else if let Some(duration) = response.retry_delay {
489                    tokio::time::sleep(duration).await;
490                    continue;
491                }
492
493                return Err(Error::ResponseError(response));
494            }
495            Err(Error::Reqwest(error)) => {
496                if let Some(duration) = duration_from_reqwest_error(&method, &error, &mut backoff) {
497                    tokio::time::sleep(duration).await;
498                    continue;
499                }
500
501                return Err(Error::Reqwest(error));
502            }
503            Err(Error::Io(error)) => {
504                if let Some(duration) = duration_from_io_error(&method, &error, &mut backoff) {
505                    tokio::time::sleep(duration).await;
506                    continue;
507                }
508
509                return Err(Error::Io(error));
510            }
511            Err(error) => return Err(error),
512        }
513    }
514}