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::{
add_dns_record_builder::ScalewayAddDnsRecordBuilder,
create_flexible_ip_builder::ScalewayCreateFlexibleIpBuilder,
create_instance_builder::ScalewayCreateInstanceBuilder,
create_project_builder::ScalewayCreateProjectBuilder,
create_security_group_builder::ScalewayCreateSecurityGroupBuilder,
create_security_group_rule_builder::ScalewayCreateSecurityGroupRuleBuilder,
create_ssh_key_builder::ScalewayCreateSSHKeyBuilder,
create_volume_builder::ScalewayCreateVolumeBuilder,
list_volumes_builder::ScalewayListVolumesBuilder,
get_project_builder::ScalewayGetProjectBuilder,
get_security_group_builder::ScalewayGetSecurityGroupBuilder,
get_security_group_rule_builder::ScalewayGetSecurityGroupRuleBuilder,
get_ssh_key_builder::ScalewayGetSSHKeyBuilder,
list_dns_zones_builder::ScalewayListDnsZonesBuilder,
list_flexible_ips_builder::ScalewayListFlexibleIpsBuilder,
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,
update_dns_record_builder::ScalewayUpdateDnsRecordBuilder,
update_flexible_ip_builder::ScalewayUpdateFlexibleIpBuilder,
update_volume_builder::ScalewayUpdateVolumeBuilder,
};
pub use data::dns_record::{DnsRecordType, ScalewayDnsRecord};
pub use data::dns_zone::{DnsZoneOrderBy, DnsZoneStatus, ScalewayDnsZone};
pub use data::architecture::ScalewayArchitecture;
pub use data::flexible_ip::{FlexibleIpType, ScalewayFlexibleIp, ScalewayFlexibleIpServerRef};
pub use data::image::{
ScalewayImage, ScalewayImageBootscript, ScalewayImageExtraVolume,
ScalewayImageExtraVolumeServer, ScalewayImageExtraVolumes, ScalewayImageRootVolume,
};
pub use data::instance::{
BootType, InstanceAction, InstanceOrderBy, ScalewayInstance, ScalewayInstanceLocation,
ScalewayIpv6, ScalewayMaintenance, ScalewayPlacementGroup, ScalewayPrivateNic,
ScalewayPublicIP, ScalewaySecurityGroup,
};
pub use data::marketplace_image::{MarketplaceImageOrderBy, ScalewayMarketplaceImage};
pub use data::marketplace_image_version::MarketplaceImageVersionOrderBy;
pub use data::marketplace_local_image::{LocalImageType, MarketplaceLocalImageOrderBy};
pub use data::security_group::{
ScalewaySecurityGroupDetails, ScalewaySecurityGroupRule, SecurityGroupPolicy,
SecurityGroupRuleAction, SecurityGroupRuleDirection, SecurityGroupRuleProtocol,
};
pub use data::project::{ProjectOrderBy, 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, SshKeyOrderBy};
pub use data::user_data::ScalewayUserData;
pub use data::user_data::ScalewayUserDataKeyList;
pub use data::volume::{ScalewayVolume, ScalewayVolumeServerRef};
pub use data::volume_type::{
ScalewayVolumeType, ScalewayVolumeTypeCapabilities, ScalewayVolumeTypeConstraints,
};
pub use data::zone::Zone;
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 patch_json_async<T>(
&self,
url: &str,
json: T,
) -> Result<reqwest::Response, ScalewayError>
where
T: Serialize + Sized,
{
let client = reqwest::Client::new();
let resp = client
.patch(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 patch_json<T>(
&self,
url: &str,
json: T,
) -> Result<reqwest::blocking::Response, ScalewayError>
where
T: Serialize + Sized,
{
let client = reqwest::blocking::Client::new();
let resp = client
.patch(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 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<Zone> {
Zone::iter().collect()
}
#[cfg(feature = "blocking")]
pub fn get_server_types(&self, zone: impl AsRef<str>) -> Result<Vec<ServerType>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
) -> Result<Vec<ServerType>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>) -> ScalewayListInstanceImagesBuilder {
ScalewayListInstanceImagesBuilder::new(self.clone(), zone.as_ref())
}
pub fn list_instances(&self, zone: impl AsRef<str>) -> ScalewayListInstanceBuilder {
ScalewayListInstanceBuilder::new(self.clone(), zone.as_ref())
}
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: impl AsRef<str>,
name: &str,
commercial_type: &str,
) -> ScalewayCreateInstanceBuilder {
ScalewayCreateInstanceBuilder::new(self.clone(), zone.as_ref(), name, commercial_type)
}
#[cfg(feature = "blocking")]
pub fn get_instance(
&self,
zone: impl AsRef<str>,
server_id: &str,
) -> Result<ScalewayInstance, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
server_id: &str,
) -> Result<ScalewayInstance, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>, server_id: &str) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
server_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
server_id: &str,
action: InstanceAction,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
server_id: &str,
action: InstanceAction,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>) -> Result<HashMap<String, bool>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
) -> Result<HashMap<String, bool>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
) -> Result<Vec<String>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
) -> Result<Vec<String>, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
) -> Result<ScalewayUserData, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
) -> Result<ScalewayUserData, ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
value: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
value: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
machine_id: &str,
key: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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 list_volume_types(&self, zone: impl AsRef<str>) -> Result<Vec<ScalewayVolumeType>, ScalewayError> {
let zone = zone.as_ref();
use data::volume_type::ScalewayVolumeTypeRoot;
let types = self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/volumes",
zone = zone
),
vec![],
)?
.json::<ScalewayVolumeTypeRoot>()?
.volumes
.into_iter()
.map(|(id, item)| ScalewayVolumeType {
id,
display_name: item.display_name,
capabilities: item.capabilities,
constraints: item.constraints,
})
.collect();
Ok(types)
}
pub async fn list_volume_types_async(
&self,
zone: impl AsRef<str>,
) -> Result<Vec<ScalewayVolumeType>, ScalewayError> {
let zone = zone.as_ref();
use data::volume_type::ScalewayVolumeTypeRoot;
let types = self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/products/volumes",
zone = zone
),
vec![],
)
.await?
.json::<ScalewayVolumeTypeRoot>()
.await?
.volumes
.into_iter()
.map(|(id, item)| ScalewayVolumeType {
id,
display_name: item.display_name,
capabilities: item.capabilities,
constraints: item.constraints,
})
.collect();
Ok(types)
}
pub fn list_volumes(&self, zone: impl AsRef<str>) -> ScalewayListVolumesBuilder {
ScalewayListVolumesBuilder::new(self.clone(), zone.as_ref())
}
#[cfg(feature = "blocking")]
pub fn get_volume(&self, zone: impl AsRef<str>, volume_id: &str) -> Result<ScalewayVolume, ScalewayError> {
let zone = zone.as_ref();
use data::volume::ScalewayVolumeRoot;
Ok(self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/volumes/{volume_id}",
zone = zone,
volume_id = volume_id
),
vec![],
)?
.json::<ScalewayVolumeRoot>()?
.volume)
}
pub async fn get_volume_async(
&self,
zone: impl AsRef<str>,
volume_id: &str,
) -> Result<ScalewayVolume, ScalewayError> {
let zone = zone.as_ref();
use data::volume::ScalewayVolumeRoot;
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/volumes/{volume_id}",
zone = zone,
volume_id = volume_id
),
vec![],
)
.await?
.json::<ScalewayVolumeRoot>()
.await?
.volume)
}
pub fn create_volume(
&self,
zone: impl AsRef<str>,
name: &str,
size: u64,
volume_type: &str,
) -> ScalewayCreateVolumeBuilder {
ScalewayCreateVolumeBuilder::new(self.clone(), zone.as_ref(), name, size, volume_type)
}
pub fn update_volume(&self, zone: impl AsRef<str>, volume_id: &str) -> ScalewayUpdateVolumeBuilder {
ScalewayUpdateVolumeBuilder::new(self.clone(), zone.as_ref(), volume_id)
}
#[cfg(feature = "blocking")]
pub fn delete_volume(&self, zone: impl AsRef<str>, volume_id: &str) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
volume_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
security_group_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
security_group_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>) -> ScalewayListSecurityGroupsBuilder {
ScalewayListSecurityGroupsBuilder::new(self.clone(), zone.as_ref())
}
pub fn get_security_group(
&self,
zone: impl AsRef<str>,
security_group_id: &str,
) -> ScalewayGetSecurityGroupBuilder {
ScalewayGetSecurityGroupBuilder::new(self.clone(), zone.as_ref(), security_group_id)
}
pub fn create_security_group(
&self,
zone: impl AsRef<str>,
name: &str,
stateful: bool,
) -> ScalewayCreateSecurityGroupBuilder {
ScalewayCreateSecurityGroupBuilder::new(self.clone(), zone.as_ref(), name, stateful)
}
pub fn list_security_group_rules(
&self,
zone: impl AsRef<str>,
security_group_id: &str,
) -> ScalewayListSecurityGroupRulesBuilder {
ScalewayListSecurityGroupRulesBuilder::new(self.clone(), zone.as_ref(), security_group_id)
}
pub fn get_security_group_rule(
&self,
zone: impl AsRef<str>,
security_group_id: &str,
rule_id: &str,
) -> ScalewayGetSecurityGroupRuleBuilder {
ScalewayGetSecurityGroupRuleBuilder::new(self.clone(), zone.as_ref(), security_group_id, rule_id)
}
pub fn create_security_group_rule(
&self,
zone: impl AsRef<str>,
security_group_id: &str,
ip_range: &str,
protocol: SecurityGroupRuleProtocol,
direction: SecurityGroupRuleDirection,
action: SecurityGroupRuleAction,
) -> ScalewayCreateSecurityGroupRuleBuilder {
ScalewayCreateSecurityGroupRuleBuilder::new(
self.clone(),
zone.as_ref(),
security_group_id,
ip_range,
protocol,
direction,
action,
)
}
#[cfg(feature = "blocking")]
pub fn delete_security_group_rule(
&self,
zone: impl AsRef<str>,
security_group_id: &str,
rule_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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: impl AsRef<str>,
security_group_id: &str,
rule_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
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?)
}
pub fn create_flexible_ip(&self, zone: impl AsRef<str>, ip_type: FlexibleIpType) -> ScalewayCreateFlexibleIpBuilder {
ScalewayCreateFlexibleIpBuilder::new(self.clone(), zone.as_ref(), ip_type)
}
pub fn list_flexible_ips(&self, zone: impl AsRef<str>) -> ScalewayListFlexibleIpsBuilder {
ScalewayListFlexibleIpsBuilder::new(self.clone(), zone.as_ref())
}
pub fn update_flexible_ip(
&self,
zone: impl AsRef<str>,
ip_id: &str,
) -> ScalewayUpdateFlexibleIpBuilder {
ScalewayUpdateFlexibleIpBuilder::new(self.clone(), zone.as_ref(), ip_id)
}
#[cfg(feature = "blocking")]
pub fn get_flexible_ip(
&self,
zone: impl AsRef<str>,
ip_id: &str,
) -> Result<ScalewayFlexibleIp, ScalewayError> {
let zone = zone.as_ref();
use data::flexible_ip::ScalewayFlexibleIpRoot;
Ok(self
.get(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/ips/{ip_id}",
zone = zone,
ip_id = ip_id
),
vec![],
)?
.json::<ScalewayFlexibleIpRoot>()?
.ip)
}
pub async fn get_flexible_ip_async(
&self,
zone: impl AsRef<str>,
ip_id: &str,
) -> Result<ScalewayFlexibleIp, ScalewayError> {
let zone = zone.as_ref();
use data::flexible_ip::ScalewayFlexibleIpRoot;
Ok(self
.get_async(
&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/ips/{ip_id}",
zone = zone,
ip_id = ip_id
),
vec![],
)
.await?
.json::<ScalewayFlexibleIpRoot>()
.await?
.ip)
}
#[cfg(feature = "blocking")]
pub fn delete_flexible_ip(&self, zone: impl AsRef<str>, ip_id: &str) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
self.delete(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/ips/{ip_id}",
zone = zone,
ip_id = ip_id
))?
.error_for_status()?;
Ok(())
}
pub async fn delete_flexible_ip_async(
&self,
zone: impl AsRef<str>,
ip_id: &str,
) -> Result<(), ScalewayError> {
let zone = zone.as_ref();
self.delete_async(&format!(
"https://api.scaleway.com/instance/v1/zones/{zone}/ips/{ip_id}",
zone = zone,
ip_id = ip_id
))
.await?
.error_for_status()?;
Ok(())
}
pub fn list_dns_zones(&self) -> ScalewayListDnsZonesBuilder {
ScalewayListDnsZonesBuilder::new(self.clone())
}
#[cfg(feature = "blocking")]
pub fn list_dns_records(&self, dns_zone: impl AsRef<str>) -> Result<Vec<ScalewayDnsRecord>, ScalewayError> {
let dns_zone = dns_zone.as_ref();
use data::dns_record::ScalewayDnsRecordsRoot;
let mut list = vec![];
let mut page = 1u32;
loop {
let result = self
.get(
&format!(
"https://api.scaleway.com/domain/v2beta1/dns-zones/{dns_zone}/records",
dns_zone = dns_zone
),
vec![("page", page.to_string()), ("page_size", "100".to_string())],
)?
.json::<ScalewayDnsRecordsRoot>()?;
if result.records.is_empty() {
break;
}
list.extend(result.records);
page += 1;
}
Ok(list)
}
pub async fn list_dns_records_async(
&self,
dns_zone: impl AsRef<str>,
) -> Result<Vec<ScalewayDnsRecord>, ScalewayError> {
let dns_zone = dns_zone.as_ref();
use data::dns_record::ScalewayDnsRecordsRoot;
let mut list = vec![];
let mut page = 1u32;
loop {
let result = self
.get_async(
&format!(
"https://api.scaleway.com/domain/v2beta1/dns-zones/{dns_zone}/records",
dns_zone = dns_zone
),
vec![("page", page.to_string()), ("page_size", "100".to_string())],
)
.await?
.json::<ScalewayDnsRecordsRoot>()
.await?;
if result.records.is_empty() {
break;
}
list.extend(result.records);
page += 1;
}
Ok(list)
}
#[cfg(feature = "blocking")]
pub fn delete_dns_record(&self, dns_zone: impl AsRef<str>, record_id: &str) -> Result<(), ScalewayError> {
let dns_zone = dns_zone.as_ref();
#[derive(serde::Serialize)]
struct DeleteChange { delete: DeleteById }
#[derive(serde::Serialize)]
struct DeleteById { id: String }
#[derive(serde::Serialize)]
struct DeleteRequest { changes: Vec<DeleteChange> }
self.post(
&format!(
"https://api.scaleway.com/domain/v2beta1/dns-zones/{dns_zone}/records",
dns_zone = dns_zone
),
DeleteRequest {
changes: vec![DeleteChange { delete: DeleteById { id: record_id.to_string() } }],
},
)?
.error_for_status()?;
Ok(())
}
pub async fn delete_dns_record_async(
&self,
dns_zone: impl AsRef<str>,
record_id: &str,
) -> Result<(), ScalewayError> {
let dns_zone = dns_zone.as_ref();
#[derive(serde::Serialize)]
struct DeleteChange { delete: DeleteById }
#[derive(serde::Serialize)]
struct DeleteById { id: String }
#[derive(serde::Serialize)]
struct DeleteRequest { changes: Vec<DeleteChange> }
self.post_async(
&format!(
"https://api.scaleway.com/domain/v2beta1/dns-zones/{dns_zone}/records",
dns_zone = dns_zone
),
DeleteRequest {
changes: vec![DeleteChange { delete: DeleteById { id: record_id.to_string() } }],
},
)
.await?
.error_for_status()?;
Ok(())
}
pub fn add_dns_record(
&self,
dns_zone: impl AsRef<str>,
name: &str,
record_type: DnsRecordType,
data: &str,
) -> ScalewayAddDnsRecordBuilder {
ScalewayAddDnsRecordBuilder::new(self.clone(), dns_zone.as_ref(), name, record_type, data)
}
pub fn update_dns_record(
&self,
dns_zone: impl AsRef<str>,
record_id: &str,
name: &str,
record_type: DnsRecordType,
data: &str,
) -> ScalewayUpdateDnsRecordBuilder {
ScalewayUpdateDnsRecordBuilder::new(self.clone(), dns_zone.as_ref(), record_id, name, record_type, data)
}
}