diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index 5226b9e..b3ff749 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -52,7 +52,8 @@ struct OperationMethod { operation_id: String, method: String, path: PathTemplate, - doc_comment: Option, + summary: Option, + description: Option, params: Vec, responses: Vec, dropshot_paginated: Option, @@ -69,10 +70,11 @@ enum OperationParameterKind { Body, } struct OperationParameter { - /// Sanitize parameter name. + /// Sanitized parameter name. name: String, /// Original parameter name provided by the API. api_name: String, + description: Option, typ: OperationParameterType, kind: OperationParameterKind, } @@ -85,6 +87,10 @@ enum OperationParameterType { struct OperationResponse { status_code: OperationResponseStatus, typ: OperationResponseType, + // TODO this isn't currently used because dropshot doesn't give us a + // particularly useful message here. + #[allow(dead_code)] + description: Option, } impl Eq for OperationResponse {} @@ -350,6 +356,7 @@ impl Generator { Ok(OperationParameter { name: sanitize(¶meter_data.name, Case::Snake), api_name: parameter_data.name.clone(), + description: parameter_data.description.clone(), typ: OperationParameterType::Type(typ), kind: OperationParameterKind::Path, }) @@ -389,6 +396,7 @@ impl Generator { Ok(OperationParameter { name: sanitize(¶meter_data.name, Case::Snake), api_name: parameter_data.name.clone(), + description: parameter_data.description.clone(), typ: OperationParameterType::Type(typ), kind: OperationParameterKind::Query( parameter_data.required, @@ -430,6 +438,7 @@ impl Generator { raw_params.push(OperationParameter { name: "body".to_string(), api_name: "body".to_string(), + description: b.description.clone(), typ, kind: OperationParameterKind::Body, }); @@ -585,7 +594,17 @@ impl Generator { success = true; } - Ok(OperationResponse { status_code, typ }) + let description = if response.description.is_empty() { + None + } else { + Some(response.description.clone()) + }; + + Ok(OperationResponse { + status_code, + typ, + description, + }) }) .collect::>>()?; @@ -597,6 +616,7 @@ impl Generator { responses.push(OperationResponse { status_code: OperationResponseStatus::Range(2), typ: OperationResponseType::Raw, + description: None, }); } @@ -607,7 +627,11 @@ impl Generator { operation_id: sanitize(operation_id, Case::Snake), method: method.to_string(), path: tmp, - doc_comment: operation.description.clone(), + summary: operation.summary.clone().filter(|s| !s.is_empty()), + description: operation + .description + .clone() + .filter(|s| !s.is_empty()), params: raw_params, responses, dropshot_paginated, @@ -811,18 +835,7 @@ impl Generator { _ => quote! { _ => Err(Error::UnexpectedResponse(response)), }, }; - // TODO document parameters - let doc_comment = format!( - "{}{}: {} {}", - method - .doc_comment - .as_ref() - .map(|s| format!("{}\n\n", s)) - .unwrap_or_else(String::new), - method.operation_id, - method.method.to_ascii_uppercase(), - method.path.to_string(), - ); + let doc_comment = make_doc_comment(method); let pre_hook = self.pre_hook.as_ref().map(|hook| { quote! { @@ -956,17 +969,7 @@ impl Generator { let item_type = item.ident(); // TODO document parameters - let doc_comment = format!( - "{}returns a Stream by making successive calls to {}", - method - .doc_comment - .as_ref() - .map(|s| format!("{}\n\n", s)) - .unwrap_or_else(String::new), - item.name(), - method.operation_id, - ); - + let doc_comment = make_stream_doc_comment(method); quote! { #[doc = #doc_comment] @@ -1256,6 +1259,89 @@ impl Generator { } } +fn make_doc_comment(method: &OperationMethod) -> String { + let mut buf = String::new(); + + if let Some(summary) = &method.summary { + buf.push_str(summary.trim_end_matches(['.', ','])); + buf.push_str("\n\n"); + } + if let Some(description) = &method.description { + buf.push_str(description); + buf.push_str("\n\n"); + } + + buf.push_str(&format!( + "Sends a `{}` request to `{}`", + method.method.to_ascii_uppercase(), + method.path.to_string(), + )); + + if method + .params + .iter() + .filter(|param| param.description.is_some()) + .count() + > 0 + { + buf.push_str("\n\nArguments:\n"); + for param in &method.params { + buf.push_str(&format!("- `{}`", param.name)); + if let Some(description) = ¶m.description { + buf.push_str(": "); + buf.push_str(description); + } + buf.push('\n'); + } + } + + buf +} + +fn make_stream_doc_comment(method: &OperationMethod) -> String { + let mut buf = String::new(); + + if let Some(summary) = &method.summary { + buf.push_str(summary.trim_end_matches(['.', ','])); + buf.push_str(" as a Stream\n\n"); + } + if let Some(description) = &method.description { + buf.push_str(description); + buf.push_str("\n\n"); + } + + buf.push_str(&format!( + "Sends repeated `{}` requests to `{}` until there are no more results.", + method.method.to_ascii_uppercase(), + method.path.to_string(), + )); + + if method + .params + .iter() + .filter(|param| param.api_name.as_str() != "page_token") + .filter(|param| param.description.is_some()) + .count() + > 0 + { + buf.push_str("\n\nArguments:\n"); + for param in &method.params { + if param.api_name.as_str() == "page_token" { + continue; + } + + buf.push_str(&format!("- `{}`", param.name)); + if let Some(description) = ¶m.description { + buf.push_str(": "); + buf.push_str(description); + } + buf.push('\n'); + } + } + + buf +} + fn last_two(items: &[T]) -> (Option<&T>, Option<&T>) { match items.len() { 0 => (None, None), diff --git a/progenitor-impl/tests/output/buildomat.out b/progenitor-impl/tests/output/buildomat.out index 2142ca8..f6403a9 100644 --- a/progenitor-impl/tests/output/buildomat.out +++ b/progenitor-impl/tests/output/buildomat.out @@ -162,7 +162,7 @@ impl Client { &self.client } - #[doc = "control_hold: POST /v1/control/hold"] + #[doc = "Sends a `POST` request to `/v1/control/hold`"] pub async fn control_hold<'a>(&'a self) -> Result, Error<()>> { let url = format!("{}/v1/control/hold", self.baseurl,); let request = self.client.post(url).build()?; @@ -174,7 +174,7 @@ impl Client { } } - #[doc = "control_resume: POST /v1/control/resume"] + #[doc = "Sends a `POST` request to `/v1/control/resume`"] pub async fn control_resume<'a>(&'a self) -> Result, Error<()>> { let url = format!("{}/v1/control/resume", self.baseurl,); let request = self.client.post(url).build()?; @@ -186,7 +186,7 @@ impl Client { } } - #[doc = "task_get: GET /v1/task/{task}"] + #[doc = "Sends a `GET` request to `/v1/task/{task}`"] pub async fn task_get<'a>( &'a self, task: &'a str, @@ -205,7 +205,7 @@ impl Client { } } - #[doc = "tasks_get: GET /v1/tasks"] + #[doc = "Sends a `GET` request to `/v1/tasks`"] pub async fn tasks_get<'a>(&'a self) -> Result>, Error<()>> { let url = format!("{}/v1/tasks", self.baseurl,); let request = self.client.get(url).build()?; @@ -217,7 +217,7 @@ impl Client { } } - #[doc = "task_submit: POST /v1/tasks"] + #[doc = "Sends a `POST` request to `/v1/tasks`"] pub async fn task_submit<'a>( &'a self, body: &'a types::TaskSubmit, @@ -232,7 +232,7 @@ impl Client { } } - #[doc = "task_events_get: GET /v1/tasks/{task}/events"] + #[doc = "Sends a `GET` request to `/v1/tasks/{task}/events`"] pub async fn task_events_get<'a>( &'a self, task: &'a str, @@ -257,7 +257,7 @@ impl Client { } } - #[doc = "task_outputs_get: GET /v1/tasks/{task}/outputs"] + #[doc = "Sends a `GET` request to `/v1/tasks/{task}/outputs`"] pub async fn task_outputs_get<'a>( &'a self, task: &'a str, @@ -276,7 +276,7 @@ impl Client { } } - #[doc = "task_output_download: GET /v1/tasks/{task}/outputs/{output}"] + #[doc = "Sends a `GET` request to `/v1/tasks/{task}/outputs/{output}`"] pub async fn task_output_download<'a>( &'a self, task: &'a str, @@ -297,7 +297,7 @@ impl Client { } } - #[doc = "user_create: POST /v1/users"] + #[doc = "Sends a `POST` request to `/v1/users`"] pub async fn user_create<'a>( &'a self, body: &'a types::UserCreate, @@ -312,7 +312,7 @@ impl Client { } } - #[doc = "whoami: GET /v1/whoami"] + #[doc = "Sends a `GET` request to `/v1/whoami`"] pub async fn whoami<'a>(&'a self) -> Result, Error<()>> { let url = format!("{}/v1/whoami", self.baseurl,); let request = self.client.get(url).build()?; @@ -324,7 +324,7 @@ impl Client { } } - #[doc = "worker_bootstrap: POST /v1/worker/bootstrap"] + #[doc = "Sends a `POST` request to `/v1/worker/bootstrap`"] pub async fn worker_bootstrap<'a>( &'a self, body: &'a types::WorkerBootstrap, @@ -339,7 +339,7 @@ impl Client { } } - #[doc = "worker_ping: GET /v1/worker/ping"] + #[doc = "Sends a `GET` request to `/v1/worker/ping`"] pub async fn worker_ping<'a>( &'a self, ) -> Result, Error<()>> { @@ -353,7 +353,7 @@ impl Client { } } - #[doc = "worker_task_append: POST /v1/worker/task/{task}/append"] + #[doc = "Sends a `POST` request to `/v1/worker/task/{task}/append`"] pub async fn worker_task_append<'a>( &'a self, task: &'a str, @@ -373,7 +373,7 @@ impl Client { } } - #[doc = "worker_task_upload_chunk: POST /v1/worker/task/{task}/chunk"] + #[doc = "Sends a `POST` request to `/v1/worker/task/{task}/chunk`"] pub async fn worker_task_upload_chunk<'a, B: Into>( &'a self, task: &'a str, @@ -393,7 +393,7 @@ impl Client { } } - #[doc = "worker_task_complete: POST /v1/worker/task/{task}/complete"] + #[doc = "Sends a `POST` request to `/v1/worker/task/{task}/complete`"] pub async fn worker_task_complete<'a>( &'a self, task: &'a str, @@ -413,7 +413,7 @@ impl Client { } } - #[doc = "worker_task_add_output: POST /v1/worker/task/{task}/output"] + #[doc = "Sends a `POST` request to `/v1/worker/task/{task}/output`"] pub async fn worker_task_add_output<'a>( &'a self, task: &'a str, @@ -433,7 +433,7 @@ impl Client { } } - #[doc = "workers_list: GET /v1/workers"] + #[doc = "Sends a `GET` request to `/v1/workers`"] pub async fn workers_list<'a>( &'a self, ) -> Result, Error<()>> { @@ -447,7 +447,7 @@ impl Client { } } - #[doc = "workers_recycle: POST /v1/workers/recycle"] + #[doc = "Sends a `POST` request to `/v1/workers/recycle`"] pub async fn workers_recycle<'a>(&'a self) -> Result, Error<()>> { let url = format!("{}/v1/workers/recycle", self.baseurl,); let request = self.client.post(url).build()?; diff --git a/progenitor-impl/tests/output/keeper.out b/progenitor-impl/tests/output/keeper.out index 9349f11..35f9879 100644 --- a/progenitor-impl/tests/output/keeper.out +++ b/progenitor-impl/tests/output/keeper.out @@ -103,7 +103,7 @@ impl Client { &self.client } - #[doc = "enrol: POST /enrol"] + #[doc = "Sends a `POST` request to `/enrol`"] pub async fn enrol<'a>( &'a self, body: &'a types::EnrolBody, @@ -118,7 +118,7 @@ impl Client { } } - #[doc = "global_jobs: GET /global/jobs"] + #[doc = "Sends a `GET` request to `/global/jobs`"] pub async fn global_jobs<'a>( &'a self, ) -> Result, Error<()>> { @@ -132,7 +132,7 @@ impl Client { } } - #[doc = "ping: GET /ping"] + #[doc = "Sends a `GET` request to `/ping`"] pub async fn ping<'a>(&'a self) -> Result, Error<()>> { let url = format!("{}/ping", self.baseurl,); let request = self.client.get(url).build()?; @@ -144,7 +144,7 @@ impl Client { } } - #[doc = "report_finish: POST /report/finish"] + #[doc = "Sends a `POST` request to `/report/finish`"] pub async fn report_finish<'a>( &'a self, body: &'a types::ReportFinishBody, @@ -159,7 +159,7 @@ impl Client { } } - #[doc = "report_output: POST /report/output"] + #[doc = "Sends a `POST` request to `/report/output`"] pub async fn report_output<'a>( &'a self, body: &'a types::ReportOutputBody, @@ -174,7 +174,7 @@ impl Client { } } - #[doc = "report_start: POST /report/start"] + #[doc = "Sends a `POST` request to `/report/start`"] pub async fn report_start<'a>( &'a self, body: &'a types::ReportStartBody, diff --git a/progenitor-impl/tests/output/nexus.out b/progenitor-impl/tests/output/nexus.out index 97423c8..5fa1472 100644 --- a/progenitor-impl/tests/output/nexus.out +++ b/progenitor-impl/tests/output/nexus.out @@ -61,7 +61,7 @@ pub mod types { pub time_modified: chrono::DateTime, } - #[doc = "Create-time parameters for a [`Disk`]"] + #[doc = "Create-time parameters for a [`Disk`](omicron_common::api::external::Disk)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DiskCreate { pub description: String, @@ -72,7 +72,7 @@ pub mod types { pub snapshot_id: Option, } - #[doc = "Parameters for the [`Disk`] to be attached or detached to an instance"] + #[doc = "Parameters for the [`Disk`](omicron_common::api::external::Disk) to be attached or detached to an instance"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DiskIdentifier { pub disk: Name, @@ -107,7 +107,7 @@ pub mod types { Faulted, } - #[doc = "Body of an HTTP response for an `HttpError`. This type can be used to deserialize an HTTP response corresponding to an error in order to access the error code, message, etc."] + #[doc = "Error information from a response."] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Error { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -209,7 +209,7 @@ pub mod types { } } - #[doc = "Create-time parameters for an [`Instance`]"] + #[doc = "Create-time parameters for an [`Instance`](omicron_common::api::external::Instance)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct InstanceCreate { pub description: String, @@ -217,14 +217,29 @@ pub mod types { pub memory: ByteCount, pub name: Name, pub ncpus: InstanceCpuCount, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub network_interfaces: Option, } - #[doc = "Migration parameters for an [`Instance`]"] + #[doc = "Migration parameters for an [`Instance`](omicron_common::api::external::Instance)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct InstanceMigrate { pub dst_sled_uuid: uuid::Uuid, } + #[derive(Serialize, Deserialize, Debug, Clone)] + #[serde(tag = "type", content = "params")] + pub enum InstanceNetworkInterfaceAttachment { + Create(InstanceNetworkInterfaceCreate), + Default, + None, + } + + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct InstanceNetworkInterfaceCreate { + pub params: Vec, + } + #[doc = "A single page of results"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct InstanceResultsPage { @@ -277,6 +292,12 @@ pub mod types { } } + #[derive(Serialize, Deserialize, Debug, Clone)] + pub enum IpNet { + V4(Ipv4Net), + V6(Ipv6Net), + } + #[doc = "An IPv4 subnet, including prefix and subnet mask"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Ipv4Net(pub String); @@ -391,6 +412,18 @@ pub mod types { pub vpc_id: uuid::Uuid, } + #[doc = "Create-time parameters for a [`NetworkInterface`](omicron_common::api::external::NetworkInterface)"] + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct NetworkInterfaceCreate { + pub description: String, + #[doc = "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, + pub subnet_name: Name, + pub vpc_name: Name, + } + #[doc = "A single page of results"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct NetworkInterfaceResultsPage { @@ -415,7 +448,7 @@ pub mod types { pub time_modified: chrono::DateTime, } - #[doc = "Create-time parameters for an [`Organization`]"] + #[doc = "Create-time parameters for an [`Organization`](crate::external_api::views::Organization)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct OrganizationCreate { pub description: String, @@ -432,7 +465,7 @@ pub mod types { pub next_page: Option, } - #[doc = "Updateable properties of an [`Organization`]"] + #[doc = "Updateable properties of an [`Organization`](crate::external_api::views::Organization)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct OrganizationUpdate { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -456,7 +489,7 @@ pub mod types { pub time_modified: chrono::DateTime, } - #[doc = "Create-time parameters for a [`Project`]"] + #[doc = "Create-time parameters for a [`Project`](crate::external_api::views::Project)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ProjectCreate { pub description: String, @@ -473,7 +506,7 @@ pub mod types { pub next_page: Option, } - #[doc = "Updateable properties of a [`Project`]"] + #[doc = "Updateable properties of a [`Project`](crate::external_api::views::Project)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ProjectUpdate { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -538,6 +571,8 @@ pub mod types { pub enum RouteDestination { #[serde(rename = "ip")] Ip(String), + #[serde(rename = "ip_net")] + IpNet(IpNet), #[serde(rename = "vpc")] Vpc(Name), #[serde(rename = "subnet")] @@ -708,6 +743,41 @@ pub mod types { pub next_page: Option, } + #[doc = "Client view of a Snapshot"] + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct Snapshot { + #[doc = "human-readable free-form text about a resource"] + pub description: String, + pub disk_id: uuid::Uuid, + #[doc = "unique, immutable, system-controlled identifier for each resource"] + pub id: uuid::Uuid, + pub name: Name, + pub project_id: uuid::Uuid, + pub size: ByteCount, + #[doc = "timestamp when this resource was created"] + pub time_created: chrono::DateTime, + #[doc = "timestamp when this resource was last modified"] + pub time_modified: chrono::DateTime, + } + + #[doc = "Create-time parameters for a [`Snapshot`](omicron_common::api::external::Snapshot)"] + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct SnapshotCreate { + pub description: String, + pub disk: Name, + pub name: Name, + } + + #[doc = "A single page of results"] + #[derive(Serialize, Deserialize, Debug, Clone)] + pub struct SnapshotResultsPage { + #[doc = "list of items on this page of results"] + pub items: Vec, + #[doc = "token used to fetch the next page of results (if any)"] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub next_page: Option, + } + #[doc = "Names are constructed by concatenating the target and metric names with ':'. Target and metric names must be lowercase alphanumeric characters with '_' separating words."] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct TimeseriesName(pub String); @@ -769,6 +839,8 @@ pub mod types { pub dns_name: Name, #[doc = "unique, immutable, system-controlled identifier for each resource"] pub id: uuid::Uuid, + #[serde(rename = "ipv6_prefix")] + pub ipv_6_prefix: Ipv6Net, pub name: Name, #[doc = "id for the project containing this VPC"] pub project_id: uuid::Uuid, @@ -780,11 +852,17 @@ pub mod types { pub time_modified: chrono::DateTime, } - #[doc = "Create-time parameters for a [`Vpc`]"] + #[doc = "Create-time parameters for a [`Vpc`](crate::external_api::views::Vpc)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcCreate { pub description: String, pub dns_name: Name, + #[serde( + rename = "ipv6_prefix", + default, + skip_serializing_if = "Option::is_none" + )] + pub ipv_6_prefix: Option, pub name: Name, } @@ -808,6 +886,8 @@ pub mod types { pub time_created: chrono::DateTime, #[doc = "timestamp when this resource was last modified"] pub time_modified: chrono::DateTime, + #[doc = "the VPC to which this rule belongs"] + pub vpc_id: uuid::Uuid, } #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -869,8 +949,8 @@ pub mod types { Instance(Name), #[serde(rename = "ip")] Ip(String), - #[serde(rename = "internet_gateway")] - InternetGateway(Name), + #[serde(rename = "ip_net")] + IpNet(IpNet), } #[doc = "The protocols that may be specified in a firewall rule's filter"] @@ -894,16 +974,6 @@ pub mod types { } } - #[doc = "A single page of results"] - #[derive(Serialize, Deserialize, Debug, Clone)] - pub struct VpcFirewallRuleResultsPage { - #[doc = "list of items on this page of results"] - pub items: Vec, - #[doc = "token used to fetch the next page of results (if any)"] - #[serde(default, skip_serializing_if = "Option::is_none")] - pub next_page: Option, - } - #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub enum VpcFirewallRuleStatus { #[serde(rename = "disabled")] @@ -930,6 +1000,10 @@ pub mod types { Subnet(Name), #[serde(rename = "instance")] Instance(Name), + #[serde(rename = "ip")] + Ip(String), + #[serde(rename = "ip_net")] + IpNet(IpNet), } #[doc = "A single rule in a VPC firewall"] @@ -940,6 +1014,7 @@ pub mod types { pub description: String, pub direction: VpcFirewallRuleDirection, pub filters: VpcFirewallRuleFilter, + pub name: Name, #[doc = "the relative priority of this rule"] pub priority: u16, pub status: VpcFirewallRuleStatus, @@ -947,24 +1022,16 @@ pub mod types { pub targets: Vec, } + #[doc = "Updateable properties of a `Vpc`'s firewall Note that VpcFirewallRules are implicitly created along with a Vpc, so there is no explicit creation."] #[derive(Serialize, Deserialize, Debug, Clone)] - pub struct VpcFirewallRuleUpdateParams( - pub std::collections::HashMap, - ); - impl std::ops::Deref for VpcFirewallRuleUpdateParams { - type Target = std::collections::HashMap; - fn deref(&self) -> &Self::Target { - &self.0 - } + pub struct VpcFirewallRuleUpdateParams { + pub rules: Vec, } + #[doc = "Collection of a [`Vpc`]'s firewall rules"] #[derive(Serialize, Deserialize, Debug, Clone)] - pub struct VpcFirewallRuleUpdateResult(pub std::collections::HashMap); - impl std::ops::Deref for VpcFirewallRuleUpdateResult { - type Target = std::collections::HashMap; - fn deref(&self) -> &Self::Target { - &self.0 - } + pub struct VpcFirewallRules { + pub rules: Vec, } #[doc = "A single page of results"] @@ -994,7 +1061,7 @@ pub mod types { pub vpc_id: uuid::Uuid, } - #[doc = "Create-time parameters for a [`VpcRouter`]"] + #[doc = "Create-time parameters for a [`VpcRouter`](crate::external_api::views::VpcRouter)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcRouterCreate { pub description: String, @@ -1028,7 +1095,7 @@ pub mod types { pub next_page: Option, } - #[doc = "Updateable properties of a [`VpcRouter`]"] + #[doc = "Updateable properties of a [`VpcRouter`](crate::external_api::views::VpcRouter)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcRouterUpdate { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1044,18 +1111,10 @@ pub mod types { pub description: String, #[doc = "unique, immutable, system-controlled identifier for each resource"] pub id: uuid::Uuid, - #[serde( - rename = "ipv4_block", - default, - skip_serializing_if = "Option::is_none" - )] - pub ipv_4_block: Option, - #[serde( - rename = "ipv6_block", - default, - skip_serializing_if = "Option::is_none" - )] - pub ipv_6_block: Option, + #[serde(rename = "ipv4_block")] + pub ipv_4_block: Ipv4Net, + #[serde(rename = "ipv6_block")] + pub ipv_6_block: Ipv6Net, pub name: Name, #[doc = "timestamp when this resource was created"] pub time_created: chrono::DateTime, @@ -1065,16 +1124,12 @@ pub mod types { pub vpc_id: uuid::Uuid, } - #[doc = "Create-time parameters for a [`VpcSubnet`]"] + #[doc = "Create-time parameters for a [`VpcSubnet`](crate::external_api::views::VpcSubnet)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcSubnetCreate { pub description: String, - #[serde( - rename = "ipv4_block", - default, - skip_serializing_if = "Option::is_none" - )] - pub ipv_4_block: Option, + #[serde(rename = "ipv4_block")] + pub ipv_4_block: Ipv4Net, #[serde( rename = "ipv6_block", default, @@ -1094,7 +1149,7 @@ pub mod types { pub next_page: Option, } - #[doc = "Updateable properties of a [`VpcSubnet`]"] + #[doc = "Updateable properties of a [`VpcSubnet`](crate::external_api::views::VpcSubnet)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcSubnetUpdate { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1115,7 +1170,7 @@ pub mod types { pub name: Option, } - #[doc = "Updateable properties of a [`Vpc`]"] + #[doc = "Updateable properties of a [`Vpc`](crate::external_api::views::Vpc)"] #[derive(Serialize, Deserialize, Debug, Clone)] pub struct VpcUpdate { #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1159,7 +1214,7 @@ impl Client { &self.client } - #[doc = "\n\nhardware_racks_get: GET /hardware/racks"] + #[doc = "List racks in the system\n\nSends a `GET` request to `/hardware/racks`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn hardware_racks_get<'a>( &'a self, limit: Option, @@ -1195,7 +1250,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to hardware_racks_get"] + #[doc = "List racks in the system as a Stream\n\nSends repeated `GET` requests to `/hardware/racks` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn hardware_racks_get_stream<'a>( &'a self, limit: Option, @@ -1230,7 +1285,7 @@ impl Client { .boxed() } - #[doc = "\n\nhardware_racks_get_rack: GET /hardware/racks/{rack_id}"] + #[doc = "Fetch information about a particular rack\n\nSends a `GET` request to `/hardware/racks/{rack_id}`\n\nArguments:\n- `rack_id`: The rack's unique ID.\n"] pub async fn hardware_racks_get_rack<'a>( &'a self, rack_id: &'a uuid::Uuid, @@ -1255,7 +1310,7 @@ impl Client { } } - #[doc = "\n\nhardware_sleds_get: GET /hardware/sleds"] + #[doc = "List sleds in the system\n\nSends a `GET` request to `/hardware/sleds`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn hardware_sleds_get<'a>( &'a self, limit: Option, @@ -1291,7 +1346,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to hardware_sleds_get"] + #[doc = "List sleds in the system as a Stream\n\nSends repeated `GET` requests to `/hardware/sleds` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn hardware_sleds_get_stream<'a>( &'a self, limit: Option, @@ -1326,7 +1381,7 @@ impl Client { .boxed() } - #[doc = "\n\nhardware_sleds_get_sled: GET /hardware/sleds/{sled_id}"] + #[doc = "Fetch information about a sled in the system\n\nSends a `GET` request to `/hardware/sleds/{sled_id}`\n\nArguments:\n- `sled_id`: The sled's unique ID.\n"] pub async fn hardware_sleds_get_sled<'a>( &'a self, sled_id: &'a uuid::Uuid, @@ -1351,7 +1406,7 @@ impl Client { } } - #[doc = "spoof_login: POST /login"] + #[doc = "Sends a `POST` request to `/login`"] pub async fn spoof_login<'a>( &'a self, body: &'a types::LoginParams, @@ -1366,19 +1421,19 @@ impl Client { } } - #[doc = "logout: POST /logout"] - pub async fn logout<'a>(&'a self) -> Result, Error<()>> { + #[doc = "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::empty(response)), - _ => Err(Error::ErrorResponse(ResponseValue::empty(response))), + 200..=299 => Ok(ResponseValue::stream(response)), + _ => Err(Error::ErrorResponse(ResponseValue::stream(response))), } } - #[doc = "\n\norganizations_get: GET /organizations"] + #[doc = "List all organizations\n\nSends a `GET` request to `/organizations`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn organizations_get<'a>( &'a self, limit: Option, @@ -1414,7 +1469,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to organizations_get"] + #[doc = "List all organizations as a Stream\n\nSends repeated `GET` requests to `/organizations` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn organizations_get_stream<'a>( &'a self, limit: Option, @@ -1450,7 +1505,7 @@ impl Client { .boxed() } - #[doc = "\n\norganizations_post: POST /organizations"] + #[doc = "Create a new organization\n\nSends a `POST` request to `/organizations`"] pub async fn organizations_post<'a>( &'a self, body: &'a types::OrganizationCreate, @@ -1471,7 +1526,7 @@ impl Client { } } - #[doc = "\n\norganizations_get_organization: GET /organizations/{organization_name}"] + #[doc = "Fetch a specific organization\n\nSends a `GET` request to `/organizations/{organization_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n"] pub async fn organizations_get_organization<'a>( &'a self, organization_name: &'a types::Name, @@ -1496,7 +1551,7 @@ impl Client { } } - #[doc = "\n\norganizations_put_organization: PUT /organizations/{organization_name}"] + #[doc = "Update a specific organization\n\nSends a `PUT` request to `/organizations/{organization_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `body`\n"] pub async fn organizations_put_organization<'a>( &'a self, organization_name: &'a types::Name, @@ -1522,7 +1577,7 @@ impl Client { } } - #[doc = "\n\norganizations_delete_organization: DELETE /organizations/{organization_name}"] + #[doc = "Delete a specific organization\n\nSends a `DELETE` request to `/organizations/{organization_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n"] pub async fn organizations_delete_organization<'a>( &'a self, organization_name: &'a types::Name, @@ -1547,7 +1602,7 @@ impl Client { } } - #[doc = "\n\norganization_projects_get: GET /organizations/{organization_name}/projects"] + #[doc = "List all projects\n\nSends a `GET` request to `/organizations/{organization_name}/projects`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn organization_projects_get<'a>( &'a self, organization_name: &'a types::Name, @@ -1588,7 +1643,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to organization_projects_get"] + #[doc = "List all projects as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects` until there are no more results.\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn organization_projects_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -1629,7 +1684,7 @@ impl Client { .boxed() } - #[doc = "\n\norganization_projects_post: POST /organizations/{organization_name}/projects"] + #[doc = "Create a new project\n\nSends a `POST` request to `/organizations/{organization_name}/projects`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `body`\n"] pub async fn organization_projects_post<'a>( &'a self, organization_name: &'a types::Name, @@ -1655,7 +1710,7 @@ impl Client { } } - #[doc = "\n\norganization_projects_get_project: GET /organizations/{organization_name}/projects/{project_name}"] + #[doc = "Fetch a specific project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n"] pub async fn organization_projects_get_project<'a>( &'a self, organization_name: &'a types::Name, @@ -1682,7 +1737,7 @@ impl Client { } } - #[doc = "\n\norganization_projects_put_project: PUT /organizations/{organization_name}/projects/{project_name}"] + #[doc = "Update a specific project\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `body`\n"] pub async fn organization_projects_put_project<'a>( &'a self, organization_name: &'a types::Name, @@ -1710,7 +1765,7 @@ impl Client { } } - #[doc = "\n\norganization_projects_delete_project: DELETE /organizations/{organization_name}/projects/{project_name}"] + #[doc = "Delete a specific project\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n"] pub async fn organization_projects_delete_project<'a>( &'a self, organization_name: &'a types::Name, @@ -1737,7 +1792,7 @@ impl Client { } } - #[doc = "\n\nproject_disks_get: GET /organizations/{organization_name}/projects/{project_name}/disks"] + #[doc = "List disks in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/disks`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn project_disks_get<'a>( &'a self, organization_name: &'a types::Name, @@ -1780,7 +1835,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to project_disks_get"] + #[doc = "List disks in a project as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/disks` until there are no more results.\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn project_disks_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -1823,7 +1878,7 @@ impl Client { .boxed() } - #[doc = "\n\nproject_disks_post: POST /organizations/{organization_name}/projects/{project_name}/disks"] + #[doc = "Create a disk in a project\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/disks`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `body`\n"] pub async fn project_disks_post<'a>( &'a self, organization_name: &'a types::Name, @@ -1851,7 +1906,7 @@ impl Client { } } - #[doc = "\n\nproject_disks_get_disk: GET /organizations/{organization_name}/projects/{project_name}/disks/{disk_name}"] + #[doc = "Fetch a single disk in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/disks/{disk_name}`"] pub async fn project_disks_get_disk<'a>( &'a self, organization_name: &'a types::Name, @@ -1880,7 +1935,7 @@ impl Client { } } - #[doc = "\n\nproject_disks_delete_disk: DELETE /organizations/{organization_name}/projects/{project_name}/disks/{disk_name}"] + #[doc = "Delete a disk from a project\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/disks/{disk_name}`"] pub async fn project_disks_delete_disk<'a>( &'a self, organization_name: &'a types::Name, @@ -1909,7 +1964,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_get: GET /organizations/{organization_name}/projects/{project_name}/instances"] + #[doc = "List instances in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/instances`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn project_instances_get<'a>( &'a self, organization_name: &'a types::Name, @@ -1952,7 +2007,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to project_instances_get"] + #[doc = "List instances in a project as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/instances` until there are no more results.\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn project_instances_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -1996,7 +2051,7 @@ impl Client { .boxed() } - #[doc = "\n\nproject_instances_post: POST /organizations/{organization_name}/projects/{project_name}/instances"] + #[doc = "Create an instance in a project\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `body`\n"] pub async fn project_instances_post<'a>( &'a self, organization_name: &'a types::Name, @@ -2024,7 +2079,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_get_instance: GET /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}"] + #[doc = "Get an instance in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}`"] pub async fn project_instances_get_instance<'a>( &'a self, organization_name: &'a types::Name, @@ -2053,7 +2108,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_delete_instance: DELETE /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}"] + #[doc = "Delete an instance from a project\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}`"] pub async fn project_instances_delete_instance<'a>( &'a self, organization_name: &'a types::Name, @@ -2082,7 +2137,7 @@ impl Client { } } - #[doc = "\n\ninstance_disks_get: GET /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks"] + #[doc = "List disks attached to this instance\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `instance_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn instance_disks_get<'a>( &'a self, organization_name: &'a types::Name, @@ -2127,7 +2182,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to instance_disks_get"] + #[doc = "List disks attached to this instance as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `instance_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn instance_disks_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -2179,7 +2234,7 @@ impl Client { .boxed() } - #[doc = "instance_disks_attach: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks/attach"] + #[doc = "Sends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks/attach`"] pub async fn instance_disks_attach<'a>( &'a self, organization_name: &'a types::Name, @@ -2209,7 +2264,7 @@ impl Client { } } - #[doc = "instance_disks_detach: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks/detach"] + #[doc = "Sends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/disks/detach`"] pub async fn instance_disks_detach<'a>( &'a self, organization_name: &'a types::Name, @@ -2239,7 +2294,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_migrate_instance: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/migrate"] + #[doc = "Migrate an instance to a different propolis-server, possibly on a different sled\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/migrate`"] pub async fn project_instances_migrate_instance<'a>( &'a self, organization_name: &'a types::Name, @@ -2269,7 +2324,197 @@ impl Client { } } - #[doc = "\n\nproject_instances_instance_reboot: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/reboot"] + #[doc = "List network interfaces attached to this instance\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `instance_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] + pub async fn instance_network_interfaces_get<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::encode_path(&instance_name.to_string()), + ); + let mut query = Vec::new(); + if let Some(v) = &limit { + query.push(("limit", v.to_string())); + } + + if let Some(v) = &page_token { + query.push(("page_token", v.to_string())); + } + + if let Some(v) = &sort_by { + query.push(("sort_by", v.to_string())); + } + + let request = self.client.get(url).query(&query).build()?; + let result = self.client.execute(request).await; + let response = result?; + match response.status().as_u16() { + 200u16 => ResponseValue::from_response(response).await, + 400u16..=499u16 => Err(Error::ErrorResponse( + ResponseValue::from_response(response).await?, + )), + 500u16..=599u16 => Err(Error::ErrorResponse( + ResponseValue::from_response(response).await?, + )), + _ => Err(Error::UnexpectedResponse(response)), + } + } + + #[doc = "List network interfaces attached to this instance as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `instance_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] + pub fn instance_network_interfaces_get_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_interfaces_get( + 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_interfaces_get( + 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() + } + + #[doc = "Create a network interface for an instance\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces`"] + pub async fn instance_network_interfaces_post<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "Get an interface attached to an instance\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces/{interface_name}`"] + pub async fn instance_network_interfaces_get_interface<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::encode_path(&instance_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "Detach a network interface from an instance\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces/{interface_name}`"] + pub async fn instance_network_interfaces_delete_interface<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::encode_path(&instance_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "Reboot an instance\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/reboot`"] pub async fn project_instances_instance_reboot<'a>( &'a self, organization_name: &'a types::Name, @@ -2298,7 +2543,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_instance_start: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/start"] + #[doc = "Boot an instance\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/start`"] pub async fn project_instances_instance_start<'a>( &'a self, organization_name: &'a types::Name, @@ -2327,7 +2572,7 @@ impl Client { } } - #[doc = "\n\nproject_instances_instance_stop: POST /organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/stop"] + #[doc = "Halt an instance\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/stop`"] pub async fn project_instances_instance_stop<'a>( &'a self, organization_name: &'a types::Name, @@ -2356,7 +2601,180 @@ impl Client { } } - #[doc = "\n\nproject_vpcs_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs"] + #[doc = "List snapshots in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/snapshots`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] + pub async fn project_snapshots_get<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + ); + let mut query = Vec::new(); + if let Some(v) = &limit { + query.push(("limit", v.to_string())); + } + + if let Some(v) = &page_token { + query.push(("page_token", v.to_string())); + } + + if let Some(v) = &sort_by { + query.push(("sort_by", v.to_string())); + } + + let request = self.client.get(url).query(&query).build()?; + let result = self.client.execute(request).await; + let response = result?; + match response.status().as_u16() { + 200u16 => ResponseValue::from_response(response).await, + 400u16..=499u16 => Err(Error::ErrorResponse( + ResponseValue::from_response(response).await?, + )), + 500u16..=599u16 => Err(Error::ErrorResponse( + ResponseValue::from_response(response).await?, + )), + _ => Err(Error::UnexpectedResponse(response)), + } + } + + #[doc = "List snapshots in a project as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/snapshots` until there are no more results.\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] + pub fn project_snapshots_get_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.project_snapshots_get(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.project_snapshots_get( + 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() + } + + #[doc = "Create a snapshot of a disk\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/snapshots`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `body`\n"] + pub async fn project_snapshots_post<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "Get a snapshot in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/snapshots/{snapshot_name}`"] + pub async fn project_snapshots_get_snapshot<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "Delete a snapshot from a project\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/snapshots/{snapshot_name}`"] + pub async fn project_snapshots_delete_snapshot<'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, + progenitor_client::encode_path(&organization_name.to_string()), + progenitor_client::encode_path(&project_name.to_string()), + progenitor_client::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)), + } + } + + #[doc = "List VPCs in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn project_vpcs_get<'a>( &'a self, organization_name: &'a types::Name, @@ -2399,7 +2817,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to project_vpcs_get"] + #[doc = "List VPCs in a project as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/vpcs` until there are no more results.\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn project_vpcs_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -2442,7 +2860,7 @@ impl Client { .boxed() } - #[doc = "\n\nproject_vpcs_post: POST /organizations/{organization_name}/projects/{project_name}/vpcs"] + #[doc = "Create a VPC in a project\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/vpcs`\n\nArguments:\n- `organization_name`: The organization's unique name.\n- `project_name`: The project's unique name within the organization.\n- `body`\n"] pub async fn project_vpcs_post<'a>( &'a self, organization_name: &'a types::Name, @@ -2470,7 +2888,7 @@ impl Client { } } - #[doc = "\n\nproject_vpcs_get_vpc: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}"] + #[doc = "Get a VPC in a project\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}`"] pub async fn project_vpcs_get_vpc<'a>( &'a self, organization_name: &'a types::Name, @@ -2499,14 +2917,14 @@ impl Client { } } - #[doc = "\n\nproject_vpcs_put_vpc: PUT /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}"] + #[doc = "Update a VPC\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}`"] pub async fn project_vpcs_put_vpc<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, vpc_name: &'a types::Name, body: &'a types::VpcUpdate, - ) -> Result, Error> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}", self.baseurl, @@ -2518,7 +2936,7 @@ impl Client { let result = self.client.execute(request).await; let response = result?; match response.status().as_u16() { - 204u16 => Ok(ResponseValue::empty(response)), + 200u16 => ResponseValue::from_response(response).await, 400u16..=499u16 => Err(Error::ErrorResponse( ResponseValue::from_response(response).await?, )), @@ -2529,7 +2947,7 @@ impl Client { } } - #[doc = "\n\nproject_vpcs_delete_vpc: DELETE /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}"] + #[doc = "Delete a vpc from a project\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}`"] pub async fn project_vpcs_delete_vpc<'a>( &'a self, organization_name: &'a types::Name, @@ -2558,16 +2976,13 @@ impl Client { } } - #[doc = "\n\nvpc_firewall_rules_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/firewall/rules"] + #[doc = "List firewall rules for a VPC\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/firewall/rules`"] pub async fn vpc_firewall_rules_get<'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> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}/firewall/rules", self.baseurl, @@ -2575,20 +2990,7 @@ impl Client { progenitor_client::encode_path(&project_name.to_string()), progenitor_client::encode_path(&vpc_name.to_string()), ); - let mut query = Vec::new(); - if let Some(v) = &limit { - query.push(("limit", v.to_string())); - } - - if let Some(v) = &page_token { - query.push(("page_token", v.to_string())); - } - - if let Some(v) = &sort_by { - query.push(("sort_by", v.to_string())); - } - - let request = self.client.get(url).query(&query).build()?; + let request = self.client.get(url).build()?; let result = self.client.execute(request).await; let response = result?; match response.status().as_u16() { @@ -2603,67 +3005,14 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to vpc_firewall_rules_get"] - pub fn vpc_firewall_rules_get_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_firewall_rules_get( - 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_firewall_rules_get( - 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() - } - - #[doc = "\n\nvpc_firewall_rules_put: PUT /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/firewall/rules"] + #[doc = "Replace the firewall rules for a VPC\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/firewall/rules`"] pub async fn vpc_firewall_rules_put<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, vpc_name: &'a types::Name, body: &'a types::VpcFirewallRuleUpdateParams, - ) -> Result, Error> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}/firewall/rules", self.baseurl, @@ -2686,7 +3035,7 @@ impl Client { } } - #[doc = "\n\nvpc_routers_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers"] + #[doc = "List VPC Custom and System Routers\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn vpc_routers_get<'a>( &'a self, organization_name: &'a types::Name, @@ -2731,7 +3080,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to vpc_routers_get"] + #[doc = "List VPC Custom and System Routers as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn vpc_routers_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -2784,7 +3133,7 @@ impl Client { .boxed() } - #[doc = "\n\nvpc_routers_post: POST /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers"] + #[doc = "Create a VPC Router\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers`"] pub async fn vpc_routers_post<'a>( &'a self, organization_name: &'a types::Name, @@ -2814,7 +3163,7 @@ impl Client { } } - #[doc = "\n\nvpc_routers_get_router: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}"] + #[doc = "Get a VPC Router\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}`"] pub async fn vpc_routers_get_router<'a>( &'a self, organization_name: &'a types::Name, @@ -2845,7 +3194,7 @@ impl Client { } } - #[doc = "\n\nvpc_routers_put_router: PUT /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}"] + #[doc = "Update a VPC Router\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}`"] pub async fn vpc_routers_put_router<'a>( &'a self, organization_name: &'a types::Name, @@ -2853,7 +3202,7 @@ impl Client { vpc_name: &'a types::Name, router_name: &'a types::Name, body: &'a types::VpcRouterUpdate, - ) -> Result, Error> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}/routers/{}", self.baseurl, @@ -2866,7 +3215,7 @@ impl Client { let result = self.client.execute(request).await; let response = result?; match response.status().as_u16() { - 204u16 => Ok(ResponseValue::empty(response)), + 200u16 => ResponseValue::from_response(response).await, 400u16..=499u16 => Err(Error::ErrorResponse( ResponseValue::from_response(response).await?, )), @@ -2877,7 +3226,7 @@ impl Client { } } - #[doc = "\n\nvpc_routers_delete_router: DELETE /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}"] + #[doc = "Delete a router from its VPC\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}`"] pub async fn vpc_routers_delete_router<'a>( &'a self, organization_name: &'a types::Name, @@ -2908,7 +3257,7 @@ impl Client { } } - #[doc = "\n\nrouters_routes_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes"] + #[doc = "List a Router's routes\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `router_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn routers_routes_get<'a>( &'a self, organization_name: &'a types::Name, @@ -2955,7 +3304,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to routers_routes_get"] + #[doc = "List a Router's routes as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `router_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn routers_routes_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -3011,7 +3360,7 @@ impl Client { .boxed() } - #[doc = "\n\nrouters_routes_post: POST /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes"] + #[doc = "Create a VPC Router\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes`"] pub async fn routers_routes_post<'a>( &'a self, organization_name: &'a types::Name, @@ -3043,7 +3392,7 @@ impl Client { } } - #[doc = "\n\nrouters_routes_get_route: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}"] + #[doc = "Get a VPC Router route\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}`"] pub async fn routers_routes_get_route<'a>( &'a self, organization_name: &'a types::Name, @@ -3076,7 +3425,7 @@ impl Client { } } - #[doc = "\n\nrouters_routes_put_route: PUT /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}"] + #[doc = "Update a Router route\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}`"] pub async fn routers_routes_put_route<'a>( &'a self, organization_name: &'a types::Name, @@ -3085,7 +3434,7 @@ impl Client { router_name: &'a types::Name, route_name: &'a types::Name, body: &'a types::RouterRouteUpdateParams, - ) -> Result, Error> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}/routers/{}/routes/{}", self.baseurl, @@ -3099,7 +3448,7 @@ impl Client { let result = self.client.execute(request).await; let response = result?; match response.status().as_u16() { - 204u16 => Ok(ResponseValue::empty(response)), + 200u16 => ResponseValue::from_response(response).await, 400u16..=499u16 => Err(Error::ErrorResponse( ResponseValue::from_response(response).await?, )), @@ -3110,7 +3459,7 @@ impl Client { } } - #[doc = "\n\nrouters_routes_delete_route: DELETE /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}"] + #[doc = "Delete a route from its router\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/routers/{router_name}/routes/{route_name}`"] pub async fn routers_routes_delete_route<'a>( &'a self, organization_name: &'a types::Name, @@ -3143,7 +3492,7 @@ impl Client { } } - #[doc = "\n\nvpc_subnets_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets"] + #[doc = "List subnets in a VPC\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn vpc_subnets_get<'a>( &'a self, organization_name: &'a types::Name, @@ -3188,7 +3537,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to vpc_subnets_get"] + #[doc = "List subnets in a VPC as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn vpc_subnets_get_stream<'a>( &'a self, organization_name: &'a types::Name, @@ -3241,7 +3590,7 @@ impl Client { .boxed() } - #[doc = "\n\nvpc_subnets_post: POST /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets"] + #[doc = "Create a subnet in a VPC\n\nSends a `POST` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets`"] pub async fn vpc_subnets_post<'a>( &'a self, organization_name: &'a types::Name, @@ -3271,7 +3620,7 @@ impl Client { } } - #[doc = "\n\nvpc_subnets_get_subnet: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}"] + #[doc = "Get subnet in a VPC\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}`"] pub async fn vpc_subnets_get_subnet<'a>( &'a self, organization_name: &'a types::Name, @@ -3302,7 +3651,7 @@ impl Client { } } - #[doc = "\n\nvpc_subnets_put_subnet: PUT /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}"] + #[doc = "Update a VPC Subnet\n\nSends a `PUT` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}`"] pub async fn vpc_subnets_put_subnet<'a>( &'a self, organization_name: &'a types::Name, @@ -3310,7 +3659,7 @@ impl Client { vpc_name: &'a types::Name, subnet_name: &'a types::Name, body: &'a types::VpcSubnetUpdate, - ) -> Result, Error> { + ) -> Result, Error> { let url = format!( "{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}", self.baseurl, @@ -3323,7 +3672,7 @@ impl Client { let result = self.client.execute(request).await; let response = result?; match response.status().as_u16() { - 204u16 => Ok(ResponseValue::empty(response)), + 200u16 => ResponseValue::from_response(response).await, 400u16..=499u16 => Err(Error::ErrorResponse( ResponseValue::from_response(response).await?, )), @@ -3334,7 +3683,7 @@ impl Client { } } - #[doc = "\n\nvpc_subnets_delete_subnet: DELETE /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}"] + #[doc = "Delete a subnet from a VPC\n\nSends a `DELETE` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}`"] pub async fn vpc_subnets_delete_subnet<'a>( &'a self, organization_name: &'a types::Name, @@ -3365,8 +3714,8 @@ impl Client { } } - #[doc = "\n\nsubnets_ips_get: GET /organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}/ips"] - pub async fn subnets_ips_get<'a>( + #[doc = "List network interfaces in a VPC subnet\n\nSends a `GET` request to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}/network-interfaces`\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `subnet_name`\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] + pub async fn subnet_network_interfaces_get<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, @@ -3377,7 +3726,7 @@ impl Client { sort_by: Option, ) -> Result, Error> { let url = format!( - "{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}/ips", + "{}/organizations/{}/projects/{}/vpcs/{}/subnets/{}/network-interfaces", self.baseurl, progenitor_client::encode_path(&organization_name.to_string()), progenitor_client::encode_path(&project_name.to_string()), @@ -3412,8 +3761,8 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to subnets_ips_get"] - pub fn subnets_ips_get_stream<'a>( + #[doc = "List network interfaces in a VPC subnet as a Stream\n\nSends repeated `GET` requests to `/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}/network-interfaces` until there are no more results.\n\nArguments:\n- `organization_name`\n- `project_name`\n- `vpc_name`\n- `subnet_name`\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] + pub fn subnet_network_interfaces_get_stream<'a>( &'a self, organization_name: &'a types::Name, project_name: &'a types::Name, @@ -3426,7 +3775,7 @@ impl Client { use futures::StreamExt; use futures::TryFutureExt; use futures::TryStreamExt; - self.subnets_ips_get( + self.subnet_network_interfaces_get( organization_name, project_name, vpc_name, @@ -3442,7 +3791,7 @@ impl Client { if state.is_none() { Ok(None) } else { - self.subnets_ips_get( + self.subnet_network_interfaces_get( organization_name, project_name, vpc_name, @@ -3468,7 +3817,7 @@ impl Client { .boxed() } - #[doc = "\n\nroles_get: GET /roles"] + #[doc = "List the built-in roles\n\nSends a `GET` request to `/roles`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n"] pub async fn roles_get<'a>( &'a self, limit: Option, @@ -3499,7 +3848,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to roles_get"] + #[doc = "List the built-in roles as a Stream\n\nSends repeated `GET` requests to `/roles` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n"] pub fn roles_get_stream<'a>( &'a self, limit: Option, @@ -3533,7 +3882,7 @@ impl Client { .boxed() } - #[doc = "\n\nroles_get_role: GET /roles/{role_name}"] + #[doc = "Fetch a specific built-in role\n\nSends a `GET` request to `/roles/{role_name}`\n\nArguments:\n- `role_name`: The built-in role's unique name.\n"] pub async fn roles_get_role<'a>( &'a self, role_name: &'a str, @@ -3558,7 +3907,7 @@ impl Client { } } - #[doc = "\n\nsagas_get: GET /sagas"] + #[doc = "List all sagas (for debugging)\n\nSends a `GET` request to `/sagas`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn sagas_get<'a>( &'a self, limit: Option, @@ -3594,7 +3943,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to sagas_get"] + #[doc = "List all sagas (for debugging) as a Stream\n\nSends repeated `GET` requests to `/sagas` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn sagas_get_stream<'a>( &'a self, limit: Option, @@ -3629,7 +3978,7 @@ impl Client { .boxed() } - #[doc = "\n\nsagas_get_saga: GET /sagas/{saga_id}"] + #[doc = "Fetch information about a single saga (for debugging)\n\nSends a `GET` request to `/sagas/{saga_id}`"] pub async fn sagas_get_saga<'a>( &'a self, saga_id: &'a uuid::Uuid, @@ -3654,7 +4003,7 @@ impl Client { } } - #[doc = "session_me: GET /session/me"] + #[doc = "Fetch the user associated with the current session\n\nSends a `GET` request to `/session/me`"] pub async fn session_me<'a>( &'a self, ) -> Result, Error> { @@ -3674,7 +4023,7 @@ impl Client { } } - #[doc = "\n\ntimeseries_schema_get: GET /timeseries/schema"] + #[doc = "List all timeseries schema\n\nSends a `GET` request to `/timeseries/schema`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n"] pub async fn timeseries_schema_get<'a>( &'a self, limit: Option, @@ -3705,7 +4054,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to timeseries_schema_get"] + #[doc = "List all timeseries schema as a Stream\n\nSends repeated `GET` requests to `/timeseries/schema` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n"] pub fn timeseries_schema_get_stream<'a>( &'a self, limit: Option, @@ -3740,7 +4089,25 @@ impl Client { .boxed() } - #[doc = "\n\nusers_get: GET /users"] + #[doc = "Refresh update metadata\n\nSends 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)), + } + } + + #[doc = "List the built-in system users\n\nSends a `GET` request to `/users`\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `page_token`: Token returned by previous call to retreive the subsequent page\n- `sort_by`\n"] pub async fn users_get<'a>( &'a self, limit: Option, @@ -3776,7 +4143,7 @@ impl Client { } } - #[doc = "\n\nreturns a Stream by making successive calls to users_get"] + #[doc = "List the built-in system users as a Stream\n\nSends repeated `GET` requests to `/users` until there are no more results.\n\nArguments:\n- `limit`: Maximum number of items returned by a single call\n- `sort_by`\n"] pub fn users_get_stream<'a>( &'a self, limit: Option, @@ -3811,7 +4178,7 @@ impl Client { .boxed() } - #[doc = "\n\nusers_get_user: GET /users/{user_name}"] + #[doc = "Fetch a specific built-in system user\n\nSends a `GET` request to `/users/{user_name}`\n\nArguments:\n- `user_name`: The built-in user's unique name.\n"] pub async fn users_get_user<'a>( &'a self, user_name: &'a types::Name, diff --git a/progenitor-impl/tests/output/test_freeform_response.out b/progenitor-impl/tests/output/test_freeform_response.out index a44766a..4ef8082 100644 --- a/progenitor-impl/tests/output/test_freeform_response.out +++ b/progenitor-impl/tests/output/test_freeform_response.out @@ -43,7 +43,7 @@ impl Client { &self.client } - #[doc = "freeform_response: GET "] + #[doc = "Sends a `GET` request to ``"] pub async fn freeform_response<'a>( &'a self, ) -> Result, Error> { diff --git a/progenitor-impl/tests/output/test_renamed_parameters.out b/progenitor-impl/tests/output/test_renamed_parameters.out index 86babcc..eb0ad2f 100644 --- a/progenitor-impl/tests/output/test_renamed_parameters.out +++ b/progenitor-impl/tests/output/test_renamed_parameters.out @@ -43,7 +43,7 @@ impl Client { &self.client } - #[doc = "renamed_parameters: GET /{ref}/{type}/{trait}"] + #[doc = "Sends a `GET` request to `/{ref}/{type}/{trait}`"] pub async fn renamed_parameters<'a>( &'a self, ref_: &'a str, diff --git a/sample_openapi/nexus.json b/sample_openapi/nexus.json index abc980f..e14c22f 100644 --- a/sample_openapi/nexus.json +++ b/sample_openapi/nexus.json @@ -16,15 +16,14 @@ "racks" ], "summary": "List racks in the system.", - "description": "", "operationId": "hardware_racks_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -34,9 +33,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -77,15 +76,14 @@ "racks" ], "summary": "Fetch information about a particular rack.", - "description": "", "operationId": "hardware_racks_get_rack", "parameters": [ { "in": "path", "name": "rack_id", + "description": "The rack's unique ID.", "required": true, "schema": { - "description": "The rack's unique ID.", "type": "string", "format": "uuid" }, @@ -118,15 +116,14 @@ "sleds" ], "summary": "List sleds in the system.", - "description": "", "operationId": "hardware_sleds_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -136,9 +133,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -179,15 +176,14 @@ "sleds" ], "summary": "Fetch information about a sled in the system.", - "description": "", "operationId": "hardware_sleds_get_sled", "parameters": [ { "in": "path", "name": "sled_id", + "description": "The sled's unique ID.", "required": true, "schema": { - "description": "The sled's unique ID.", "type": "string", "format": "uuid" }, @@ -250,7 +246,12 @@ "operationId": "logout", "responses": { "default": { - "description": "" + "description": "", + "content": { + "*/*": { + "schema": {} + } + } } } } @@ -261,15 +262,14 @@ "organizations" ], "summary": "List all organizations.", - "description": "", "operationId": "organizations_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -279,9 +279,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -320,7 +320,6 @@ "organizations" ], "summary": "Create a new organization.", - "description": "", "operationId": "organizations_post", "requestBody": { "content": { @@ -358,12 +357,12 @@ "organizations" ], "summary": "Fetch a specific organization", - "description": "", "operationId": "organizations_get_organization", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -395,12 +394,12 @@ "organizations" ], "summary": "Update a specific organization.", - "description": "", "operationId": "organizations_put_organization", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -442,12 +441,12 @@ "organizations" ], "summary": "Delete a specific organization.", - "description": "", "operationId": "organizations_delete_organization", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -474,15 +473,14 @@ "projects" ], "summary": "List all projects.", - "description": "", "operationId": "organization_projects_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -492,9 +490,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -510,6 +508,7 @@ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -542,12 +541,12 @@ "projects" ], "summary": "Create a new project.", - "description": "", "operationId": "organization_projects_post", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -591,12 +590,12 @@ "projects" ], "summary": "Fetch a specific project", - "description": "", "operationId": "organization_projects_get_project", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -606,6 +605,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -637,12 +637,12 @@ "projects" ], "summary": "Update a specific project.", - "description": "", "operationId": "organization_projects_put_project", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -652,6 +652,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -693,12 +694,12 @@ "projects" ], "summary": "Delete a specific project.", - "description": "", "operationId": "organization_projects_delete_project", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -708,6 +709,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -734,15 +736,14 @@ "disks" ], "summary": "List disks in a project.", - "description": "", "operationId": "project_disks_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -752,9 +753,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -770,6 +771,7 @@ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -779,6 +781,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -811,12 +814,12 @@ "disks" ], "summary": "Create a disk in a project.", - "description": "", "operationId": "project_disks_post", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -826,6 +829,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -869,7 +873,6 @@ "disks" ], "summary": "Fetch a single disk in a project.", - "description": "", "operationId": "project_disks_get_disk", "parameters": [ { @@ -924,7 +927,6 @@ "disks" ], "summary": "Delete a disk from a project.", - "description": "", "operationId": "project_disks_delete_disk", "parameters": [ { @@ -974,15 +976,14 @@ "instances" ], "summary": "List instances in a project.", - "description": "", "operationId": "project_instances_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -992,9 +993,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -1010,6 +1011,7 @@ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1019,6 +1021,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1051,12 +1054,12 @@ "instances" ], "summary": "Create an instance in a project.", - "description": "", "operationId": "project_instances_post", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1066,6 +1069,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1109,7 +1113,6 @@ "instances" ], "summary": "Get an instance in a project.", - "description": "", "operationId": "project_instances_get_instance", "parameters": [ { @@ -1164,7 +1167,6 @@ "instances" ], "summary": "Delete an instance from a project.", - "description": "", "operationId": "project_instances_delete_instance", "parameters": [ { @@ -1214,15 +1216,14 @@ "instances" ], "summary": "List disks attached to this instance.", - "description": "", "operationId": "instance_disks_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -1232,9 +1233,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -1432,7 +1433,6 @@ "instances" ], "summary": "Migrate an instance to a different propolis-server, possibly on a different sled.", - "description": "", "operationId": "project_instances_migrate_instance", "parameters": [ { @@ -1493,13 +1493,284 @@ } } }, + "/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces": { + "get": { + "tags": [ + "instances" + ], + "summary": "List network interfaces attached to this instance.", + "operationId": "instance_network_interfaces_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + }, + "style": "form" + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", + "schema": { + "nullable": true, + "type": "string" + }, + "style": "form" + }, + { + "in": "query", + "name": "sort_by", + "schema": { + "$ref": "#/components/schemas/NameSortMode" + }, + "style": "form" + }, + { + "in": "path", + "name": "instance_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NetworkInterfaceResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": true + }, + "post": { + "tags": [ + "instances" + ], + "summary": "Create a network interface for an instance.", + "operationId": "instance_network_interfaces_post", + "parameters": [ + { + "in": "path", + "name": "instance_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NetworkInterfaceCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NetworkInterface" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/network-interfaces/{interface_name}": { + "get": { + "tags": [ + "instances" + ], + "summary": "Get an interface attached to an instance.", + "operationId": "instance_network_interfaces_get_interface", + "parameters": [ + { + "in": "path", + "name": "instance_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "interface_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NetworkInterface" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "tags": [ + "instances" + ], + "summary": "Detach a network interface from an instance.", + "operationId": "instance_network_interfaces_delete_interface", + "parameters": [ + { + "in": "path", + "name": "instance_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "interface_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, "/organizations/{organization_name}/projects/{project_name}/instances/{instance_name}/reboot": { "post": { "tags": [ "instances" ], "summary": "Reboot an instance.", - "description": "", "operationId": "project_instances_instance_reboot", "parameters": [ { @@ -1556,7 +1827,6 @@ "instances" ], "summary": "Boot an instance.", - "description": "", "operationId": "project_instances_instance_start", "parameters": [ { @@ -1613,7 +1883,6 @@ "instances" ], "summary": "Halt an instance.", - "description": "", "operationId": "project_instances_instance_stop", "parameters": [ { @@ -1664,21 +1933,20 @@ } } }, - "/organizations/{organization_name}/projects/{project_name}/vpcs": { + "/organizations/{organization_name}/projects/{project_name}/snapshots": { "get": { "tags": [ - "vpcs" + "snapshots" ], - "summary": "List VPCs in a project.", - "description": "", - "operationId": "project_vpcs_get", + "summary": "List snapshots in a project.", + "operationId": "project_snapshots_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -1688,9 +1956,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -1706,6 +1974,7 @@ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1715,6 +1984,247 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SnapshotResultsPage" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + }, + "x-dropshot-pagination": true + }, + "post": { + "tags": [ + "snapshots" + ], + "summary": "Create a snapshot of a disk.", + "operationId": "project_snapshots_post", + "parameters": [ + { + "in": "path", + "name": "organization_name", + "description": "The organization's unique name.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "description": "The project's unique name within the organization.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SnapshotCreate" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "successful creation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Snapshot" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/organizations/{organization_name}/projects/{project_name}/snapshots/{snapshot_name}": { + "get": { + "tags": [ + "snapshots" + ], + "summary": "Get a snapshot in a project.", + "operationId": "project_snapshots_get_snapshot", + "parameters": [ + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "snapshot_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Snapshot" + } + } + } + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + }, + "delete": { + "tags": [ + "snapshots" + ], + "summary": "Delete a snapshot from a project.", + "operationId": "project_snapshots_delete_snapshot", + "parameters": [ + { + "in": "path", + "name": "organization_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "snapshot_name", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + } + ], + "responses": { + "204": { + "description": "successful deletion" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, + "/organizations/{organization_name}/projects/{project_name}/vpcs": { + "get": { + "tags": [ + "vpcs" + ], + "summary": "List VPCs in a project.", + "operationId": "project_vpcs_get", + "parameters": [ + { + "in": "query", + "name": "limit", + "description": "Maximum number of items returned by a single call", + "schema": { + "nullable": true, + "type": "integer", + "format": "uint32", + "minimum": 1 + }, + "style": "form" + }, + { + "in": "query", + "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", + "schema": { + "nullable": true, + "type": "string" + }, + "style": "form" + }, + { + "in": "query", + "name": "sort_by", + "schema": { + "$ref": "#/components/schemas/NameSortMode" + }, + "style": "form" + }, + { + "in": "path", + "name": "organization_name", + "description": "The organization's unique name.", + "required": true, + "schema": { + "$ref": "#/components/schemas/Name" + }, + "style": "simple" + }, + { + "in": "path", + "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1747,12 +2257,12 @@ "vpcs" ], "summary": "Create a VPC in a project.", - "description": "", "operationId": "project_vpcs_post", "parameters": [ { "in": "path", "name": "organization_name", + "description": "The organization's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1762,6 +2272,7 @@ { "in": "path", "name": "project_name", + "description": "The project's unique name within the organization.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -1805,7 +2316,6 @@ "vpcs" ], "summary": "Get a VPC in a project.", - "description": "", "operationId": "project_vpcs_get_vpc", "parameters": [ { @@ -1860,7 +2370,6 @@ "vpcs" ], "summary": "Update a VPC.", - "description": "", "operationId": "project_vpcs_put_vpc", "parameters": [ { @@ -1902,8 +2411,15 @@ "required": true }, "responses": { - "204": { - "description": "resource updated" + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vpc" + } + } + } }, "4XX": { "$ref": "#/components/responses/Error" @@ -1918,7 +2434,6 @@ "vpcs" ], "summary": "Delete a vpc from a project.", - "description": "", "operationId": "project_vpcs_delete_vpc", "parameters": [ { @@ -1968,39 +2483,8 @@ "firewall" ], "summary": "List firewall rules for a VPC.", - "description": "", "operationId": "vpc_firewall_rules_get", "parameters": [ - { - "in": "query", - "name": "limit", - "schema": { - "nullable": true, - "description": "Maximum number of items returned by a single call", - "type": "integer", - "format": "uint32", - "minimum": 1 - }, - "style": "form" - }, - { - "in": "query", - "name": "page_token", - "schema": { - "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", - "type": "string" - }, - "style": "form" - }, - { - "in": "query", - "name": "sort_by", - "schema": { - "$ref": "#/components/schemas/NameSortMode" - }, - "style": "form" - }, { "in": "path", "name": "organization_name", @@ -2035,7 +2519,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VpcFirewallRuleResultsPage" + "$ref": "#/components/schemas/VpcFirewallRules" } } } @@ -2046,15 +2530,13 @@ "5XX": { "$ref": "#/components/responses/Error" } - }, - "x-dropshot-pagination": true + } }, "put": { "tags": [ "firewall" ], "summary": "Replace the firewall rules for a VPC", - "description": "", "operationId": "vpc_firewall_rules_put", "parameters": [ { @@ -2101,7 +2583,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/VpcFirewallRuleUpdateResult" + "$ref": "#/components/schemas/VpcFirewallRules" } } } @@ -2121,15 +2603,14 @@ "routers" ], "summary": "List VPC Custom and System Routers", - "description": "", "operationId": "vpc_routers_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -2139,9 +2620,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -2207,7 +2688,6 @@ "routers" ], "summary": "Create a VPC Router", - "description": "", "operationId": "vpc_routers_post", "parameters": [ { @@ -2274,7 +2754,6 @@ "routers" ], "summary": "Get a VPC Router", - "description": "", "operationId": "vpc_routers_get_router", "parameters": [ { @@ -2338,7 +2817,6 @@ "routers" ], "summary": "Update a VPC Router", - "description": "", "operationId": "vpc_routers_put_router", "parameters": [ { @@ -2389,8 +2867,15 @@ "required": true }, "responses": { - "204": { - "description": "resource updated" + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VpcRouter" + } + } + } }, "4XX": { "$ref": "#/components/responses/Error" @@ -2405,7 +2890,6 @@ "routers" ], "summary": "Delete a router from its VPC", - "description": "", "operationId": "vpc_routers_delete_router", "parameters": [ { @@ -2464,15 +2948,14 @@ "routes" ], "summary": "List a Router's routes", - "description": "", "operationId": "routers_routes_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -2482,9 +2965,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -2559,7 +3042,6 @@ "routes" ], "summary": "Create a VPC Router", - "description": "", "operationId": "routers_routes_post", "parameters": [ { @@ -2635,7 +3117,6 @@ "routes" ], "summary": "Get a VPC Router route", - "description": "", "operationId": "routers_routes_get_route", "parameters": [ { @@ -2708,7 +3189,6 @@ "routes" ], "summary": "Update a Router route", - "description": "", "operationId": "routers_routes_put_route", "parameters": [ { @@ -2768,8 +3248,15 @@ "required": true }, "responses": { - "204": { - "description": "resource updated" + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RouterRoute" + } + } + } }, "4XX": { "$ref": "#/components/responses/Error" @@ -2784,7 +3271,6 @@ "routes" ], "summary": "Delete a route from its router", - "description": "", "operationId": "routers_routes_delete_route", "parameters": [ { @@ -2852,15 +3338,14 @@ "subnets" ], "summary": "List subnets in a VPC.", - "description": "", "operationId": "vpc_subnets_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -2870,9 +3355,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -2938,7 +3423,6 @@ "subnets" ], "summary": "Create a subnet in a VPC.", - "description": "", "operationId": "vpc_subnets_post", "parameters": [ { @@ -3005,7 +3489,6 @@ "subnets" ], "summary": "Get subnet in a VPC.", - "description": "", "operationId": "vpc_subnets_get_subnet", "parameters": [ { @@ -3069,7 +3552,6 @@ "subnets" ], "summary": "Update a VPC Subnet.", - "description": "", "operationId": "vpc_subnets_put_subnet", "parameters": [ { @@ -3120,8 +3602,15 @@ "required": true }, "responses": { - "204": { - "description": "resource updated" + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VpcSubnet" + } + } + } }, "4XX": { "$ref": "#/components/responses/Error" @@ -3136,7 +3625,6 @@ "subnets" ], "summary": "Delete a subnet from a VPC.", - "description": "", "operationId": "vpc_subnets_delete_subnet", "parameters": [ { @@ -3189,21 +3677,20 @@ } } }, - "/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}/ips": { + "/organizations/{organization_name}/projects/{project_name}/vpcs/{vpc_name}/subnets/{subnet_name}/network-interfaces": { "get": { "tags": [ "subnets" ], - "summary": "List IP addresses on a VPC subnet.", - "description": "", - "operationId": "subnets_ips_get", + "summary": "List network interfaces in a VPC subnet.", + "operationId": "subnet_network_interfaces_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -3213,9 +3700,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -3292,15 +3779,14 @@ "roles" ], "summary": "List the built-in roles", - "description": "", "operationId": "roles_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -3310,9 +3796,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -3345,15 +3831,14 @@ "roles" ], "summary": "Fetch a specific built-in role", - "description": "", "operationId": "roles_get_role", "parameters": [ { "in": "path", "name": "role_name", + "description": "The built-in role's unique name.", "required": true, "schema": { - "description": "The built-in role's unique name.", "type": "string" }, "style": "simple" @@ -3385,15 +3870,14 @@ "sagas" ], "summary": "List all sagas (for debugging)", - "description": "", "operationId": "sagas_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -3403,9 +3887,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -3446,7 +3930,6 @@ "sagas" ], "summary": "Fetch information about a single saga (for debugging)", - "description": "", "operationId": "sagas_get_saga", "parameters": [ { @@ -3513,15 +3996,14 @@ "metrics" ], "summary": "List all timeseries schema", - "description": "", "operationId": "timeseries_schema_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -3531,9 +4013,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -3560,21 +4042,40 @@ "x-dropshot-pagination": true } }, + "/updates/refresh": { + "post": { + "tags": [ + "updates" + ], + "summary": "Refresh update metadata", + "operationId": "updates_refresh", + "responses": { + "204": { + "description": "resource updated" + }, + "4XX": { + "$ref": "#/components/responses/Error" + }, + "5XX": { + "$ref": "#/components/responses/Error" + } + } + } + }, "/users": { "get": { "tags": [ "users" ], "summary": "List the built-in system users", - "description": "", "operationId": "users_get", "parameters": [ { "in": "query", "name": "limit", + "description": "Maximum number of items returned by a single call", "schema": { "nullable": true, - "description": "Maximum number of items returned by a single call", "type": "integer", "format": "uint32", "minimum": 1 @@ -3584,9 +4085,9 @@ { "in": "query", "name": "page_token", + "description": "Token returned by previous call to retreive the subsequent page", "schema": { "nullable": true, - "description": "Token returned by previous call to retreive the subsequent page", "type": "string" }, "style": "form" @@ -3627,12 +4128,12 @@ "users" ], "summary": "Fetch a specific built-in system user", - "description": "", "operationId": "users_get_user", "parameters": [ { "in": "path", "name": "user_name", + "description": "The built-in user's unique name.", "required": true, "schema": { "$ref": "#/components/schemas/Name" @@ -3759,7 +4260,7 @@ ] }, "DiskCreate": { - "description": "Create-time parameters for a [`Disk`]", + "description": "Create-time parameters for a [`Disk`](omicron_common::api::external::Disk)", "type": "object", "properties": { "description": { @@ -3790,7 +4291,7 @@ ] }, "DiskIdentifier": { - "description": "Parameters for the [`Disk`] to be attached or detached to an instance", + "description": "Parameters for the [`Disk`](omicron_common::api::external::Disk) to be attached or detached to an instance", "type": "object", "properties": { "disk": { @@ -3948,7 +4449,7 @@ ] }, "Error": { - "description": "Body of an HTTP response for an `HttpError`. This type can be used to deserialize an HTTP response corresponding to an error in order to access the error code, message, etc.", + "description": "Error information from a response.", "type": "object", "properties": { "error_code": { @@ -4090,7 +4591,7 @@ "minimum": 0 }, "InstanceCreate": { - "description": "Create-time parameters for an [`Instance`]", + "description": "Create-time parameters for an [`Instance`](omicron_common::api::external::Instance)", "type": "object", "properties": { "description": { @@ -4107,6 +4608,14 @@ }, "ncpus": { "$ref": "#/components/schemas/InstanceCpuCount" + }, + "network_interfaces": { + "description": "The network interfaces to be created for this instance.", + "allOf": [ + { + "$ref": "#/components/schemas/InstanceNetworkInterfaceAttachment" + } + ] } }, "required": [ @@ -4118,7 +4627,7 @@ ] }, "InstanceMigrate": { - "description": "Migration parameters for an [`Instance`]", + "description": "Migration parameters for an [`Instance`](omicron_common::api::external::Instance)", "type": "object", "properties": { "dst_sled_uuid": { @@ -4130,6 +4639,74 @@ "dst_sled_uuid" ] }, + "InstanceNetworkInterfaceAttachment": { + "description": "Describes an attachment of a `NetworkInterface` to an `Instance`, at the time the instance is created.", + "oneOf": [ + { + "description": "Create one or more `NetworkInterface`s for the `Instance`", + "type": "object", + "properties": { + "params": { + "$ref": "#/components/schemas/InstanceNetworkInterfaceCreate" + }, + "type": { + "type": "string", + "enum": [ + "Create" + ] + } + }, + "required": [ + "params", + "type" + ] + }, + { + "description": "Default networking setup, which creates a single interface with an auto-assigned IP address from project's \"default\" VPC and \"default\" VPC Subnet.", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "Default" + ] + } + }, + "required": [ + "type" + ] + }, + { + "description": "No network interfaces at all will be created for the instance.", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "None" + ] + } + }, + "required": [ + "type" + ] + } + ] + }, + "InstanceNetworkInterfaceCreate": { + "type": "object", + "properties": { + "params": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NetworkInterfaceCreate" + } + } + }, + "required": [ + "params" + ] + }, "InstanceResultsPage": { "description": "A single page of results", "type": "object", @@ -4167,18 +4744,47 @@ "destroyed" ] }, + "IpNet": { + "description": "An `IpNet` represents an IP network, either IPv4 or IPv6.", + "oneOf": [ + { + "type": "object", + "properties": { + "V4": { + "$ref": "#/components/schemas/Ipv4Net" + } + }, + "required": [ + "V4" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "V6": { + "$ref": "#/components/schemas/Ipv6Net" + } + }, + "required": [ + "V6" + ], + "additionalProperties": false + } + ] + }, "Ipv4Net": { "title": "An IPv4 subnet", "description": "An IPv4 subnet, including prefix and subnet mask", "type": "string", - "pattern": "^(10\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9]\\.){2}(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[0-9]|2[0-8]|[8-9]))$^(172\\.16\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[2-9]|2[0-8]))$^(192\\.168\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[6-9]|2[0-8]))$", + "pattern": "(^(10\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9]\\.){2}(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[0-9]|2[0-8]|[8-9]))$)|(^(172\\.16\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[2-9]|2[0-8]))$)|(^(192\\.168\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])\\.(25[0-5]|[1-2][0-4][0-9]|[1-9][0-9]|[0-9])/(1[6-9]|2[0-8]))$)", "maxLength": 18 }, "Ipv6Net": { "title": "An IPv6 subnet", "description": "An IPv6 subnet, including prefix and subnet mask", "type": "string", - "pattern": "^(fd|FD)00:((([0-9a-fA-F]{1,4}\\:){6}[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,6}:))/(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-6])$", + "pattern": "^(fd|FD)[0-9a-fA-F]{2}:((([0-9a-fA-F]{1,4}\\:){6}[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,6}:))/(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-6])$", "maxLength": 43 }, "L4PortRange": { @@ -4288,6 +4894,46 @@ "vpc_id" ] }, + "NetworkInterfaceCreate": { + "description": "Create-time parameters for a [`NetworkInterface`](omicron_common::api::external::NetworkInterface)", + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "ip": { + "nullable": true, + "description": "The IP address for the interface. One will be auto-assigned if not provided.", + "type": "string", + "format": "ip" + }, + "name": { + "$ref": "#/components/schemas/Name" + }, + "subnet_name": { + "description": "The VPC Subnet in which to create the interface.", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, + "vpc_name": { + "description": "The VPC in which to create the interface.", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + } + }, + "required": [ + "description", + "name", + "subnet_name", + "vpc_name" + ] + }, "NetworkInterfaceResultsPage": { "description": "A single page of results", "type": "object", @@ -4350,7 +4996,7 @@ ] }, "OrganizationCreate": { - "description": "Create-time parameters for an [`Organization`]", + "description": "Create-time parameters for an [`Organization`](crate::external_api::views::Organization)", "type": "object", "properties": { "description": { @@ -4387,7 +5033,7 @@ ] }, "OrganizationUpdate": { - "description": "Updateable properties of an [`Organization`]", + "description": "Updateable properties of an [`Organization`](crate::external_api::views::Organization)", "type": "object", "properties": { "description": { @@ -4450,7 +5096,7 @@ ] }, "ProjectCreate": { - "description": "Create-time parameters for a [`Project`]", + "description": "Create-time parameters for a [`Project`](crate::external_api::views::Project)", "type": "object", "properties": { "description": { @@ -4487,7 +5133,7 @@ ] }, "ProjectUpdate": { - "description": "Updateable properties of a [`Project`]", + "description": "Updateable properties of a [`Project`](crate::external_api::views::Project)", "type": "object", "properties": { "description": { @@ -4610,9 +5256,10 @@ ] }, "RouteDestination": { - "description": "A subset of [`NetworkTarget`], `RouteDestination` specifies the kind of network traffic that will be matched to be forwarded to the [`RouteTarget`].", + "description": "A `RouteDestination` is used to match traffic with a routing rule, on the destination of that traffic.\n\nWhen 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.", "oneOf": [ { + "description": "Route applies to traffic destined for a specific IP address", "type": "object", "properties": { "type": { @@ -4632,6 +5279,26 @@ ] }, { + "description": "Route applies to traffic destined for a specific IP subnet", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ip_net" + ] + }, + "value": { + "$ref": "#/components/schemas/IpNet" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "description": "Route applies to traffic destined for the given VPC.", "type": "object", "properties": { "type": { @@ -4650,6 +5317,7 @@ ] }, { + "description": "Route applies to traffic", "type": "object", "properties": { "type": { @@ -4670,9 +5338,10 @@ ] }, "RouteTarget": { - "description": "A subset of [`NetworkTarget`], `RouteTarget` specifies all possible targets that a route can forward to.", + "description": "A `RouteTarget` describes the possible locations that traffic matching a route destination can be sent.", "oneOf": [ { + "description": "Forward traffic to a particular IP address.", "type": "object", "properties": { "type": { @@ -4692,6 +5361,7 @@ ] }, { + "description": "Forward traffic to a VPC", "type": "object", "properties": { "type": { @@ -4710,6 +5380,7 @@ ] }, { + "description": "Forward traffic to a VPC Subnet", "type": "object", "properties": { "type": { @@ -4728,6 +5399,7 @@ ] }, { + "description": "Forward traffic to a specific instance", "type": "object", "properties": { "type": { @@ -4746,6 +5418,7 @@ ] }, { + "description": "Forward traffic to an internet gateway", "type": "object", "properties": { "type": { @@ -5168,6 +5841,106 @@ "items" ] }, + "Snapshot": { + "description": "Client view of a Snapshot", + "type": "object", + "properties": { + "description": { + "description": "human-readable free-form text about a resource", + "type": "string" + }, + "disk_id": { + "type": "string", + "format": "uuid" + }, + "id": { + "description": "unique, immutable, system-controlled identifier for each resource", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "unique, mutable, user-controlled identifier for each resource", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, + "project_id": { + "type": "string", + "format": "uuid" + }, + "size": { + "$ref": "#/components/schemas/ByteCount" + }, + "time_created": { + "description": "timestamp when this resource was created", + "type": "string", + "format": "date-time" + }, + "time_modified": { + "description": "timestamp when this resource was last modified", + "type": "string", + "format": "date-time" + } + }, + "required": [ + "description", + "disk_id", + "id", + "name", + "project_id", + "size", + "time_created", + "time_modified" + ] + }, + "SnapshotCreate": { + "description": "Create-time parameters for a [`Snapshot`](omicron_common::api::external::Snapshot)", + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "disk": { + "description": "The name of the disk to be snapshotted", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, + "name": { + "$ref": "#/components/schemas/Name" + } + }, + "required": [ + "description", + "disk", + "name" + ] + }, + "SnapshotResultsPage": { + "description": "A single page of results", + "type": "object", + "properties": { + "items": { + "description": "list of items on this page of results", + "type": "array", + "items": { + "$ref": "#/components/schemas/Snapshot" + } + }, + "next_page": { + "nullable": true, + "description": "token used to fetch the next page of results (if any)", + "type": "string" + } + }, + "required": [ + "items" + ] + }, "TimeseriesName": { "title": "The name of a timeseries", "description": "Names are constructed by concatenating the target and metric names with ':'. Target and metric names must be lowercase alphanumeric characters with '_' separating words.", @@ -5305,6 +6078,14 @@ "type": "string", "format": "uuid" }, + "ipv6_prefix": { + "description": "The unique local IPv6 address range for subnets in this VPC", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" + } + ] + }, "name": { "description": "unique, mutable, user-controlled identifier for each resource", "allOf": [ @@ -5338,6 +6119,7 @@ "description", "dns_name", "id", + "ipv6_prefix", "name", "project_id", "system_router_id", @@ -5346,7 +6128,7 @@ ] }, "VpcCreate": { - "description": "Create-time parameters for a [`Vpc`]", + "description": "Create-time parameters for a [`Vpc`](crate::external_api::views::Vpc)", "type": "object", "properties": { "description": { @@ -5355,6 +6137,15 @@ "dns_name": { "$ref": "#/components/schemas/Name" }, + "ipv6_prefix": { + "nullable": true, + "description": "The IPv6 prefix for this VPC.\n\nAll 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.", + "allOf": [ + { + "$ref": "#/components/schemas/Ipv6Net" + } + ] + }, "name": { "$ref": "#/components/schemas/Name" } @@ -5440,6 +6231,11 @@ "description": "timestamp when this resource was last modified", "type": "string", "format": "date-time" + }, + "vpc_id": { + "description": "the VPC to which this rule belongs", + "type": "string", + "format": "uuid" } }, "required": [ @@ -5453,7 +6249,8 @@ "status", "targets", "time_created", - "time_modified" + "time_modified", + "vpc_id" ] }, "VpcFirewallRuleAction": { @@ -5501,9 +6298,10 @@ } }, "VpcFirewallRuleHostFilter": { - "description": "A subset of [`NetworkTarget`], `VpcFirewallRuleHostFilter` specifies all possible targets that a route can forward to.", + "description": "The `VpcFirewallRuleHostFilter` is used to filter traffic on the basis of its source or destination host.", "oneOf": [ { + "description": "The rule applies to traffic from/to all instances in the VPC", "type": "object", "properties": { "type": { @@ -5522,6 +6320,7 @@ ] }, { + "description": "The rule applies to traffic from/to all instances in the VPC Subnet", "type": "object", "properties": { "type": { @@ -5540,6 +6339,7 @@ ] }, { + "description": "The rule applies to traffic from/to this specific instance", "type": "object", "properties": { "type": { @@ -5558,6 +6358,7 @@ ] }, { + "description": "The rule applies to traffic from/to a specific IP address", "type": "object", "properties": { "type": { @@ -5577,16 +6378,17 @@ ] }, { + "description": "The rule applies to traffic from/to a specific IP subnet", "type": "object", "properties": { "type": { "type": "string", "enum": [ - "internet_gateway" + "ip_net" ] }, "value": { - "$ref": "#/components/schemas/Name" + "$ref": "#/components/schemas/IpNet" } }, "required": [ @@ -5605,27 +6407,6 @@ "ICMP" ] }, - "VpcFirewallRuleResultsPage": { - "description": "A single page of results", - "type": "object", - "properties": { - "items": { - "description": "list of items on this page of results", - "type": "array", - "items": { - "$ref": "#/components/schemas/VpcFirewallRule" - } - }, - "next_page": { - "nullable": true, - "description": "token used to fetch the next page of results (if any)", - "type": "string" - } - }, - "required": [ - "items" - ] - }, "VpcFirewallRuleStatus": { "type": "string", "enum": [ @@ -5634,9 +6415,10 @@ ] }, "VpcFirewallRuleTarget": { - "description": "A subset of [`NetworkTarget`], `VpcFirewallRuleTarget` specifies all possible targets that a firewall rule can be attached to.", + "description": "A `VpcFirewallRuleTarget` is used to specify the set of [`Instance`]s to which a firewall rule applies.", "oneOf": [ { + "description": "The rule applies to all instances in the VPC", "type": "object", "properties": { "type": { @@ -5655,6 +6437,7 @@ ] }, { + "description": "The rule applies to all instances in the VPC Subnet", "type": "object", "properties": { "type": { @@ -5673,6 +6456,7 @@ ] }, { + "description": "The rule applies to this specific instance", "type": "object", "properties": { "type": { @@ -5689,6 +6473,45 @@ "type", "value" ] + }, + { + "description": "The rule applies to a specific IP address", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ip" + ] + }, + "value": { + "type": "string", + "format": "ip" + } + }, + "required": [ + "type", + "value" + ] + }, + { + "description": "The rule applies to a specific IP subnet", + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ip_net" + ] + }, + "value": { + "$ref": "#/components/schemas/IpNet" + } + }, + "required": [ + "type", + "value" + ] } ] }, @@ -5724,6 +6547,14 @@ } ] }, + "name": { + "description": "name of the rule, unique to this VPC", + "allOf": [ + { + "$ref": "#/components/schemas/Name" + } + ] + }, "priority": { "description": "the relative priority of this rule", "type": "integer", @@ -5751,24 +6582,41 @@ "description", "direction", "filters", + "name", "priority", "status", "targets" ] }, "VpcFirewallRuleUpdateParams": { - "description": "Updateable properties of a [`Vpc`]'s firewall Note that VpcFirewallRules are implicitly created along with a Vpc, so there is no explicit creation.", + "description": "Updateable properties of a `Vpc`'s firewall Note that VpcFirewallRules are implicitly created along with a Vpc, so there is no explicit creation.", "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/VpcFirewallRuleUpdate" - } + "properties": { + "rules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VpcFirewallRuleUpdate" + } + } + }, + "required": [ + "rules" + ] }, - "VpcFirewallRuleUpdateResult": { - "description": "Response to an update replacing [`Vpc`]'s firewall", + "VpcFirewallRules": { + "description": "Collection of a [`Vpc`]'s firewall rules", "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/VpcFirewallRule" - } + "properties": { + "rules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VpcFirewallRule" + } + } + }, + "required": [ + "rules" + ] }, "VpcResultsPage": { "description": "A single page of results", @@ -5842,7 +6690,7 @@ ] }, "VpcRouterCreate": { - "description": "Create-time parameters for a [`VpcRouter`]", + "description": "Create-time parameters for a [`VpcRouter`](crate::external_api::views::VpcRouter)", "type": "object", "properties": { "description": { @@ -5886,7 +6734,7 @@ ] }, "VpcRouterUpdate": { - "description": "Updateable properties of a [`VpcRouter`]", + "description": "Updateable properties of a [`VpcRouter`](crate::external_api::views::VpcRouter)", "type": "object", "properties": { "description": { @@ -5917,7 +6765,6 @@ "format": "uuid" }, "ipv4_block": { - "nullable": true, "description": "The IPv4 subnet CIDR block.", "allOf": [ { @@ -5926,7 +6773,6 @@ ] }, "ipv6_block": { - "nullable": true, "description": "The IPv6 subnet CIDR block.", "allOf": [ { @@ -5961,6 +6807,8 @@ "required": [ "description", "id", + "ipv4_block", + "ipv6_block", "name", "time_created", "time_modified", @@ -5968,14 +6816,14 @@ ] }, "VpcSubnetCreate": { - "description": "Create-time parameters for a [`VpcSubnet`]", + "description": "Create-time parameters for a [`VpcSubnet`](crate::external_api::views::VpcSubnet)", "type": "object", "properties": { "description": { "type": "string" }, "ipv4_block": { - "nullable": true, + "description": "The IPv4 address range for this subnet.\n\nIt must be allocated from an RFC 1918 private address range, and must not overlap with any other existing subnet in the VPC.", "allOf": [ { "$ref": "#/components/schemas/Ipv4Net" @@ -5984,6 +6832,7 @@ }, "ipv6_block": { "nullable": true, + "description": "The IPv6 address range for this subnet.\n\nIt 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.", "allOf": [ { "$ref": "#/components/schemas/Ipv6Net" @@ -5996,6 +6845,7 @@ }, "required": [ "description", + "ipv4_block", "name" ] }, @@ -6021,7 +6871,7 @@ ] }, "VpcSubnetUpdate": { - "description": "Updateable properties of a [`VpcSubnet`]", + "description": "Updateable properties of a [`VpcSubnet`](crate::external_api::views::VpcSubnet)", "type": "object", "properties": { "description": { @@ -6055,7 +6905,7 @@ } }, "VpcUpdate": { - "description": "Updateable properties of a [`Vpc`]", + "description": "Updateable properties of a [`Vpc`](crate::external_api::views::Vpc)", "type": "object", "properties": { "description": { @@ -6104,5 +6954,133 @@ ] } } - } + }, + "tags": [ + { + "name": "disks", + "description": "Virtual disks are used to store instance-local data which includes the operating system.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "firewall", + "description": "Firewall operation controls the flow of network data into a VPC", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "hidden", + "description": "TODO operations that will not ship to customers", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "instances", + "description": "Virtual machine instances are the basic unit of computation. These operations are used for provisioning, controlling, and destroying instances.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "metrics", + "description": "Metrics provide insight into the operation of the Oxide deployment. These include telemetry on hardware and software components that can be used to understand the current state as well as to diagnose issues.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "organizations", + "description": "Organizations represent a subset of users and projects in an Oxide deployment.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "projects", + "description": "Projects are a grouping of associated resources such as instances and disks within an organization for purposes of billing and access control.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "racks", + "description": "These operations pertain to hardware inventory and management. Racks are the unit of expansion of an Oxide deployment. Racks are in turn composed of sleds, switches, power supplies, and a cabled backplane.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "roles", + "description": "Roles are a component of Identity and Access Management (IAM) that allow a user or agent account access to additional permissions.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "routers", + "description": "Routers direct the flow of network traffic into, out of, and within a VPC via routes.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "routes", + "description": "Routes define router policy.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "sagas", + "description": "Sagas are the abstraction used to represent multi-step operations within the Oxide deployment. These operations can be used to query saga status and report errors.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "sleds", + "description": "This tag should be moved into hardware", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "snapshots", + "description": "Snapshots of Virtual Disks at a particular point in time.", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "subnets", + "description": "This tag should be moved into a generic network tag", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "updates", + "description": "This tag should be moved into a operations tag", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "users", + "description": "This tag should be moved into an IAM tag", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + }, + { + "name": "vpcs", + "description": "A Virtual Private Cloud (VPC) is an isolated network environment that should probaby be moved into a more generic networking tag", + "externalDocs": { + "url": "http://oxide.computer/docs/#xxx" + } + } + ] } \ No newline at end of file