Google for Rust Developers
- 5 minutes read - 1031 wordsBackground
I’m a neophyte Rust developer but I’m very familiar with developing against Google’s APIs|services using its SDKs in its a subset (Golang, Python, JavaScript) of its supported (Go, Java, JavaScript,Python, Ruby, PHP, C#, C++) languages. It’s curious to me that, while Google invests in Rust, it has not added support for Rust (and I guess Swift would be another contender) to its SDK portfolio.
This would be easier to accept if Google’s SDK story weren’t so complicated and poorly explained. Once you’re familiar with Google’s SDK story for a specific language, life is good but picking a supported language at random (e.g. JavaScript or PHP) and trying to identify which SDK you should use for a specific service and where the documentation is located could require trawling across Google’s own domains, GitHub repos, language-specific repositories etc.
Google is one of the Founding Platinum Members of the Rust Foundation. Google’s [Android Open Source Project (AOSP)] supports Rust development and Google is advocating for Rust in the Linux kernel.
If it’s not clear already, Google is not Google and, while some product areas (e.g. Android) may be adopting Rust, the rest of the businesses haven’t. This post is my attempt to summarize the status quo and provide other developers with some guidelines on how to approach developing Rust apps that integrate with Google’s APIs (services). I’ll caveat this by saying that I’m a noob Rust developer, everything that follows is likely to change rapidly and, if you’re committed, thanks to some excellent decisions made at the foundation of Google’s developer strategy, you can (probably) do almost anything you need to do with Google’s APIs|services.
APIs Explorer
Google provides a single view into the entirety of its APIs through APIs Explorer. If an API is not listed on APIs Explorer, then it’s probably (not definitively) not available. APIs Explorer not only lists the APIs but, as you’d expect, it documents the APIs’ methods and their request and response types. This content is machine-generated and so it’s very unlikely that it’s incorrect. APIs Explorer method pages often include a “Try this API” which is a browser pane comprising a form generated from the API method’s request type that allows you to plug in your values and EXECUTE
the method.
SUGGESTION Try API method using “Try this API” to ensure that you understand what request message is required by a method to invoke it and to understand the response message that is returned.
Client Libraries Explained
Because it’s confusing, Google needs to document why there are multiple SDKs for each language for each API. What’s not explained is that this is a result of history and that Google is not Google.
(REST) API Client Libraries
Historically, every public Google service was exposed through a REST API. Because Google has been publishing APIs for a considerable time, Google’s mechanisms predate OpenAPI (formerly Swagger). Google publishes metadata (schemas) for its REST APIs using so-called Discovery Documents. Because it’s consistent, Google publishes Discovery Documents for all its REST APIs services using another service called the Google API Discovery Service. APIs Explorer is effectively an enumeration of the Discovery Service and all its documents.
NOTE Google Cloud Endpoints and I assume Google API Gateway (formerly Apigee), both generate OpenAPI schemas for user-published services.
Turtles You can use APIs Explorer to list the Discovery Service and then “Try the API” for the Discovery Service’s
list
method to list the Discovery Service’s Discovery Document…
With a Discovery Document for a service (as you would using e.g. OpenAPI), it’s possible to generate a language-specific SDK to interact with the service. Google documents Building a Client Library and, as you’d expect has tools that automate this. There’s an open source equivalent called [Google APIs Client Generator(https://github.com/google/apis-client-generator). This generator does not generate Rust see this issue and see below.
For its supported languages, Google automatically generates and publishes SDKs (called “API Client Libraries”) and documentation for every service represented by a Discovery Document in the Discovery Service. Here’s the list by language.
Enterprising Rust developers realized that this is a gateway to automatically provide Rust SDKs for all of Google’s public REST APIs:
- Google-API bindings for Rust
- google-apis-rs [Maintenance Mode]
Here’s an example using Google Service Usage v1 API.
git clone git@github.com:google-apis-rs/generator.git
cd generator
SUGGESTION In order to determine which APIs
gcloud
is using, you can append--log-http
to anygcloud
command and the output will include details of underlying REST calls. In this case, I incorrectly thought the API being used wasservicemanagement
but, after runninggcloud services list --enabled --project=${PROJECT} --log-http
, I realized the underlying API is actuallyserviceusage
.
NOTE Google’s REST reference documentation lists all available API versions. To clarify the order of API versions:
vXalpha
beforevXbeta
beforevX
To use the generator
, we’ll want a copy of our service’s Discovery Document. Using APIs Explorer, we can find it using the Discovery Service list method here
https://serviceusage.googleapis.com/$discovery/rest?version=v1
NOTE If you can determine the service’s host name (i.e.
serviceusage
), then you can determine the URL to its Disovery Document
SERVICE="serviceusage"
VERSION="v1"
# Or your preferred location
mkdir -p \
${PWD}/specs/${SERVICE}/${VERSION} \
${PWD}/output/${SERVICE}/${VERSION}
curl \
--silent \
--output ${PWD}/specs/${SERVICE}/${VERSION}/spec.json \
https://${SERVICE}.googleapis.com/\$discovery/rest?version=${VERSION}
NOTE Ensure you escape the
$
prepended to$discovery
(\$discovery
)
Then:
cargo run \
-- \
generate \
${PWD}/specs/${SERVICE}/${VERSION}/spec.json \
${PWD}/output/${SERVICE}/${VERSION}
This (should) generate a library and a binary (cli) project. The library project (${PWD}/output/${SERVICE}/${VERSION}/lib
) is the one we’re interested in. You’ll need to add this to your project’s dependencies
:
[package]
name = "serviceusage"
version = "0.1.0"
edition = "2021"
[dependencies]
google-serviceusage-v1 = { path = "/path/to/generator/output/serviceusage/v1/lib" }
One challenge with generated code (Discovery, OpenAPI, gRPC) is that it’s generally not “idiomatic”. Idiomatic in this context infers that the SDK shape (look and feel) is as they’d expect having used other libraries|SDKs in the language. As an aside, one advantage of the SDKs being shaped more by their being Google APIs than the specific language is that it’s quite easy to translate code from one langauge to another.
To provide more idiomatic libraries, Google Cloud Platform (and only the subset of the Google Cloud Platform services, i.e. not Ads, not Workspace etc.) has a set of SDKs called Cloud Client Libraries.