#[allow(unused_imports)] use progenitor_client::{encode_path, RequestBuilderExt}; pub use progenitor_client::{ByteStream, Error, ResponseValue}; #[allow(unused_imports)] use reqwest::header::{HeaderMap, HeaderValue}; pub mod types { use serde::{Deserialize, Serialize}; #[allow(unused_imports)] use std::convert::TryFrom; ///A type storing a range over `T`. /// ///This type supports ranges similar to the `RangeTo`, `Range` and /// `RangeFrom` types in the standard library. Those cover `(..end)`, /// `(start..end)`, and `(start..)` respectively. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type")] pub enum BinRangedouble { ///A range unbounded below and exclusively above, `..end`. #[serde(rename = "range_to")] RangeTo { end: f64 }, ///A range bounded inclusively below and exclusively above, /// `start..end`. #[serde(rename = "range")] Range { end: f64, start: f64 }, ///A range bounded inclusively below and unbounded above, `start..`. #[serde(rename = "range_from")] RangeFrom { start: f64 }, } ///A type storing a range over `T`. /// ///This type supports ranges similar to the `RangeTo`, `Range` and /// `RangeFrom` types in the standard library. Those cover `(..end)`, /// `(start..end)`, and `(start..)` respectively. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type")] pub enum BinRangeint64 { ///A range unbounded below and exclusively above, `..end`. #[serde(rename = "range_to")] RangeTo { end: i64 }, ///A range bounded inclusively below and exclusively above, /// `start..end`. #[serde(rename = "range")] Range { end: i64, start: i64 }, ///A range bounded inclusively below and unbounded above, `start..`. #[serde(rename = "range_from")] RangeFrom { start: i64 }, } ///Type storing bin edges and a count of samples within it. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Bindouble { ///The total count of samples in this bin. pub count: u64, ///The range of the support covered by this bin. pub range: BinRangedouble, } ///Type storing bin edges and a count of samples within it. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Binint64 { ///The total count of samples in this bin. pub count: u64, ///The range of the support covered by this bin. pub range: BinRangeint64, } #[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 for BlockSize { type Error = &'static str; fn try_from(value: i64) -> Result { 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 } } ///A cumulative or counter data type. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Cumulativedouble { pub start_time: chrono::DateTime, pub value: f64, } ///A cumulative or counter data type. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Cumulativeint64 { pub start_time: chrono::DateTime, pub value: i64, } ///A `Datum` is a single sampled data point from a metric. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type", content = "datum")] pub enum Datum { #[serde(rename = "bool")] Bool(bool), #[serde(rename = "i64")] I64(i64), #[serde(rename = "f64")] F64(f64), #[serde(rename = "string")] String(String), #[serde(rename = "bytes")] Bytes(Vec), #[serde(rename = "cumulative_i64")] CumulativeI64(Cumulativeint64), #[serde(rename = "cumulative_f64")] CumulativeF64(Cumulativedouble), #[serde(rename = "histogram_i64")] HistogramI64(Histogramint64), #[serde(rename = "histogram_f64")] HistogramF64(Histogramdouble), } ///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 { 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)] #[serde(tag = "type", content = "value")] pub enum Digest { #[serde(rename = "sha256")] Sha256(String), } ///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, ///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, pub state: DiskState, ///timestamp when this resource was created pub time_created: chrono::DateTime, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, } #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub enum DiskMetricName { #[serde(rename = "activated")] Activated, #[serde(rename = "flush")] Flush, #[serde(rename = "read")] Read, #[serde(rename = "read_bytes")] ReadBytes, #[serde(rename = "write")] Write, #[serde(rename = "write_bytes")] WriteBytes, } impl ToString for DiskMetricName { fn to_string(&self) -> String { match *self { Self::Activated => "activated".to_string(), Self::Flush => "flush".to_string(), Self::Read => "read".to_string(), Self::ReadBytes => "read_bytes".to_string(), Self::Write => "write".to_string(), Self::WriteBytes => "write_bytes".to_string(), } } } impl std::str::FromStr for DiskMetricName { type Err = &'static str; fn from_str(value: &str) -> Result { match value { "activated" => Ok(Self::Activated), "flush" => Ok(Self::Flush), "read" => Ok(Self::Read), "read_bytes" => Ok(Self::ReadBytes), "write" => Ok(Self::Write), "write_bytes" => Ok(Self::WriteBytes), _ => Err("invalid value"), } } } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct DiskResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, pub message: String, pub request_id: String, } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ExternalIp { pub ip: std::net::IpAddr, pub kind: IpKind, } ///Parameters for creating an external IP address for instances. #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type")] pub enum ExternalIpCreate { ///An IP address providing both inbound and outbound access. The /// address is automatically-assigned from the provided IP Pool, or all /// available pools if not specified. #[serde(rename = "ephemeral")] Ephemeral { #[serde(default, skip_serializing_if = "Option::is_none")] pool_name: Option, }, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ExternalIpResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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 { 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 { 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 { 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, } ///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, ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///URL source of this image, if any #[serde(default, skip_serializing_if = "Option::is_none")] pub url: Option, ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///A simple type for managing a histogram metric. /// ///A histogram maintains the count of any number of samples, over a set of /// bins. Bins are specified on construction via their _left_ edges, /// inclusive. There can't be any "gaps" in the bins, and an additional bin /// may be added to the left, right, or both so that the bins extend to the /// entire range of the support. /// ///Note that any gaps, unsorted bins, or non-finite values will result in /// an error. /// ///Example ------- ```rust use oximeter::histogram::{BinRange, Histogram}; /// ///let edges = [0i64, 10, 20]; let mut hist = /// Histogram::new(&edges).unwrap(); assert_eq!(hist.n_bins(), 4); // One /// additional bin for the range (20..) assert_eq!(hist.n_samples(), 0); /// hist.sample(4); hist.sample(100); assert_eq!(hist.n_samples(), 2); /// ///let data = hist.iter().collect::>(); assert_eq!(data[0].range, /// BinRange::range(i64::MIN, 0)); // An additional bin for `..0` /// assert_eq!(data[0].count, 0); // Nothing is in this bin /// ///assert_eq!(data[1].range, BinRange::range(0, 10)); // The range `0..10` /// assert_eq!(data[1].count, 1); // 4 is sampled into this bin ``` /// ///Notes ----- /// ///Histograms may be constructed either from their left bin edges, or from /// a sequence of ranges. In either case, the left-most bin may be converted /// upon construction. In particular, if the left-most value is not equal to /// the minimum of the support, a new bin will be added from the minimum to /// that provided value. If the left-most value _is_ the support's minimum, /// because the provided bin was unbounded below, such as `(..0)`, then that /// bin will be converted into one bounded below, `(MIN..0)` in this case. /// ///The short of this is that, most of the time, it shouldn't matter. If one /// specifies the extremes of the support as their bins, be aware that the /// left-most may be converted from a `BinRange::RangeTo` into a /// `BinRange::Range`. In other words, the first bin of a histogram is /// _always_ a `Bin::Range` or a `Bin::RangeFrom` after construction. In /// fact, every bin is one of those variants, the `BinRange::RangeTo` is /// only provided as a convenience during construction. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Histogramdouble { pub bins: Vec, pub n_samples: u64, pub start_time: chrono::DateTime, } ///A simple type for managing a histogram metric. /// ///A histogram maintains the count of any number of samples, over a set of /// bins. Bins are specified on construction via their _left_ edges, /// inclusive. There can't be any "gaps" in the bins, and an additional bin /// may be added to the left, right, or both so that the bins extend to the /// entire range of the support. /// ///Note that any gaps, unsorted bins, or non-finite values will result in /// an error. /// ///Example ------- ```rust use oximeter::histogram::{BinRange, Histogram}; /// ///let edges = [0i64, 10, 20]; let mut hist = /// Histogram::new(&edges).unwrap(); assert_eq!(hist.n_bins(), 4); // One /// additional bin for the range (20..) assert_eq!(hist.n_samples(), 0); /// hist.sample(4); hist.sample(100); assert_eq!(hist.n_samples(), 2); /// ///let data = hist.iter().collect::>(); assert_eq!(data[0].range, /// BinRange::range(i64::MIN, 0)); // An additional bin for `..0` /// assert_eq!(data[0].count, 0); // Nothing is in this bin /// ///assert_eq!(data[1].range, BinRange::range(0, 10)); // The range `0..10` /// assert_eq!(data[1].count, 1); // 4 is sampled into this bin ``` /// ///Notes ----- /// ///Histograms may be constructed either from their left bin edges, or from /// a sequence of ranges. In either case, the left-most bin may be converted /// upon construction. In particular, if the left-most value is not equal to /// the minimum of the support, a new bin will be added from the minimum to /// that provided value. If the left-most value _is_ the support's minimum, /// because the provided bin was unbounded below, such as `(..0)`, then that /// bin will be converted into one bounded below, `(MIN..0)` in this case. /// ///The short of this is that, most of the time, it shouldn't matter. If one /// specifies the extremes of the support as their bins, be aware that the /// left-most may be converted from a `BinRange::RangeTo` into a /// `BinRange::Range`. In other words, the first bin of a histogram is /// _always_ a `Bin::Range` or a `Bin::RangeFrom` after construction. In /// fact, every bin is one of those variants, the `BinRange::RangeTo` is /// only provided as a convenience during construction. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Histogramint64 { pub bins: Vec, pub n_samples: u64, pub start_time: chrono::DateTime, } ///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 { 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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IdentityProviderResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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 { 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 { 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, ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///URL source of this image, if any #[serde(default, skip_serializing_if = "Option::is_none")] pub url: Option, ///Version of this, if any #[serde(default, skip_serializing_if = "Option::is_none")] pub version: Option, } ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, pub time_run_state_updated: chrono::DateTime, } ///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, ///The external IP addresses provided to this instance. /// ///By default, all instances have outbound connectivity, but no inbound /// connectivity. These external addresses can be used to provide a /// fixed, known IP address for making inbound connections to the /// instance. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub external_ips: Vec, pub hostname: String, pub memory: ByteCount, pub name: Name, pub ncpus: InstanceCpuCount, ///The network interfaces to be created for this instance. #[serde(default = "defaults::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, } ///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), #[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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///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 { 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"), } } } ///The kind of an external IP address for an instance #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] pub enum IpKind { #[serde(rename = "ephemeral")] Ephemeral, #[serde(rename = "floating")] Floating, } impl ToString for IpKind { fn to_string(&self) -> String { match *self { Self::Ephemeral => "ephemeral".to_string(), Self::Floating => "floating".to_string(), } } } impl std::str::FromStr for IpKind { type Err = &'static str; fn from_str(value: &str) -> Result { match value { "ephemeral" => Ok(Self::Ephemeral), "floating" => Ok(Self::Floating), _ => 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 { Err("") .or_else(|_: Self::Error| Ok(Self::V4(Ipv4Net::try_from(value)?))) .or_else(|_: Self::Error| Ok(Self::V6(Ipv6Net::try_from(value)?))) .map_err(|_: Self::Error| "string conversion failed for all variants") } } impl std::convert::TryFrom<&String> for IpNet { type Error = &'static str; fn try_from(value: &String) -> Result { Self::try_from(value.as_str()) } } impl std::convert::TryFrom for IpNet { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl ToString for IpNet { fn to_string(&self) -> String { match self { Self::V4(x) => x.to_string(), Self::V6(x) => x.to_string(), } } } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub project_id: Option, ///timestamp when this resource was created pub time_created: chrono::DateTime, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub organization: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub project: Option, } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IpPoolRange { pub id: uuid::Uuid, pub range: IpRange, pub time_created: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IpPoolRangeResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IpPoolResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } #[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 { if regress :: Regex :: new ("^(10\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/([8-9]|1[0-9]|2[0-9]|3[0-2])|172\\.(1[6-9]|2[0-9]|3[0-1])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/(1[2-9]|2[0-9]|3[0-2])|192\\.168\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/(1[6-9]|2[0-9]|3[0-2]))$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(10\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/([8-9]|1[0-9]|2[0-9]|3[0-2])|172\\.(1[6-9]|2[0-9]|3[0-1])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/(1[2-9]|2[0-9]|3[0-2])|192\\.168\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\/(1[6-9]|2[0-9]|3[0-2]))$\"") ; } Ok(Self(value.to_string())) } } impl std::convert::TryFrom<&String> for Ipv4Net { type Error = &'static str; fn try_from(value: &String) -> Result { Self::try_from(value.as_str()) } } impl std::convert::TryFrom for Ipv4Net { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for Ipv4Net { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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 { if regress :: Regex :: new ("^([fF][dD])[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}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^([fF][dD])[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}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\"") ; } Ok(Self(value.to_string())) } } impl std::convert::TryFrom<&String> for Ipv6Net { type Error = &'static str; fn try_from(value: &String) -> Result { Self::try_from(value.as_str()) } } impl std::convert::TryFrom for Ipv6Net { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for Ipv6Net { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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 { 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::try_from(value.as_str()) } } impl std::convert::TryFrom for L4PortRange { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for L4PortRange { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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 { 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::try_from(value.as_str()) } } impl std::convert::TryFrom for MacAddr { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for MacAddr { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::custom(e.to_string())) } } ///A `Measurement` is a timestamped datum from a single metric #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Measurement { pub datum: Datum, pub timestamp: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct MeasurementResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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 '-'. Names cannot be a UUID though they may contain a UUID. #[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 { if value.len() > 63usize { return Err("longer than 63 characters"); } if regress :: Regex :: new ("^(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)^[a-z][a-z0-9-]*[a-zA-Z0-9]$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$)^[a-z][a-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::try_from(value.as_str()) } } impl std::convert::TryFrom for Name { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for Name { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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 { 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 { 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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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, 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///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, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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 { 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, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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 { 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, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RackResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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 { 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::try_from(value.as_str()) } } impl std::convert::TryFrom for RoleName { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for RoleName { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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 { 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///Updateable properties of a [`RouterRoute`] #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RouterRouteUpdateParams { #[serde(default, skip_serializing_if = "Option::is_none")] pub description: Option, pub destination: RouteDestination, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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, ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, ///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 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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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 { 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, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct SledResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } #[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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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 { 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::try_from(value.as_str()) } } impl std::convert::TryFrom for TimeseriesName { type Error = &'static str; fn try_from(value: String) -> Result { Self::try_from(value.as_str()) } } impl<'de> serde::Deserialize<'de> for TimeseriesName { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { Self::try_from(String::deserialize(deserializer)?) .map_err(|e| ::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, pub datum_type: DatumType, pub field_schema: Vec, 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct UserBuiltinResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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 { 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, } ///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, 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, ///timestamp when this resource was created pub time_created: chrono::DateTime, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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 { 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 { 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>, ///If present, the destination ports this rule applies to. #[serde(default, skip_serializing_if = "Option::is_none")] pub ports: Option>, ///If present, the networking protocols this rule applies to. #[serde(default, skip_serializing_if = "Option::is_none")] pub protocols: Option>, } ///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 { 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 { 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, } ///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, } ///Collection of a [`Vpc`]'s firewall rules #[derive(Clone, Debug, Deserialize, Serialize)] pub struct VpcFirewallRules { pub rules: Vec, } ///A single page of results #[derive(Clone, Debug, Deserialize, Serialize)] pub struct VpcResultsPage { ///list of items on this page of results pub items: Vec, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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 { 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } ///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, ///timestamp when this resource was last modified pub time_modified: chrono::DateTime, ///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, 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, ///token used to fetch the next page of results (if any) #[serde(default, skip_serializing_if = "Option::is_none")] pub next_page: Option, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } ///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, #[serde(default, skip_serializing_if = "Option::is_none")] pub dns_name: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub name: Option, } mod defaults { pub(super) fn instance_create_network_interfaces( ) -> super::InstanceNetworkInterfaceAttachment { super::InstanceNetworkInterfaceAttachment::Default } } } #[derive(Clone, Debug)] ///Client for Oxide Region API /// ///API for interacting with the Oxide control plane pub struct Client { pub(crate) baseurl: String, pub(crate) client: reqwest::Client, } impl Client { /// Create a new client. /// /// `baseurl` is the base URL provided to the internal /// `reqwest::Client`, and should include a scheme and hostname, /// as well as port and a path stem if applicable. 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) } /// Construct a new client with an existing `reqwest::Client`, /// allowing more control over its configuration. /// /// `baseurl` is the base URL provided to the internal /// `reqwest::Client`, and should include a scheme and hostname, /// as well as port and a path stem if applicable. pub fn new_with_client(baseurl: &str, client: reqwest::Client) -> Self { Self { baseurl: baseurl.to_string(), client, } } /// Return the base URL to which requests are made. pub fn baseurl(&self) -> &String { &self.baseurl } /// Return the internal `reqwest::Client` used to make requests. pub fn client(&self) -> &reqwest::Client { &self.client } } impl Client { ///Get a disk by id /// ///Sends a `GET` request to `/by-id/disks/{id}` pub async fn disk_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/disks/{}", self.baseurl, encode_path(&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)), } } ///Get a global image by id /// ///Sends a `GET` request to `/by-id/global-images/{id}` pub async fn image_global_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/global-images/{}", self.baseurl, encode_path(&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 an image by id /// ///Sends a `GET` request to `/by-id/images/{id}` pub async fn image_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/images/{}", self.baseurl, encode_path(&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)), } } ///Get an instance by id /// ///Sends a `GET` request to `/by-id/instances/{id}` pub async fn instance_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/instances/{}", self.baseurl, encode_path(&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)), } } ///Get an instance's network interface by id /// ///Sends a `GET` request to `/by-id/network-interfaces/{id}` pub async fn instance_network_interface_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/network-interfaces/{}", self.baseurl, encode_path(&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)), } } ///Get an organization by id /// ///Sends a `GET` request to `/by-id/organizations/{id}` pub async fn organization_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/organizations/{}", self.baseurl, encode_path(&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)), } } ///Get a project by id /// ///Sends a `GET` request to `/by-id/projects/{id}` pub async fn project_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/projects/{}", self.baseurl, encode_path(&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)), } } ///Get a snapshot by id /// ///Sends a `GET` request to `/by-id/snapshots/{id}` pub async fn snapshot_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/snapshots/{}", self.baseurl, encode_path(&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)), } } ///Get a vpc router route by id /// ///Sends a `GET` request to `/by-id/vpc-router-routes/{id}` pub async fn vpc_router_route_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/vpc-router-routes/{}", self.baseurl, encode_path(&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)), } } ///Get a VPC Router by id /// ///Sends a `GET` request to `/by-id/vpc-routers/{id}` pub async fn vpc_router_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/vpc-routers/{}", self.baseurl, encode_path(&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)), } } ///Get a VPC subnet by id /// ///Sends a `GET` request to `/by-id/vpc-subnets/{id}` pub async fn vpc_subnet_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/vpc-subnets/{}", self.baseurl, encode_path(&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)), } } ///Get a VPC by id /// ///Sends a `GET` request to `/by-id/vpcs/{id}` pub async fn vpc_view_by_id<'a>( &'a self, id: &'a uuid::Uuid, ) -> Result, Error> { let url = format!( "{}/by-id/vpcs/{}", self.baseurl, encode_path(&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)), } } ///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, Error> { 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, 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() { 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)), } } ///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, Error> { 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/hardware/racks", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/hardware/sleds", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/images", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/ip-pools", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, ) -> Result, Error> { let url = format!( "{}/ip-pools/{}/ranges", self.baseurl, encode_path(&pool_name.to_string()), ); let mut query = Vec::with_capacity(2usize); 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, ) -> impl futures::Stream>> + 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, 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, 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, Error> { 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, Error> { 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>( &'a self, silo_name: &'a types::Name, provider_name: &'a types::Name, body: B, ) -> Result, Error> { 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, Error> { 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/organizations", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects", self.baseurl, encode_path(&organization_name.to_string()), ); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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)), } } ///Get 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, 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, 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)), } } ///Fetch metrics for a disk /// ///Sends a `GET` request to /// `/organizations/{organization_name}/projects/{project_name}/disks/ /// {disk_name}/metrics/{metric_name}` /// ///Arguments: /// - `organization_name` /// - `project_name` /// - `disk_name` /// - `metric_name` /// - `end_time`: An exclusive end time of metrics. /// - `limit`: Maximum number of items returned by a single call /// - `page_token`: Token returned by previous call to retrieve the /// subsequent page /// - `start_time`: An inclusive start time of metrics. pub async fn disk_metrics_list<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, disk_name: &'a types::Name, metric_name: types::DiskMetricName, end_time: Option<&'a chrono::DateTime>, limit: Option, page_token: Option<&'a str>, start_time: Option<&'a chrono::DateTime>, ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/disks/{}/metrics/{}", self.baseurl, encode_path(&organization_name.to_string()), encode_path(&project_name.to_string()), encode_path(&disk_name.to_string()), encode_path(&metric_name.to_string()), ); let mut query = Vec::with_capacity(4usize); if let Some(v) = &end_time { query.push(("end_time", v.to_string())); } 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) = &start_time { query.push(("start_time", 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)), } } ///Fetch metrics for a disk as a Stream /// ///Sends repeated `GET` requests to /// `/organizations/{organization_name}/projects/{project_name}/disks/ /// {disk_name}/metrics/{metric_name}` until there are no more results. /// ///Arguments: /// - `organization_name` /// - `project_name` /// - `disk_name` /// - `metric_name` /// - `end_time`: An exclusive end time of metrics. /// - `limit`: Maximum number of items returned by a single call /// - `start_time`: An inclusive start time of metrics. pub fn disk_metrics_list_stream<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, disk_name: &'a types::Name, metric_name: types::DiskMetricName, end_time: Option<&'a chrono::DateTime>, limit: Option, start_time: Option<&'a chrono::DateTime>, ) -> impl futures::Stream>> + Unpin + '_ { use futures::StreamExt; use futures::TryFutureExt; use futures::TryStreamExt; self.disk_metrics_list( organization_name, project_name, disk_name, metric_name, end_time, limit, None, start_time, ) .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_metrics_list( organization_name, project_name, disk_name, metric_name, None, 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() } ///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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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)), } } ///List external IP addresses associated with an instance /// ///Sends a `GET` request to /// `/organizations/{organization_name}/projects/{project_name}/instances/ /// {instance_name}/external-ips` pub async fn instance_external_ip_list<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, instance_name: &'a types::Name, ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/instances/{}/external-ips", 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)), } } ///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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, 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, max_bytes: Option, most_recent: Option, ) -> Result, 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::with_capacity(3usize); 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, 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::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, page_token: Option<&'a str>, ) -> Result, Error> { let url = format!("{}/roles", self.baseurl,); let mut query = Vec::with_capacity(2usize); 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, ) -> impl futures::Stream>> + 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/sagas", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/session/me/sshkeys", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/silos", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!( "{}/silos/{}/identity-providers", self.baseurl, encode_path(&silo_name.to_string()), ); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, 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, 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/system/user", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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, 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, page_token: Option<&'a str>, ) -> Result, Error> { let url = format!("{}/timeseries/schema", self.baseurl,); let mut query = Vec::with_capacity(2usize); 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, ) -> impl futures::Stream>> + 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, 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, page_token: Option<&'a str>, sort_by: Option, ) -> Result, Error> { let url = format!("{}/users", self.baseurl,); let mut query = Vec::with_capacity(3usize); 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, sort_by: Option, ) -> impl futures::Stream>> + 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() } } pub mod prelude { pub use super::Client; }