Origin Cloud SDK for Rust
The Rust client for Origin Cloud's REST APIs. Its service crates are generated
from the API definitions in
origincloudhq/api; origincloud-core is
what they share: credentials, endpoints, retries, errors, long-running
operations and read-your-writes.
[]
= "0.1"
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
| Crate | API |
|---|---|
origincloud-core |
The client every service crate uses, and longrunning::v1beta1 for resuming an operation by name |
origincloud-pvs |
Persistent volumes: volumes, snapshots, storage classes (origincloud_pvs::v1beta1) |
origincloud-location |
Regions and zones, and the services each zone offers (origincloud_location::v1beta1) |
origincloud-compute |
Instances, images, key pairs, volume attachments and the instance catalog (origincloud_compute::v1beta1) |
origincloud-network |
VPCs, subnets, routing, gateways, floating IPs, network interfaces, security groups, ACLs and DNS policies (origincloud_network::v1beta1) |
origincloud-resourcemanager |
Organizations, projects and their quotas (origincloud_resourcemanager::v1beta1) |
origincloud-iam |
Users, service accounts, roles, role bindings, permissions and the audit log (origincloud_iam::v1beta1) |
origincloud-billing |
Billing accounts and the projects they pay for, payment methods, cost and usage, spend limits and the price list (origincloud_billing::v1beta1) |
origincloud-observability |
The metrics the platform collects for a project's compute instances, volumes and network interfaces (origincloud_observability::v1beta1) |
origincloud-support |
Support cases, each a conversation between an organization and Origin Cloud support about a question or a problem (origincloud_support::v1beta1) |
origincloud-dns |
Hosted zones, their record sets, and private zones' VPC attachments (origincloud_dns::v1beta1) |
origincloud-sts |
The security token service: it turns a token from an identity provider outside Origin Cloud, such as a CI job's OIDC token, into the access token of a WORKLOAD service account that trusts it through a federated credential (origincloud_sts::v1beta1) |
origincloud-kms |
Grants: permission for one platform host to use one key for one operation and one encryption context, for at most an hour at a time (origincloud_kms::v1beta1) |
Example
use FieldMask;
use Client;
use ;
async
Credentials
Client::new takes the first of:
ORIGINCLOUD_ACCESS_TOKEN: an access token, sent as it is.ORIGINCLOUD_CLIENT_IDandORIGINCLOUD_CLIENT_SECRET: a service account's credential, exchanged for access tokens as they expire. This is what automation should use where it can't present an OIDC token.- A CI job's OIDC token, exchanged at the security token service for the
access token of the
WORKLOADservice account whose federated credential trusts the job: no secret to store. In a GitHub Actions job grantedpermissions: id-token: writethere is nothing to configure; elsewhere,ORIGINCLOUD_OIDC_TOKEN_FILEnames a file holding the token (any CI provider's, or a Kubernetes projected token), read again at every exchange, orORIGINCLOUD_OIDC_TOKENholds the token itself, as GitLab CI sets it for anid_tokensentry of that name; the file comes first. The token is exchanged again a minute before the access token expires, with a fresh job token; a token given inORIGINCLOUD_OIDC_TOKENcan't be renewed, so it is exchanged again as it is, until it expires itself. Once found, this step's errors are returned rather than passed over;ORIGINCLOUD_OIDC_DISABLED=trueleaves it out,ORIGINCLOUD_STS_ENDPOINTpoints it at another STS (defaulthttps://sts.origincloudapis.eu) andORIGINCLOUD_OIDC_AUDIENCErequests GitHub's token for another audience (the same default). - The session the
originCLI stored at its last login (origin id login). - On an instance that runs as a service account, its credential from the
instance's metadata service: nothing to configure, and no secret on the
instance. Off an instance, this step fails within about two seconds;
ORIGINCLOUD_METADATA_DISABLED=trueleaves it out, andORIGINCLOUD_METADATA_ENDPOINTpoints it at another address.
Client::builder().credentials(...) sets them explicitly instead.
Behaviour
- Endpoints. Every service answers at
{service}.origincloudapis.eu, which serves every resource wherever it lives.ClientBuilder::region, orORIGINCLOUD_REGION, picks a region's front door instead,{service}.{region}.origincloudapis.eu, for the services that have one; a global service, such as location, keeps its regionless host. - Names. A resource's
nameis its relative name; its full resource name,//{service}.origincloudapis.eu/{name}, is what references carry.origincloud_core::FullNameparses one (refusing a URN, a relative name, a regional or zonal host, a version), builds one withfrom_relative, and gives itsservice,host,relativename andurl; principals and roles are iam names (principal,role). A request'snameorparenttakes either form. A full name is checked against the type the field refers to: the client's own service for its own resources, the referenced type's service otherwise (a billing account'sparenttakes//resourcemanager.origincloudapis.eu/organizations/o). It is sent as its relative name, in the path and the body alike, and a full name on any other host is refused before anything is sent. - Operations. A create, update or delete returns an
Operation; itswaitreturns the resource once the change is complete, or the error the change failed with. - Retries. A call answered as retryable is sent again with a growing delay,
when sending it again is safe: a read, or a mutation with a request id. The
client fills in an empty request id, so a retried create never creates twice.
ClientBuilder::max_attemptsbounds every call; a service client'swith_options(CallOptions::new().max_attempts(1))turns retries off for the calls made through it, for a mutation that must not be sent twice. - Read-your-writes. The client keeps the consistency token each write
answers with and sends it with later calls, so a read right after a write, or
after waiting on an operation, sees it. The token answered last is the one
kept: of concurrent writes, a read is sure to see the last answered. Clients
given the same
ClientBuilder::consistency_token_storeshare one token. A call the API refuses because its token isn't one is sent again once without it, and the token is dropped. - Pages. Each list method has an
all_...counterpart that streams every page. - Errors. A refused call returns
Error::Api; branch onError::reason, the platform's error code.ApiError::metadatasays more about some reasons, such as the name of the resource aCONFLICTis about. - Runtime. The clients are
async, on Tokio, and send their calls with reqwest; in a browser, see below.
In a browser
The crates build for wasm32-unknown-unknown, for a web app written in Rust
(Leptos, Yew, Dioxus, ...). There is no Tokio there: calls go out through the
browser's fetch, retries wait on setTimeout, and the futures run on the
app's executor, such as wasm_bindgen_futures::spawn_local. They aren't
Send there (the bound is origincloud_core::MaybeSend, the boxed future
MaybeSendFuture), but Client and
the Credentials it holds still are Send + Sync, so a client can live in
the framework's reactive state.
A browser has no environment, files, CI token or metadata service, so only
these credentials exist there, and Client::new without them fails with
Error::NoCredentials:
AccessToken: a token the page already holds, such as the user's from its OIDC login.- Your own
Credentials, for a token the page renews itself. ServiceAccountonly with the featureservice-account-wasm, for a wasm runtime that isn't a browser (Node.js, Deno, an edge worker). It is left out by default because a browser app, its Web Workers included, is downloaded by whoever loads it, and a client secret in it with it.
let client = builder
.credentials
.build?;
ClientBuilder::timeout bounds each attempt there too; a reqwest::Client
set with ClientBuilder::http_client has no connect timeout or proxy
settings in a browser, which leaves them to the browser. A response body is
read whole and then held to the same 32 MiB limit. A retry waits at most
about 24.8 days there, the longest a browser timer can, however long the
server asks.
A call to a method that authenticates no caller, such as billing's legal
documents, carries no User-Agent and no consistency token, only Accept, so
the browser sends it without a CORS preflight.
Versions
A service crate's modules are its API's versions: origincloud_pvs::v1beta1 is
the preview version of the PVS API and may change in incompatible ways, like
the API itself. The crates follow semantic versioning; before 1.0, a minor
version may change the Rust API incompatibly.
Contributing
Issues and pull requests are welcome. The service crates are generated from the API definitions, so a change to what a service offers starts as an issue; see CONTRIBUTING.md for how the SDK is built and checked.
License
Apache License 2.0; see LICENSE.