200 stable releases (34 major)
new 76.0.0 | Dec 12, 2024 |
---|---|
75.0.1 | Dec 4, 2024 |
75.0.0 | Nov 20, 2024 |
74.0.1 | Nov 13, 2024 |
40.0.3 |
|
#152 in Web programming
517 downloads per month
Used in 2 crates
330KB
4.5K
SLoC
Taskcluster API Client
This library is a complete interface to Taskcluster in Rust. It provides asynchronous interfaces for all Taskcluster API methods, as well as a few utility functions.
Usage
See docs.rs for detailed usage information.
Compatibility
This library is co-versioned with Taskcluster itself. That is, a client with version x.y.z contains API methods corresponding to Taskcluster version x.y.z. Taskcluster is careful to maintain API compatibility, and guarantees it within a major version. That means that any client with version x.* will work against any Taskcluster services at version x.*, and is very likely to work for many other major versions of the Taskcluster services. Any incompatibilities are noted in the Changelog.
lib.rs
:
Taskcluster Client for Rust
For a general guide to using Taskcluster clients, see Calling Taskcluster APIs.
This client is a convenience wrapper around reqwest
that provides named functions for each API
endpoint and adds functionality such as authentication and retries.
Usage
Setup
Before calling an API end-point, you'll need to build a client, using the
ClientBuilder
type. This allows construction of a client with only the
necessary features, following the builder pattern. You must at least supply a root URL to identify
the Taskcluster deployment to which the API calls should be directed.
There is a type for each service, e.g., Queue
and Auth
. Each service type defines functions
spepcific to the API endpoints for that service. Each has a new
associated function that
takes an Into<ClientBuilder>
. As a shortcut, you may pass a string to new
that will be treated
as a root URL.
Here is a simple setup and use of an un-authenticated client:
use taskcluster::Auth;
let auth = Auth::new(root_url)?;
let resp = auth.client("static/taskcluster/root").await?;
assert_eq!(resp, json!({"clientId": "static/taskcluster/root"}));
Ok(())
Here is an example with credentials provided, in this case via the standard environment variables.
use std::env;
use taskcluster::{ClientBuilder, Queue, Credentials};
let creds = Credentials::from_env()?;
let root_url = env::var("TASKCLUSTER_ROOT_URL").unwrap();
let client = Queue::new(ClientBuilder::new(&root_url).credentials(creds))?;
let res = client.cancelTask("G08bnnBuR6yDhDLJkJ6KiA").await?;
println!("{}", res.get("status").unwrap());
Ok(())
Authorized Scopes
If you wish to perform requests on behalf of a third-party that has smaller set of scopes than you do, you can specify which scopes your request should be allowed to use.
These "authorized scopes" are configured on the client:
use std::env;
use serde_json::json;
use taskcluster::{ClientBuilder, Queue, Credentials};
let creds = Credentials::from_env()?;
let root_url = env::var("TASKCLUSTER_ROOT_URL").unwrap();
let client = Queue::new(
ClientBuilder::new(&root_url)
.credentials(creds)
.authorized_scopes(vec!["just:one-scope"]))?;
let res = client.createTask("G08bnnBuR6yDhDLJkJ6KiA", &task).await?;
Ok(())
Calling API Methods
API methods are available as methods on the corresponding client object. They are capitalized in
snakeCase (e.g., createTask
) to match the Taskcluster documentation.
Each method takes arguments in the following order, where appropriate to the method:
- Positional arguments (strings interpolated into the URL)
- Request body (payload)
- URL query arguments
The payload comes in the form of a serde_json::Value
, the contents of which should match the API
method's input schema. URL query arguments are all optional.
For example, the following lists all Auth clients:
use taskcluster::{Auth, ClientBuilder, Credentials};
let auth = Auth::new(ClientBuilder::new(&root_url))?;
let mut continuation_token: Option<String> = None;
let limit = Some("10");
loop {
let res = auth
.listClients(None, continuation_token.as_deref(), limit)
.await?;
for client in res.get("clients").unwrap().as_array().unwrap() {
println!("{:?}", client);
}
if let Some(v) = res.get("continuationToken") {
continuation_token = Some(v.as_str().unwrap().to_owned());
} else {
break;
}
}
Error Handling
All 5xx (server error) responses are automatically retried.
All 4xx (client error) responses are converted to Result::Err
.
All other responses are treated as successful responses.
Note that this includes 3xx (redirection) responses; the client does not automatically follow such redirects.
Client methods return anyhow::Error
, but this can be downcast to a reqwest::Error
if needed.
As a shortcut for the common case of getting the HTTP status code for an error, use err_status_code
.
The reqwest::StatusCode
type that this returns is re-exported from this crate.
Low-Level Access
Instead of using service-specific types, it is possible to call API methods directly by path, using
the Client
type:
use std::env;
use taskcluster::{ClientBuilder, Credentials};
let creds = Credentials::from_env()?;
let root_url = env::var("TASKCLUSTER_ROOT_URL").unwrap();
let client = ClientBuilder::new(&root_url).credentials(creds).build()?;
let resp = client.request("POST", "api/queue/v1/task/G08bnnBuR6yDhDLJkJ6KiA/cancel", None, None).await?;
assert!(resp.status().is_success());
Uploading and Downloading Objects
The taskcluster-upload
and taskcluster-download
crates contain dedicated support for resilient uploads and downloads to/from the Taskcluster object service.
This comes in the form of functions that will both interface with the object service API and perform the negotiated upload/download method.
In all cases, you must supply a pre-configured Object
client, as well as required parameters to the object service API methods.
Generating URLs
To generate a unsigned URL for an API method, use <method>_url
:
use taskcluster::{Auth, ClientBuilder};
let root_url = env::var("TASKCLUSTER_ROOT_URL").unwrap();
let auth = Auth::new(ClientBuilder::new(&root_url))?;
let url = auth.listClients_url(Some("static/"), None, None)?;
assert_eq!(url, "https://tc-tests.example.com/api/auth/v1/clients/?prefix=static%2F".to_owned());
Generating Temporary Credentials
The create_named_temp_creds
method creates
temporary credentials:
use std::env;
use std::time::Duration;
use taskcluster::Credentials;
let creds = Credentials::from_env()?;
let temp_creds = creds.create_named_temp_creds(
"new-client-id",
Duration::from_secs(3600),
vec!["scope1", "scope2"])?;
assert_eq!(temp_creds.client_id, "new-client-id");
There is also a create_temp_creds
method which creates unamed temporary credentials, but its use
is not recommended.
Generating Timestamps
Taskcluster APIs expects ISO 8601 timestamps, of the sort generated by the JS Date.toJSON
method.
The chrono
crate supports generating compatible timestamps if included with the serde
feature.
This crate re-exports chrono
with that feature enabled.
To duplicate the functionality of the fromNow
function from other Taskcluster client libraries, use something like this:
use taskcluster::chrono::{DateTime, Utc, Duration};
use serde_json::json;
let expires = Utc::now() + Duration::days(2);
let json = json!({ "expires": expires });
Generating SlugIDs
Use the slugid crate to create slugIds (such as for a taskId).
Dependencies
~13–25MB
~450K SLoC