Introducing the Clever Cloud Rust SDK - Clever Cloud
Back to clever-cloud.com

Well, if you need some logos, we provide these:

svg ·  png
Red Clever Cloud logo
svg ·  png
svg ·  png
White Clever Cloud logo
svg · png
White Clever Cloud logo
svg · png
Posted at April 28, 2022 — Engineering

Introducing the Clever Cloud Rust SDK

Hello 🖖, fellow humans and robots! Our engineering team is proud to announce a brand new Rust software development kit (sdk), also known as “clevercloud-sdk” on crates.io.

Some of you may have noticed that there are new repositories on our GitHub organization. Those repositories are named “clevercloud-sdk-rust” and “oauth10a-rust“. Their goal is to provide a convenient way to interact with the Clever Cloud’s API with interesting features that we will highlights in this blog post.

Built to be asynchronous

The software development kit and the oauth 1.0a client are mainly built on top of two crates that are well-known in the community. Those are hyper, and the asynchronous runtime that power it, named tokio.

The main idea behind using the hyper crate and by extension the tokio asynchronous runtime is to leverage the current ecosystem that gravitates around these crates and efforts to integrate a new kernel API called io_uring. Once this new kernel API will be integrated into the tokio runtime, this will lead to significant performance, enhancement according to the tokio’s announcement blog post. We can’t wait for this enhancement that will give us a way to iterate faster! 🚀

Observability in mind

These crates are developed with the idea to be fully observable. It has been achieved through others well-known crates as log and tracing, or using community initiatives like the prometheus crate. Integrations of those crates are taking part of the compiler feature flags system provided by the cargo project.

Standard logging facade

First, you need to know that the standard logging facade is enabled by default. It will output useful information of internals behaviors of above crates, using the standard logger if it is defined. It will help you to understand how calls to the Clever Cloud’s API are achieved with some debug information, if you need so.

if you want to disable it, you have to disable the default sets of enabled features. This could be achieved using the following syntax for the clevercloud-sdk crate in your Cargo.toml file.

clevercloud-sdk = { version = "^0.10.0", default-features = false }

Metrics-oriented

At Clever Cloud, we think that metrics are important. They help to understand systems by correlating things that doesn’t seem to be related in the first place.

This is why we have launched Clever Cloud Metrics rather soon, some years ago. We recently added more features to it by providing more ways to query Clever Cloud Metrics, thanks to Erlenmeyer which is a time series query language proxy. You can find more details of how you could use it through this blog post.

Lastly, we have announced the Tardis product which empowers you to send us your metrics and we take care of the rest as we always do and more recently we have integrated pre-built Grafana’s dashboards to help you to visualize your applications and add-ons state, you can learn more about it here.

Coming back to our crates. You can enable metrics collection using the prometheus crate, by enabling the metrics flags at crate-level in your Cargo.toml file. It could be achieved using the following syntax.

clevercloud-sdk = { version = "^0.10.0", features = ["metrics"] }

Once this feature is enabled, there isn’t much more to do. You will need to expose metrics through an HTTP server or send them using the prometheus push gateway. This part is described in the prometheus crate’s documentation or in its examples.

Tracing capabilities

Last but not least, a pillar of observability is tracing. According to the OpenTelemetry initiative and documentation, tracing is explained as such:

Traces track the progression of a single request, called a trace, as it is handled by services that make up an application. The request may be initiated by a user or an application. Distributed tracing is a form of tracing that traverses process, network and security boundaries. Each unit of work in a trace is called a span; a trace is a tree of spans. Spans are objects that represent the work being done by individual services or components involved in a request as it flows through a system. A span contains a span context, which is a set of globally unique identifiers that represent the unique request that each span is a part of. A span provides Request, Error and Duration (RED) metrics that can be used to debug availability as well as performance issues…

OpenTelemetry documentation

If you want to take a closer look to tracing, even if it is not in Rust, you can take a look at the OpenTelemetry GitHub organization. There are plenty of libraries, SDKs and documentation to help you to build your tracing solution or integrate with an already existing one. Besides, if you are using the rust language and maybe the tokio runtime, you can have a look at those blog posts which explain how tracing works in the above asynchronous runtime and how to visualize them using the console or using the OpenTelemetry connector which allow to send traces to more sinks, the list is available on the rust OpenTelemetry GitHub repository.

So how do we concretely enable the tracing feature using the clevercloud-sdk ? As mentioned above all features are driven using a feature flag, so to get tracing capabilities, you need to enable the trace flag.

clevercloud-sdk = { version = "^0.10.0", features = ["trace"] }

Once the feature flag has been enabled, you will need to collect and send traces using the above connector and sinks.

How does it look?

Let us look at a concrete example to illustrate what the clevercloud-sdk looks like. But before going through the usage of the clevercloud-sdk, I will introduce you to the dependencies and requirements you will need. The first thing you need to achieve is to declare crates in the Cargo.toml file.

[dependencies]
tokio = { version = "^1.17.0", features = ["full"] }
clevercloud-sdk = { version = "^0.10.0", features = ["metrics", "tokio", "trace", "jsonschemas"] }

We are now able to write a proper piece of software using the clevercloud-sdk. Here is an example of how to use the SDK:

...
use clevercloud_sdk::{
    oauth10a::{
        proxy::{self, ProxyConnectorBuilder},
        Credentials,
    },
    v2::myself,
    Client,
};
...

// See the full code at:
// - https://github.com/CleverCloud/clevercloud-sdk-rust/blob/main/examples/cleverctl
// - https://github.com/CleverCloud/clevercloud-sdk-rust/blob/main/examples/cleverctl/src/cmd/myself.rs
pub async fn get(config: Arc<Configuration>, output: &Output) -> Result<(), Error> {
    let credentials: Credentials = config.credentials.to_owned().into();
    let connector = ProxyConnectorBuilder::try_from_env().map_err(Error::ProxyConnector)?;
    let client = Client::builder()
        .with_credentials(credentials)
        .build(connector);

    let user = myself::get(&client).await.map_err(Error::Get)?;

    println!(
        "{}",
        output
            .format(&user)
            .map_err(|err| Error::FormatOutput(Box::new(err)))?
    );

    Ok(())
}

Another example of the sdk which interact with add-ons:

...
use clevercloud_sdk::{
    oauth10a::{
        proxy::{self, ProxyConnectorBuilder},
        Credentials,
    },
    v2::addon,
    Client,
};
...

// See the full code at:
// - https://github.com/CleverCloud/clevercloud-sdk-rust/blob/main/examples/cleverctl
// - https://github.com/CleverCloud/clevercloud-sdk-rust/blob/main/examples/cleverctl/src/cmd/addon/mod.rs 
pub async fn list(
    config: Arc<Configuration>,
    output: &Output,
    organisation_id: &str,
) -> Result<(), Error> {
    let credentials: Credentials = config.credentials.to_owned().into();
    let connector = ProxyConnectorBuilder::try_from_env().map_err(Error::ProxyConnector)?;
    let client = Client::builder()
        .with_credentials(credentials)
        .build(connector);

    let addons = addon::list(&client, organisation_id)
        .await
        .map_err(|err| Error::List(organisation_id.to_owned(), err))?;

    println!(
        "{}",
        output
            .format(&addons)
            .map_err(|err| Error::FormatOutput(Box::new(err)))?
    );
    Ok(())
}

You can find the entire source code of the command line interface example in the clevercloud-sdk project into the examples repository or you can follow this link.

What’s next?

Let’s have a look at the incoming features that are to be integrated into these crates.

Biscuit and oauth2 bearer token

At Clever Cloud, we are working on a new authentication and authorization token called Biscuit. More details about it in the introduction blog post.

This new authentication and authorization token will work with the OAuth 2.0 standard. One job of the SDK and the client under the hood is to ease the transition from OAuth 1.0a to OAuth 2.0 using Biscuit.

New features!

The Software Development Kit will grow to support the entire API. The next feature is the integration of the event bus in order to subscribe to events that happen on Clever Cloud’s platform. You will be able to get notifications about a deployment of an application and so on…

Besides, those crates are used to build another software that you have discovered in another blog post. It introduce a Kubernetes operator that you may use on OpenShift, that exposes Clever Cloud’s add-ons as Custom Resources.

Tags:

Florentin Dubois

Senior software engineer @clever_cloud , former technical leader @OVHcloud, working on distributed systems and network infrastructures.

Follow me

Check out our Blog

We write about programming, security and Clever Cloud products

Join thousands of developers already using Clever Cloud. And try it for free!

Create your account now to start your apps and collaborate within a few minutes. For free with 20€ offered.

By signing up, your agree to our terms of use
Or
Sign in with Github