From 82915c25f6bfa0ad780525ecc89fd6f1f687bc11 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Thu, 20 Jun 2024 11:29:56 -0500 Subject: [PATCH 1/4] rename IP pools list and view endpoints --- end-to-end-tests/src/bin/commtest.rs | 58 +++++++++++----------- nexus/src/external_api/http_entrypoints.rs | 27 ++++++---- nexus/tests/output/nexus_tags.txt | 8 +-- openapi/nexus.json | 14 +++--- 4 files changed, 58 insertions(+), 49 deletions(-) diff --git a/end-to-end-tests/src/bin/commtest.rs b/end-to-end-tests/src/bin/commtest.rs index 05e15faafc..ee470cb635 100644 --- a/end-to-end-tests/src/bin/commtest.rs +++ b/end-to-end-tests/src/bin/commtest.rs @@ -279,37 +279,37 @@ async fn rack_prepare( })?; let pool_name = "default"; - api_retry!( - if let Err(e) = oxide.ip_pool_view().pool("default").send().await { - if let Some(reqwest::StatusCode::NOT_FOUND) = e.status() { - print!("default ip pool does not exist, creating ..."); - oxide - .ip_pool_create() - .body(IpPoolCreate { - name: pool_name.parse().unwrap(), - description: "Default IP pool".to_string(), - }) - .send() - .await?; - oxide - .ip_pool_silo_link() - .pool(pool_name) - .body(IpPoolLinkSilo { - silo: NameOrId::Name("recovery".parse().unwrap()), - is_default: true, - }) - .send() - .await?; - println!("done"); - Ok(()) - } else { - Err(e) - } - } else { - println!("default ip pool already exists"); + api_retry!(if let Err(e) = + oxide.system_ip_pool_view().pool("default").send().await + { + if let Some(reqwest::StatusCode::NOT_FOUND) = e.status() { + print!("default ip pool does not exist, creating ..."); + oxide + .ip_pool_create() + .body(IpPoolCreate { + name: pool_name.parse().unwrap(), + description: "Default IP pool".to_string(), + }) + .send() + .await?; + oxide + .ip_pool_silo_link() + .pool(pool_name) + .body(IpPoolLinkSilo { + silo: NameOrId::Name("recovery".parse().unwrap()), + is_default: true, + }) + .send() + .await?; + println!("done"); Ok(()) + } else { + Err(e) } - )?; + } else { + println!("default ip pool already exists"); + Ok(()) + })?; let pool = api_retry!( oxide diff --git a/nexus/src/external_api/http_entrypoints.rs b/nexus/src/external_api/http_entrypoints.rs index 350836441e..c27d64224a 100644 --- a/nexus/src/external_api/http_entrypoints.rs +++ b/nexus/src/external_api/http_entrypoints.rs @@ -116,17 +116,17 @@ pub(crate) fn external_api() -> NexusApiDescription { api.register(project_update)?; api.register(project_policy_view)?; api.register(project_policy_update)?; - api.register(project_ip_pool_list)?; - api.register(project_ip_pool_view)?; + api.register(ip_pool_list)?; + api.register(ip_pool_view)?; // Operator-Accessible IP Pools API - api.register(ip_pool_list)?; + api.register(system_ip_pool_list)?; + api.register(system_ip_pool_view)?; api.register(ip_pool_create)?; api.register(ip_pool_silo_list)?; api.register(ip_pool_silo_link)?; api.register(ip_pool_silo_unlink)?; api.register(ip_pool_silo_update)?; - api.register(ip_pool_view)?; api.register(ip_pool_delete)?; api.register(ip_pool_update)?; // Variants for internal services @@ -1506,12 +1506,14 @@ async fn project_policy_update( // IP Pools /// List IP pools +/// +/// List IP pools linked to current silo. #[endpoint { method = GET, path = "/v1/ip-pools", - tags = ["projects"], + tags = ["silos"], }] -async fn project_ip_pool_list( +async fn ip_pool_list( rqctx: RequestContext, query_params: Query, ) -> Result>, HttpError> { @@ -1546,12 +1548,14 @@ async fn project_ip_pool_list( } /// Fetch IP pool +/// +/// Fetch IP pool linked to current silo. #[endpoint { method = GET, path = "/v1/ip-pools/{pool}", - tags = ["projects"], + tags = ["silos"], }] -async fn project_ip_pool_view( +async fn ip_pool_view( rqctx: RequestContext, path_params: Path, ) -> Result, HttpError> { @@ -1574,13 +1578,16 @@ async fn project_ip_pool_view( .await } +// Note system_ prefix only on list and view because they need to be distinguished +// from silo-scoped list and view + /// List IP pools #[endpoint { method = GET, path = "/v1/system/ip-pools", tags = ["system/networking"], }] -async fn ip_pool_list( +async fn system_ip_pool_list( rqctx: RequestContext, query_params: Query, ) -> Result>, HttpError> { @@ -1647,7 +1654,7 @@ async fn ip_pool_create( path = "/v1/system/ip-pools/{pool}", tags = ["system/networking"], }] -async fn ip_pool_view( +async fn system_ip_pool_view( rqctx: RequestContext, path_params: Path, ) -> Result, HttpError> { diff --git a/nexus/tests/output/nexus_tags.txt b/nexus/tests/output/nexus_tags.txt index a32fe5c4b9..19aa2275a0 100644 --- a/nexus/tests/output/nexus_tags.txt +++ b/nexus/tests/output/nexus_tags.txt @@ -85,8 +85,6 @@ API operations found with tag "projects" OPERATION ID METHOD URL PATH project_create POST /v1/projects project_delete DELETE /v1/projects/{project} -project_ip_pool_list GET /v1/ip-pools -project_ip_pool_view GET /v1/ip-pools/{pool} project_list GET /v1/projects project_policy_update PUT /v1/projects/{project}/policy project_policy_view GET /v1/projects/{project}/policy @@ -115,6 +113,8 @@ certificate_list GET /v1/certificates certificate_view GET /v1/certificates/{certificate} group_list GET /v1/groups group_view GET /v1/groups/{group_id} +ip_pool_list GET /v1/ip-pools +ip_pool_view GET /v1/ip-pools/{pool} policy_update PUT /v1/policy policy_view GET /v1/policy user_list GET /v1/users @@ -155,7 +155,6 @@ API operations found with tag "system/networking" OPERATION ID METHOD URL PATH ip_pool_create POST /v1/system/ip-pools ip_pool_delete DELETE /v1/system/ip-pools/{pool} -ip_pool_list GET /v1/system/ip-pools ip_pool_range_add POST /v1/system/ip-pools/{pool}/ranges/add ip_pool_range_list GET /v1/system/ip-pools/{pool}/ranges ip_pool_range_remove POST /v1/system/ip-pools/{pool}/ranges/remove @@ -169,7 +168,6 @@ ip_pool_silo_unlink DELETE /v1/system/ip-pools/{pool}/sil ip_pool_silo_update PUT /v1/system/ip-pools/{pool}/silos/{silo} ip_pool_update PUT /v1/system/ip-pools/{pool} ip_pool_utilization_view GET /v1/system/ip-pools/{pool}/utilization -ip_pool_view GET /v1/system/ip-pools/{pool} networking_address_lot_block_list GET /v1/system/networking/address-lot/{address_lot}/blocks networking_address_lot_create POST /v1/system/networking/address-lot networking_address_lot_delete DELETE /v1/system/networking/address-lot/{address_lot} @@ -195,6 +193,8 @@ networking_switch_port_settings_create POST /v1/system/networking/switch-p networking_switch_port_settings_delete DELETE /v1/system/networking/switch-port-settings networking_switch_port_settings_list GET /v1/system/networking/switch-port-settings networking_switch_port_settings_view GET /v1/system/networking/switch-port-settings/{port} +system_ip_pool_list GET /v1/system/ip-pools +system_ip_pool_view GET /v1/system/ip-pools/{pool} API operations found with tag "system/silos" OPERATION ID METHOD URL PATH diff --git a/openapi/nexus.json b/openapi/nexus.json index 01ec9aeb56..4beb115354 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -2679,10 +2679,11 @@ "/v1/ip-pools": { "get": { "tags": [ - "projects" + "silos" ], "summary": "List IP pools", - "operationId": "project_ip_pool_list", + "description": "List IP pools linked to current silo.", + "operationId": "ip_pool_list", "parameters": [ { "in": "query", @@ -2738,10 +2739,11 @@ "/v1/ip-pools/{pool}": { "get": { "tags": [ - "projects" + "silos" ], "summary": "Fetch IP pool", - "operationId": "project_ip_pool_view", + "description": "Fetch IP pool linked to current silo.", + "operationId": "ip_pool_view", "parameters": [ { "in": "path", @@ -5267,7 +5269,7 @@ "system/networking" ], "summary": "List IP pools", - "operationId": "ip_pool_list", + "operationId": "system_ip_pool_list", "parameters": [ { "in": "query", @@ -5361,7 +5363,7 @@ "system/networking" ], "summary": "Fetch IP pool", - "operationId": "ip_pool_view", + "operationId": "system_ip_pool_view", "parameters": [ { "in": "path", From fa9a4c1a145d640a126929e71419bd6c27704726 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Fri, 21 Jun 2024 17:25:24 -0500 Subject: [PATCH 2/4] Revert "rename IP pools list and view endpoints" 82915c25f6bfa0ad780525ecc89fd6f1f687bc11 --- end-to-end-tests/src/bin/commtest.rs | 58 +++++++++++----------- nexus/src/external_api/http_entrypoints.rs | 27 ++++------ nexus/tests/output/nexus_tags.txt | 8 +-- openapi/nexus.json | 14 +++--- 4 files changed, 49 insertions(+), 58 deletions(-) diff --git a/end-to-end-tests/src/bin/commtest.rs b/end-to-end-tests/src/bin/commtest.rs index ee470cb635..05e15faafc 100644 --- a/end-to-end-tests/src/bin/commtest.rs +++ b/end-to-end-tests/src/bin/commtest.rs @@ -279,37 +279,37 @@ async fn rack_prepare( })?; let pool_name = "default"; - api_retry!(if let Err(e) = - oxide.system_ip_pool_view().pool("default").send().await - { - if let Some(reqwest::StatusCode::NOT_FOUND) = e.status() { - print!("default ip pool does not exist, creating ..."); - oxide - .ip_pool_create() - .body(IpPoolCreate { - name: pool_name.parse().unwrap(), - description: "Default IP pool".to_string(), - }) - .send() - .await?; - oxide - .ip_pool_silo_link() - .pool(pool_name) - .body(IpPoolLinkSilo { - silo: NameOrId::Name("recovery".parse().unwrap()), - is_default: true, - }) - .send() - .await?; - println!("done"); - Ok(()) + api_retry!( + if let Err(e) = oxide.ip_pool_view().pool("default").send().await { + if let Some(reqwest::StatusCode::NOT_FOUND) = e.status() { + print!("default ip pool does not exist, creating ..."); + oxide + .ip_pool_create() + .body(IpPoolCreate { + name: pool_name.parse().unwrap(), + description: "Default IP pool".to_string(), + }) + .send() + .await?; + oxide + .ip_pool_silo_link() + .pool(pool_name) + .body(IpPoolLinkSilo { + silo: NameOrId::Name("recovery".parse().unwrap()), + is_default: true, + }) + .send() + .await?; + println!("done"); + Ok(()) + } else { + Err(e) + } } else { - Err(e) + println!("default ip pool already exists"); + Ok(()) } - } else { - println!("default ip pool already exists"); - Ok(()) - })?; + )?; let pool = api_retry!( oxide diff --git a/nexus/src/external_api/http_entrypoints.rs b/nexus/src/external_api/http_entrypoints.rs index c27d64224a..350836441e 100644 --- a/nexus/src/external_api/http_entrypoints.rs +++ b/nexus/src/external_api/http_entrypoints.rs @@ -116,17 +116,17 @@ pub(crate) fn external_api() -> NexusApiDescription { api.register(project_update)?; api.register(project_policy_view)?; api.register(project_policy_update)?; - api.register(ip_pool_list)?; - api.register(ip_pool_view)?; + api.register(project_ip_pool_list)?; + api.register(project_ip_pool_view)?; // Operator-Accessible IP Pools API - api.register(system_ip_pool_list)?; - api.register(system_ip_pool_view)?; + api.register(ip_pool_list)?; api.register(ip_pool_create)?; api.register(ip_pool_silo_list)?; api.register(ip_pool_silo_link)?; api.register(ip_pool_silo_unlink)?; api.register(ip_pool_silo_update)?; + api.register(ip_pool_view)?; api.register(ip_pool_delete)?; api.register(ip_pool_update)?; // Variants for internal services @@ -1506,14 +1506,12 @@ async fn project_policy_update( // IP Pools /// List IP pools -/// -/// List IP pools linked to current silo. #[endpoint { method = GET, path = "/v1/ip-pools", - tags = ["silos"], + tags = ["projects"], }] -async fn ip_pool_list( +async fn project_ip_pool_list( rqctx: RequestContext, query_params: Query, ) -> Result>, HttpError> { @@ -1548,14 +1546,12 @@ async fn ip_pool_list( } /// Fetch IP pool -/// -/// Fetch IP pool linked to current silo. #[endpoint { method = GET, path = "/v1/ip-pools/{pool}", - tags = ["silos"], + tags = ["projects"], }] -async fn ip_pool_view( +async fn project_ip_pool_view( rqctx: RequestContext, path_params: Path, ) -> Result, HttpError> { @@ -1578,16 +1574,13 @@ async fn ip_pool_view( .await } -// Note system_ prefix only on list and view because they need to be distinguished -// from silo-scoped list and view - /// List IP pools #[endpoint { method = GET, path = "/v1/system/ip-pools", tags = ["system/networking"], }] -async fn system_ip_pool_list( +async fn ip_pool_list( rqctx: RequestContext, query_params: Query, ) -> Result>, HttpError> { @@ -1654,7 +1647,7 @@ async fn ip_pool_create( path = "/v1/system/ip-pools/{pool}", tags = ["system/networking"], }] -async fn system_ip_pool_view( +async fn ip_pool_view( rqctx: RequestContext, path_params: Path, ) -> Result, HttpError> { diff --git a/nexus/tests/output/nexus_tags.txt b/nexus/tests/output/nexus_tags.txt index 19aa2275a0..a32fe5c4b9 100644 --- a/nexus/tests/output/nexus_tags.txt +++ b/nexus/tests/output/nexus_tags.txt @@ -85,6 +85,8 @@ API operations found with tag "projects" OPERATION ID METHOD URL PATH project_create POST /v1/projects project_delete DELETE /v1/projects/{project} +project_ip_pool_list GET /v1/ip-pools +project_ip_pool_view GET /v1/ip-pools/{pool} project_list GET /v1/projects project_policy_update PUT /v1/projects/{project}/policy project_policy_view GET /v1/projects/{project}/policy @@ -113,8 +115,6 @@ certificate_list GET /v1/certificates certificate_view GET /v1/certificates/{certificate} group_list GET /v1/groups group_view GET /v1/groups/{group_id} -ip_pool_list GET /v1/ip-pools -ip_pool_view GET /v1/ip-pools/{pool} policy_update PUT /v1/policy policy_view GET /v1/policy user_list GET /v1/users @@ -155,6 +155,7 @@ API operations found with tag "system/networking" OPERATION ID METHOD URL PATH ip_pool_create POST /v1/system/ip-pools ip_pool_delete DELETE /v1/system/ip-pools/{pool} +ip_pool_list GET /v1/system/ip-pools ip_pool_range_add POST /v1/system/ip-pools/{pool}/ranges/add ip_pool_range_list GET /v1/system/ip-pools/{pool}/ranges ip_pool_range_remove POST /v1/system/ip-pools/{pool}/ranges/remove @@ -168,6 +169,7 @@ ip_pool_silo_unlink DELETE /v1/system/ip-pools/{pool}/sil ip_pool_silo_update PUT /v1/system/ip-pools/{pool}/silos/{silo} ip_pool_update PUT /v1/system/ip-pools/{pool} ip_pool_utilization_view GET /v1/system/ip-pools/{pool}/utilization +ip_pool_view GET /v1/system/ip-pools/{pool} networking_address_lot_block_list GET /v1/system/networking/address-lot/{address_lot}/blocks networking_address_lot_create POST /v1/system/networking/address-lot networking_address_lot_delete DELETE /v1/system/networking/address-lot/{address_lot} @@ -193,8 +195,6 @@ networking_switch_port_settings_create POST /v1/system/networking/switch-p networking_switch_port_settings_delete DELETE /v1/system/networking/switch-port-settings networking_switch_port_settings_list GET /v1/system/networking/switch-port-settings networking_switch_port_settings_view GET /v1/system/networking/switch-port-settings/{port} -system_ip_pool_list GET /v1/system/ip-pools -system_ip_pool_view GET /v1/system/ip-pools/{pool} API operations found with tag "system/silos" OPERATION ID METHOD URL PATH diff --git a/openapi/nexus.json b/openapi/nexus.json index 4beb115354..01ec9aeb56 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -2679,11 +2679,10 @@ "/v1/ip-pools": { "get": { "tags": [ - "silos" + "projects" ], "summary": "List IP pools", - "description": "List IP pools linked to current silo.", - "operationId": "ip_pool_list", + "operationId": "project_ip_pool_list", "parameters": [ { "in": "query", @@ -2739,11 +2738,10 @@ "/v1/ip-pools/{pool}": { "get": { "tags": [ - "silos" + "projects" ], "summary": "Fetch IP pool", - "description": "Fetch IP pool linked to current silo.", - "operationId": "ip_pool_view", + "operationId": "project_ip_pool_view", "parameters": [ { "in": "path", @@ -5269,7 +5267,7 @@ "system/networking" ], "summary": "List IP pools", - "operationId": "system_ip_pool_list", + "operationId": "ip_pool_list", "parameters": [ { "in": "query", @@ -5363,7 +5361,7 @@ "system/networking" ], "summary": "Fetch IP pool", - "operationId": "system_ip_pool_view", + "operationId": "ip_pool_view", "parameters": [ { "in": "path", From e839eee9eb7e61006af7ce68da54b25b222d3951 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Mon, 24 Jun 2024 14:25:14 -0500 Subject: [PATCH 3/4] just go with current_silo_. oh well --- nexus/src/external_api/http_entrypoints.rs | 13 +++++++++---- nexus/tests/output/nexus_tags.txt | 4 ++-- openapi/nexus.json | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/nexus/src/external_api/http_entrypoints.rs b/nexus/src/external_api/http_entrypoints.rs index 350836441e..f27234f916 100644 --- a/nexus/src/external_api/http_entrypoints.rs +++ b/nexus/src/external_api/http_entrypoints.rs @@ -116,8 +116,8 @@ pub(crate) fn external_api() -> NexusApiDescription { api.register(project_update)?; api.register(project_policy_view)?; api.register(project_policy_update)?; - api.register(project_ip_pool_list)?; - api.register(project_ip_pool_view)?; + api.register(current_silo_ip_pool_list)?; + api.register(current_silo_ip_pool_view)?; // Operator-Accessible IP Pools API api.register(ip_pool_list)?; @@ -1505,13 +1505,18 @@ async fn project_policy_update( // IP Pools +// current_silo prefix is needed to distinguish silo-scoped endpoints from +// fleet-scoped. In other cases we might choose to put the prefix on the fleet +// endpoints, but in this case the vast majority of IP pool-related endpoints +// are at fleet level, so we put the prefix on the silo-scoped endpoints. + /// List IP pools #[endpoint { method = GET, path = "/v1/ip-pools", tags = ["projects"], }] -async fn project_ip_pool_list( +async fn current_silo_ip_pool_list( rqctx: RequestContext, query_params: Query, ) -> Result>, HttpError> { @@ -1551,7 +1556,7 @@ async fn project_ip_pool_list( path = "/v1/ip-pools/{pool}", tags = ["projects"], }] -async fn project_ip_pool_view( +async fn current_silo_ip_pool_view( rqctx: RequestContext, path_params: Path, ) -> Result, HttpError> { diff --git a/nexus/tests/output/nexus_tags.txt b/nexus/tests/output/nexus_tags.txt index a32fe5c4b9..50b40db31a 100644 --- a/nexus/tests/output/nexus_tags.txt +++ b/nexus/tests/output/nexus_tags.txt @@ -83,10 +83,10 @@ system_policy_view GET /v1/system/policy API operations found with tag "projects" OPERATION ID METHOD URL PATH +current_silo_ip_pool_list GET /v1/ip-pools +current_silo_ip_pool_view GET /v1/ip-pools/{pool} project_create POST /v1/projects project_delete DELETE /v1/projects/{project} -project_ip_pool_list GET /v1/ip-pools -project_ip_pool_view GET /v1/ip-pools/{pool} project_list GET /v1/projects project_policy_update PUT /v1/projects/{project}/policy project_policy_view GET /v1/projects/{project}/policy diff --git a/openapi/nexus.json b/openapi/nexus.json index 01ec9aeb56..83daab7887 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -2682,7 +2682,7 @@ "projects" ], "summary": "List IP pools", - "operationId": "project_ip_pool_list", + "operationId": "current_silo_ip_pool_list", "parameters": [ { "in": "query", @@ -2741,7 +2741,7 @@ "projects" ], "summary": "Fetch IP pool", - "operationId": "project_ip_pool_view", + "operationId": "current_silo_ip_pool_view", "parameters": [ { "in": "path", From fdae9ba884b8210d393d90d93b7cff2ca7dad119 Mon Sep 17 00:00:00 2001 From: David Crespo Date: Wed, 26 Jun 2024 11:50:18 -0500 Subject: [PATCH 4/4] bump nexus api version because adam said so --- nexus/src/lib.rs | 2 +- nexus/tests/integration_tests/commands.rs | 2 +- openapi/nexus.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nexus/src/lib.rs b/nexus/src/lib.rs index 6a23048693..82eab61d48 100644 --- a/nexus/src/lib.rs +++ b/nexus/src/lib.rs @@ -57,7 +57,7 @@ extern crate slog; /// to stdout. pub fn run_openapi_external() -> Result<(), String> { external_api() - .openapi("Oxide Region API", "20240502.0") + .openapi("Oxide Region API", "20240626.0") .description("API for interacting with the Oxide control plane") .contact_url("https://oxide.computer") .contact_email("api@oxide.computer") diff --git a/nexus/tests/integration_tests/commands.rs b/nexus/tests/integration_tests/commands.rs index 2eaf24d907..ba755f1049 100644 --- a/nexus/tests/integration_tests/commands.rs +++ b/nexus/tests/integration_tests/commands.rs @@ -109,7 +109,7 @@ fn test_nexus_openapi() { .expect("stdout was not valid OpenAPI"); assert_eq!(spec.openapi, "3.0.3"); assert_eq!(spec.info.title, "Oxide Region API"); - assert_eq!(spec.info.version, "20240502.0"); + assert_eq!(spec.info.version, "20240626.0"); // Spot check a couple of items. assert!(!spec.paths.paths.is_empty()); diff --git a/openapi/nexus.json b/openapi/nexus.json index 4668166e1b..525193cc62 100644 --- a/openapi/nexus.json +++ b/openapi/nexus.json @@ -7,7 +7,7 @@ "url": "https://oxide.computer", "email": "api@oxide.computer" }, - "version": "20240502.0" + "version": "20240626.0" }, "paths": { "/device/auth": {