progenitor/progenitor-impl/tests/output/nexus-positional.out

8010 lines
297 KiB
Plaintext

#[allow(unused_imports)]
use progenitor_client::{encode_path, RequestBuilderExt};
pub use progenitor_client::{ByteStream, Error, ResponseValue};
pub mod types {
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BlockSize(i64);
impl std::ops::Deref for BlockSize {
type Target = i64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<i64> for BlockSize {
type Error = &'static str;
fn try_from(value: i64) -> Result<Self, Self::Error> {
if ![512_i64, 2048_i64, 4096_i64].contains(&value) {
Err("invalid value")
} else {
Ok(Self(value))
}
}
}
///A count of bytes, typically used either for memory or storage capacity
///
///The maximum supported byte count is [`i64::MAX`]. This makes it
/// somewhat inconvenient to define constructors: a u32 constructor can be
/// infallible, but an i64 constructor can fail (if the value is negative)
/// and a u64 constructor can fail (if the value is larger than i64::MAX).
/// We provide all of these for consumers' convenience.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ByteCount(pub u64);
impl std::ops::Deref for ByteCount {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
///The type of an individual datum of a metric.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum DatumType {
#[serde(rename = "bool")]
Bool,
#[serde(rename = "i64")]
I64,
#[serde(rename = "f64")]
F64,
#[serde(rename = "string")]
String,
#[serde(rename = "bytes")]
Bytes,
#[serde(rename = "cumulative_i64")]
CumulativeI64,
#[serde(rename = "cumulative_f64")]
CumulativeF64,
#[serde(rename = "histogram_i64")]
HistogramI64,
#[serde(rename = "histogram_f64")]
HistogramF64,
}
impl ToString for DatumType {
fn to_string(&self) -> String {
match *self {
Self::Bool => "bool".to_string(),
Self::I64 => "i64".to_string(),
Self::F64 => "f64".to_string(),
Self::String => "string".to_string(),
Self::Bytes => "bytes".to_string(),
Self::CumulativeI64 => "cumulative_i64".to_string(),
Self::CumulativeF64 => "cumulative_f64".to_string(),
Self::HistogramI64 => "histogram_i64".to_string(),
Self::HistogramF64 => "histogram_f64".to_string(),
}
}
}
impl std::str::FromStr for DatumType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"bool" => Ok(Self::Bool),
"i64" => Ok(Self::I64),
"f64" => Ok(Self::F64),
"string" => Ok(Self::String),
"bytes" => Ok(Self::Bytes),
"cumulative_i64" => Ok(Self::CumulativeI64),
"cumulative_f64" => Ok(Self::CumulativeF64),
"histogram_i64" => Ok(Self::HistogramI64),
"histogram_f64" => Ok(Self::HistogramF64),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DerEncodedKeyPair {
///request signing private key (base64 encoded der file)
pub private_key: String,
///request signing public certificate (base64 encoded der file)
pub public_cert: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceAccessTokenRequest {
pub client_id: uuid::Uuid,
pub device_code: String,
pub grant_type: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceAuthRequest {
pub client_id: uuid::Uuid,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceAuthVerify {
pub user_code: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Digest {
#[serde(rename = "type")]
pub type_: DigestType,
pub value: String,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum DigestType {
#[serde(rename = "sha256")]
Sha256,
}
impl ToString for DigestType {
fn to_string(&self) -> String {
match *self {
Self::Sha256 => "sha256".to_string(),
}
}
}
impl std::str::FromStr for DigestType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"sha256" => Ok(Self::Sha256),
_ => Err("invalid value"),
}
}
}
///Client view of a [`Disk`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Disk {
pub block_size: ByteCount,
///human-readable free-form text about a resource
pub description: String,
pub device_path: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub image_id: Option<uuid::Uuid>,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
pub project_id: uuid::Uuid,
pub size: ByteCount,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub snapshot_id: Option<uuid::Uuid>,
pub state: DiskState,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for a
/// [`Disk`](omicron_common::api::external::Disk)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DiskCreate {
pub description: String,
///initial source for this disk
pub disk_source: DiskSource,
pub name: Name,
///total size of the Disk in bytes
pub size: ByteCount,
}
///Parameters for the [`Disk`](omicron_common::api::external::Disk) to be
/// attached or detached to an instance
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DiskIdentifier {
pub name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DiskResultsPage {
///list of items on this page of results
pub items: Vec<Disk>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Different sources for a disk
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum DiskSource {
///Create a blank disk
#[serde(rename = "blank")]
Blank {
///size of blocks for this Disk. valid values are: 512, 2048, or
/// 4096
block_size: BlockSize,
},
///Create a disk from a disk snapshot
#[serde(rename = "snapshot")]
Snapshot { snapshot_id: uuid::Uuid },
///Create a disk from a project image
#[serde(rename = "image")]
Image { image_id: uuid::Uuid },
///Create a disk from a global image
#[serde(rename = "global_image")]
GlobalImage { image_id: uuid::Uuid },
}
///State of a Disk (primarily: attached or not)
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "state", content = "instance")]
pub enum DiskState {
#[serde(rename = "creating")]
Creating,
#[serde(rename = "detached")]
Detached,
///Disk is being attached to the given Instance
#[serde(rename = "attaching")]
Attaching(uuid::Uuid),
///Disk is attached to the given Instance
#[serde(rename = "attached")]
Attached(uuid::Uuid),
///Disk is being detached from the given Instance
#[serde(rename = "detaching")]
Detaching(uuid::Uuid),
#[serde(rename = "destroyed")]
Destroyed,
#[serde(rename = "faulted")]
Faulted,
}
///OS image distribution
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Distribution {
///The name of the distribution (e.g. "alpine" or "ubuntu")
pub name: Name,
///The version of the distribution (e.g. "3.10" or "18.04")
pub version: String,
}
///Error information from a response.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Error {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error_code: Option<String>,
pub message: String,
pub request_id: String,
}
///The name and type information for a field of a timeseries schema.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FieldSchema {
pub name: String,
pub source: FieldSource,
pub ty: FieldType,
}
///The source from which a field is derived, the target or metric.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum FieldSource {
#[serde(rename = "target")]
Target,
#[serde(rename = "metric")]
Metric,
}
impl ToString for FieldSource {
fn to_string(&self) -> String {
match *self {
Self::Target => "target".to_string(),
Self::Metric => "metric".to_string(),
}
}
}
impl std::str::FromStr for FieldSource {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"target" => Ok(Self::Target),
"metric" => Ok(Self::Metric),
_ => Err("invalid value"),
}
}
}
///The `FieldType` identifies the data type of a target or metric field.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum FieldType {
#[serde(rename = "string")]
String,
#[serde(rename = "i64")]
I64,
#[serde(rename = "ip_addr")]
IpAddr,
#[serde(rename = "uuid")]
Uuid,
#[serde(rename = "bool")]
Bool,
}
impl ToString for FieldType {
fn to_string(&self) -> String {
match *self {
Self::String => "string".to_string(),
Self::I64 => "i64".to_string(),
Self::IpAddr => "ip_addr".to_string(),
Self::Uuid => "uuid".to_string(),
Self::Bool => "bool".to_string(),
}
}
}
impl std::str::FromStr for FieldType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"string" => Ok(Self::String),
"i64" => Ok(Self::I64),
"ip_addr" => Ok(Self::IpAddr),
"uuid" => Ok(Self::Uuid),
"bool" => Ok(Self::Bool),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum FleetRole {
#[serde(rename = "admin")]
Admin,
#[serde(rename = "collaborator")]
Collaborator,
#[serde(rename = "viewer")]
Viewer,
}
impl ToString for FleetRole {
fn to_string(&self) -> String {
match *self {
Self::Admin => "admin".to_string(),
Self::Collaborator => "collaborator".to_string(),
Self::Viewer => "viewer".to_string(),
}
}
}
impl std::str::FromStr for FleetRole {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"admin" => Ok(Self::Admin),
"collaborator" => Ok(Self::Collaborator),
"viewer" => Ok(Self::Viewer),
_ => Err("invalid value"),
}
}
}
///Client view of a [`Policy`], which describes how this resource may be
/// accessed
///
///Note that the Policy only describes access granted explicitly for this
/// resource. The policies of parent resources can also cause a user to
/// have access to this resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FleetRolePolicy {
///Roles directly assigned on this resource
pub role_assignments: Vec<FleetRoleRoleAssignment>,
}
///Describes the assignment of a particular role on a particular resource
/// to a particular identity (user, group, etc.)
///
///The resource is not part of this structure. Rather, [`RoleAssignment`]s
/// are put into a [`Policy`] and that Policy is applied to a particular
/// resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FleetRoleRoleAssignment {
pub identity_id: uuid::Uuid,
pub identity_type: IdentityType,
pub role_name: FleetRole,
}
///Client view of global Images
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GlobalImage {
///size of blocks in bytes
pub block_size: ByteCount,
///human-readable free-form text about a resource
pub description: String,
///Hash of the image contents, if applicable
#[serde(default, skip_serializing_if = "Option::is_none")]
pub digest: Option<Digest>,
///Image distribution
pub distribution: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///total size in bytes
pub size: ByteCount,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///URL source of this image, if any
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
///Image version
pub version: String,
}
///Create-time parameters for an
/// [`GlobalImage`](omicron_common::api::external::GlobalImage)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GlobalImageCreate {
///block size in bytes
pub block_size: BlockSize,
pub description: String,
///OS image distribution
pub distribution: Distribution,
pub name: Name,
///The source of the image's contents.
pub source: ImageSource,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GlobalImageResultsPage {
///list of items on this page of results
pub items: Vec<GlobalImage>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Supported set of sort modes for scanning by id only.
///
///Currently, we only support scanning in ascending order.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum IdSortMode {
#[serde(rename = "id_ascending")]
IdAscending,
}
impl ToString for IdSortMode {
fn to_string(&self) -> String {
match *self {
Self::IdAscending => "id_ascending".to_string(),
}
}
}
impl std::str::FromStr for IdSortMode {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"id_ascending" => Ok(Self::IdAscending),
_ => Err("invalid value"),
}
}
}
///Client view of an [`IdentityProvider`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IdentityProvider {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///Identity provider type
pub provider_type: IdentityProviderType,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IdentityProviderResultsPage {
///list of items on this page of results
pub items: Vec<IdentityProvider>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum IdentityProviderType {
#[serde(rename = "saml")]
Saml,
}
impl ToString for IdentityProviderType {
fn to_string(&self) -> String {
match *self {
Self::Saml => "saml".to_string(),
}
}
}
impl std::str::FromStr for IdentityProviderType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"saml" => Ok(Self::Saml),
_ => Err("invalid value"),
}
}
}
///Describes what kind of identity is described by an id
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum IdentityType {
#[serde(rename = "silo_user")]
SiloUser,
}
impl ToString for IdentityType {
fn to_string(&self) -> String {
match *self {
Self::SiloUser => "silo_user".to_string(),
}
}
}
impl std::str::FromStr for IdentityType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"silo_user" => Ok(Self::SiloUser),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum IdpMetadataSource {
#[serde(rename = "url")]
Url { url: String },
#[serde(rename = "base64_encoded_xml")]
Base64EncodedXml { data: String },
}
///Client view of project Images
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Image {
///size of blocks in bytes
pub block_size: ByteCount,
///human-readable free-form text about a resource
pub description: String,
///Hash of the image contents, if applicable
#[serde(default, skip_serializing_if = "Option::is_none")]
pub digest: Option<Digest>,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///The project the disk belongs to
pub project_id: uuid::Uuid,
///total size in bytes
pub size: ByteCount,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///URL source of this image, if any
#[serde(default, skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
///Version of this, if any
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
}
///Create-time parameters for an
/// [`Image`](omicron_common::api::external::Image)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ImageCreate {
///block size in bytes
pub block_size: BlockSize,
pub description: String,
pub name: Name,
///The source of the image's contents.
pub source: ImageSource,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ImageResultsPage {
///list of items on this page of results
pub items: Vec<Image>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///The source of the underlying image.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum ImageSource {
#[serde(rename = "url")]
Url { url: String },
#[serde(rename = "snapshot")]
Snapshot { id: uuid::Uuid },
#[serde(rename = "you_can_boot_anything_as_long_as_its_alpine")]
YouCanBootAnythingAsLongAsItsAlpine,
}
///Client view of an [`Instance`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Instance {
///human-readable free-form text about a resource
pub description: String,
///RFC1035-compliant hostname for the Instance.
pub hostname: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///memory allocated for this Instance
pub memory: ByteCount,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///number of CPUs allocated for this Instance
pub ncpus: InstanceCpuCount,
///id for the project containing this Instance
pub project_id: uuid::Uuid,
pub run_state: InstanceState,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
pub time_run_state_updated: chrono::DateTime<chrono::offset::Utc>,
}
///The number of CPUs in an Instance
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InstanceCpuCount(pub u16);
impl std::ops::Deref for InstanceCpuCount {
type Target = u16;
fn deref(&self) -> &Self::Target {
&self.0
}
}
///Create-time parameters for an
/// [`Instance`](omicron_common::api::external::Instance)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InstanceCreate {
pub description: String,
///The disks to be created or attached for this instance.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub disks: Vec<InstanceDiskAttachment>,
pub hostname: String,
pub memory: ByteCount,
pub name: Name,
pub ncpus: InstanceCpuCount,
///The network interfaces to be created for this instance.
#[serde(default = "instance_create_network_interfaces")]
pub network_interfaces: InstanceNetworkInterfaceAttachment,
///User data for instance initialization systems (such as cloud-init).
/// Must be a Base64-encoded string, as specified in RFC 4648 § 4 (+ and
/// / characters with padding). Maximum 32 KiB unencoded data.
#[serde(default)]
pub user_data: String,
}
fn instance_create_network_interfaces() -> InstanceNetworkInterfaceAttachment {
InstanceNetworkInterfaceAttachment::Default
}
///Describe the instance's disks at creation time
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum InstanceDiskAttachment {
///During instance creation, create and attach disks
#[serde(rename = "create")]
Create {
description: String,
///initial source for this disk
disk_source: DiskSource,
name: Name,
///total size of the Disk in bytes
size: ByteCount,
},
///During instance creation, attach this disk
#[serde(rename = "attach")]
Attach {
///A disk name to attach
name: Name,
},
}
///Migration parameters for an
/// [`Instance`](omicron_common::api::external::Instance)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InstanceMigrate {
pub dst_sled_id: uuid::Uuid,
}
///Describes an attachment of a `NetworkInterface` to an `Instance`, at the
/// time the instance is created.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "params")]
pub enum InstanceNetworkInterfaceAttachment {
///Create one or more `NetworkInterface`s for the `Instance`.
///
///If more than one interface is provided, then the first will be
/// designated the primary interface for the instance.
#[serde(rename = "create")]
Create(Vec<NetworkInterfaceCreate>),
#[serde(rename = "default")]
Default,
#[serde(rename = "none")]
None,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InstanceResultsPage {
///list of items on this page of results
pub items: Vec<Instance>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Contents of an Instance's serial console buffer.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InstanceSerialConsoleData {
///The bytes starting from the requested offset up to either the end of
/// the buffer or the request's `max_bytes`. Provided as a u8 array
/// rather than a string, as it may not be UTF-8.
pub data: Vec<u8>,
///The absolute offset since boot (suitable for use as `byte_offset` in
/// a subsequent request) of the last byte returned in `data`.
pub last_byte_offset: u64,
}
///Running state of an Instance (primarily: booted or stopped)
///
///This typically reflects whether it's starting, running, stopping, or
/// stopped, but also includes states related to the Instance's lifecycle
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum InstanceState {
#[serde(rename = "creating")]
Creating,
#[serde(rename = "starting")]
Starting,
#[serde(rename = "running")]
Running,
#[serde(rename = "stopping")]
Stopping,
#[serde(rename = "stopped")]
Stopped,
#[serde(rename = "rebooting")]
Rebooting,
#[serde(rename = "migrating")]
Migrating,
#[serde(rename = "repairing")]
Repairing,
#[serde(rename = "failed")]
Failed,
#[serde(rename = "destroyed")]
Destroyed,
}
impl ToString for InstanceState {
fn to_string(&self) -> String {
match *self {
Self::Creating => "creating".to_string(),
Self::Starting => "starting".to_string(),
Self::Running => "running".to_string(),
Self::Stopping => "stopping".to_string(),
Self::Stopped => "stopped".to_string(),
Self::Rebooting => "rebooting".to_string(),
Self::Migrating => "migrating".to_string(),
Self::Repairing => "repairing".to_string(),
Self::Failed => "failed".to_string(),
Self::Destroyed => "destroyed".to_string(),
}
}
}
impl std::str::FromStr for InstanceState {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"creating" => Ok(Self::Creating),
"starting" => Ok(Self::Starting),
"running" => Ok(Self::Running),
"stopping" => Ok(Self::Stopping),
"stopped" => Ok(Self::Stopped),
"rebooting" => Ok(Self::Rebooting),
"migrating" => Ok(Self::Migrating),
"repairing" => Ok(Self::Repairing),
"failed" => Ok(Self::Failed),
"destroyed" => Ok(Self::Destroyed),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum IpNet {
V4(Ipv4Net),
V6(Ipv6Net),
}
impl std::convert::TryFrom<&str> for IpNet {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
Err("")
.or_else(|_: Self::Error| Ok(Self::V4(Ipv4Net::try_from(value)?)))
.or_else(|_: Self::Error| Ok(Self::V6(Ipv6Net::try_from(value)?)))
.or_else(|_: Self::Error| Err("string conversion failed for all variants"))
}
}
impl std::convert::TryFrom<String> for IpNet {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
///Identity-related metadata that's included in nearly all public API
/// objects
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPool {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for an IP Pool.
///
///See [`IpPool`](omicron_nexus::external_api::views::IpPool)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPoolCreate {
pub description: String,
pub name: Name,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPoolRange {
pub id: uuid::Uuid,
pub range: IpRange,
pub time_created: chrono::DateTime<chrono::offset::Utc>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPoolRangeResultsPage {
///list of items on this page of results
pub items: Vec<IpPoolRange>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPoolResultsPage {
///list of items on this page of results
pub items: Vec<IpPool>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Parameters for updating an IP Pool
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IpPoolUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum IpRange {
V4(Ipv4Range),
V6(Ipv6Range),
}
///An IPv4 subnet, including prefix and subnet mask
#[derive(Clone, Debug, Serialize)]
pub struct Ipv4Net(String);
impl std::ops::Deref for Ipv4Net {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for Ipv4Net {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 18usize {
return Err("longer than 18 characters");
}
if regress :: Regex :: new ("(^(10\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9]\\.){2}(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[0-9]|2[0-8]|[8-9]))$)|(^(172\\.16\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[2-9]|2[0-8]))$)|(^(192\\.168\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[6-9]|2[0-8]))$)") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"(^(10\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9]\\.){2}(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[0-9]|2[0-8]|[8-9]))$)|(^(172\\.16\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[2-9]|2[0-8]))$)|(^(192\\.168\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[6-9]|2[0-8]))$)\"") ; }
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for Ipv4Net {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for Ipv4Net {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///A non-decreasing IPv4 address range, inclusive of both ends.
///
///The first address must be less than or equal to the last address.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ipv4Range {
pub first: std::net::Ipv4Addr,
pub last: std::net::Ipv4Addr,
}
///An IPv6 subnet, including prefix and subnet mask
#[derive(Clone, Debug, Serialize)]
pub struct Ipv6Net(String);
impl std::ops::Deref for Ipv6Net {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for Ipv6Net {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 43usize {
return Err("longer than 43 characters");
}
if regress :: Regex :: new ("^(fd|FD)[0-9a-fA-F]{2}:((([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,6}:))/(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-6])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(fd|FD)[0-9a-fA-F]{2}:((([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,6}:))/(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-6])$\"") ; }
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for Ipv6Net {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for Ipv6Net {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///A non-decreasing IPv6 address range, inclusive of both ends.
///
///The first address must be less than or equal to the last address.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ipv6Range {
pub first: std::net::Ipv6Addr,
pub last: std::net::Ipv6Addr,
}
///An inclusive-inclusive range of IP ports. The second port may be omitted
/// to represent a single port
#[derive(Clone, Debug, Serialize)]
pub struct L4PortRange(String);
impl std::ops::Deref for L4PortRange {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for L4PortRange {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 11usize {
return Err("longer than 11 characters");
}
if value.len() < 1usize {
return Err("shorter than 1 characters");
}
if regress::Regex::new("^[0-9]{1,5}(-[0-9]{1,5})?$")
.unwrap()
.find(value)
.is_none()
{
return Err("doesn't match pattern \"^[0-9]{1,5}(-[0-9]{1,5})?$\"");
}
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for L4PortRange {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for L4PortRange {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///A Media Access Control address, in EUI-48 format
#[derive(Clone, Debug, Serialize)]
pub struct MacAddr(String);
impl std::ops::Deref for MacAddr {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for MacAddr {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 17usize {
return Err("longer than 17 characters");
}
if value.len() < 17usize {
return Err("shorter than 17 characters");
}
if regress::Regex::new("^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$")
.unwrap()
.find(value)
.is_none()
{
return Err("doesn't match pattern \"^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$\"");
}
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for MacAddr {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for MacAddr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///Names must begin with a lower case ASCII letter, be composed exclusively
/// of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end
/// with a '-'.
#[derive(Clone, Debug, Serialize)]
pub struct Name(String);
impl std::ops::Deref for Name {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for Name {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 63usize {
return Err("longer than 63 characters");
}
if regress::Regex::new("[a-z](|[a-zA-Z0-9-]*[a-zA-Z0-9])")
.unwrap()
.find(value)
.is_none()
{
return Err("doesn't match pattern \"[a-z](|[a-zA-Z0-9-]*[a-zA-Z0-9])\"");
}
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for Name {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for Name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///Supported set of sort modes for scanning by name or id
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum NameOrIdSortMode {
#[serde(rename = "name_ascending")]
NameAscending,
#[serde(rename = "name_descending")]
NameDescending,
#[serde(rename = "id_ascending")]
IdAscending,
}
impl ToString for NameOrIdSortMode {
fn to_string(&self) -> String {
match *self {
Self::NameAscending => "name_ascending".to_string(),
Self::NameDescending => "name_descending".to_string(),
Self::IdAscending => "id_ascending".to_string(),
}
}
}
impl std::str::FromStr for NameOrIdSortMode {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"name_ascending" => Ok(Self::NameAscending),
"name_descending" => Ok(Self::NameDescending),
"id_ascending" => Ok(Self::IdAscending),
_ => Err("invalid value"),
}
}
}
///Supported set of sort modes for scanning by name only
///
///Currently, we only support scanning in ascending order.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum NameSortMode {
#[serde(rename = "name_ascending")]
NameAscending,
}
impl ToString for NameSortMode {
fn to_string(&self) -> String {
match *self {
Self::NameAscending => "name_ascending".to_string(),
}
}
}
impl std::str::FromStr for NameSortMode {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"name_ascending" => Ok(Self::NameAscending),
_ => Err("invalid value"),
}
}
}
///A `NetworkInterface` represents a virtual network interface device.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkInterface {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///The Instance to which the interface belongs.
pub instance_id: uuid::Uuid,
///The IP address assigned to this interface.
pub ip: std::net::IpAddr,
///The MAC address assigned to this interface.
pub mac: MacAddr,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///True if this interface is the primary for the instance to which it's
/// attached.
pub primary: bool,
///The subnet to which the interface belongs.
pub subnet_id: uuid::Uuid,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///The VPC to which the interface belongs.
pub vpc_id: uuid::Uuid,
}
///Create-time parameters for a
/// [`NetworkInterface`](omicron_common::api::external::NetworkInterface)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkInterfaceCreate {
pub description: String,
///The IP address for the interface. One will be auto-assigned if not
/// provided.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ip: Option<std::net::IpAddr>,
pub name: Name,
///The VPC Subnet in which to create the interface.
pub subnet_name: Name,
///The VPC in which to create the interface.
pub vpc_name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkInterfaceResultsPage {
///list of items on this page of results
pub items: Vec<NetworkInterface>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Parameters for updating a
/// [`NetworkInterface`](omicron_common::api::external::NetworkInterface).
///
///Note that modifying IP addresses for an interface is not yet supported,
/// a new interface must be created instead.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkInterfaceUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
///Make a secondary interface the instance's primary interface.
///
///If applied to a secondary interface, that interface will become the
/// primary on the next reboot of the instance. Note that this may have
/// implications for routing between instances, as the new primary
/// interface will be on a distinct subnet from the previous primary
/// interface.
///
///Note that this can only be used to select a new primary interface
/// for an instance. Requests to change the primary interface into a
/// secondary will return an error.
#[serde(default)]
pub make_primary: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum Null {}
impl ToString for Null {
fn to_string(&self) -> String {
match *self {}
}
}
impl std::str::FromStr for Null {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
_ => Err("invalid value"),
}
}
}
///Client view of an [`Organization`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Organization {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for an
/// [`Organization`](crate::external_api::views::Organization)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrganizationCreate {
pub description: String,
pub name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrganizationResultsPage {
///list of items on this page of results
pub items: Vec<Organization>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum OrganizationRole {
#[serde(rename = "admin")]
Admin,
#[serde(rename = "collaborator")]
Collaborator,
#[serde(rename = "viewer")]
Viewer,
}
impl ToString for OrganizationRole {
fn to_string(&self) -> String {
match *self {
Self::Admin => "admin".to_string(),
Self::Collaborator => "collaborator".to_string(),
Self::Viewer => "viewer".to_string(),
}
}
}
impl std::str::FromStr for OrganizationRole {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"admin" => Ok(Self::Admin),
"collaborator" => Ok(Self::Collaborator),
"viewer" => Ok(Self::Viewer),
_ => Err("invalid value"),
}
}
}
///Client view of a [`Policy`], which describes how this resource may be
/// accessed
///
///Note that the Policy only describes access granted explicitly for this
/// resource. The policies of parent resources can also cause a user to
/// have access to this resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrganizationRolePolicy {
///Roles directly assigned on this resource
pub role_assignments: Vec<OrganizationRoleRoleAssignment>,
}
///Describes the assignment of a particular role on a particular resource
/// to a particular identity (user, group, etc.)
///
///The resource is not part of this structure. Rather, [`RoleAssignment`]s
/// are put into a [`Policy`] and that Policy is applied to a particular
/// resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrganizationRoleRoleAssignment {
pub identity_id: uuid::Uuid,
pub identity_type: IdentityType,
pub role_name: OrganizationRole,
}
///Updateable properties of an
/// [`Organization`](crate::external_api::views::Organization)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OrganizationUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
///Client view of a [`Project`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Project {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
pub organization_id: uuid::Uuid,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for a
/// [`Project`](crate::external_api::views::Project)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProjectCreate {
pub description: String,
pub name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProjectResultsPage {
///list of items on this page of results
pub items: Vec<Project>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum ProjectRole {
#[serde(rename = "admin")]
Admin,
#[serde(rename = "collaborator")]
Collaborator,
#[serde(rename = "viewer")]
Viewer,
}
impl ToString for ProjectRole {
fn to_string(&self) -> String {
match *self {
Self::Admin => "admin".to_string(),
Self::Collaborator => "collaborator".to_string(),
Self::Viewer => "viewer".to_string(),
}
}
}
impl std::str::FromStr for ProjectRole {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"admin" => Ok(Self::Admin),
"collaborator" => Ok(Self::Collaborator),
"viewer" => Ok(Self::Viewer),
_ => Err("invalid value"),
}
}
}
///Client view of a [`Policy`], which describes how this resource may be
/// accessed
///
///Note that the Policy only describes access granted explicitly for this
/// resource. The policies of parent resources can also cause a user to
/// have access to this resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProjectRolePolicy {
///Roles directly assigned on this resource
pub role_assignments: Vec<ProjectRoleRoleAssignment>,
}
///Describes the assignment of a particular role on a particular resource
/// to a particular identity (user, group, etc.)
///
///The resource is not part of this structure. Rather, [`RoleAssignment`]s
/// are put into a [`Policy`] and that Policy is applied to a particular
/// resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProjectRoleRoleAssignment {
pub identity_id: uuid::Uuid,
pub identity_type: IdentityType,
pub role_name: ProjectRole,
}
///Updateable properties of a
/// [`Project`](crate::external_api::views::Project)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProjectUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
///Client view of an [`Rack`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Rack {
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RackResultsPage {
///list of items on this page of results
pub items: Vec<Rack>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Client view of a [`Role`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Role {
pub description: String,
pub name: RoleName,
}
///Role names consist of two string components separated by dot (".").
#[derive(Clone, Debug, Serialize)]
pub struct RoleName(String);
impl std::ops::Deref for RoleName {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for RoleName {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if value.len() > 63usize {
return Err("longer than 63 characters");
}
if regress::Regex::new("[a-z-]+\\.[a-z-]+")
.unwrap()
.find(value)
.is_none()
{
return Err("doesn't match pattern \"[a-z-]+\\.[a-z-]+\"");
}
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for RoleName {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for RoleName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RoleResultsPage {
///list of items on this page of results
pub items: Vec<Role>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///A `RouteDestination` is used to match traffic with a routing rule, on
/// the destination of that traffic.
///
///When traffic is to be sent to a destination that is within a given
/// `RouteDestination`, the corresponding [`RouterRoute`] applies, and
/// traffic will be forward to the [`RouteTarget`] for that rule.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum RouteDestination {
///Route applies to traffic destined for a specific IP address
#[serde(rename = "ip")]
Ip(std::net::IpAddr),
///Route applies to traffic destined for a specific IP subnet
#[serde(rename = "ip_net")]
IpNet(IpNet),
///Route applies to traffic destined for the given VPC.
#[serde(rename = "vpc")]
Vpc(Name),
///Route applies to traffic
#[serde(rename = "subnet")]
Subnet(Name),
}
///A `RouteTarget` describes the possible locations that traffic matching a
/// route destination can be sent.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum RouteTarget {
///Forward traffic to a particular IP address.
#[serde(rename = "ip")]
Ip(std::net::IpAddr),
///Forward traffic to a VPC
#[serde(rename = "vpc")]
Vpc(Name),
///Forward traffic to a VPC Subnet
#[serde(rename = "subnet")]
Subnet(Name),
///Forward traffic to a specific instance
#[serde(rename = "instance")]
Instance(Name),
///Forward traffic to an internet gateway
#[serde(rename = "internet_gateway")]
InternetGateway(Name),
}
///A route defines a rule that governs where traffic should be sent based
/// on its destination.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RouterRoute {
///human-readable free-form text about a resource
pub description: String,
pub destination: RouteDestination,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///Describes the kind of router. Set at creation. `read-only`
pub kind: RouterRouteKind,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
pub target: RouteTarget,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///The VPC Router to which the route belongs.
pub vpc_router_id: uuid::Uuid,
}
///Create-time parameters for a [`RouterRoute`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RouterRouteCreateParams {
pub description: String,
pub destination: RouteDestination,
pub name: Name,
pub target: RouteTarget,
}
///The classification of a [`RouterRoute`] as defined by the system. The
/// kind determines certain attributes such as if the route is modifiable
/// and describes how or where the route was created.
///
///See [RFD-21](https://rfd.shared.oxide.computer/rfd/0021#concept-router) for more context
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum RouterRouteKind {
#[serde(rename = "default")]
Default,
#[serde(rename = "vpc_subnet")]
VpcSubnet,
#[serde(rename = "vpc_peering")]
VpcPeering,
#[serde(rename = "custom")]
Custom,
}
impl ToString for RouterRouteKind {
fn to_string(&self) -> String {
match *self {
Self::Default => "default".to_string(),
Self::VpcSubnet => "vpc_subnet".to_string(),
Self::VpcPeering => "vpc_peering".to_string(),
Self::Custom => "custom".to_string(),
}
}
}
impl std::str::FromStr for RouterRouteKind {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"default" => Ok(Self::Default),
"vpc_subnet" => Ok(Self::VpcSubnet),
"vpc_peering" => Ok(Self::VpcPeering),
"custom" => Ok(Self::Custom),
_ => Err("invalid value"),
}
}
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RouterRouteResultsPage {
///list of items on this page of results
pub items: Vec<RouterRoute>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Updateable properties of a [`RouterRoute`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RouterRouteUpdateParams {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub destination: RouteDestination,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
pub target: RouteTarget,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Saga {
pub id: uuid::Uuid,
pub state: SagaState,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "error")]
pub enum SagaErrorInfo {
#[serde(rename = "action_failed")]
ActionFailed { source_error: serde_json::Value },
#[serde(rename = "deserialize_failed")]
DeserializeFailed { message: String },
#[serde(rename = "injected_error")]
InjectedError,
#[serde(rename = "serialize_failed")]
SerializeFailed { message: String },
#[serde(rename = "subsaga_create_failed")]
SubsagaCreateFailed { message: String },
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SagaResultsPage {
///list of items on this page of results
pub items: Vec<Saga>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "state")]
pub enum SagaState {
#[serde(rename = "running")]
Running,
#[serde(rename = "succeeded")]
Succeeded,
#[serde(rename = "failed")]
Failed {
error_info: SagaErrorInfo,
error_node_name: String,
},
}
///Identity-related metadata that's included in nearly all public API
/// objects
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SamlIdentityProvider {
///service provider endpoint where the response will be sent
pub acs_url: String,
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///idp's entity id
pub idp_entity_id: String,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///optional request signing public certificate (base64 encoded der
/// file)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub public_cert: Option<String>,
///service provider endpoint where the idp should send log out requests
pub slo_url: String,
///sp's client id
pub sp_client_id: String,
///customer's technical contact for saml configuration
pub technical_contact_email: String,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time identity-related parameters
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SamlIdentityProviderCreate {
///service provider endpoint where the response will be sent
pub acs_url: String,
pub description: String,
///idp's entity id
pub idp_entity_id: String,
///the source of an identity provider metadata descriptor
pub idp_metadata_source: IdpMetadataSource,
pub name: Name,
///optional request signing key pair
#[serde(default, skip_serializing_if = "Option::is_none")]
pub signing_keypair: Option<DerEncodedKeyPair>,
///service provider endpoint where the idp should send log out requests
pub slo_url: String,
///sp's client id
pub sp_client_id: String,
///customer's technical contact for saml configuration
pub technical_contact_email: String,
}
///Client view of currently authed user.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SessionUser {
pub id: uuid::Uuid,
}
///Client view of a ['Silo']
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Silo {
///human-readable free-form text about a resource
pub description: String,
///A silo where discoverable is false can be retrieved only by its id -
/// it will not be part of the "list all silos" output.
pub discoverable: bool,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///User provision type
pub user_provision_type: UserProvisionType,
}
///Create-time parameters for a [`Silo`](crate::external_api::views::Silo)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SiloCreate {
pub description: String,
pub discoverable: bool,
pub name: Name,
pub user_provision_type: UserProvisionType,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SiloResultsPage {
///list of items on this page of results
pub items: Vec<Silo>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum SiloRole {
#[serde(rename = "admin")]
Admin,
#[serde(rename = "collaborator")]
Collaborator,
#[serde(rename = "viewer")]
Viewer,
}
impl ToString for SiloRole {
fn to_string(&self) -> String {
match *self {
Self::Admin => "admin".to_string(),
Self::Collaborator => "collaborator".to_string(),
Self::Viewer => "viewer".to_string(),
}
}
}
impl std::str::FromStr for SiloRole {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"admin" => Ok(Self::Admin),
"collaborator" => Ok(Self::Collaborator),
"viewer" => Ok(Self::Viewer),
_ => Err("invalid value"),
}
}
}
///Client view of a [`Policy`], which describes how this resource may be
/// accessed
///
///Note that the Policy only describes access granted explicitly for this
/// resource. The policies of parent resources can also cause a user to
/// have access to this resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SiloRolePolicy {
///Roles directly assigned on this resource
pub role_assignments: Vec<SiloRoleRoleAssignment>,
}
///Describes the assignment of a particular role on a particular resource
/// to a particular identity (user, group, etc.)
///
///The resource is not part of this structure. Rather, [`RoleAssignment`]s
/// are put into a [`Policy`] and that Policy is applied to a particular
/// resource.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SiloRoleRoleAssignment {
pub identity_id: uuid::Uuid,
pub identity_type: IdentityType,
pub role_name: SiloRole,
}
///Client view of an [`Sled`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Sled {
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
pub service_address: String,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SledResultsPage {
///list of items on this page of results
pub items: Vec<Sled>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Client view of a Snapshot
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Snapshot {
///human-readable free-form text about a resource
pub description: String,
pub disk_id: uuid::Uuid,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
pub project_id: uuid::Uuid,
pub size: ByteCount,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for a
/// [`Snapshot`](omicron_common::api::external::Snapshot)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SnapshotCreate {
pub description: String,
///The name of the disk to be snapshotted
pub disk: Name,
pub name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SnapshotResultsPage {
///list of items on this page of results
pub items: Vec<Snapshot>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SpoofLoginBody {
pub username: String,
}
///Client view of a [`SshKey`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SshKey {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///SSH public key, e.g., `"ssh-ed25519 AAAAC3NzaC..."`
pub public_key: String,
///The user to whom this key belongs
pub silo_user_id: uuid::Uuid,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for an
/// [`SshKey`](crate::external_api::views::SshKey)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SshKeyCreate {
pub description: String,
pub name: Name,
///SSH public key, e.g., `"ssh-ed25519 AAAAC3NzaC..."`
pub public_key: String,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SshKeyResultsPage {
///list of items on this page of results
pub items: Vec<SshKey>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Names are constructed by concatenating the target and metric names with
/// ':'. Target and metric names must be lowercase alphanumeric characters
/// with '_' separating words.
#[derive(Clone, Debug, Serialize)]
pub struct TimeseriesName(String);
impl std::ops::Deref for TimeseriesName {
type Target = String;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::TryFrom<&str> for TimeseriesName {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if regress::Regex::new(
"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*)",
)
.unwrap()
.find(value)
.is_none()
{
return Err ("doesn't match pattern \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*)\"") ;
}
Ok(Self(value.to_string()))
}
}
impl std::convert::TryFrom<String> for TimeseriesName {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(value.as_str())
}
}
impl<'de> serde::Deserialize<'de> for TimeseriesName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Self::try_from(String::deserialize(deserializer)?)
.map_err(|e| <D::Error as serde::de::Error>::custom(e.to_string()))
}
}
///The schema for a timeseries.
///
///This includes the name of the timeseries, as well as the datum type of
/// its metric and the schema for each field.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TimeseriesSchema {
pub created: chrono::DateTime<chrono::offset::Utc>,
pub datum_type: DatumType,
pub field_schema: Vec<FieldSchema>,
pub timeseries_name: TimeseriesName,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TimeseriesSchemaResultsPage {
///list of items on this page of results
pub items: Vec<TimeseriesSchema>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Client view of a [`User`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct User {
///Human-readable name that can identify the user
pub display_name: String,
pub id: uuid::Uuid,
}
///Client view of a [`UserBuiltin`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UserBuiltin {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UserBuiltinResultsPage {
///list of items on this page of results
pub items: Vec<UserBuiltin>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///How users will be provisioned in a silo during authentication.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum UserProvisionType {
#[serde(rename = "fixed")]
Fixed,
#[serde(rename = "jit")]
Jit,
}
impl ToString for UserProvisionType {
fn to_string(&self) -> String {
match *self {
Self::Fixed => "fixed".to_string(),
Self::Jit => "jit".to_string(),
}
}
}
impl std::str::FromStr for UserProvisionType {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"fixed" => Ok(Self::Fixed),
"jit" => Ok(Self::Jit),
_ => Err("invalid value"),
}
}
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UserResultsPage {
///list of items on this page of results
pub items: Vec<User>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Client view of a [`Vpc`]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Vpc {
///human-readable free-form text about a resource
pub description: String,
///The name used for the VPC in DNS.
pub dns_name: Name,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///The unique local IPv6 address range for subnets in this VPC
pub ipv6_prefix: Ipv6Net,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///id for the project containing this VPC
pub project_id: uuid::Uuid,
///id for the system router where subnet default routes are registered
pub system_router_id: uuid::Uuid,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
}
///Create-time parameters for a [`Vpc`](crate::external_api::views::Vpc)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcCreate {
pub description: String,
pub dns_name: Name,
///The IPv6 prefix for this VPC.
///
///All IPv6 subnets created from this VPC must be taken from this
/// range, which sould be a Unique Local Address in the range
/// `fd00::/48`. The default VPC Subnet will have the first `/64` range
/// from this prefix.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ipv6_prefix: Option<Ipv6Net>,
pub name: Name,
}
///A single rule in a VPC firewall
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcFirewallRule {
///whether traffic matching the rule should be allowed or dropped
pub action: VpcFirewallRuleAction,
///human-readable free-form text about a resource
pub description: String,
///whether this rule is for incoming or outgoing traffic
pub direction: VpcFirewallRuleDirection,
///reductions on the scope of the rule
pub filters: VpcFirewallRuleFilter,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///the relative priority of this rule
pub priority: u16,
///whether this rule is in effect
pub status: VpcFirewallRuleStatus,
///list of sets of instances that the rule applies to
pub targets: Vec<VpcFirewallRuleTarget>,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///the VPC to which this rule belongs
pub vpc_id: uuid::Uuid,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum VpcFirewallRuleAction {
#[serde(rename = "allow")]
Allow,
#[serde(rename = "deny")]
Deny,
}
impl ToString for VpcFirewallRuleAction {
fn to_string(&self) -> String {
match *self {
Self::Allow => "allow".to_string(),
Self::Deny => "deny".to_string(),
}
}
}
impl std::str::FromStr for VpcFirewallRuleAction {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"allow" => Ok(Self::Allow),
"deny" => Ok(Self::Deny),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum VpcFirewallRuleDirection {
#[serde(rename = "inbound")]
Inbound,
#[serde(rename = "outbound")]
Outbound,
}
impl ToString for VpcFirewallRuleDirection {
fn to_string(&self) -> String {
match *self {
Self::Inbound => "inbound".to_string(),
Self::Outbound => "outbound".to_string(),
}
}
}
impl std::str::FromStr for VpcFirewallRuleDirection {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"inbound" => Ok(Self::Inbound),
"outbound" => Ok(Self::Outbound),
_ => Err("invalid value"),
}
}
}
///Filter for a firewall rule. A given packet must match every field that
/// is present for the rule to apply to it. A packet matches a field if any
/// entry in that field matches the packet.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcFirewallRuleFilter {
///If present, the sources (if incoming) or destinations (if outgoing)
/// this rule applies to.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hosts: Option<Vec<VpcFirewallRuleHostFilter>>,
///If present, the destination ports this rule applies to.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ports: Option<Vec<L4PortRange>>,
///If present, the networking protocols this rule applies to.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub protocols: Option<Vec<VpcFirewallRuleProtocol>>,
}
///The `VpcFirewallRuleHostFilter` is used to filter traffic on the basis
/// of its source or destination host.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum VpcFirewallRuleHostFilter {
///The rule applies to traffic from/to all instances in the VPC
#[serde(rename = "vpc")]
Vpc(Name),
///The rule applies to traffic from/to all instances in the VPC Subnet
#[serde(rename = "subnet")]
Subnet(Name),
///The rule applies to traffic from/to this specific instance
#[serde(rename = "instance")]
Instance(Name),
///The rule applies to traffic from/to a specific IP address
#[serde(rename = "ip")]
Ip(std::net::IpAddr),
///The rule applies to traffic from/to a specific IP subnet
#[serde(rename = "ip_net")]
IpNet(IpNet),
}
///The protocols that may be specified in a firewall rule's filter
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum VpcFirewallRuleProtocol {
#[serde(rename = "TCP")]
Tcp,
#[serde(rename = "UDP")]
Udp,
#[serde(rename = "ICMP")]
Icmp,
}
impl ToString for VpcFirewallRuleProtocol {
fn to_string(&self) -> String {
match *self {
Self::Tcp => "TCP".to_string(),
Self::Udp => "UDP".to_string(),
Self::Icmp => "ICMP".to_string(),
}
}
}
impl std::str::FromStr for VpcFirewallRuleProtocol {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"TCP" => Ok(Self::Tcp),
"UDP" => Ok(Self::Udp),
"ICMP" => Ok(Self::Icmp),
_ => Err("invalid value"),
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum VpcFirewallRuleStatus {
#[serde(rename = "disabled")]
Disabled,
#[serde(rename = "enabled")]
Enabled,
}
impl ToString for VpcFirewallRuleStatus {
fn to_string(&self) -> String {
match *self {
Self::Disabled => "disabled".to_string(),
Self::Enabled => "enabled".to_string(),
}
}
}
impl std::str::FromStr for VpcFirewallRuleStatus {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"disabled" => Ok(Self::Disabled),
"enabled" => Ok(Self::Enabled),
_ => Err("invalid value"),
}
}
}
///A `VpcFirewallRuleTarget` is used to specify the set of [`Instance`]s to
/// which a firewall rule applies.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "value")]
pub enum VpcFirewallRuleTarget {
///The rule applies to all instances in the VPC
#[serde(rename = "vpc")]
Vpc(Name),
///The rule applies to all instances in the VPC Subnet
#[serde(rename = "subnet")]
Subnet(Name),
///The rule applies to this specific instance
#[serde(rename = "instance")]
Instance(Name),
///The rule applies to a specific IP address
#[serde(rename = "ip")]
Ip(std::net::IpAddr),
///The rule applies to a specific IP subnet
#[serde(rename = "ip_net")]
IpNet(IpNet),
}
///A single rule in a VPC firewall
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcFirewallRuleUpdate {
///whether traffic matching the rule should be allowed or dropped
pub action: VpcFirewallRuleAction,
///human-readable free-form text about a resource
pub description: String,
///whether this rule is for incoming or outgoing traffic
pub direction: VpcFirewallRuleDirection,
///reductions on the scope of the rule
pub filters: VpcFirewallRuleFilter,
///name of the rule, unique to this VPC
pub name: Name,
///the relative priority of this rule
pub priority: u16,
///whether this rule is in effect
pub status: VpcFirewallRuleStatus,
///list of sets of instances that the rule applies to
pub targets: Vec<VpcFirewallRuleTarget>,
}
///Updateable properties of a `Vpc`'s firewall Note that VpcFirewallRules
/// are implicitly created along with a Vpc, so there is no explicit
/// creation.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcFirewallRuleUpdateParams {
pub rules: Vec<VpcFirewallRuleUpdate>,
}
///Collection of a [`Vpc`]'s firewall rules
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcFirewallRules {
pub rules: Vec<VpcFirewallRule>,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcResultsPage {
///list of items on this page of results
pub items: Vec<Vpc>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///A VPC router defines a series of rules that indicate where traffic
/// should be sent depending on its destination.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcRouter {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
pub kind: VpcRouterKind,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///The VPC to which the router belongs.
pub vpc_id: uuid::Uuid,
}
///Create-time parameters for a
/// [`VpcRouter`](crate::external_api::views::VpcRouter)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcRouterCreate {
pub description: String,
pub name: Name,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum VpcRouterKind {
#[serde(rename = "system")]
System,
#[serde(rename = "custom")]
Custom,
}
impl ToString for VpcRouterKind {
fn to_string(&self) -> String {
match *self {
Self::System => "system".to_string(),
Self::Custom => "custom".to_string(),
}
}
}
impl std::str::FromStr for VpcRouterKind {
type Err = &'static str;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"system" => Ok(Self::System),
"custom" => Ok(Self::Custom),
_ => Err("invalid value"),
}
}
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcRouterResultsPage {
///list of items on this page of results
pub items: Vec<VpcRouter>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Updateable properties of a
/// [`VpcRouter`](crate::external_api::views::VpcRouter)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcRouterUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
///A VPC subnet represents a logical grouping for instances that allows
/// network traffic between them, within a IPv4 subnetwork or optionall an
/// IPv6 subnetwork.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcSubnet {
///human-readable free-form text about a resource
pub description: String,
///unique, immutable, system-controlled identifier for each resource
pub id: uuid::Uuid,
///The IPv4 subnet CIDR block.
pub ipv4_block: Ipv4Net,
///The IPv6 subnet CIDR block.
pub ipv6_block: Ipv6Net,
///unique, mutable, user-controlled identifier for each resource
pub name: Name,
///timestamp when this resource was created
pub time_created: chrono::DateTime<chrono::offset::Utc>,
///timestamp when this resource was last modified
pub time_modified: chrono::DateTime<chrono::offset::Utc>,
///The VPC to which the subnet belongs.
pub vpc_id: uuid::Uuid,
}
///Create-time parameters for a
/// [`VpcSubnet`](crate::external_api::views::VpcSubnet)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcSubnetCreate {
pub description: String,
///The IPv4 address range for this subnet.
///
///It must be allocated from an RFC 1918 private address range, and
/// must not overlap with any other existing subnet in the VPC.
pub ipv4_block: Ipv4Net,
///The IPv6 address range for this subnet.
///
///It must be allocated from the RFC 4193 Unique Local Address range,
/// with the prefix equal to the parent VPC's prefix. A random `/64`
/// block will be assigned if one is not provided. It must not overlap
/// with any existing subnet in the VPC.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ipv6_block: Option<Ipv6Net>,
pub name: Name,
}
///A single page of results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcSubnetResultsPage {
///list of items on this page of results
pub items: Vec<VpcSubnet>,
///token used to fetch the next page of results (if any)
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_page: Option<String>,
}
///Updateable properties of a
/// [`VpcSubnet`](crate::external_api::views::VpcSubnet)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcSubnetUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
///Updateable properties of a [`Vpc`](crate::external_api::views::Vpc)
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct VpcUpdate {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub dns_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
}
}
#[derive(Clone)]
pub struct Client {
pub(crate) baseurl: String,
pub(crate) client: reqwest::Client,
}
impl Client {
pub fn new(baseurl: &str) -> Self {
let dur = std::time::Duration::from_secs(15);
let client = reqwest::ClientBuilder::new()
.connect_timeout(dur)
.timeout(dur)
.build()
.unwrap();
Self::new_with_client(baseurl, client)
}
pub fn new_with_client(baseurl: &str, client: reqwest::Client) -> Self {
Self {
baseurl: baseurl.to_string(),
client,
}
}
pub fn baseurl(&self) -> &String {
&self.baseurl
}
pub fn client(&self) -> &reqwest::Client {
&self.client
}
}
impl Client {
///Start an OAuth 2.0 Device Authorization Grant
///
///This endpoint is designed to be accessed from an *unauthenticated* API
/// client. It generates and records a `device_code` and `user_code` which
/// must be verified and confirmed prior to a token being granted.
///
///Sends a `POST` request to `/device/auth`
pub async fn device_auth_request<'a>(
&'a self,
body: &'a types::DeviceAuthRequest,
) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!("{}/device/auth", self.baseurl,);
let request = self.client.post(url).form_urlencoded(&body)?.build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///Confirm an OAuth 2.0 Device Authorization Grant
///
///This endpoint is designed to be accessed by the user agent (browser),
/// not the client requesting the token. So we do not actually return the
/// token here; it will be returned in response to the poll on
/// `/device/token`.
///
///Sends a `POST` request to `/device/confirm`
pub async fn device_auth_confirm<'a>(
&'a self,
body: &'a types::DeviceAuthVerify,
) -> Result<ResponseValue<Option<types::Null>>, Error<types::Error>> {
let url = format!("{}/device/confirm", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Request a device access token
///
///This endpoint should be polled by the client until the user code is
/// verified and the grant is confirmed.
///
///Sends a `POST` request to `/device/token`
pub async fn device_access_token<'a>(
&'a self,
body: &'a types::DeviceAccessTokenRequest,
) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!("{}/device/token", self.baseurl,);
let request = self.client.post(url).form_urlencoded(&body)?.build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///List racks in the system
///
///Sends a `GET` request to `/hardware/racks`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn rack_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::IdSortMode>,
) -> Result<ResponseValue<types::RackResultsPage>, Error<types::Error>> {
let url = format!("{}/hardware/racks", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List racks in the system as a Stream
///
///Sends repeated `GET` requests to `/hardware/racks` until there are no
/// more results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn rack_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::IdSortMode>,
) -> impl futures::Stream<Item = Result<types::Rack, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.rack_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.rack_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch information about a particular rack
///
///Sends a `GET` request to `/hardware/racks/{rack_id}`
///
///Arguments:
/// - `rack_id`: The rack's unique ID.
pub async fn rack_view<'a>(
&'a self,
rack_id: &'a uuid::Uuid,
) -> Result<ResponseValue<types::Rack>, Error<types::Error>> {
let url = format!(
"{}/hardware/racks/{}",
self.baseurl,
encode_path(&rack_id.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List sleds in the system
///
///Sends a `GET` request to `/hardware/sleds`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn sled_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::IdSortMode>,
) -> Result<ResponseValue<types::SledResultsPage>, Error<types::Error>> {
let url = format!("{}/hardware/sleds", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List sleds in the system as a Stream
///
///Sends repeated `GET` requests to `/hardware/sleds` until there are no
/// more results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn sled_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::IdSortMode>,
) -> impl futures::Stream<Item = Result<types::Sled, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.sled_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.sled_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch information about a sled in the system
///
///Sends a `GET` request to `/hardware/sleds/{sled_id}`
///
///Arguments:
/// - `sled_id`: The sled's unique ID.
pub async fn sled_view<'a>(
&'a self,
sled_id: &'a uuid::Uuid,
) -> Result<ResponseValue<types::Sled>, Error<types::Error>> {
let url = format!(
"{}/hardware/sleds/{}",
self.baseurl,
encode_path(&sled_id.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List global images
///
///Returns a list of all the global images. Global images are returned
/// sorted by creation date, with the most recent images appearing first.
///
///Sends a `GET` request to `/images`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn image_global_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::GlobalImageResultsPage>, Error<types::Error>> {
let url = format!("{}/images", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List global images as a Stream
///
///Returns a list of all the global images. Global images are returned
/// sorted by creation date, with the most recent images appearing first.
///
///Sends repeated `GET` requests to `/images` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn image_global_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::GlobalImage, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.image_global_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.image_global_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a global image
///
///Create a new global image. This image can then be used by any user as a
/// base for instances.
///
///Sends a `POST` request to `/images`
pub async fn image_global_create<'a>(
&'a self,
body: &'a types::GlobalImageCreate,
) -> Result<ResponseValue<types::GlobalImage>, Error<types::Error>> {
let url = format!("{}/images", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get a global image
///
///Returns the details of a specific global image.
///
///Sends a `GET` request to `/images/{image_name}`
pub async fn image_global_view<'a>(
&'a self,
image_name: &'a types::Name,
) -> Result<ResponseValue<types::GlobalImage>, Error<types::Error>> {
let url = format!(
"{}/images/{}",
self.baseurl,
encode_path(&image_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a global image
///
///Permanently delete a global image. This operation cannot be undone. Any
/// instances using the global image will continue to run, however new
/// instances can not be created with this image.
///
///Sends a `DELETE` request to `/images/{image_name}`
pub async fn image_global_delete<'a>(
&'a self,
image_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/images/{}",
self.baseurl,
encode_path(&image_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List IP Pools
///
///Sends a `GET` request to `/ip-pools`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn ip_pool_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameOrIdSortMode>,
) -> Result<ResponseValue<types::IpPoolResultsPage>, Error<types::Error>> {
let url = format!("{}/ip-pools", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List IP Pools as a Stream
///
///Sends repeated `GET` requests to `/ip-pools` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn ip_pool_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameOrIdSortMode>,
) -> impl futures::Stream<Item = Result<types::IpPool, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.ip_pool_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.ip_pool_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a new IP Pool
///
///Sends a `POST` request to `/ip-pools`
pub async fn ip_pool_create<'a>(
&'a self,
body: &'a types::IpPoolCreate,
) -> Result<ResponseValue<types::IpPool>, Error<types::Error>> {
let url = format!("{}/ip-pools", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch a single IP Pool
///
///Sends a `GET` request to `/ip-pools/{pool_name}`
pub async fn ip_pool_view<'a>(
&'a self,
pool_name: &'a types::Name,
) -> Result<ResponseValue<types::IpPool>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update an IP Pool
///
///Sends a `PUT` request to `/ip-pools/{pool_name}`
pub async fn ip_pool_update<'a>(
&'a self,
pool_name: &'a types::Name,
body: &'a types::IpPoolUpdate,
) -> Result<ResponseValue<types::IpPool>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete an IP Pool
///
///Sends a `DELETE` request to `/ip-pools/{pool_name}`
pub async fn ip_pool_delete<'a>(
&'a self,
pool_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the ranges of IP addresses within an existing IP Pool
///
///Note that ranges are listed sorted by their first address.
///
///Sends a `GET` request to `/ip-pools/{pool_name}/ranges`
///
///Arguments:
/// - `pool_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
pub async fn ip_pool_range_list<'a>(
&'a self,
pool_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
) -> Result<ResponseValue<types::IpPoolRangeResultsPage>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}/ranges",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the ranges of IP addresses within an existing IP Pool as a Stream
///
///Note that ranges are listed sorted by their first address.
///
///Sends repeated `GET` requests to `/ip-pools/{pool_name}/ranges` until
/// there are no more results.
///
///Arguments:
/// - `pool_name`
/// - `limit`: Maximum number of items returned by a single call
pub fn ip_pool_range_list_stream<'a>(
&'a self,
pool_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
) -> impl futures::Stream<Item = Result<types::IpPoolRange, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.ip_pool_range_list(pool_name, limit, None)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.ip_pool_range_list(pool_name, None, state.as_deref())
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Add a new range to an existing IP Pool
///
///Sends a `POST` request to `/ip-pools/{pool_name}/ranges/add`
pub async fn ip_pool_range_add<'a>(
&'a self,
pool_name: &'a types::Name,
body: &'a types::IpRange,
) -> Result<ResponseValue<types::IpPoolRange>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}/ranges/add",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Remove a range from an existing IP Pool
///
///Sends a `POST` request to `/ip-pools/{pool_name}/ranges/remove`
pub async fn ip_pool_range_remove<'a>(
&'a self,
pool_name: &'a types::Name,
body: &'a types::IpRange,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/ip-pools/{}/ranges/remove",
self.baseurl,
encode_path(&pool_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Sends a `POST` request to `/login`
pub async fn spoof_login<'a>(
&'a self,
body: &'a types::SpoofLoginBody,
) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!("{}/login", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///Ask the user to login to their identity provider
///
///Either display a page asking a user for their credentials, or redirect
/// them to their identity provider.
///
///Sends a `GET` request to `/login/{silo_name}/{provider_name}`
pub async fn login<'a>(
&'a self,
silo_name: &'a types::Name,
provider_name: &'a types::Name,
) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!(
"{}/login/{}/{}",
self.baseurl,
encode_path(&silo_name.to_string()),
encode_path(&provider_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///Consume some sort of credentials, and authenticate a user
///
///Either receive a username and password, or some sort of identity
/// provider data (like a SAMLResponse). Use these to set the user's session
/// cookie.
///
///Sends a `POST` request to `/login/{silo_name}/{provider_name}`
pub async fn consume_credentials<'a, B: Into<reqwest::Body>>(
&'a self,
silo_name: &'a types::Name,
provider_name: &'a types::Name,
body: B,
) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!(
"{}/login/{}/{}",
self.baseurl,
encode_path(&silo_name.to_string()),
encode_path(&provider_name.to_string()),
);
let request = self
.client
.post(url)
.header(
reqwest::header::CONTENT_TYPE,
reqwest::header::HeaderValue::from_static("application/octet-stream"),
)
.body(body)
.build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///Sends a `POST` request to `/logout`
pub async fn logout<'a>(&'a self) -> Result<ResponseValue<ByteStream>, Error<ByteStream>> {
let url = format!("{}/logout", self.baseurl,);
let request = self.client.post(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200..=299 => Ok(ResponseValue::stream(response)),
_ => Err(Error::ErrorResponse(ResponseValue::stream(response))),
}
}
///List all organizations
///
///Sends a `GET` request to `/organizations`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn organization_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameOrIdSortMode>,
) -> Result<ResponseValue<types::OrganizationResultsPage>, Error<types::Error>> {
let url = format!("{}/organizations", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all organizations as a Stream
///
///Sends repeated `GET` requests to `/organizations` until there are no
/// more results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn organization_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameOrIdSortMode>,
) -> impl futures::Stream<Item = Result<types::Organization, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.organization_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.organization_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a new organization
///
///Sends a `POST` request to `/organizations`
pub async fn organization_create<'a>(
&'a self,
body: &'a types::OrganizationCreate,
) -> Result<ResponseValue<types::Organization>, Error<types::Error>> {
let url = format!("{}/organizations", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch a specific organization
///
///Sends a `GET` request to `/organizations/{organization_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
pub async fn organization_view<'a>(
&'a self,
organization_name: &'a types::Name,
) -> Result<ResponseValue<types::Organization>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a specific organization
///
///Sends a `PUT` request to `/organizations/{organization_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `body`
pub async fn organization_update<'a>(
&'a self,
organization_name: &'a types::Name,
body: &'a types::OrganizationUpdate,
) -> Result<ResponseValue<types::Organization>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a specific organization
///
///Sends a `DELETE` request to `/organizations/{organization_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
pub async fn organization_delete<'a>(
&'a self,
organization_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch the IAM policy for this Organization
///
///Sends a `GET` request to `/organizations/{organization_name}/policy`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
pub async fn organization_policy_view<'a>(
&'a self,
organization_name: &'a types::Name,
) -> Result<ResponseValue<types::OrganizationRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/policy",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update the IAM policy for this Organization
///
///Sends a `PUT` request to `/organizations/{organization_name}/policy`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `body`
pub async fn organization_policy_update<'a>(
&'a self,
organization_name: &'a types::Name,
body: &'a types::OrganizationRolePolicy,
) -> Result<ResponseValue<types::OrganizationRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/policy",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all projects
///
///Sends a `GET` request to `/organizations/{organization_name}/projects`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn project_list<'a>(
&'a self,
organization_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameOrIdSortMode>,
) -> Result<ResponseValue<types::ProjectResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all projects as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects` until there are no more
/// results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn project_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameOrIdSortMode>,
) -> impl futures::Stream<Item = Result<types::Project, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.project_list(organization_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.project_list(organization_name, None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a new project
///
///Sends a `POST` request to `/organizations/{organization_name}/projects`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `body`
pub async fn project_create<'a>(
&'a self,
organization_name: &'a types::Name,
body: &'a types::ProjectCreate,
) -> Result<ResponseValue<types::Project>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects",
self.baseurl,
encode_path(&organization_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch a specific project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
pub async fn project_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
) -> Result<ResponseValue<types::Project>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a specific project
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn project_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::ProjectUpdate,
) -> Result<ResponseValue<types::Project>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a specific project
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
pub async fn project_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List disks in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/disks`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn disk_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::DiskResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/disks",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List disks in a project as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/disks` until
/// there are no more results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn disk_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Disk, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.disk_list(organization_name, project_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.disk_list(
organization_name,
project_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a disk in a project
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/disks`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn disk_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::DiskCreate,
) -> Result<ResponseValue<types::Disk>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/disks",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch a single disk in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/disks/
/// {disk_name}`
pub async fn disk_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
disk_name: &'a types::Name,
) -> Result<ResponseValue<types::Disk>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/disks/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&disk_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a disk from a project
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/disks/
/// {disk_name}`
pub async fn disk_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
disk_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/disks/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&disk_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List images
///
///List images in a project. The images are returned sorted by creation
/// date, with the most recent images appearing first.
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/images`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn image_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::ImageResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/images",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List images as a Stream
///
///List images in a project. The images are returned sorted by creation
/// date, with the most recent images appearing first.
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/images`
/// until there are no more results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn image_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Image, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.image_list(organization_name, project_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.image_list(
organization_name,
project_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create an image
///
///Create a new image in a project.
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/images`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn image_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::ImageCreate,
) -> Result<ResponseValue<types::Image>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/images",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get an image
///
///Get the details of a specific image in a project.
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/images/
/// {image_name}`
pub async fn image_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
image_name: &'a types::Name,
) -> Result<ResponseValue<types::Image>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/images/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&image_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete an image
///
///Permanently delete an image from a project. This operation cannot be
/// undone. Any instances in the project using the image will continue to
/// run, however new instances can not be created with this image.
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/images/
/// {image_name}`
pub async fn image_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
image_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/images/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&image_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List instances in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn instance_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::InstanceResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List instances in a project as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/instances`
/// until there are no more results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn instance_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Instance, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.instance_list(organization_name, project_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.instance_list(
organization_name,
project_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create an instance in a project
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn instance_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::InstanceCreate,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get an instance in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}`
pub async fn instance_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete an instance from a project
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}`
pub async fn instance_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List disks attached to this instance
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/disks`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `instance_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn instance_disk_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::DiskResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/disks",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List disks attached to this instance as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/disks` until there are no more results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `instance_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn instance_disk_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Disk, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.instance_disk_list(
organization_name,
project_name,
instance_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.instance_disk_list(
organization_name,
project_name,
instance_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/disks/attach`
pub async fn instance_disk_attach<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
body: &'a types::DiskIdentifier,
) -> Result<ResponseValue<types::Disk>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/disks/attach",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
202u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/disks/detach`
pub async fn instance_disk_detach<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
body: &'a types::DiskIdentifier,
) -> Result<ResponseValue<types::Disk>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/disks/detach",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
202u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Migrate an instance to a different propolis-server, possibly on a
/// different sled
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/migrate`
pub async fn instance_migrate<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
body: &'a types::InstanceMigrate,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/migrate",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List network interfaces attached to this instance
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `instance_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn instance_network_interface_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::NetworkInterfaceResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/network-interfaces",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List network interfaces attached to this instance as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces` until there are no more results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `instance_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn instance_network_interface_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::NetworkInterface, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.instance_network_interface_list(
organization_name,
project_name,
instance_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.instance_network_interface_list(
organization_name,
project_name,
instance_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a network interface for an instance
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces`
pub async fn instance_network_interface_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
body: &'a types::NetworkInterfaceCreate,
) -> Result<ResponseValue<types::NetworkInterface>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/network-interfaces",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get an interface attached to an instance
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces/{interface_name}`
pub async fn instance_network_interface_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
interface_name: &'a types::Name,
) -> Result<ResponseValue<types::NetworkInterface>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/network-interfaces/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
encode_path(&interface_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update information about an instance's network interface
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces/{interface_name}`
pub async fn instance_network_interface_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
interface_name: &'a types::Name,
body: &'a types::NetworkInterfaceUpdate,
) -> Result<ResponseValue<types::NetworkInterface>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/network-interfaces/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
encode_path(&interface_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Detach a network interface from an instance
///
///Note that the primary interface for an instance cannot be deleted if
/// there are any secondary interfaces. A new primary interface must be
/// designated first. The primary interface can be deleted if there are no
/// secondary interfaces.
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/network-interfaces/{interface_name}`
pub async fn instance_network_interface_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
interface_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/network-interfaces/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
encode_path(&interface_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Reboot an instance
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/reboot`
pub async fn instance_reboot<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/reboot",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
202u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get contents of an instance's serial console
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/serial-console`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `instance_name`
/// - `from_start`: Character index in the serial buffer from which to read,
/// counting the bytes output since instance start. If this is not
/// provided, `most_recent` must be provided, and if this *is* provided,
/// `most_recent` must *not* be provided.
/// - `max_bytes`: Maximum number of bytes of buffered serial console
/// contents to return. If the requested range runs to the end of the
/// available buffer, the data returned will be shorter than `max_bytes`.
/// - `most_recent`: Character index in the serial buffer from which to
/// read, counting *backward* from the most recently buffered data
/// retrieved from the instance. (See note on `from_start` about mutual
/// exclusivity)
pub async fn instance_serial_console<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
from_start: Option<u64>,
max_bytes: Option<u64>,
most_recent: Option<u64>,
) -> Result<ResponseValue<types::InstanceSerialConsoleData>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/serial-console",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &from_start {
query.push(("from_start", v.to_string()));
}
if let Some(v) = &max_bytes {
query.push(("max_bytes", v.to_string()));
}
if let Some(v) = &most_recent {
query.push(("most_recent", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Boot an instance
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/start`
pub async fn instance_start<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/start",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
202u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Halt an instance
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/instances/
/// {instance_name}/stop`
pub async fn instance_stop<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
instance_name: &'a types::Name,
) -> Result<ResponseValue<types::Instance>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/instances/{}/stop",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&instance_name.to_string()),
);
let request = self.client.post(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
202u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch the IAM policy for this Project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/policy`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
pub async fn project_policy_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
) -> Result<ResponseValue<types::ProjectRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/policy",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update the IAM policy for this Project
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/policy`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn project_policy_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::ProjectRolePolicy,
) -> Result<ResponseValue<types::ProjectRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/policy",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List snapshots in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/snapshots`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn snapshot_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::SnapshotResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/snapshots",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List snapshots in a project as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/snapshots`
/// until there are no more results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn snapshot_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Snapshot, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.snapshot_list(organization_name, project_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.snapshot_list(
organization_name,
project_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a snapshot of a disk
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/snapshots`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn snapshot_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::SnapshotCreate,
) -> Result<ResponseValue<types::Snapshot>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/snapshots",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get a snapshot in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/snapshots/
/// {snapshot_name}`
pub async fn snapshot_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
snapshot_name: &'a types::Name,
) -> Result<ResponseValue<types::Snapshot>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/snapshots/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&snapshot_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a snapshot from a project
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/snapshots/
/// {snapshot_name}`
pub async fn snapshot_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
snapshot_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/snapshots/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&snapshot_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List VPCs in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn vpc_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::VpcResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List VPCs in a project as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs` until
/// there are no more results.
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn vpc_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::Vpc, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.vpc_list(organization_name, project_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.vpc_list(
organization_name,
project_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a VPC in a project
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs`
///
///Arguments:
/// - `organization_name`: The organization's unique name.
/// - `project_name`: The project's unique name within the organization.
/// - `body`
pub async fn vpc_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
body: &'a types::VpcCreate,
) -> Result<ResponseValue<types::Vpc>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get a VPC in a project
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}`
pub async fn vpc_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
) -> Result<ResponseValue<types::Vpc>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a VPC
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}`
pub async fn vpc_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
body: &'a types::VpcUpdate,
) -> Result<ResponseValue<types::Vpc>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a vpc from a project
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}`
pub async fn vpc_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List firewall rules for a VPC
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/firewall/rules`
pub async fn vpc_firewall_rules_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
) -> Result<ResponseValue<types::VpcFirewallRules>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/firewall/rules",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Replace the firewall rules for a VPC
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/firewall/rules`
pub async fn vpc_firewall_rules_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
body: &'a types::VpcFirewallRuleUpdateParams,
) -> Result<ResponseValue<types::VpcFirewallRules>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/firewall/rules",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List VPC Custom and System Routers
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn vpc_router_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::VpcRouterResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List VPC Custom and System Routers as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers` until there are no more results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn vpc_router_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::VpcRouter, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.vpc_router_list(
organization_name,
project_name,
vpc_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.vpc_router_list(
organization_name,
project_name,
vpc_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a VPC Router
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers`
pub async fn vpc_router_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
body: &'a types::VpcRouterCreate,
) -> Result<ResponseValue<types::VpcRouter>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get a VPC Router
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}`
pub async fn vpc_router_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
) -> Result<ResponseValue<types::VpcRouter>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a VPC Router
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}`
pub async fn vpc_router_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
body: &'a types::VpcRouterUpdate,
) -> Result<ResponseValue<types::VpcRouter>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a router from its VPC
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}`
pub async fn vpc_router_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List a Router's routes
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `router_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn vpc_router_route_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::RouterRouteResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List a Router's routes as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes` until there are no more
/// results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `router_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn vpc_router_route_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::RouterRoute, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.vpc_router_route_list(
organization_name,
project_name,
vpc_name,
router_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.vpc_router_route_list(
organization_name,
project_name,
vpc_name,
router_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a VPC Router
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes`
pub async fn vpc_router_route_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
body: &'a types::RouterRouteCreateParams,
) -> Result<ResponseValue<types::RouterRoute>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get a VPC Router route
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes/{route_name}`
pub async fn vpc_router_route_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
route_name: &'a types::Name,
) -> Result<ResponseValue<types::RouterRoute>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
encode_path(&route_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a Router route
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes/{route_name}`
pub async fn vpc_router_route_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
route_name: &'a types::Name,
body: &'a types::RouterRouteUpdateParams,
) -> Result<ResponseValue<types::RouterRoute>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
encode_path(&route_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a route from its router
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/routers/{router_name}/routes/{route_name}`
pub async fn vpc_router_route_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
router_name: &'a types::Name,
route_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&router_name.to_string()),
encode_path(&route_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List subnets in a VPC
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn vpc_subnet_list<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::VpcSubnetResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List subnets in a VPC as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets` until there are no more results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn vpc_subnet_list_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::VpcSubnet, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.vpc_subnet_list(
organization_name,
project_name,
vpc_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.vpc_subnet_list(
organization_name,
project_name,
vpc_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a subnet in a VPC
///
///Sends a `POST` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets`
pub async fn vpc_subnet_create<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
body: &'a types::VpcSubnetCreate,
) -> Result<ResponseValue<types::VpcSubnet>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get subnet in a VPC
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets/{subnet_name}`
pub async fn vpc_subnet_view<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
subnet_name: &'a types::Name,
) -> Result<ResponseValue<types::VpcSubnet>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&subnet_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update a VPC Subnet
///
///Sends a `PUT` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets/{subnet_name}`
pub async fn vpc_subnet_update<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
subnet_name: &'a types::Name,
body: &'a types::VpcSubnetUpdate,
) -> Result<ResponseValue<types::VpcSubnet>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&subnet_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a subnet from a VPC
///
///Sends a `DELETE` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets/{subnet_name}`
pub async fn vpc_subnet_delete<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
subnet_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&subnet_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List network interfaces in a VPC subnet
///
///Sends a `GET` request to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets/{subnet_name}/network-interfaces`
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `subnet_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn vpc_subnet_list_network_interfaces<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
subnet_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::NetworkInterfaceResultsPage>, Error<types::Error>> {
let url = format!(
"{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}/network-interfaces",
self.baseurl,
encode_path(&organization_name.to_string()),
encode_path(&project_name.to_string()),
encode_path(&vpc_name.to_string()),
encode_path(&subnet_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List network interfaces in a VPC subnet as a Stream
///
///Sends repeated `GET` requests to
/// `/organizations/{organization_name}/projects/{project_name}/vpcs/
/// {vpc_name}/subnets/{subnet_name}/network-interfaces` until there are no
/// more results.
///
///Arguments:
/// - `organization_name`
/// - `project_name`
/// - `vpc_name`
/// - `subnet_name`
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn vpc_subnet_list_network_interfaces_stream<'a>(
&'a self,
organization_name: &'a types::Name,
project_name: &'a types::Name,
vpc_name: &'a types::Name,
subnet_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::NetworkInterface, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.vpc_subnet_list_network_interfaces(
organization_name,
project_name,
vpc_name,
subnet_name,
limit,
None,
sort_by,
)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.vpc_subnet_list_network_interfaces(
organization_name,
project_name,
vpc_name,
subnet_name,
None,
state.as_deref(),
None,
)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch the top-level IAM policy
///
///Sends a `GET` request to `/policy`
pub async fn policy_view<'a>(
&'a self,
) -> Result<ResponseValue<types::FleetRolePolicy>, Error<types::Error>> {
let url = format!("{}/policy", self.baseurl,);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update the top-level IAM policy
///
///Sends a `PUT` request to `/policy`
pub async fn policy_update<'a>(
&'a self,
body: &'a types::FleetRolePolicy,
) -> Result<ResponseValue<types::FleetRolePolicy>, Error<types::Error>> {
let url = format!("{}/policy", self.baseurl,);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the built-in roles
///
///Sends a `GET` request to `/roles`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
pub async fn role_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
) -> Result<ResponseValue<types::RoleResultsPage>, Error<types::Error>> {
let url = format!("{}/roles", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the built-in roles as a Stream
///
///Sends repeated `GET` requests to `/roles` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
pub fn role_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
) -> impl futures::Stream<Item = Result<types::Role, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.role_list(limit, None)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.role_list(None, state.as_deref())
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch a specific built-in role
///
///Sends a `GET` request to `/roles/{role_name}`
///
///Arguments:
/// - `role_name`: The built-in role's unique name.
pub async fn role_view<'a>(
&'a self,
role_name: &'a str,
) -> Result<ResponseValue<types::Role>, Error<types::Error>> {
let url = format!(
"{}/roles/{}",
self.baseurl,
encode_path(&role_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all sagas (for debugging)
///
///Sends a `GET` request to `/sagas`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn saga_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::IdSortMode>,
) -> Result<ResponseValue<types::SagaResultsPage>, Error<types::Error>> {
let url = format!("{}/sagas", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all sagas (for debugging) as a Stream
///
///Sends repeated `GET` requests to `/sagas` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn saga_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::IdSortMode>,
) -> impl futures::Stream<Item = Result<types::Saga, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.saga_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.saga_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch information about a single saga (for debugging)
///
///Sends a `GET` request to `/sagas/{saga_id}`
pub async fn saga_view<'a>(
&'a self,
saga_id: &'a uuid::Uuid,
) -> Result<ResponseValue<types::Saga>, Error<types::Error>> {
let url = format!(
"{}/sagas/{}",
self.baseurl,
encode_path(&saga_id.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch the user associated with the current session
///
///Sends a `GET` request to `/session/me`
pub async fn session_me<'a>(
&'a self,
) -> Result<ResponseValue<types::SessionUser>, Error<types::Error>> {
let url = format!("{}/session/me", self.baseurl,);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the current user's SSH public keys
///
///Sends a `GET` request to `/session/me/sshkeys`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn session_sshkey_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::SshKeyResultsPage>, Error<types::Error>> {
let url = format!("{}/session/me/sshkeys", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the current user's SSH public keys as a Stream
///
///Sends repeated `GET` requests to `/session/me/sshkeys` until there are
/// no more results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn session_sshkey_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::SshKey, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.session_sshkey_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.session_sshkey_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a new SSH public key for the current user
///
///Sends a `POST` request to `/session/me/sshkeys`
pub async fn session_sshkey_create<'a>(
&'a self,
body: &'a types::SshKeyCreate,
) -> Result<ResponseValue<types::SshKey>, Error<types::Error>> {
let url = format!("{}/session/me/sshkeys", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Get (by name) an SSH public key belonging to the current user
///
///Sends a `GET` request to `/session/me/sshkeys/{ssh_key_name}`
pub async fn session_sshkey_view<'a>(
&'a self,
ssh_key_name: &'a types::Name,
) -> Result<ResponseValue<types::SshKey>, Error<types::Error>> {
let url = format!(
"{}/session/me/sshkeys/{}",
self.baseurl,
encode_path(&ssh_key_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete (by name) an SSH public key belonging to the current user
///
///Sends a `DELETE` request to `/session/me/sshkeys/{ssh_key_name}`
pub async fn session_sshkey_delete<'a>(
&'a self,
ssh_key_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/session/me/sshkeys/{}",
self.baseurl,
encode_path(&ssh_key_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Sends a `GET` request to `/silos`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn silo_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameOrIdSortMode>,
) -> Result<ResponseValue<types::SiloResultsPage>, Error<types::Error>> {
let url = format!("{}/silos", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Sends repeated `GET` requests to `/silos` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn silo_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameOrIdSortMode>,
) -> impl futures::Stream<Item = Result<types::Silo, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.silo_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.silo_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Create a new silo
///
///Sends a `POST` request to `/silos`
pub async fn silo_create<'a>(
&'a self,
body: &'a types::SiloCreate,
) -> Result<ResponseValue<types::Silo>, Error<types::Error>> {
let url = format!("{}/silos", self.baseurl,);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Fetch a specific silo
///
///Sends a `GET` request to `/silos/{silo_name}`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
pub async fn silo_view<'a>(
&'a self,
silo_name: &'a types::Name,
) -> Result<ResponseValue<types::Silo>, Error<types::Error>> {
let url = format!(
"{}/silos/{}",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Delete a specific silo
///
///Sends a `DELETE` request to `/silos/{silo_name}`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
pub async fn silo_delete<'a>(
&'a self,
silo_name: &'a types::Name,
) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!(
"{}/silos/{}",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let request = self.client.delete(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List Silo identity providers
///
///Sends a `GET` request to `/silos/{silo_name}/identity_providers`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn silo_identity_provider_list<'a>(
&'a self,
silo_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::IdentityProviderResultsPage>, Error<types::Error>> {
let url = format!(
"{}/silos/{}/identity_providers",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List Silo identity providers as a Stream
///
///Sends repeated `GET` requests to `/silos/{silo_name}/identity_providers`
/// until there are no more results.
///
///Arguments:
/// - `silo_name`: The silo's unique name.
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn silo_identity_provider_list_stream<'a>(
&'a self,
silo_name: &'a types::Name,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::IdentityProvider, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.silo_identity_provider_list(silo_name, limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.silo_identity_provider_list(silo_name, None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch the IAM policy for this Silo
///
///Sends a `GET` request to `/silos/{silo_name}/policy`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
pub async fn silo_policy_view<'a>(
&'a self,
silo_name: &'a types::Name,
) -> Result<ResponseValue<types::SiloRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/silos/{}/policy",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Update the IAM policy for this Silo
///
///Sends a `PUT` request to `/silos/{silo_name}/policy`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
/// - `body`
pub async fn silo_policy_update<'a>(
&'a self,
silo_name: &'a types::Name,
body: &'a types::SiloRolePolicy,
) -> Result<ResponseValue<types::SiloRolePolicy>, Error<types::Error>> {
let url = format!(
"{}/silos/{}/policy",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let request = self.client.put(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///Create a new SAML identity provider for a silo
///
///Sends a `POST` request to `/silos/{silo_name}/saml_identity_providers`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
/// - `body`
pub async fn silo_identity_provider_create<'a>(
&'a self,
silo_name: &'a types::Name,
body: &'a types::SamlIdentityProviderCreate,
) -> Result<ResponseValue<types::SamlIdentityProvider>, Error<types::Error>> {
let url = format!(
"{}/silos/{}/saml_identity_providers",
self.baseurl,
encode_path(&silo_name.to_string()),
);
let request = self.client.post(url).json(&body).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
201u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///GET a silo's SAML identity provider
///
///Sends a `GET` request to
/// `/silos/{silo_name}/saml_identity_providers/{provider_name}`
///
///Arguments:
/// - `silo_name`: The silo's unique name.
/// - `provider_name`: The SAML identity provider's name
pub async fn silo_identity_provider_view<'a>(
&'a self,
silo_name: &'a types::Name,
provider_name: &'a types::Name,
) -> Result<ResponseValue<types::SamlIdentityProvider>, Error<types::Error>> {
let url = format!(
"{}/silos/{}/saml_identity_providers/{}",
self.baseurl,
encode_path(&silo_name.to_string()),
encode_path(&provider_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the built-in system users
///
///Sends a `GET` request to `/system/user`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn system_user_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::NameSortMode>,
) -> Result<ResponseValue<types::UserBuiltinResultsPage>, Error<types::Error>> {
let url = format!("{}/system/user", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List the built-in system users as a Stream
///
///Sends repeated `GET` requests to `/system/user` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn system_user_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::NameSortMode>,
) -> impl futures::Stream<Item = Result<types::UserBuiltin, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.system_user_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.system_user_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Fetch a specific built-in system user
///
///Sends a `GET` request to `/system/user/{user_name}`
///
///Arguments:
/// - `user_name`: The built-in user's unique name.
pub async fn system_user_view<'a>(
&'a self,
user_name: &'a types::Name,
) -> Result<ResponseValue<types::UserBuiltin>, Error<types::Error>> {
let url = format!(
"{}/system/user/{}",
self.baseurl,
encode_path(&user_name.to_string()),
);
let request = self.client.get(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all timeseries schema
///
///Sends a `GET` request to `/timeseries/schema`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
pub async fn timeseries_schema_get<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
) -> Result<ResponseValue<types::TimeseriesSchemaResultsPage>, Error<types::Error>> {
let url = format!("{}/timeseries/schema", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List all timeseries schema as a Stream
///
///Sends repeated `GET` requests to `/timeseries/schema` until there are no
/// more results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
pub fn timeseries_schema_get_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
) -> impl futures::Stream<Item = Result<types::TimeseriesSchema, Error<types::Error>>> + Unpin + '_
{
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.timeseries_schema_get(limit, None)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.timeseries_schema_get(None, state.as_deref())
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
///Refresh update metadata
///
///Sends a `POST` request to `/updates/refresh`
pub async fn updates_refresh<'a>(&'a self) -> Result<ResponseValue<()>, Error<types::Error>> {
let url = format!("{}/updates/refresh", self.baseurl,);
let request = self.client.post(url).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
204u16 => Ok(ResponseValue::empty(response)),
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List users
///
///Sends a `GET` request to `/users`
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `page_token`: Token returned by previous call to retrieve the
/// subsequent page
/// - `sort_by`
pub async fn user_list<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
page_token: Option<&'a str>,
sort_by: Option<types::IdSortMode>,
) -> Result<ResponseValue<types::UserResultsPage>, Error<types::Error>> {
let url = format!("{}/users", self.baseurl,);
let mut query = Vec::new();
if let Some(v) = &limit {
query.push(("limit", v.to_string()));
}
if let Some(v) = &page_token {
query.push(("page_token", v.to_string()));
}
if let Some(v) = &sort_by {
query.push(("sort_by", v.to_string()));
}
let request = self.client.get(url).query(&query).build()?;
let result = self.client.execute(request).await;
let response = result?;
match response.status().as_u16() {
200u16 => ResponseValue::from_response(response).await,
400u16..=499u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
500u16..=599u16 => Err(Error::ErrorResponse(
ResponseValue::from_response(response).await?,
)),
_ => Err(Error::UnexpectedResponse(response)),
}
}
///List users as a Stream
///
///Sends repeated `GET` requests to `/users` until there are no more
/// results.
///
///Arguments:
/// - `limit`: Maximum number of items returned by a single call
/// - `sort_by`
pub fn user_list_stream<'a>(
&'a self,
limit: Option<std::num::NonZeroU32>,
sort_by: Option<types::IdSortMode>,
) -> impl futures::Stream<Item = Result<types::User, Error<types::Error>>> + Unpin + '_ {
use futures::StreamExt;
use futures::TryFutureExt;
use futures::TryStreamExt;
self.user_list(limit, None, sort_by)
.map_ok(move |page| {
let page = page.into_inner();
let first = futures::stream::iter(page.items.into_iter().map(Ok));
let rest = futures::stream::try_unfold(page.next_page, move |state| async move {
if state.is_none() {
Ok(None)
} else {
self.user_list(None, state.as_deref(), None)
.map_ok(|page| {
let page = page.into_inner();
Some((
futures::stream::iter(page.items.into_iter().map(Ok)),
page.next_page,
))
})
.await
}
})
.try_flatten();
first.chain(rest)
})
.try_flatten_stream()
.boxed()
}
}