From 9f7efb5024d42f45f82f621e1296572bb95fd773 Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 8 Oct 2025 02:40:14 +0000 Subject: [PATCH 1/3] [spr] initial version Created using spr 1.3.6-beta.1 --- .github/buildomat/jobs/dpd_openapi.sh | 28 ------------------- Cargo.lock | 1 + dpd-api/Cargo.toml | 1 + dpd-api/src/lib.rs | 28 +++++++++++++++++++ dpd-client/src/lib.rs | 2 +- dpd/src/api_server.rs | 25 ++++++++++------- dropshot-apis/src/main.rs | 4 +-- .../{dpd.json => dpd/dpd-1.0.0-40fbc6.json} | 2 +- openapi/dpd/dpd-latest.json | 1 + 9 files changed, 50 insertions(+), 42 deletions(-) delete mode 100644 .github/buildomat/jobs/dpd_openapi.sh rename openapi/{dpd.json => dpd/dpd-1.0.0-40fbc6.json} (99%) create mode 120000 openapi/dpd/dpd-latest.json diff --git a/.github/buildomat/jobs/dpd_openapi.sh b/.github/buildomat/jobs/dpd_openapi.sh deleted file mode 100644 index 8a66b6a..0000000 --- a/.github/buildomat/jobs/dpd_openapi.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -#: -#: name = "dpd_openapi" -#: variety = "basic" -#: target = "helios-2.0" -#: output_rules = [ -#: "/out/*", -#: ] -#: -#: [[publish]] -#: series = "openapi" -#: name = "dpd.json" -#: from_output = "/out/dpd.json" -#: -#: [[publish]] -#: series = "openapi" -#: name = "dpd.json.sha256.txt" -#: from_output = "/out/dpd.json.sha256.txt" - -set -o errexit -set -o pipefail -set -o xtrace - -banner copy -pfexec mkdir -p /out -pfexec chown "$UID" /out -cp openapi/dpd.json /out/dpd.json -digest -a sha256 /out/dpd.json > /out/dpd.json.sha256.txt diff --git a/Cargo.lock b/Cargo.lock index 3d9dc6e..41d4570 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1493,6 +1493,7 @@ dependencies = [ "common 0.1.0", "dpd-types", "dropshot", + "dropshot-api-manager-types", "oxnet", "schemars", "serde", diff --git a/dpd-api/Cargo.toml b/dpd-api/Cargo.toml index 35f806d..3640867 100644 --- a/dpd-api/Cargo.toml +++ b/dpd-api/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" common.workspace = true dpd-types.workspace = true dropshot.workspace = true +dropshot-api-manager-types.workspace = true oxnet.workspace = true schemars.workspace = true serde.workspace = true diff --git a/dpd-api/src/lib.rs b/dpd-api/src/lib.rs index 28b4d74..e2d9a31 100644 --- a/dpd-api/src/lib.rs +++ b/dpd-api/src/lib.rs @@ -36,6 +36,7 @@ use dropshot::{ HttpResponseOk, HttpResponseUpdatedNoContent, PaginationParams, Path, Query, RequestContext, ResultsPage, TypedBody, }; +use dropshot_api_manager_types::api_versions; use oxnet::{Ipv4Net, Ipv6Net}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -43,6 +44,33 @@ use transceiver_controller::{ Datapath, Monitors, PowerState, message::LedState, }; +api_versions!([ + // WHEN CHANGING THE API (part 1 of 2): + // + // +- Pick a new semver and define it in the list below. The list MUST + // | remain sorted, which generally means that your version should go at + // | the very top. + // | + // | Duplicate this line, uncomment the *second* copy, update that copy for + // | your new API version, and leave the first copy commented out as an + // | example for the next person. + // v + // (next_int, IDENT), + (1, INITIAL), +]); + +// WHEN CHANGING THE API (part 2 of 2): +// +// The call to `api_versions!` above defines constants of type +// `semver::Version` that you can use in your Dropshot API definition to specify +// the version when a particular endpoint was added or removed. For example, if +// you used: +// +// (2, ADD_FOOBAR) +// +// Then you could use `VERSION_ADD_FOOBAR` as the version in which endpoints +// were added or removed. + #[dropshot::api_description] pub trait DpdApi { type Context; diff --git a/dpd-client/src/lib.rs b/dpd-client/src/lib.rs index 35ac31b..0bb4a7c 100644 --- a/dpd-client/src/lib.rs +++ b/dpd-client/src/lib.rs @@ -31,7 +31,7 @@ pub struct ClientState { // Automatically generate the client bindings using Progenitor. progenitor::generate_api!( - spec = "../openapi/dpd.json", + spec = "../openapi/dpd/dpd-latest.json", interface = Positional, inner_type = crate::ClientState, pre_hook = (|state: &crate::ClientState, request: &reqwest::Request| { diff --git a/dpd/src/api_server.rs b/dpd/src/api_server.rs index 1952316..90fa078 100644 --- a/dpd/src/api_server.rs +++ b/dpd/src/api_server.rs @@ -33,6 +33,7 @@ use dpd_types::switch_port::Led; use dpd_types::switch_port::ManagementMode; use dpd_types::transceivers::Transceiver; use dropshot::ClientErrorStatusCode; +use dropshot::ClientSpecifiesVersionInHeader; use dropshot::EmptyScanParams; use dropshot::HttpError; use dropshot::HttpResponseCreated; @@ -45,6 +46,7 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::TypedBody; +use dropshot::VersionPolicy; use dropshot::WhichPage; use slog::{debug, error, info, o}; use transceiver_controller::Datapath; @@ -2614,17 +2616,20 @@ fn launch_server( default_handler_task_mode: dropshot::HandlerTaskMode::Detached, log_headers: vec![], }; - let log = switch - .log - .new(o!("unit" => "api-server", "server_id" => id.to_string())); - - slog::info!(log, "starting api server {id} on {addr}"); - dropshot::HttpServerStarter::new( - &config_dropshot, - http_api(), - switch.clone(), - &log, + + let server = dropshot::ServerBuilder::new( + api_description, + ctx, + log.new(o!("unit" => "api-server", "server_id" => id.to_string())), ) + .config(config_dropshot) + .version_policy(VersionPolicy::Dynamic(Box::new( + ClientSpecifiesVersionInHeader::new( + omicron_common::api::VERSION_HEADER, + dpd_api::latest_version(), + ), + ))) + .build_starter() .map(|s| s.start()) .map_err(|e| anyhow::anyhow!(e.to_string())) } diff --git a/dropshot-apis/src/main.rs b/dropshot-apis/src/main.rs index d64ffaa..1ce83c2 100644 --- a/dropshot-apis/src/main.rs +++ b/dropshot-apis/src/main.rs @@ -32,8 +32,8 @@ pub fn environment() -> anyhow::Result { pub fn all_apis() -> anyhow::Result { let apis = vec![ManagedApiConfig { ident: "dpd", - versions: Versions::Lockstep { - version: semver::Version::new(0, 1, 0), + versions: Versions::Versioned { + supported_versions: dpd_api::supported_versions(), }, title: "Oxide Switch Dataplane Controller", metadata: ManagedApiMetadata { diff --git a/openapi/dpd.json b/openapi/dpd/dpd-1.0.0-40fbc6.json similarity index 99% rename from openapi/dpd.json rename to openapi/dpd/dpd-1.0.0-40fbc6.json index 043692f..e8fb696 100644 --- a/openapi/dpd.json +++ b/openapi/dpd/dpd-1.0.0-40fbc6.json @@ -7,7 +7,7 @@ "url": "https://oxide.computer", "email": "api@oxide.computer" }, - "version": "0.1.0" + "version": "1.0.0" }, "paths": { "/all-settings": { diff --git a/openapi/dpd/dpd-latest.json b/openapi/dpd/dpd-latest.json new file mode 120000 index 0000000..a3945e5 --- /dev/null +++ b/openapi/dpd/dpd-latest.json @@ -0,0 +1 @@ +dpd-1.0.0-40fbc6.json \ No newline at end of file From d648b205a298832940a70989ba27a6c5eda22f48 Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 8 Oct 2025 02:59:16 +0000 Subject: [PATCH 2/3] try again Created using spr 1.3.6-beta.1 --- dpd/src/api_server.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpd/src/api_server.rs b/dpd/src/api_server.rs index 90fa078..3327153 100644 --- a/dpd/src/api_server.rs +++ b/dpd/src/api_server.rs @@ -2617,7 +2617,7 @@ fn launch_server( log_headers: vec![], }; - let server = dropshot::ServerBuilder::new( + dropshot::ServerBuilder::new( api_description, ctx, log.new(o!("unit" => "api-server", "server_id" => id.to_string())), From 480f65e6134b797dbefddda8eb26047e3a1b00f2 Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 8 Oct 2025 05:25:28 +0000 Subject: [PATCH 3/3] fix up issues Created using spr 1.3.6-beta.1 --- dpd/src/api_server.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/dpd/src/api_server.rs b/dpd/src/api_server.rs index 3327153..e1558ef 100644 --- a/dpd/src/api_server.rs +++ b/dpd/src/api_server.rs @@ -2616,22 +2616,21 @@ fn launch_server( default_handler_task_mode: dropshot::HandlerTaskMode::Detached, log_headers: vec![], }; - - dropshot::ServerBuilder::new( - api_description, - ctx, - log.new(o!("unit" => "api-server", "server_id" => id.to_string())), - ) - .config(config_dropshot) - .version_policy(VersionPolicy::Dynamic(Box::new( - ClientSpecifiesVersionInHeader::new( - omicron_common::api::VERSION_HEADER, - dpd_api::latest_version(), - ), - ))) - .build_starter() - .map(|s| s.start()) - .map_err(|e| anyhow::anyhow!(e.to_string())) + let log = switch + .log + .new(o!("unit" => "api-server", "server_id" => id.to_string())); + + dropshot::ServerBuilder::new(http_api(), switch, log) + .config(config_dropshot) + .version_policy(VersionPolicy::Dynamic(Box::new( + ClientSpecifiesVersionInHeader::new( + omicron_common::api::VERSION_HEADER, + dpd_api::latest_version(), + ), + ))) + .build_starter() + .map(|s| s.start()) + .map_err(|e| anyhow::anyhow!(e.to_string())) } // Manage the set of api servers currently listening for requests. When a