mod api_error;
mod builder;
mod data;
mod scaleway_error;
pub use api_error::{ScalewayApiError, ScalewayApiErrorDetails};
use builder::list_marketplace_image_versions_builder::ScalewayListMarketplaceImageVersionsBuilder;
use data::availability::ScalewayAvailabilityRoot;
use data::instance::ScalewayInstanceRoot;
use data::server_type::ScalewayServerTypeRoot;
use reqwest::header::CONTENT_TYPE;
use serde::Serialize;
use serde_json::json;
use std::collections::HashMap;
pub use builder::{
create_instance_builder::ScalewayCreateInstanceBuilder,
create_project_builder::ScalewayCreateProjectBuilder,
create_security_group_builder::ScalewayCreateSecurityGroupBuilder,
create_security_group_rule_builder::ScalewayCreateSecurityGroupRuleBuilder,
create_ssh_key_builder::ScalewayCreateSSHKeyBuilder,
get_project_builder::ScalewayGetProjectBuilder,
get_security_group_builder::ScalewayGetSecurityGroupBuilder,
get_security_group_rule_builder::ScalewayGetSecurityGroupRuleBuilder,
get_ssh_key_builder::ScalewayGetSSHKeyBuilder,
list_instance_builder::ScalewayListInstanceBuilder,
list_instance_images_builder::ScalewayListInstanceImagesBuilder,
list_marketplace_images_builder::ScalewayListMarketplaceImagesBuilder,
list_marketplace_local_images_builder::LocalImageListType,
list_marketplace_local_images_builder::ScalewayListMarketplaceLocalImagesBuilder,
list_projects_builder::ScalewayListProjectsBuilder,
list_security_group_rules_builder::ScalewayListSecurityGroupRulesBuilder,
list_security_groups_builder::ScalewayListSecurityGroupsBuilder,
list_ssh_keys_builder::ScalewayListSSHKeysBuilder,
};
pub use data::architecture::ScalewayArchitecture;
pub use data::image::{
ScalewayImage, ScalewayImageBootscript, ScalewayImageExtraVolume,
ScalewayImageExtraVolumeServer, ScalewayImageExtraVolumes, ScalewayImageRootVolume,
};
pub use data::instance::{
ScalewayInstance, ScalewayInstanceLocation, ScalewayIpv6, ScalewayMaintenance,
ScalewayPlacementGroup, ScalewayPrivateNic, ScalewayPublicIP, ScalewaySecurityGroup,
};
pub use data::marketplace_image::ScalewayMarketplaceImage;
pub use data::security_group::{
ScalewaySecurityGroupDetails, ScalewaySecurityGroupRule, SecurityGroupPolicy,
SecurityGroupRuleAction, SecurityGroupRuleDirection, SecurityGroupRuleProtocol,
};
pub use data::project::ScalewayProject;
pub use data::server_type::ServerType;
pub use data::api_key::ScalewayApiKey;
pub use data::application::ScalewayApplication;
pub use data::user::ScalewayUser;
pub use data::ssh_key::ScalewaySSHKey;
pub use data::user_data::ScalewayUserData;
pub use data::user_data::ScalewayUserDataKeyList;
pub use scaleway_error::ScalewayError;
#[derive(Clone)]
pub struct ScalewayApi {
secret_key: String,
}
impl<'a> ScalewayApi {
pub fn new<S>(secret_key: S) -> ScalewayApi
where
S: Into<String>,
{
ScalewayApi {
secret_key: secret_key.into(),
}
}
async fn get_async(
&self,
url: &str,
query: Vec<(&'static str, String)>,
) -> Result<reqwest::Response, ScalewayError> {
let client = reqwest::Client::new();
let resp = client
.get(url)
.header("X-Auth-Token", &self.secret_key)
.query(&query)
.send()
.await
.map_err(|e| ScalewayError::Reqwest(e))?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json().await?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
#[cfg(feature = "blocking")]
fn get(
&self,
url: &str,
query: Vec<(&'static str, String)>,
) -> Result<reqwest::blocking::Response, ScalewayError> {
let client = reqwest::blocking::Client::new();
let resp = client
.get(url)
.header("X-Auth-Token", &self.secret_key)
.query(&query)
.send()?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json()?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
async fn post_async<T>(&self, url: &str, json: T) -> Result<reqwest::Response, ScalewayError>
where
T: Serialize + Sized,
{
let client = reqwest::Client::new();
let resp = client
.post(url)
.header("X-Auth-Token", &self.secret_key)
.json(&json)
.send()
.await?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json().await?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
#[cfg(feature = "blocking")]
fn post<T>(&self, url: &str, json: T) -> Result<reqwest::blocking::Response, ScalewayError>
where
T: Serialize + Sized,
{
let client = reqwest::blocking::Client::new();
let resp = client
.post(url)
.header("X-Auth-Token", &self.secret_key)
.json(&json)
.send()?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json()?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
async fn patch_async(
&self,
url: &str,
content: &str,
) -> Result<reqwest::Response, ScalewayError> {
let client = reqwest::Client::new();
let resp = client
.patch(url)
.header(CONTENT_TYPE, "text/plain")
.header("X-Auth-Token", &self.secret_key)
.body(content.to_string())
.send()
.await?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json().await?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
#[cfg(feature = "blocking")]
fn patch(
&self,
url: &str,
content: &str,
) -> Result<reqwest::blocking::Response, ScalewayError> {
let client = reqwest::blocking::Client::new();
let resp = client
.patch(url)
.header(CONTENT_TYPE, "text/plain")
.header("X-Auth-Token", &self.secret_key)
.body(content.to_string())
.send()?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json()?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
async fn delete_async(&self, url: &str) -> Result<reqwest::Response, ScalewayError> {
let client = reqwest::Client::new();
let resp = client
.delete(url)
.header("X-Auth-Token", &self.secret_key)
.send()
.await?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json().await?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
#[cfg(feature = "blocking")]
fn delete(&self, url: &str) -> Result<reqwest::blocking::Response, ScalewayError> {
let client = reqwest::blocking::Client::new();
let resp = client
.delete(url)
.header("X-Auth-Token", &self.secret_key)
.send()?;
let status = resp.status();
if status.is_client_error() {
let result: ScalewayApiError = resp.json()?;
Err(ScalewayError::Api(result))
} else {
Ok(resp.error_for_status()?)
}
}
pub fn az_list() -> Vec<&'static str> {
vec![
"fr-par-1", "fr-par-2", "fr-par-3", "nl-ams-1", "nl-ams-2", "nl-ams-3", "pl-waw-1",
"pl-waw-2", "pl-waw-3", "it-mil-1",
]
}
#[cfg(feature = "blocking")]
pub fn get_server_types(&self, zone: &str) -> Result<Vec<ServerType>, ScalewayError> {
let types: Vec<ServerType> = self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/servers",
zone = zone
),
vec![],
)?
.json::<ScalewayServerTypeRoot>()?
.servers
.servers
.into_iter()
.map(|(id, item)| ServerType {
id,
location: zone.to_string(),
alt_names: item.alt_names,
arch: item.arch,
ncpus: item.ncpus,
ram: item.ram,
gpu: item.gpu,
monthly_price: item.monthly_price,
hourly_price: item.hourly_price,
network: item.network,
})
.collect();
Ok(types)
}
pub async fn get_server_types_async(
&self,
zone: &str,
) -> Result<Vec<ServerType>, ScalewayError> {
let types: Vec<ServerType> = self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/servers",
zone = zone
),
vec![],
)
.await?
.json::<ScalewayServerTypeRoot>()
.await?
.servers
.servers
.into_iter()
.map(|(id, item)| ServerType {
id,
location: zone.to_string(),
alt_names: item.alt_names,
arch: item.arch,
ncpus: item.ncpus,
ram: item.ram,
gpu: item.gpu,
monthly_price: item.monthly_price,
hourly_price: item.hourly_price,
network: item.network,
})
.collect();
Ok(types)
}
pub fn list_images(&self, zone: &str) -> ScalewayListInstanceImagesBuilder {
ScalewayListInstanceImagesBuilder::new(self.clone(), zone)
}
pub fn list_instances(&self, zone: &str) -> ScalewayListInstanceBuilder {
ScalewayListInstanceBuilder::new(self.clone(), zone)
}
pub fn list_marketplace_instances(&self) -> ScalewayListMarketplaceImagesBuilder {
ScalewayListMarketplaceImagesBuilder::new(self.clone())
}
pub fn list_marketplace_instance_versions(
&self,
image_id: &str,
) -> ScalewayListMarketplaceImageVersionsBuilder {
ScalewayListMarketplaceImageVersionsBuilder::new(self.clone(), image_id)
}
pub fn list_marketplace_local_images(
&self,
list_type: LocalImageListType,
) -> ScalewayListMarketplaceLocalImagesBuilder {
ScalewayListMarketplaceLocalImagesBuilder::new(self.clone(), list_type)
}
pub fn create_instance(
&self,
zone: &str,
name: &str,
commercial_type: &str,
) -> ScalewayCreateInstanceBuilder {
ScalewayCreateInstanceBuilder::new(self.clone(), zone, name, commercial_type)
}
#[cfg(feature = "blocking")]
pub fn get_instance(
&self,
zone: &str,
server_id: &str,
) -> Result<ScalewayInstance, ScalewayError> {
Ok(self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}",
zone = zone,
server_id = server_id
),
vec![],
)?
.json::<ScalewayInstanceRoot>()?
.server)
}
pub async fn get_instance_async(
&self,
zone: &str,
server_id: &str,
) -> Result<ScalewayInstance, ScalewayError> {
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}",
zone = zone,
server_id = server_id
),
vec![],
)
.await?
.json::<ScalewayInstanceRoot>()
.await?
.server)
}
#[cfg(feature = "blocking")]
pub fn delete_instance(&self, zone: &str, server_id: &str) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}",
zone = zone,
server_id = server_id
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_instance_async(
&self,
zone: &str,
server_id: &str,
) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}",
zone = zone,
server_id = server_id
))
.await?
.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn perform_instance_action(
&self,
zone: &str,
server_id: &str,
action: &str,
) -> Result<(), ScalewayError> {
self.post(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/action",
zone = zone,
server_id = server_id
),
json!({"action": action}),
)?
.error_for_status()?;
Ok(())
}
pub async fn perform_instance_action_async(
&self,
zone: &str,
server_id: &str,
action: &str,
) -> Result<(), ScalewayError> {
self.post_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/action",
zone = zone,
server_id = server_id
),
json!({"action": action}),
)
.await?
.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn list_availability(&self, zone: &str) -> Result<HashMap<String, bool>, ScalewayError> {
let servers = self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/servers/availability",
zone = zone
),
vec![],
)?
.json::<ScalewayAvailabilityRoot>()?
.servers
.servers
.into_iter()
.map(|(id, available)| (id, available.availability == "available"))
.collect();
Ok(servers)
}
pub async fn list_availability_async(
&self,
zone: &str,
) -> Result<HashMap<String, bool>, ScalewayError> {
let servers = self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/servers/availability",
zone = zone
),
vec![],
)
.await?
.json::<ScalewayAvailabilityRoot>()
.await?
.servers
.servers
.into_iter()
.map(|(id, available)| (id, available.availability == "available"))
.collect();
Ok(servers)
}
#[cfg(feature = "blocking")]
pub fn list_userdata_keys(
&self,
zone: &str,
machine_id: &str,
) -> Result<Vec<String>, ScalewayError> {
let user_data = self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data",
zone = zone,
server_id = machine_id,
),
vec![],
)?
.json::<ScalewayUserDataKeyList>()?
.user_data;
Ok(user_data)
}
pub async fn list_userdata_keys_async(
&self,
zone: &str,
machine_id: &str,
) -> Result<Vec<String>, ScalewayError> {
let user_data = self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data",
zone = zone,
server_id = machine_id,
),
vec![],
)
.await?
.json::<ScalewayUserDataKeyList>()
.await?
.user_data;
Ok(user_data)
}
#[cfg(feature = "blocking")]
pub fn get_userdata(
&self,
zone: &str,
machine_id: &str,
key: &str,
) -> Result<ScalewayUserData, ScalewayError> {
let servers = self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
),
vec![],
)?
.json::<ScalewayUserData>()?;
Ok(servers)
}
pub async fn get_userdata_async(
&self,
zone: &str,
machine_id: &str,
key: &str,
) -> Result<ScalewayUserData, ScalewayError> {
let user_data = self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
),
vec![],
)
.await?
.json::<ScalewayUserData>()
.await?;
Ok(user_data)
}
#[cfg(feature = "blocking")]
pub fn set_userdata(
&self,
zone: &str,
machine_id: &str,
key: &str,
value: &str,
) -> Result<(), ScalewayError> {
self
.patch(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
), value)?
.error_for_status()?;
Ok(())
}
pub async fn set_userdata_async(
&self,
zone: &str,
machine_id: &str,
key: &str,
value: &str,
) -> Result<(), ScalewayError> {
self
.patch_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
), value)
.await?.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn delete_userdata(
&self,
zone: &str,
machine_id: &str,
key: &str,
) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_userdata_async(
&self,
zone: &str,
machine_id: &str,
key: &str,
) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/servers/{server_id}/user_data/{key}",
zone = zone,
server_id = machine_id,
key = key,
))
.await?
.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn delete_volume(&self, zone: &str, volume_id: &str) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/volumes/{volume_id}",
zone = zone,
volume_id = volume_id,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_volume_async(
&self,
zone: &str,
volume_id: &str,
) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/volumes/{volume_id}",
zone = zone,
volume_id = volume_id,
))
.await?
.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn delete_securitygroup(
&self,
zone: &str,
security_group_id: &str,
) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/security_groups/{security_group_id}",
zone = zone,
security_group_id = security_group_id,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_securitygroup_async(
&self,
zone: &str,
security_group_id: &str,
) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/security_groups/{security_group_id}",
zone = zone,
security_group_id = security_group_id,
))
.await?
.error_for_status()?;
Ok(())
}
pub fn list_security_groups(&self, zone: &str) -> ScalewayListSecurityGroupsBuilder {
ScalewayListSecurityGroupsBuilder::new(self.clone(), zone)
}
pub fn get_security_group(
&self,
zone: &str,
security_group_id: &str,
) -> ScalewayGetSecurityGroupBuilder {
ScalewayGetSecurityGroupBuilder::new(self.clone(), zone, security_group_id)
}
pub fn create_security_group(
&self,
zone: &str,
name: &str,
stateful: bool,
) -> ScalewayCreateSecurityGroupBuilder {
ScalewayCreateSecurityGroupBuilder::new(self.clone(), zone, name, stateful)
}
pub fn list_security_group_rules(
&self,
zone: &str,
security_group_id: &str,
) -> ScalewayListSecurityGroupRulesBuilder {
ScalewayListSecurityGroupRulesBuilder::new(self.clone(), zone, security_group_id)
}
pub fn get_security_group_rule(
&self,
zone: &str,
security_group_id: &str,
rule_id: &str,
) -> ScalewayGetSecurityGroupRuleBuilder {
ScalewayGetSecurityGroupRuleBuilder::new(self.clone(), zone, security_group_id, rule_id)
}
pub fn create_security_group_rule(
&self,
zone: &str,
security_group_id: &str,
ip_range: &str,
protocol: SecurityGroupRuleProtocol,
direction: SecurityGroupRuleDirection,
action: SecurityGroupRuleAction,
) -> ScalewayCreateSecurityGroupRuleBuilder {
ScalewayCreateSecurityGroupRuleBuilder::new(
self.clone(),
zone,
security_group_id,
ip_range,
protocol,
direction,
action,
)
}
#[cfg(feature = "blocking")]
pub fn delete_security_group_rule(
&self,
zone: &str,
security_group_id: &str,
rule_id: &str,
) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/security_groups/{sg_id}/rules/{rule_id}",
zone = zone,
sg_id = security_group_id,
rule_id = rule_id,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_security_group_rule_async(
&self,
zone: &str,
security_group_id: &str,
rule_id: &str,
) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/security_groups/{sg_id}/rules/{rule_id}",
zone = zone,
sg_id = security_group_id,
rule_id = rule_id,
))
.await?
.error_for_status()?;
Ok(())
}
pub fn list_ssh_keys(&self) -> ScalewayListSSHKeysBuilder {
ScalewayListSSHKeysBuilder::new(self.clone())
}
pub fn get_ssh_key(&self, ssh_key_id: &str) -> ScalewayGetSSHKeyBuilder {
ScalewayGetSSHKeyBuilder::new(self.clone(), ssh_key_id)
}
#[cfg(feature = "blocking")]
pub fn get_api_key(&self, access_key: &str) -> Result<ScalewayApiKey, ScalewayError> {
Ok(self
.get(
&format!(
"https://api.scaleway.com/iam/v1alpha1/api-keys/{access_key}",
access_key = access_key
),
vec![],
)?
.json::<ScalewayApiKey>()?)
}
pub async fn get_api_key_async(
&self,
access_key: &str,
) -> Result<ScalewayApiKey, ScalewayError> {
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/iam/v1alpha1/api-keys/{access_key}",
access_key = access_key
),
vec![],
)
.await?
.json::<ScalewayApiKey>()
.await?)
}
pub fn create_ssh_key(&self, name: &str, public_key: &str) -> ScalewayCreateSSHKeyBuilder {
ScalewayCreateSSHKeyBuilder::new(self.clone(), name, public_key)
}
#[cfg(feature = "blocking")]
pub fn delete_ssh_key(&self, ssh_key_id: &str) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/iam/v1alpha1/ssh-keys/{ssh_key_id}",
ssh_key_id = ssh_key_id,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_ssh_key_async(&self, ssh_key_id: &str) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/iam/v1alpha1/ssh-keys/{ssh_key_id}",
ssh_key_id = ssh_key_id,
))
.await?
.error_for_status()?;
Ok(())
}
pub fn list_projects(&self) -> ScalewayListProjectsBuilder {
ScalewayListProjectsBuilder::new(self.clone())
}
pub fn get_project(&self, project_id: &str) -> ScalewayGetProjectBuilder {
ScalewayGetProjectBuilder::new(self.clone(), project_id)
}
pub fn create_project(
&self,
name: &str,
organization_id: &str,
) -> ScalewayCreateProjectBuilder {
ScalewayCreateProjectBuilder::new(self.clone(), name, organization_id)
}
#[cfg(feature = "blocking")]
pub fn delete_project(&self, project_id: &str) -> Result<(), ScalewayError> {
self.delete(&format!(
"https://api.scaleway.com/account/v3/projects/{project_id}",
project_id = project_id,
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_project_async(&self, project_id: &str) -> Result<(), ScalewayError> {
self.delete_async(&format!(
"https://api.scaleway.com/account/v3/projects/{project_id}",
project_id = project_id,
))
.await?
.error_for_status()?;
Ok(())
}
#[cfg(feature = "blocking")]
pub fn get_application(
&self,
application_id: &str,
) -> Result<ScalewayApplication, ScalewayError> {
Ok(self
.get(
&format!(
"https://api.scaleway.com/iam/v1alpha1/applications/{application_id}",
application_id = application_id
),
vec![],
)?
.json::<ScalewayApplication>()?)
}
pub async fn get_application_async(
&self,
application_id: &str,
) -> Result<ScalewayApplication, ScalewayError> {
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/iam/v1alpha1/applications/{application_id}",
application_id = application_id
),
vec![],
)
.await?
.json::<ScalewayApplication>()
.await?)
}
#[cfg(feature = "blocking")]
pub fn get_user(&self, user_id: &str) -> Result<ScalewayUser, ScalewayError> {
Ok(self
.get(
&format!(
"https://api.scaleway.com/iam/v1alpha1/users/{user_id}",
user_id = user_id
),
vec![],
)?
.json::<ScalewayUser>()?)
}
pub async fn get_user_async(&self, user_id: &str) -> Result<ScalewayUser, ScalewayError> {
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/iam/v1alpha1/users/{user_id}",
user_id = user_id
),
vec![],
)
.await?
.json::<ScalewayUser>()
.await?)
}
}