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