Skip to content

Commit b129a0e

Browse files
[nexus] Clean up API versioning: chain conversions, fix module docs
This PR refactors a set of versioned type conversions to properly follow the [API versioning guide's](https://github.com/oxidecomputer/dropshot-api-manager/blob/main/guides/new-version.md) recommendations, including chaining through consecutive versions, ordering conventions, and aligning types to correctly match the ranges and where they should be defined. Changes: - Chain InstanceCreate conversions: v2025122300 → v2026010300 → v2026010500 → params - Update endpoint handlers to delegate through the version chain - Add per-section validity docs for modules where types have different supersession versions - Remove empty v2026011501.rs after types moved to v2026010500
1 parent 1121324 commit b129a0e

File tree

9 files changed

+638
-553
lines changed

9 files changed

+638
-553
lines changed

nexus/external-api/src/lib.rs

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ mod v2025122300;
4141
mod v2026010100;
4242
mod v2026010300;
4343
mod v2026010500;
44-
mod v2026011501;
4544

4645
#[cfg(test)]
4746
mod test_utils;
@@ -1610,8 +1609,8 @@ pub trait NexusExternalApi {
16101609
floating_params: TypedBody<v2026010300::FloatingIpCreate>,
16111610
) -> Result<HttpResponseCreated<views::FloatingIp>, HttpError> {
16121611
let floating_params =
1613-
floating_params.try_map(v2026011501::FloatingIpCreate::try_from)?;
1614-
Self::v2026011501_floating_ip_create(
1612+
floating_params.try_map(v2026010500::FloatingIpCreate::try_from)?;
1613+
Self::v2026010500_floating_ip_create(
16151614
rqctx,
16161615
query_params,
16171616
floating_params,
@@ -1627,10 +1626,10 @@ pub trait NexusExternalApi {
16271626
tags = ["floating-ips"],
16281627
versions = VERSION_POOL_SELECTION_ENUMS..VERSION_RENAME_ADDRESS_SELECTOR_TO_ADDRESS_ALLOCATOR,
16291628
}]
1630-
async fn v2026011501_floating_ip_create(
1629+
async fn v2026010500_floating_ip_create(
16311630
rqctx: RequestContext<Self::Context>,
16321631
query_params: Query<params::ProjectSelector>,
1633-
floating_params: TypedBody<v2026011501::FloatingIpCreate>,
1632+
floating_params: TypedBody<v2026010500::FloatingIpCreate>,
16341633
) -> Result<HttpResponseCreated<views::FloatingIp>, HttpError> {
16351634
Self::floating_ip_create(
16361635
rqctx,
@@ -2161,44 +2160,32 @@ pub trait NexusExternalApi {
21612160

21622161
/// Create instance
21632162
#[endpoint {
2164-
operation_id = "disk_create",
21652163
method = POST,
21662164
path = "/v1/instances",
21672165
tags = ["instances"],
2168-
versions = ..VERSION_LOCAL_STORAGE,
2166+
versions = VERSION_MULTICAST_IMPLICIT_LIFECYCLE_UPDATES..,
21692167
}]
2170-
async fn v2025112000_instance_create(
2168+
async fn instance_create(
21712169
rqctx: RequestContext<Self::Context>,
21722170
query_params: Query<params::ProjectSelector>,
2173-
new_instance: TypedBody<v2025112000::InstanceCreate>,
2174-
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2175-
Self::v2025121200_instance_create(
2176-
rqctx,
2177-
query_params,
2178-
new_instance.map(Into::into),
2179-
)
2180-
.await
2181-
}
2171+
new_instance: TypedBody<params::InstanceCreate>,
2172+
) -> Result<HttpResponseCreated<Instance>, HttpError>;
21822173

21832174
/// Create instance
21842175
#[endpoint {
21852176
operation_id = "instance_create",
21862177
method = POST,
21872178
path = "/v1/instances",
21882179
tags = ["instances"],
2189-
versions = VERSION_LOCAL_STORAGE..VERSION_IP_VERSION_AND_MULTIPLE_DEFAULT_POOLS,
2180+
versions = VERSION_POOL_SELECTION_ENUMS..VERSION_MULTICAST_IMPLICIT_LIFECYCLE_UPDATES,
21902181
}]
2191-
async fn v2025121200_instance_create(
2182+
async fn v2026010500_instance_create(
21922183
rqctx: RequestContext<Self::Context>,
21932184
query_params: Query<params::ProjectSelector>,
2194-
new_instance: TypedBody<v2025121200::InstanceCreate>,
2185+
new_instance: TypedBody<v2026010500::InstanceCreate>,
21952186
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2196-
Self::v2026010100_instance_create(
2197-
rqctx,
2198-
query_params,
2199-
new_instance.map(Into::into),
2200-
)
2201-
.await
2187+
Self::instance_create(rqctx, query_params, new_instance.map(Into::into))
2188+
.await
22022189
}
22032190

22042191
/// Create instance
@@ -2207,16 +2194,19 @@ pub trait NexusExternalApi {
22072194
method = POST,
22082195
path = "/v1/instances",
22092196
tags = ["instances"],
2210-
versions =
2211-
VERSION_IP_VERSION_AND_MULTIPLE_DEFAULT_POOLS..VERSION_DUAL_STACK_NICS,
2197+
versions = VERSION_DUAL_STACK_NICS..VERSION_POOL_SELECTION_ENUMS,
22122198
}]
2213-
async fn v2026010100_instance_create(
2199+
async fn v2026010300_instance_create(
22142200
rqctx: RequestContext<Self::Context>,
22152201
query_params: Query<params::ProjectSelector>,
2216-
new_instance: TypedBody<v2026010100::InstanceCreate>,
2202+
new_instance: TypedBody<v2026010300::InstanceCreate>,
22172203
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2218-
let new_instance = new_instance.try_map(TryInto::try_into)?;
2219-
Self::instance_create(rqctx, query_params, new_instance).await
2204+
Self::v2026010500_instance_create(
2205+
rqctx,
2206+
query_params,
2207+
new_instance.try_map(TryInto::try_into)?,
2208+
)
2209+
.await
22202210
}
22212211

22222212
/// Create instance
@@ -2225,15 +2215,20 @@ pub trait NexusExternalApi {
22252215
method = POST,
22262216
path = "/v1/instances",
22272217
tags = ["instances"],
2228-
versions = VERSION_DUAL_STACK_NICS..VERSION_POOL_SELECTION_ENUMS,
2218+
versions =
2219+
VERSION_IP_VERSION_AND_MULTIPLE_DEFAULT_POOLS..VERSION_DUAL_STACK_NICS,
22292220
}]
2230-
async fn v2026010300_instance_create(
2221+
async fn v2025122300_instance_create(
22312222
rqctx: RequestContext<Self::Context>,
22322223
query_params: Query<params::ProjectSelector>,
2233-
new_instance: TypedBody<v2026010300::InstanceCreate>,
2224+
new_instance: TypedBody<v2025122300::InstanceCreate>,
22342225
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2235-
let new_instance = new_instance.try_map(TryInto::try_into)?;
2236-
Self::instance_create(rqctx, query_params, new_instance).await
2226+
Self::v2026010300_instance_create(
2227+
rqctx,
2228+
query_params,
2229+
new_instance.try_map(TryInto::try_into)?,
2230+
)
2231+
.await
22372232
}
22382233

22392234
/// Create instance
@@ -2242,29 +2237,41 @@ pub trait NexusExternalApi {
22422237
method = POST,
22432238
path = "/v1/instances",
22442239
tags = ["instances"],
2245-
versions = VERSION_POOL_SELECTION_ENUMS..VERSION_MULTICAST_IMPLICIT_LIFECYCLE_UPDATES,
2240+
versions = VERSION_LOCAL_STORAGE..VERSION_IP_VERSION_AND_MULTIPLE_DEFAULT_POOLS,
22462241
}]
2247-
async fn v2026010500_instance_create(
2242+
async fn v2025120300_instance_create(
22482243
rqctx: RequestContext<Self::Context>,
22492244
query_params: Query<params::ProjectSelector>,
2250-
new_instance: TypedBody<v2026010500::InstanceCreate>,
2245+
new_instance: TypedBody<v2025120300::InstanceCreate>,
22512246
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2252-
Self::instance_create(rqctx, query_params, new_instance.map(Into::into))
2253-
.await
2247+
Self::v2025122300_instance_create(
2248+
rqctx,
2249+
query_params,
2250+
new_instance.map(Into::into),
2251+
)
2252+
.await
22542253
}
22552254

22562255
/// Create instance
22572256
#[endpoint {
2257+
operation_id = "instance_create",
22582258
method = POST,
22592259
path = "/v1/instances",
22602260
tags = ["instances"],
2261-
versions = VERSION_MULTICAST_IMPLICIT_LIFECYCLE_UPDATES..,
2261+
versions = ..VERSION_LOCAL_STORAGE,
22622262
}]
2263-
async fn instance_create(
2263+
async fn v2025112000_instance_create(
22642264
rqctx: RequestContext<Self::Context>,
22652265
query_params: Query<params::ProjectSelector>,
2266-
new_instance: TypedBody<params::InstanceCreate>,
2267-
) -> Result<HttpResponseCreated<Instance>, HttpError>;
2266+
new_instance: TypedBody<v2025112000::InstanceCreate>,
2267+
) -> Result<HttpResponseCreated<Instance>, HttpError> {
2268+
Self::v2025120300_instance_create(
2269+
rqctx,
2270+
query_params,
2271+
new_instance.map(Into::into),
2272+
)
2273+
.await
2274+
}
22682275

22692276
/// Fetch instance
22702277
#[endpoint {

nexus/external-api/src/v2025112000.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
//! Nexus external types that changed from 2025112000 to 2025120300
5+
//! Nexus external types that changed from 2025112000 (INITIAL) to 2025120300
6+
//! (LOCAL_STORAGE).
67
7-
use crate::v2025121200;
8+
use crate::v2025120300;
89
use crate::v2026010100;
910
use nexus_types::external_api::params;
1011
use omicron_common::api::external;
@@ -220,9 +221,9 @@ pub struct InstanceCreate {
220221
/// By default, all instances have outbound connectivity, but no inbound
221222
/// connectivity. These external addresses can be used to provide a fixed,
222223
/// known IP address for making inbound connections to the instance.
223-
// Delegates through v2025121200 → params::ExternalIpCreate
224+
// Delegates through v2025120300 → params::ExternalIpCreate
224225
#[serde(default)]
225-
pub external_ips: Vec<v2025121200::ExternalIpCreate>,
226+
pub external_ips: Vec<v2025120300::ExternalIpCreate>,
226227

227228
/// The multicast groups this instance should join.
228229
///
@@ -302,9 +303,9 @@ pub struct InstanceCreate {
302303
pub cpu_platform: Option<external::InstanceCpuPlatform>,
303304
}
304305

305-
impl From<InstanceCreate> for v2025121200::InstanceCreate {
306-
fn from(old: InstanceCreate) -> v2025121200::InstanceCreate {
307-
v2025121200::InstanceCreate {
306+
impl From<InstanceCreate> for v2025120300::InstanceCreate {
307+
fn from(old: InstanceCreate) -> v2025120300::InstanceCreate {
308+
v2025120300::InstanceCreate {
308309
identity: old.identity,
309310
ncpus: old.ncpus,
310311
memory: old.memory,

0 commit comments

Comments
 (0)