diff --git a/Cargo.lock b/Cargo.lock index f61187e..92022cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1938,6 +1938,7 @@ dependencies = [ "lldpd-api", "lldpd-common", "lldpd-types", + "omicron-common", "protocol 0.1.0", "schemars", "serde", @@ -1956,6 +1957,7 @@ name = "lldpd-api" version = "0.1.0" dependencies = [ "dropshot", + "dropshot-api-manager-types", "lldpd-types", "protocol 0.1.0", "schemars", diff --git a/Cargo.toml b/Cargo.toml index a0e3bbe..96cbfee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ protocol = { path = "protocol" } # oxide dependencies from github dpd-client = { git = "https://github.com/oxidecomputer/dendrite", branch = "main" } +omicron-common = { git = "https://github.com/oxidecomputer/omicron", branch = "main" } # public dependencies from crates.io anyhow = "1.0" diff --git a/dropshot-apis/src/main.rs b/dropshot-apis/src/main.rs index 8d49631..a912d6b 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: "lldpd", - versions: Versions::Lockstep { - version: semver::Version::new(0, 0, 1), + versions: Versions::Versioned { + supported_versions: lldpd_api::supported_versions(), }, title: "Oxide LLDP Daemon", metadata: ManagedApiMetadata { diff --git a/lldpd-api/Cargo.toml b/lldpd-api/Cargo.toml index 2ecf755..fee92ef 100644 --- a/lldpd-api/Cargo.toml +++ b/lldpd-api/Cargo.toml @@ -6,6 +6,7 @@ license = "MPL-2.0" [dependencies] dropshot.workspace = true +dropshot-api-manager-types.workspace = true lldpd-types.workspace = true protocol.workspace = true schemars.workspace = true diff --git a/lldpd-api/src/lib.rs b/lldpd-api/src/lib.rs index aa924c3..b13884a 100644 --- a/lldpd-api/src/lib.rs +++ b/lldpd-api/src/lib.rs @@ -11,6 +11,7 @@ use dropshot::{ HttpResponseOk, HttpResponseUpdatedNoContent, PaginationParams, Path, Query, RequestContext, ResultsPage, TypedBody, }; +use dropshot_api_manager_types::api_versions; use lldpd_types::{ build_info::BuildInfo, interfaces::{Interface, InterfaceAdd}, @@ -20,6 +21,33 @@ use protocol::types::{ChassisId, PortId, SystemCapabilities}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +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 LldpdApi { type Context; diff --git a/lldpd-client/src/lib.rs b/lldpd-client/src/lib.rs index fabaf00..df2daf0 100644 --- a/lldpd-client/src/lib.rs +++ b/lldpd-client/src/lib.rs @@ -15,7 +15,7 @@ pub const fn default_port() -> u16 { // Automatically generate the client bindings using Progenitor. progenitor::generate_api!( - spec = "../openapi/lldpd.json", + spec = "../openapi/lldpd/lldpd-latest.json", interface = Positional, inner_type = slog::Logger, pre_hook = (|log: &slog::Logger, request: &reqwest::Request| { diff --git a/lldpd/Cargo.toml b/lldpd/Cargo.toml index 4b8693c..7406498 100644 --- a/lldpd/Cargo.toml +++ b/lldpd/Cargo.toml @@ -17,6 +17,7 @@ http.workspace = true lldpd-api.workspace = true lldpd-common.workspace = true lldpd-types.workspace = true +omicron-common.workspace = true protocol.workspace = true signal-hook.workspace = true serde.workspace = true diff --git a/lldpd/src/api_server.rs b/lldpd/src/api_server.rs index cdc4518..f0c3d13 100644 --- a/lldpd/src/api_server.rs +++ b/lldpd/src/api_server.rs @@ -12,6 +12,7 @@ use std::net::Ipv4Addr; use std::net::SocketAddr; use std::sync::Arc; +use dropshot::ClientSpecifiesVersionInHeader; use dropshot::EmptyScanParams; use dropshot::HttpError; use dropshot::HttpResponseCreated; @@ -24,6 +25,7 @@ use dropshot::Query; use dropshot::RequestContext; use dropshot::ResultsPage; use dropshot::TypedBody; +use dropshot::VersionPolicy; use dropshot::WhichPage; use lldpd_api::*; use lldpd_types::build_info::BuildInfo; @@ -573,17 +575,22 @@ fn launch_server( default_handler_task_mode: dropshot::HandlerTaskMode::Detached, log_headers: Vec::new(), }; - let log = global - .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, + dropshot::ServerBuilder::new( http_api(), global.clone(), - &log, + global + .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, + lldpd_api::latest_version(), + ), + ))) + .build_starter() .map(|s| s.start()) .map_err(|e| anyhow::anyhow!(e.to_string())) } diff --git a/openapi/lldpd.json b/openapi/lldpd/lldpd-1.0.0-c4e95f.json similarity index 99% rename from openapi/lldpd.json rename to openapi/lldpd/lldpd-1.0.0-c4e95f.json index 22f74c1..19ce75e 100644 --- a/openapi/lldpd.json +++ b/openapi/lldpd/lldpd-1.0.0-c4e95f.json @@ -7,7 +7,7 @@ "url": "https://oxide.computer", "email": "api@oxide.computer" }, - "version": "0.0.1" + "version": "1.0.0" }, "paths": { "/build-info": { diff --git a/openapi/lldpd/lldpd-latest.json b/openapi/lldpd/lldpd-latest.json new file mode 120000 index 0000000..8dd1c55 --- /dev/null +++ b/openapi/lldpd/lldpd-latest.json @@ -0,0 +1 @@ +lldpd-1.0.0-c4e95f.json \ No newline at end of file