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..e1558ef 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; @@ -2618,15 +2620,17 @@ fn launch_server( .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, - ) - .map(|s| s.start()) - .map_err(|e| anyhow::anyhow!(e.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 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