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