From 58a88865a603318ca17227ea3069eb6080d66a5f Mon Sep 17 00:00:00 2001 From: John Gallagher Date: Mon, 13 Jan 2025 08:27:45 -0500 Subject: [PATCH] Use strongly-typed BlueprintUuid (#7328) A few yaks deep, I found myself wanting to do some diesel stuff that applied to blueprint IDs, but then realized we were still modeling them as plain `Uuid`. This converts most of them to `BlueprintUuid` (while leaving the Nexus external API untouched, which does affect a few Nexus internal endpoints too, hence the occasional `.as_untyped_uuid()` that shows up in this PR). --- Cargo.lock | 2 + clients/nexus-client/src/lib.rs | 1 + dev-tools/omdb/src/bin/omdb/nexus.rs | 45 +++--- dev-tools/reconfigurator-cli/src/main.rs | 20 +-- .../reconfigurator-cli/tests/test_basic.rs | 3 +- end-to-end-tests/Cargo.toml | 1 + end-to-end-tests/src/noop_blueprint.rs | 3 +- live-tests/Cargo.toml | 1 + live-tests/tests/common/reconfigurator.rs | 3 +- nexus/db-model/src/deployment.rs | 98 ++++++------ nexus/db-queries/src/db/datastore/dataset.rs | 7 +- .../db-queries/src/db/datastore/deployment.rs | 142 ++++++++++-------- nexus/db-queries/src/db/datastore/rack.rs | 12 +- .../src/db/datastore/support_bundle.rs | 14 +- nexus/db-queries/src/db/datastore/vpc.rs | 5 +- .../reconfigurator/execution/src/datasets.rs | 22 ++- nexus/reconfigurator/execution/src/dns.rs | 4 +- nexus/reconfigurator/execution/src/lib.rs | 4 +- .../execution/src/omicron_physical_disks.rs | 3 +- .../execution/src/omicron_zones.rs | 3 +- .../blueprint_editor/sled_editor/datasets.rs | 8 +- .../planning/src/planner/rng.rs | 9 +- nexus/reconfigurator/preparation/src/lib.rs | 7 +- nexus/reconfigurator/simulation/src/errors.rs | 8 +- nexus/reconfigurator/simulation/src/system.rs | 21 ++- .../background/tasks/blueprint_execution.rs | 3 +- .../app/background/tasks/blueprint_load.rs | 8 +- nexus/src/internal_api/http_entrypoints.rs | 4 +- nexus/test-utils/src/lib.rs | 7 +- nexus/types/src/deployment.rs | 14 +- openapi/nexus-internal.json | 42 ++++-- sled-agent/src/rack_setup/service.rs | 4 +- 32 files changed, 299 insertions(+), 229 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40bd736257..b1eafb53fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2892,6 +2892,7 @@ dependencies = [ "nexus-client", "omicron-sled-agent", "omicron-test-utils", + "omicron-uuid-kinds", "omicron-workspace-hack", "oxide-client", "rand", @@ -6926,6 +6927,7 @@ dependencies = [ "omicron-common", "omicron-rpaths", "omicron-test-utils", + "omicron-uuid-kinds", "omicron-workspace-hack", "pq-sys", "reqwest", diff --git a/clients/nexus-client/src/lib.rs b/clients/nexus-client/src/lib.rs index 777f351056..af0a86cd8f 100644 --- a/clients/nexus-client/src/lib.rs +++ b/clients/nexus-client/src/lib.rs @@ -50,6 +50,7 @@ progenitor::generate_api!( OmicronPhysicalDisksConfig = omicron_common::disk::OmicronPhysicalDisksConfig, RecoverySiloConfig = nexus_sled_agent_shared::recovery_silo::RecoverySiloConfig, Srv = nexus_types::internal_api::params::Srv, + TypedUuidForBlueprintKind = omicron_uuid_kinds::BlueprintUuid, TypedUuidForCollectionKind = omicron_uuid_kinds::CollectionUuid, TypedUuidForDatasetKind = omicron_uuid_kinds::TypedUuid, TypedUuidForDemoSagaKind = omicron_uuid_kinds::DemoSagaUuid, diff --git a/dev-tools/omdb/src/bin/omdb/nexus.rs b/dev-tools/omdb/src/bin/omdb/nexus.rs index eb7d74b340..6382c9f0c8 100644 --- a/dev-tools/omdb/src/bin/omdb/nexus.rs +++ b/dev-tools/omdb/src/bin/omdb/nexus.rs @@ -52,9 +52,11 @@ use nexus_types::internal_api::background::RegionSnapshotReplacementGarbageColle use nexus_types::internal_api::background::RegionSnapshotReplacementStartStatus; use nexus_types::internal_api::background::RegionSnapshotReplacementStepStatus; use nexus_types::inventory::BaseboardId; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::CollectionUuid; use omicron_uuid_kinds::DemoSagaUuid; use omicron_uuid_kinds::GenericUuid; +use omicron_uuid_kinds::ParseError; use omicron_uuid_kinds::PhysicalDiskUuid; use omicron_uuid_kinds::SledUuid; use reedline::DefaultPrompt; @@ -186,11 +188,11 @@ enum BlueprintsCommands { #[derive(Debug, Clone, Copy)] enum BlueprintIdOrCurrentTarget { CurrentTarget, - BlueprintId(Uuid), + BlueprintId(BlueprintUuid), } impl FromStr for BlueprintIdOrCurrentTarget { - type Err = uuid::Error; + type Err = ParseError; fn from_str(s: &str) -> Result { if matches!(s, "current-target" | "current" | "target") { @@ -206,7 +208,7 @@ impl BlueprintIdOrCurrentTarget { async fn resolve_to_id( &self, client: &nexus_client::Client, - ) -> anyhow::Result { + ) -> anyhow::Result { match self { Self::CurrentTarget => { let target = client @@ -224,15 +226,18 @@ impl BlueprintIdOrCurrentTarget { client: &nexus_client::Client, ) -> anyhow::Result { let id = self.resolve_to_id(client).await?; - let response = client.blueprint_view(&id).await.with_context(|| { - let suffix = match self { - BlueprintIdOrCurrentTarget::CurrentTarget => { - " (current target)" - } - BlueprintIdOrCurrentTarget::BlueprintId(_) => "", - }; - format!("fetching blueprint {id}{suffix}") - })?; + let response = client + .blueprint_view(id.as_untyped_uuid()) + .await + .with_context(|| { + let suffix = match self { + BlueprintIdOrCurrentTarget::CurrentTarget => { + " (current target)" + } + BlueprintIdOrCurrentTarget::BlueprintId(_) => "", + }; + format!("fetching blueprint {id}{suffix}") + })?; Ok(response.into_inner()) } } @@ -282,7 +287,7 @@ enum BlueprintTargetCommands { #[derive(Debug, Args)] struct BlueprintTargetSetArgs { /// id of blueprint to make target - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, /// whether this blueprint should be enabled enabled: BlueprintTargetSetEnabled, /// if specified, diff against the current target and wait for confirmation @@ -2311,7 +2316,7 @@ async fn cmd_nexus_blueprints_delete( ) -> Result<(), anyhow::Error> { let blueprint_id = args.blueprint_id.resolve_to_id(client).await?; let _ = client - .blueprint_delete(&blueprint_id) + .blueprint_delete(blueprint_id.as_untyped_uuid()) .await .with_context(|| format!("deleting blueprint {blueprint_id}"))?; println!("blueprint {blueprint_id} deleted"); @@ -2350,14 +2355,16 @@ async fn cmd_nexus_blueprints_target_set( if args.diff { let current_target = get_current_target().await?; let blueprint1 = client - .blueprint_view(¤t_target.target_id) + .blueprint_view(current_target.target_id.as_untyped_uuid()) .await .context("failed to fetch target blueprint")? .into_inner(); - let blueprint2 = - client.blueprint_view(&args.blueprint_id).await.with_context( - || format!("fetching blueprint {}", args.blueprint_id), - )?; + let blueprint2 = client + .blueprint_view(args.blueprint_id.as_untyped_uuid()) + .await + .with_context(|| { + format!("fetching blueprint {}", args.blueprint_id) + })?; let diff = blueprint2.diff_since_blueprint(&blueprint1); println!("{}", diff.display()); println!( diff --git a/dev-tools/reconfigurator-cli/src/main.rs b/dev-tools/reconfigurator-cli/src/main.rs index f1ce603965..2fd53f09a8 100644 --- a/dev-tools/reconfigurator-cli/src/main.rs +++ b/dev-tools/reconfigurator-cli/src/main.rs @@ -33,6 +33,7 @@ use nexus_types::deployment::{Blueprint, UnstableReconfiguratorState}; use omicron_common::api::external::Generation; use omicron_common::api::external::Name; use omicron_common::policy::NEXUS_REDUNDANCY; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::CollectionUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::OmicronZoneUuid; @@ -47,7 +48,6 @@ use std::io::BufRead; use std::io::IsTerminal; use swrite::{swriteln, SWrite}; use tabled::Tabled; -use uuid::Uuid; mod log_capture; @@ -403,7 +403,7 @@ struct InventoryArgs { #[derive(Debug, Args)] struct BlueprintPlanArgs { /// id of the blueprint on which this one will be based - parent_blueprint_id: Uuid, + parent_blueprint_id: BlueprintUuid, /// id of the inventory collection to use in planning /// /// Must be provided unless there is only one collection in the loaded @@ -414,7 +414,7 @@ struct BlueprintPlanArgs { #[derive(Debug, Args)] struct BlueprintEditArgs { /// id of the blueprint to edit - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, /// "creator" field for the new blueprint #[arg(long)] creator: Option, @@ -441,7 +441,7 @@ enum BlueprintEditCommands { #[derive(Debug, Args)] struct BlueprintArgs { /// id of the blueprint - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, } #[derive(Debug, Args)] @@ -451,7 +451,7 @@ struct BlueprintDiffDnsArgs { /// DNS version to diff against dns_version: u32, /// id of the blueprint - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, } #[derive(Clone, Copy, Debug, ValueEnum)] @@ -465,13 +465,13 @@ struct BlueprintDiffInventoryArgs { /// id of the inventory collection collection_id: CollectionUuid, /// id of the blueprint - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, } #[derive(Debug, Args)] struct BlueprintSaveArgs { /// id of the blueprint - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, /// output file filename: Utf8PathBuf, } @@ -479,9 +479,9 @@ struct BlueprintSaveArgs { #[derive(Debug, Args)] struct BlueprintDiffArgs { /// id of the first blueprint - blueprint1_id: Uuid, + blueprint1_id: BlueprintUuid, /// id of the second blueprint - blueprint2_id: Uuid, + blueprint2_id: BlueprintUuid, } #[derive(Debug, Subcommand)] @@ -728,7 +728,7 @@ fn cmd_blueprint_list( #[derive(Tabled)] #[tabled(rename_all = "SCREAMING_SNAKE_CASE")] struct BlueprintRow { - id: Uuid, + id: BlueprintUuid, parent: Cow<'static, str>, time_created: String, } diff --git a/dev-tools/reconfigurator-cli/tests/test_basic.rs b/dev-tools/reconfigurator-cli/tests/test_basic.rs index 14573fa461..bab0115616 100644 --- a/dev-tools/reconfigurator-cli/tests/test_basic.rs +++ b/dev-tools/reconfigurator-cli/tests/test_basic.rs @@ -22,6 +22,7 @@ use omicron_test_utils::dev::test_cmds::path_to_executable; use omicron_test_utils::dev::test_cmds::run_command; use omicron_test_utils::dev::test_cmds::Redactor; use omicron_test_utils::dev::test_cmds::EXIT_SUCCESS; +use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::SledUuid; use slog::debug; use std::io::BufReader; @@ -270,7 +271,7 @@ async fn test_blueprint_edit(cptestctx: &ControlPlaneTestContext) { .expect("failed to import new blueprint"); let found_blueprint = nexus_client - .blueprint_view(&new_blueprint.id) + .blueprint_view(new_blueprint.id.as_untyped_uuid()) .await .expect("failed to find imported blueprint in Nexus") .into_inner(); diff --git a/end-to-end-tests/Cargo.toml b/end-to-end-tests/Cargo.toml index bbf5eb20f6..47f1fe6385 100644 --- a/end-to-end-tests/Cargo.toml +++ b/end-to-end-tests/Cargo.toml @@ -20,6 +20,7 @@ internal-dns-types.workspace = true nexus-client.workspace = true omicron-sled-agent.workspace = true omicron-test-utils.workspace = true +omicron-uuid-kinds.workspace = true oxide-client.workspace = true rand.workspace = true reqwest = { workspace = true, features = ["cookies"] } diff --git a/end-to-end-tests/src/noop_blueprint.rs b/end-to-end-tests/src/noop_blueprint.rs index 66fdf33772..a7d5693d52 100644 --- a/end-to-end-tests/src/noop_blueprint.rs +++ b/end-to-end-tests/src/noop_blueprint.rs @@ -8,6 +8,7 @@ use internal_dns_types::names::ServiceName; use nexus_client::Client as NexusClient; use omicron_test_utils::dev::poll::{wait_for_condition, CondCheckError}; use omicron_test_utils::dev::test_setup_log; +use omicron_uuid_kinds::GenericUuid; use slog::{debug, info}; use slog_error_chain::InlineErrorChain; use std::time::Duration; @@ -68,7 +69,7 @@ async fn new_blueprint_noop() { // Fetch its parent. let parent_blueprint = nexus_client - .blueprint_view(&parent_blueprint_id) + .blueprint_view(parent_blueprint_id.as_untyped_uuid()) .await .expect("failed to fetch parent blueprint") .into_inner(); diff --git a/live-tests/Cargo.toml b/live-tests/Cargo.toml index ac0b39a5a5..7961e3b87f 100644 --- a/live-tests/Cargo.toml +++ b/live-tests/Cargo.toml @@ -31,6 +31,7 @@ nexus-sled-agent-shared.workspace = true nexus-types.workspace = true omicron-common.workspace = true omicron-test-utils.workspace = true +omicron-uuid-kinds.workspace = true reqwest.workspace = true serde.workspace = true slog.workspace = true diff --git a/live-tests/tests/common/reconfigurator.rs b/live-tests/tests/common/reconfigurator.rs index ae060b5b4c..d2c1235f8a 100644 --- a/live-tests/tests/common/reconfigurator.rs +++ b/live-tests/tests/common/reconfigurator.rs @@ -9,6 +9,7 @@ use nexus_client::types::BlueprintTargetSet; use nexus_reconfigurator_planning::blueprint_builder::BlueprintBuilder; use nexus_types::deployment::{Blueprint, PlanningInput}; use nexus_types::inventory::Collection; +use omicron_uuid_kinds::GenericUuid; use slog::{debug, info}; /// Modify the system by editing the current target blueprint @@ -57,7 +58,7 @@ pub async fn blueprint_edit_current_target( // Fetch the actual blueprint. let blueprint1 = nexus - .blueprint_view(&target_blueprint.target_id) + .blueprint_view(target_blueprint.target_id.as_untyped_uuid()) .await .context("fetch current target blueprint")? .into_inner(); diff --git a/nexus/db-model/src/deployment.rs b/nexus/db-model/src/deployment.rs index a44b81e943..d140edcde1 100644 --- a/nexus/db-model/src/deployment.rs +++ b/nexus/db-model/src/deployment.rs @@ -47,9 +47,9 @@ use omicron_common::api::internal::shared::NetworkInterface; use omicron_common::disk::DiskIdentity; use omicron_common::zpool_name::ZpoolName; use omicron_uuid_kinds::{ - DatasetKind, ExternalIpKind, ExternalIpUuid, GenericUuid, OmicronZoneKind, - OmicronZoneUuid, PhysicalDiskKind, SledKind, SledUuid, ZpoolKind, - ZpoolUuid, + BlueprintKind, BlueprintUuid, DatasetKind, ExternalIpKind, ExternalIpUuid, + GenericUuid, OmicronZoneKind, OmicronZoneUuid, PhysicalDiskKind, SledKind, + SledUuid, ZpoolKind, ZpoolUuid, }; use std::net::{IpAddr, SocketAddrV6}; use uuid::Uuid; @@ -58,8 +58,8 @@ use uuid::Uuid; #[derive(Queryable, Insertable, Clone, Debug, Selectable)] #[diesel(table_name = blueprint)] pub struct Blueprint { - pub id: Uuid, - pub parent_blueprint_id: Option, + pub id: DbTypedUuid, + pub parent_blueprint_id: Option>, pub internal_dns_version: Generation, pub external_dns_version: Generation, pub cockroachdb_fingerprint: String, @@ -72,8 +72,8 @@ pub struct Blueprint { impl From<&'_ nexus_types::deployment::Blueprint> for Blueprint { fn from(bp: &'_ nexus_types::deployment::Blueprint) -> Self { Self { - id: bp.id, - parent_blueprint_id: bp.parent_blueprint_id, + id: bp.id.into(), + parent_blueprint_id: bp.parent_blueprint_id.map(From::from), internal_dns_version: Generation(bp.internal_dns_version), external_dns_version: Generation(bp.external_dns_version), cockroachdb_fingerprint: bp.cockroachdb_fingerprint.clone(), @@ -90,8 +90,8 @@ impl From<&'_ nexus_types::deployment::Blueprint> for Blueprint { impl From for nexus_types::deployment::BlueprintMetadata { fn from(value: Blueprint) -> Self { Self { - id: value.id, - parent_blueprint_id: value.parent_blueprint_id, + id: value.id.into(), + parent_blueprint_id: value.parent_blueprint_id.map(From::from), internal_dns_version: *value.internal_dns_version, external_dns_version: *value.external_dns_version, cockroachdb_fingerprint: value.cockroachdb_fingerprint, @@ -112,7 +112,7 @@ impl From for nexus_types::deployment::BlueprintMetadata { #[diesel(table_name = bp_target)] pub struct BpTarget { pub version: SqlU32, - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub enabled: bool, pub time_made_target: DateTime, } @@ -121,7 +121,7 @@ impl BpTarget { pub fn new(version: u32, target: BlueprintTarget) -> Self { Self { version: version.into(), - blueprint_id: target.target_id, + blueprint_id: target.target_id.into(), enabled: target.enabled, time_made_target: target.time_made_target, } @@ -131,7 +131,7 @@ impl BpTarget { impl From for nexus_types::deployment::BlueprintTarget { fn from(value: BpTarget) -> Self { Self { - target_id: value.blueprint_id, + target_id: value.blueprint_id.into(), enabled: value.enabled, time_made_target: value.time_made_target, } @@ -142,7 +142,7 @@ impl From for nexus_types::deployment::BlueprintTarget { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_sled_state)] pub struct BpSledState { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub sled_id: DbTypedUuid, pub sled_state: SledState, } @@ -199,20 +199,20 @@ impl From for BlueprintPhysicalDiskDisposition { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_sled_omicron_physical_disks)] pub struct BpSledOmicronPhysicalDisks { - pub blueprint_id: Uuid, - pub sled_id: Uuid, + pub blueprint_id: DbTypedUuid, + pub sled_id: DbTypedUuid, pub generation: Generation, } impl BpSledOmicronPhysicalDisks { pub fn new( - blueprint_id: Uuid, - sled_id: Uuid, + blueprint_id: BlueprintUuid, + sled_id: SledUuid, disks_config: &BlueprintPhysicalDisksConfig, ) -> Self { Self { - blueprint_id, - sled_id, + blueprint_id: blueprint_id.into(), + sled_id: sled_id.into(), generation: Generation(disks_config.generation), } } @@ -222,8 +222,8 @@ impl BpSledOmicronPhysicalDisks { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_omicron_physical_disk)] pub struct BpOmicronPhysicalDisk { - pub blueprint_id: Uuid, - pub sled_id: Uuid, + pub blueprint_id: DbTypedUuid, + pub sled_id: DbTypedUuid, pub vendor: String, pub serial: String, @@ -237,13 +237,13 @@ pub struct BpOmicronPhysicalDisk { impl BpOmicronPhysicalDisk { pub fn new( - blueprint_id: Uuid, - sled_id: Uuid, + blueprint_id: BlueprintUuid, + sled_id: SledUuid, disk_config: &BlueprintPhysicalDiskConfig, ) -> Self { Self { - blueprint_id, - sled_id, + blueprint_id: blueprint_id.into(), + sled_id: sled_id.into(), vendor: disk_config.identity.vendor.clone(), serial: disk_config.identity.serial.clone(), model: disk_config.identity.model.clone(), @@ -322,19 +322,19 @@ impl From for BlueprintDatasetDisposition { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_sled_omicron_datasets)] pub struct BpSledOmicronDatasets { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub sled_id: DbTypedUuid, pub generation: Generation, } impl BpSledOmicronDatasets { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, sled_id: SledUuid, datasets_config: &BlueprintDatasetsConfig, ) -> Self { Self { - blueprint_id, + blueprint_id: blueprint_id.into(), sled_id: sled_id.into(), generation: Generation(datasets_config.generation), } @@ -345,7 +345,7 @@ impl BpSledOmicronDatasets { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_omicron_dataset)] pub struct BpOmicronDataset { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub sled_id: DbTypedUuid, pub id: DbTypedUuid, @@ -364,12 +364,12 @@ pub struct BpOmicronDataset { impl BpOmicronDataset { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, sled_id: SledUuid, dataset_config: &BlueprintDatasetConfig, ) -> Self { Self { - blueprint_id, + blueprint_id: blueprint_id.into(), sled_id: sled_id.into(), id: dataset_config.id.into(), disposition: to_db_bp_dataset_disposition( @@ -423,19 +423,19 @@ impl TryFrom for BlueprintDatasetConfig { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_sled_omicron_zones)] pub struct BpSledOmicronZones { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub sled_id: DbTypedUuid, pub generation: Generation, } impl BpSledOmicronZones { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, sled_id: SledUuid, zones_config: &BlueprintZonesConfig, ) -> Self { Self { - blueprint_id, + blueprint_id: blueprint_id.into(), sled_id: sled_id.into(), generation: Generation(zones_config.generation), } @@ -445,7 +445,7 @@ impl BpSledOmicronZones { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_omicron_zone)] pub struct BpOmicronZone { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub sled_id: DbTypedUuid, pub id: DbTypedUuid, pub zone_type: ZoneType, @@ -474,7 +474,7 @@ pub struct BpOmicronZone { impl BpOmicronZone { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, sled_id: SledUuid, blueprint_zone: &BlueprintZoneConfig, ) -> anyhow::Result { @@ -487,7 +487,7 @@ impl BpOmicronZone { let mut bp_omicron_zone = BpOmicronZone { // Fill in the known fields that don't require inspecting // `blueprint_zone.zone_type` - blueprint_id, + blueprint_id: blueprint_id.into(), sled_id: sled_id.into(), id: blueprint_zone.id.into(), external_ip_id, @@ -938,7 +938,7 @@ impl From for BlueprintZoneDisposition { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_omicron_zone_nic)] pub struct BpOmicronZoneNic { - blueprint_id: Uuid, + blueprint_id: DbTypedUuid, pub id: Uuid, name: Name, ip: IpNetwork, @@ -951,7 +951,7 @@ pub struct BpOmicronZoneNic { impl BpOmicronZoneNic { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, zone: &BlueprintZoneConfig, ) -> Result, anyhow::Error> { let Some((_, nic)) = zone.zone_type.external_networking() else { @@ -959,7 +959,7 @@ impl BpOmicronZoneNic { }; let nic = OmicronZoneNic::new(zone.id, nic)?; Ok(Some(Self { - blueprint_id, + blueprint_id: blueprint_id.into(), id: nic.id, name: nic.name, ip: nic.ip, @@ -998,7 +998,7 @@ impl From for OmicronZoneNic { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_clickhouse_cluster_config)] pub struct BpClickhouseClusterConfig { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub generation: Generation, pub max_used_server_id: i64, pub max_used_keeper_id: i64, @@ -1009,11 +1009,11 @@ pub struct BpClickhouseClusterConfig { impl BpClickhouseClusterConfig { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, config: &ClickhouseClusterConfig, ) -> anyhow::Result { Ok(BpClickhouseClusterConfig { - blueprint_id, + blueprint_id: blueprint_id.into(), generation: Generation(config.generation), max_used_server_id: config .max_used_server_id @@ -1040,19 +1040,19 @@ impl BpClickhouseClusterConfig { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_clickhouse_keeper_zone_id_to_node_id)] pub struct BpClickhouseKeeperZoneIdToNodeId { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub omicron_zone_id: DbTypedUuid, pub keeper_id: i64, } impl BpClickhouseKeeperZoneIdToNodeId { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, omicron_zone_id: OmicronZoneUuid, keeper_id: KeeperId, ) -> anyhow::Result { Ok(BpClickhouseKeeperZoneIdToNodeId { - blueprint_id, + blueprint_id: blueprint_id.into(), omicron_zone_id: omicron_zone_id.into(), keeper_id: keeper_id .0 @@ -1065,19 +1065,19 @@ impl BpClickhouseKeeperZoneIdToNodeId { #[derive(Queryable, Clone, Debug, Selectable, Insertable)] #[diesel(table_name = bp_clickhouse_server_zone_id_to_node_id)] pub struct BpClickhouseServerZoneIdToNodeId { - pub blueprint_id: Uuid, + pub blueprint_id: DbTypedUuid, pub omicron_zone_id: DbTypedUuid, pub server_id: i64, } impl BpClickhouseServerZoneIdToNodeId { pub fn new( - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, omicron_zone_id: OmicronZoneUuid, server_id: ServerId, ) -> anyhow::Result { Ok(BpClickhouseServerZoneIdToNodeId { - blueprint_id, + blueprint_id: blueprint_id.into(), omicron_zone_id: omicron_zone_id.into(), server_id: server_id .0 diff --git a/nexus/db-queries/src/db/datastore/dataset.rs b/nexus/db-queries/src/db/datastore/dataset.rs index 938927ff5e..b61dec3304 100644 --- a/nexus/db-queries/src/db/datastore/dataset.rs +++ b/nexus/db-queries/src/db/datastore/dataset.rs @@ -361,6 +361,7 @@ mod test { use nexus_reconfigurator_planning::blueprint_builder::BlueprintBuilder; use omicron_common::api::internal::shared::DatasetKind as ApiDatasetKind; use omicron_test_utils::dev; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::PhysicalDiskUuid; use omicron_uuid_kinds::SledUuid; @@ -553,14 +554,14 @@ mod test { let bp1 = { let mut bp1 = bp0.clone(); - bp1.id = Uuid::new_v4(); + bp1.id = BlueprintUuid::new_v4(); bp1.parent_blueprint_id = Some(bp0.id); bp1 }; bp_insert_and_make_target(&opctx, &datastore, &bp1).await; - let old_blueprint_id = BlueprintUuid::from_untyped_uuid(bp0.id); - let current_blueprint_id = BlueprintUuid::from_untyped_uuid(bp1.id); + let old_blueprint_id = bp0.id; + let current_blueprint_id = bp1.id; // Upsert referencing old blueprint: Error datastore diff --git a/nexus/db-queries/src/db/datastore/deployment.rs b/nexus/db-queries/src/db/datastore/deployment.rs index 573ba70780..20af6e4187 100644 --- a/nexus/db-queries/src/db/datastore/deployment.rs +++ b/nexus/db-queries/src/db/datastore/deployment.rs @@ -38,6 +38,7 @@ use diesel::OptionalExtension; use diesel::QueryDsl; use diesel::RunQueryDsl; use futures::FutureExt; +use nexus_db_model::to_db_typed_uuid; use nexus_db_model::Blueprint as DbBlueprint; use nexus_db_model::BpClickhouseClusterConfig; use nexus_db_model::BpClickhouseKeeperZoneIdToNodeId; @@ -151,13 +152,11 @@ impl DataStore { ) .await .map_err(|txn_error| txn_error.into_diesel(&err))?; - let bp_id_current = - BlueprintUuid::from_untyped_uuid(target.target_id); - if bp_id_current != bp_id { + if target.target_id != bp_id { return Err(err.bail( Error::invalid_request(format!( "blueprint target has changed from {} -> {}", - bp_id, bp_id_current + bp_id, target.target_id )) .into(), )); @@ -197,13 +196,13 @@ impl DataStore { // It's helpful to assemble some values before entering the transaction // so that we can produce the `Error` type that we want here. let row_blueprint = DbBlueprint::from(blueprint); - let blueprint_id = row_blueprint.id; + let blueprint_id = BlueprintUuid::from(row_blueprint.id); let sled_states = blueprint .sled_state .iter() .map(|(&sled_id, &state)| BpSledState { - blueprint_id, + blueprint_id: blueprint_id.into(), sled_id: sled_id.into(), sled_state: state.into(), }) @@ -215,7 +214,7 @@ impl DataStore { .map(|(sled_id, disks_config)| { BpSledOmicronPhysicalDisks::new( blueprint_id, - sled_id.into_untyped_uuid(), + *sled_id, disks_config, ) }) @@ -225,11 +224,7 @@ impl DataStore { .iter() .flat_map(|(sled_id, disks_config)| { disks_config.disks.iter().map(move |disk| { - BpOmicronPhysicalDisk::new( - blueprint_id, - sled_id.into_untyped_uuid(), - disk, - ) + BpOmicronPhysicalDisk::new(blueprint_id, *sled_id, disk) }) }) .collect::>(); @@ -471,7 +466,8 @@ impl DataStore { ) -> Result { opctx.authorize(authz::Action::Read, authz_blueprint).await?; let conn = self.pool_connection_authorized(opctx).await?; - let blueprint_id = authz_blueprint.id(); + let blueprint_id = + BlueprintUuid::from_untyped_uuid(authz_blueprint.id()); // Read the metadata from the primary blueprint row, and ensure that it // exists. @@ -488,7 +484,7 @@ impl DataStore { use db::schema::blueprint::dsl; let Some(blueprint) = dsl::blueprint - .filter(dsl::id.eq(blueprint_id)) + .filter(dsl::id.eq(to_db_typed_uuid(blueprint_id))) .select(DbBlueprint::as_select()) .get_result_async(&*conn) .await @@ -501,7 +497,7 @@ impl DataStore { }; ( - blueprint.parent_blueprint_id, + blueprint.parent_blueprint_id.map(From::from), *blueprint.internal_dns_version, *blueprint.external_dns_version, blueprint.cockroachdb_fingerprint, @@ -534,7 +530,7 @@ impl DataStore { dsl::sled_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpSledState::as_select()) .load_async(&*conn) .await @@ -572,7 +568,7 @@ impl DataStore { dsl::sled_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpSledOmicronZones::as_select()) .load_async(&*conn) .await @@ -616,7 +612,7 @@ impl DataStore { dsl::sled_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpSledOmicronPhysicalDisks::as_select()) .load_async(&*conn) .await @@ -628,7 +624,7 @@ impl DataStore { for s in batch { let old = blueprint_physical_disks.insert( - SledUuid::from_untyped_uuid(s.sled_id), + s.sled_id.into(), BlueprintPhysicalDisksConfig { generation: *s.generation, disks: Vec::new(), @@ -660,7 +656,7 @@ impl DataStore { dsl::sled_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpSledOmicronDatasets::as_select()) .load_async(&*conn) .await @@ -704,7 +700,7 @@ impl DataStore { dsl::id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpOmicronZoneNic::as_select()) .load_async(&*conn) .await @@ -741,7 +737,7 @@ impl DataStore { dsl::id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpOmicronZone::as_select()) .load_async(&*conn) .await @@ -818,7 +814,7 @@ impl DataStore { dsl::id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpOmicronPhysicalDisk::as_select()) .load_async(&*conn) .await @@ -830,7 +826,7 @@ impl DataStore { for d in batch { let sled_disks = blueprint_disks - .get_mut(&SledUuid::from_untyped_uuid(d.sled_id)) + .get_mut(&d.sled_id.into()) .ok_or_else(|| { // This error means that we found a row in // bp_omicron_physical_disk with no associated record in @@ -860,7 +856,7 @@ impl DataStore { dsl::id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpOmicronDataset::as_select()) .load_async(&*conn) .await @@ -909,7 +905,7 @@ impl DataStore { use db::schema::bp_clickhouse_cluster_config::dsl; let res = dsl::bp_clickhouse_cluster_config - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))) .select(BpClickhouseClusterConfig::as_select()) .get_result_async(&*conn) .await @@ -932,7 +928,10 @@ impl DataStore { dsl::omicron_zone_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter( + dsl::blueprint_id + .eq(to_db_typed_uuid(blueprint_id)), + ) .select( BpClickhouseKeeperZoneIdToNodeId::as_select(), ) @@ -979,7 +978,10 @@ impl DataStore { dsl::omicron_zone_id, &p.current_pagparams(), ) - .filter(dsl::blueprint_id.eq(blueprint_id)) + .filter( + dsl::blueprint_id + .eq(to_db_typed_uuid(blueprint_id)), + ) .select( BpClickhouseServerZoneIdToNodeId::as_select(), ) @@ -1079,7 +1081,8 @@ impl DataStore { authz_blueprint: &authz::Blueprint, ) -> Result<(), Error> { opctx.authorize(authz::Action::Delete, authz_blueprint).await?; - let blueprint_id = authz_blueprint.id(); + let blueprint_id = + BlueprintUuid::from_untyped_uuid(authz_blueprint.id()); // As with inserting a whole blueprint, we remove it in one big // transaction. Similar considerations apply. We could @@ -1126,7 +1129,7 @@ impl DataStore { let nblueprints = { use db::schema::blueprint::dsl; diesel::delete( - dsl::blueprint.filter(dsl::id.eq(blueprint_id)), + dsl::blueprint.filter(dsl::id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1146,7 +1149,7 @@ impl DataStore { use db::schema::bp_sled_state::dsl; diesel::delete( dsl::bp_sled_state - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1157,7 +1160,7 @@ impl DataStore { use db::schema::bp_sled_omicron_physical_disks::dsl; diesel::delete( dsl::bp_sled_omicron_physical_disks - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1166,7 +1169,7 @@ impl DataStore { use db::schema::bp_omicron_physical_disk::dsl; diesel::delete( dsl::bp_omicron_physical_disk - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1177,7 +1180,7 @@ impl DataStore { use db::schema::bp_sled_omicron_datasets::dsl; diesel::delete( dsl::bp_sled_omicron_datasets - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1186,7 +1189,7 @@ impl DataStore { use db::schema::bp_omicron_dataset::dsl; diesel::delete( dsl::bp_omicron_dataset - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1197,7 +1200,7 @@ impl DataStore { use db::schema::bp_sled_omicron_zones::dsl; diesel::delete( dsl::bp_sled_omicron_zones - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1207,7 +1210,7 @@ impl DataStore { use db::schema::bp_omicron_zone::dsl; diesel::delete( dsl::bp_omicron_zone - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1217,7 +1220,7 @@ impl DataStore { use db::schema::bp_omicron_zone_nic::dsl; diesel::delete( dsl::bp_omicron_zone_nic - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1227,7 +1230,7 @@ impl DataStore { use db::schema::bp_clickhouse_cluster_config::dsl; diesel::delete( dsl::bp_clickhouse_cluster_config - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1236,7 +1239,7 @@ impl DataStore { let nclickhouse_keepers = { use db::schema::bp_clickhouse_keeper_zone_id_to_node_id::dsl; diesel::delete(dsl::bp_clickhouse_keeper_zone_id_to_node_id - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1245,7 +1248,7 @@ impl DataStore { let nclickhouse_servers = { use db::schema::bp_clickhouse_server_zone_id_to_node_id::dsl; diesel::delete(dsl::bp_clickhouse_server_zone_id_to_node_id - .filter(dsl::blueprint_id.eq(blueprint_id)), + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(blueprint_id))), ) .execute_async(&conn) .await? @@ -1531,7 +1534,7 @@ impl DataStore { .limit(1), ), ) - .filter(dsl::blueprint_id.eq(target.target_id)) + .filter(dsl::blueprint_id.eq(to_db_typed_uuid(target.target_id))) .insert_into(dsl::bp_target); let conn = self.pool_connection_authorized(opctx).await?; @@ -1630,7 +1633,8 @@ impl DataStore { } // Helper to create an `authz::Blueprint` for a specific blueprint ID -fn authz_blueprint_from_id(blueprint_id: Uuid) -> authz::Blueprint { +fn authz_blueprint_from_id(blueprint_id: BlueprintUuid) -> authz::Blueprint { + let blueprint_id = blueprint_id.into_untyped_uuid(); authz::Blueprint::new( authz::FLEET, blueprint_id, @@ -1642,10 +1646,10 @@ fn authz_blueprint_from_id(blueprint_id: Uuid) -> authz::Blueprint { #[derive(Debug)] enum InsertTargetError { /// The requested target blueprint ID does not exist in the blueprint table. - NoSuchBlueprint(Uuid), + NoSuchBlueprint(BlueprintUuid), /// The requested target blueprint's parent does not match the current /// target. - ParentNotTarget(Uuid), + ParentNotTarget(BlueprintUuid), /// Any other error Other(DieselError), } @@ -1653,9 +1657,10 @@ enum InsertTargetError { impl From for Error { fn from(value: InsertTargetError) -> Self { match value { - InsertTargetError::NoSuchBlueprint(id) => { - Error::not_found_by_id(ResourceType::Blueprint, &id) - } + InsertTargetError::NoSuchBlueprint(id) => Error::not_found_by_id( + ResourceType::Blueprint, + id.as_untyped_uuid(), + ), InsertTargetError::ParentNotTarget(id) => { Error::invalid_request(format!( "Blueprint {id}'s parent blueprint is not the current \ @@ -1792,7 +1797,7 @@ impl From for Error { /// ``` #[derive(Debug, Clone, Copy)] struct InsertTargetQuery { - target_id: Uuid, + target_id: BlueprintUuid, enabled: bool, time_made_target: DateTime, } @@ -1878,7 +1883,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(" WHERE "); out.push_identifier(bp_dsl::id::NAME)?; out.push_sql(" = "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(") IS NULL, "); out.push_bind_param::( &NO_SUCH_BLUEPRINT_SENTINEL, @@ -1894,7 +1901,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(", current_target WHERE "); out.push_identifier(bp_dsl::id::NAME)?; out.push_sql(" = "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(" AND current_target.blueprint_id = "); out.push_identifier(bp_dsl::parent_blueprint_id::NAME)?; out.push_sql( @@ -1906,7 +1915,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(" WHERE "); out.push_identifier(bp_dsl::id::NAME)?; out.push_sql(" = "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(" AND "); out.push_identifier(bp_dsl::parent_blueprint_id::NAME)?; out.push_sql( @@ -1916,7 +1927,9 @@ impl QueryFragment for InsertTargetQuery { ) = 1, ", ); out.push_sql(" CAST("); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(" AS text), "); out.push_bind_param::( &PARENT_NOT_TARGET_SENTINEL, @@ -1933,7 +1946,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(" WHERE "); out.push_identifier(bp_dsl::id::NAME)?; out.push_sql(" = "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(" AND "); out.push_identifier(bp_dsl::parent_blueprint_id::NAME)?; out.push_sql( @@ -1948,7 +1963,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(" WHERE "); out.push_identifier(bp_dsl::id::NAME)?; out.push_sql(" = "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(" AND "); out.push_identifier(bp_dsl::parent_blueprint_id::NAME)?; out.push_sql(" IS NOT NULL AND "); @@ -1966,7 +1983,9 @@ impl QueryFragment for InsertTargetQuery { out.push_sql(","); out.push_identifier(dsl::time_made_target::NAME)?; out.push_sql(") SELECT new_target.new_version, "); - out.push_bind_param::(&self.target_id)?; + out.push_bind_param::( + self.target_id.as_untyped_uuid(), + )?; out.push_sql(","); out.push_bind_param::(&self.enabled)?; out.push_sql(","); @@ -2058,7 +2077,7 @@ mod tests { // this function will silently ignore them unless they're manually added. async fn ensure_blueprint_fully_deleted( datastore: &DataStore, - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, ) { let conn = datastore.pool_connection_for_tests().await.unwrap(); @@ -2066,7 +2085,10 @@ mod tests { ($table:ident, $blueprint_id_col:ident) => {{ use db::schema::$table::dsl; let result = dsl::$table - .filter(dsl::$blueprint_id_col.eq(blueprint_id)) + .filter( + dsl::$blueprint_id_col + .eq(to_db_typed_uuid(blueprint_id)), + ) .count() .get_result_async(&*conn) .await; @@ -2156,7 +2178,7 @@ mod tests { async fn blueprint_list_all_ids( opctx: &OpContext, datastore: &DataStore, - ) -> Vec { + ) -> Vec { datastore .blueprints_list(opctx, &DataPageParams::max_page()) .await @@ -2476,7 +2498,7 @@ mod tests { // Trying to insert a target that doesn't reference a blueprint should // fail with a relevant error message. - let nonexistent_blueprint_id = Uuid::new_v4(); + let nonexistent_blueprint_id = BlueprintUuid::new_v4(); let err = datastore .blueprint_target_set_current( &opctx, diff --git a/nexus/db-queries/src/db/datastore/rack.rs b/nexus/db-queries/src/db/datastore/rack.rs index fb59164a50..07b03e2e37 100644 --- a/nexus/db-queries/src/db/datastore/rack.rs +++ b/nexus/db-queries/src/db/datastore/rack.rs @@ -1038,7 +1038,7 @@ mod test { use omicron_common::api::internal::shared::SourceNatConfig; use omicron_common::zpool_name::ZpoolName; use omicron_test_utils::dev; - use omicron_uuid_kinds::{ExternalIpUuid, OmicronZoneUuid}; + use omicron_uuid_kinds::{BlueprintUuid, ExternalIpUuid, OmicronZoneUuid}; use omicron_uuid_kinds::{GenericUuid, ZpoolUuid}; use omicron_uuid_kinds::{SledUuid, TypedUuid}; use oxnet::IpNet; @@ -1054,7 +1054,7 @@ mod test { rack_id: Uuid::parse_str(nexus_test_utils::RACK_UUID).unwrap(), rack_subnet: nexus_test_utils::RACK_SUBNET.parse().unwrap(), blueprint: Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), blueprint_zones: BTreeMap::new(), blueprint_disks: BTreeMap::new(), blueprint_datasets: BTreeMap::new(), @@ -1540,7 +1540,7 @@ mod test { }, ); let blueprint = Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), sled_state: sled_states_active(blueprint_zones.keys().copied()), blueprint_zones, blueprint_disks: BTreeMap::new(), @@ -1801,7 +1801,7 @@ mod test { ); let blueprint = Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), sled_state: sled_states_active(blueprint_zones.keys().copied()), blueprint_zones, blueprint_disks: BTreeMap::new(), @@ -2013,7 +2013,7 @@ mod test { }, ); let blueprint = Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), sled_state: sled_states_active(blueprint_zones.keys().copied()), blueprint_zones, blueprint_disks: BTreeMap::new(), @@ -2156,7 +2156,7 @@ mod test { ); let blueprint = Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), sled_state: sled_states_active(blueprint_zones.keys().copied()), blueprint_zones, blueprint_disks: BTreeMap::new(), diff --git a/nexus/db-queries/src/db/datastore/support_bundle.rs b/nexus/db-queries/src/db/datastore/support_bundle.rs index 52f120d49a..17f578a528 100644 --- a/nexus/db-queries/src/db/datastore/support_bundle.rs +++ b/nexus/db-queries/src/db/datastore/support_bundle.rs @@ -27,7 +27,6 @@ use omicron_common::api::external::DataPageParams; use omicron_common::api::external::Error; use omicron_common::api::external::ListResultVec; use omicron_common::api::external::LookupResult; -use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::SupportBundleUuid; @@ -280,7 +279,7 @@ impl DataStore { &conn, "support_bundle_fail_expunged", opctx, - BlueprintUuid::from_untyped_uuid(blueprint.id), + blueprint.id, |conn| { let invalid_nexus_zones = invalid_nexus_zones.clone(); let valid_nexus_zones = valid_nexus_zones.clone(); @@ -483,6 +482,7 @@ mod test { use nexus_types::deployment::BlueprintZoneType; use omicron_common::api::internal::shared::DatasetKind::Debug as DebugDatasetKind; use omicron_test_utils::dev; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::PhysicalDiskUuid; use omicron_uuid_kinds::SledUuid; @@ -1035,7 +1035,7 @@ mod test { // Expunge the bundle's dataset (manually) let bp2 = { let mut bp2 = bp1.clone(); - bp2.id = Uuid::new_v4(); + bp2.id = BlueprintUuid::new_v4(); bp2.parent_blueprint_id = Some(bp1.id); expunge_dataset_for_bundle(&mut bp2, &bundle); bp2 @@ -1152,7 +1152,7 @@ mod test { // Expunge the bundle's dataset (manually) let bp2 = { let mut bp2 = bp1.clone(); - bp2.id = Uuid::new_v4(); + bp2.id = BlueprintUuid::new_v4(); bp2.parent_blueprint_id = Some(bp1.id); expunge_dataset_for_bundle(&mut bp2, &bundle); bp2 @@ -1241,7 +1241,7 @@ mod test { // is a prerequisite for the bundle not later being re-assigned. let bp2 = { let mut bp2 = bp1.clone(); - bp2.id = Uuid::new_v4(); + bp2.id = BlueprintUuid::new_v4(); bp2.parent_blueprint_id = Some(bp1.id); expunge_dataset_for_bundle(&mut bp2, &bundle); bp2 @@ -1273,7 +1273,7 @@ mod test { // Expunge the bundle's Nexus let bp3 = { let mut bp3 = bp2.clone(); - bp3.id = Uuid::new_v4(); + bp3.id = BlueprintUuid::new_v4(); bp3.parent_blueprint_id = Some(bp2.id); expunge_nexus_for_bundle(&mut bp3, &bundle); bp3 @@ -1375,7 +1375,7 @@ mod test { // Expunge the bundle's Nexus (manually) let bp2 = { let mut bp2 = bp1.clone(); - bp2.id = Uuid::new_v4(); + bp2.id = BlueprintUuid::new_v4(); bp2.parent_blueprint_id = Some(bp1.id); expunge_nexus_for_bundle(&mut bp2, &bundle); bp2 diff --git a/nexus/db-queries/src/db/datastore/vpc.rs b/nexus/db-queries/src/db/datastore/vpc.rs index 4691bede83..8ebda4fa21 100644 --- a/nexus/db-queries/src/db/datastore/vpc.rs +++ b/nexus/db-queries/src/db/datastore/vpc.rs @@ -2777,6 +2777,7 @@ mod tests { use omicron_common::api::external; use omicron_common::api::external::Generation; use omicron_test_utils::dev; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::InstanceUuid; use omicron_uuid_kinds::SledUuid; @@ -3162,7 +3163,7 @@ mod tests { // the target. let bp2 = { let mut bp2 = bp1.clone(); - bp2.id = Uuid::new_v4(); + bp2.id = BlueprintUuid::new_v4(); bp2.parent_blueprint_id = Some(bp1.id); let sled2_zones = bp2 .blueprint_zones @@ -3269,7 +3270,7 @@ mod tests { // (But other services are still running.) let bp4 = { let mut bp4 = bp3.clone(); - bp4.id = Uuid::new_v4(); + bp4.id = BlueprintUuid::new_v4(); bp4.parent_blueprint_id = Some(bp3.id); // Sled index 2's Nexus is quiesced (should be included). diff --git a/nexus/reconfigurator/execution/src/datasets.rs b/nexus/reconfigurator/execution/src/datasets.rs index b0aa7410f0..8ccae17d83 100644 --- a/nexus/reconfigurator/execution/src/datasets.rs +++ b/nexus/reconfigurator/execution/src/datasets.rs @@ -339,12 +339,11 @@ mod tests { let nzones_with_durable_datasets = all_datasets.len(); assert!(nzones_with_durable_datasets > 0); - let bp_id = BlueprintUuid::from_untyped_uuid(blueprint.id); let EnsureDatasetsResult { inserted, updated, removed } = ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -369,7 +368,7 @@ mod tests { ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -431,7 +430,7 @@ mod tests { ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter().chain(&new_zones), ) .await @@ -506,12 +505,11 @@ mod tests { .await; let mut all_datasets = get_all_datasets_from_zones(&blueprint); - let bp_id = BlueprintUuid::from_untyped_uuid(blueprint.id); let EnsureDatasetsResult { inserted, updated, removed } = ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -536,7 +534,7 @@ mod tests { ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -607,12 +605,11 @@ mod tests { reservation: None, compression: CompressionAlgorithm::Off, }); - let bp_id = BlueprintUuid::from_untyped_uuid(blueprint.id); let EnsureDatasetsResult { inserted, updated, removed } = ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -656,7 +653,7 @@ mod tests { ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -724,12 +721,11 @@ mod tests { compression: CompressionAlgorithm::Off, }); - let bp_id = BlueprintUuid::from_untyped_uuid(blueprint.id); let EnsureDatasetsResult { inserted, updated, removed } = ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await @@ -751,7 +747,7 @@ mod tests { ensure_dataset_records_exist( opctx, datastore, - bp_id, + blueprint.id, all_datasets.iter(), ) .await diff --git a/nexus/reconfigurator/execution/src/dns.rs b/nexus/reconfigurator/execution/src/dns.rs index 56e9348f21..7fab2fb052 100644 --- a/nexus/reconfigurator/execution/src/dns.rs +++ b/nexus/reconfigurator/execution/src/dns.rs @@ -364,6 +364,7 @@ mod test { use omicron_common::policy::OXIMETER_REDUNDANCY; use omicron_common::zpool_name::ZpoolName; use omicron_test_utils::dev::test_setup_log; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::ExternalIpUuid; use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::ZpoolUuid; @@ -375,7 +376,6 @@ mod test { use std::net::Ipv6Addr; use std::net::SocketAddrV6; use std::sync::Arc; - use uuid::Uuid; type ControlPlaneTestContext = nexus_test_utils::ControlPlaneTestContext; @@ -657,7 +657,7 @@ mod test { let dns_empty = dns_config_empty(); let initial_dns_generation = dns_empty.generation; let mut blueprint = Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), blueprint_zones, blueprint_disks: BTreeMap::new(), blueprint_datasets: BTreeMap::new(), diff --git a/nexus/reconfigurator/execution/src/lib.rs b/nexus/reconfigurator/execution/src/lib.rs index 543b9bd278..948a67dbf0 100644 --- a/nexus/reconfigurator/execution/src/lib.rs +++ b/nexus/reconfigurator/execution/src/lib.rs @@ -18,7 +18,6 @@ use nexus_types::deployment::SledFilter; use nexus_types::external_api::views::SledState; use nexus_types::identity::Asset; use omicron_physical_disks::DeployDisksDone; -use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::SledUuid; @@ -390,7 +389,6 @@ fn register_dataset_records_step<'a>( datastore: &'a DataStore, blueprint: &'a Blueprint, ) { - let bp_id = BlueprintUuid::from_untyped_uuid(blueprint.id); registrar .new_step( ExecutionStepId::Ensure, @@ -399,7 +397,7 @@ fn register_dataset_records_step<'a>( datasets::ensure_dataset_records_exist( &opctx, datastore, - bp_id, + blueprint.id, blueprint .all_omicron_datasets(BlueprintDatasetFilter::All) .map(|(_sled_id, dataset)| dataset), diff --git a/nexus/reconfigurator/execution/src/omicron_physical_disks.rs b/nexus/reconfigurator/execution/src/omicron_physical_disks.rs index 137e378410..eebb47a0cb 100644 --- a/nexus/reconfigurator/execution/src/omicron_physical_disks.rs +++ b/nexus/reconfigurator/execution/src/omicron_physical_disks.rs @@ -162,6 +162,7 @@ mod test { use omicron_common::disk::DiskManagementStatus; use omicron_common::disk::DisksManagementResult; use omicron_common::disk::OmicronPhysicalDisksConfig; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::PhysicalDiskUuid; @@ -178,7 +179,7 @@ mod test { fn create_blueprint( blueprint_disks: BTreeMap, ) -> (BlueprintTarget, Blueprint) { - let id = Uuid::new_v4(); + let id = BlueprintUuid::new_v4(); ( BlueprintTarget { target_id: id, diff --git a/nexus/reconfigurator/execution/src/omicron_zones.rs b/nexus/reconfigurator/execution/src/omicron_zones.rs index 98d8bed358..78ea40efbd 100644 --- a/nexus/reconfigurator/execution/src/omicron_zones.rs +++ b/nexus/reconfigurator/execution/src/omicron_zones.rs @@ -359,6 +359,7 @@ mod test { }; use omicron_common::api::external::Generation; use omicron_common::zpool_name::ZpoolName; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::SledUuid; use omicron_uuid_kinds::ZpoolUuid; @@ -372,7 +373,7 @@ mod test { fn create_blueprint( blueprint_zones: BTreeMap, ) -> (BlueprintTarget, Blueprint) { - let id = Uuid::new_v4(); + let id = BlueprintUuid::new_v4(); ( BlueprintTarget { target_id: id, diff --git a/nexus/reconfigurator/planning/src/blueprint_editor/sled_editor/datasets.rs b/nexus/reconfigurator/planning/src/blueprint_editor/sled_editor/datasets.rs index 6e60626bb9..7258f5b5d2 100644 --- a/nexus/reconfigurator/planning/src/blueprint_editor/sled_editor/datasets.rs +++ b/nexus/reconfigurator/planning/src/blueprint_editor/sled_editor/datasets.rs @@ -608,7 +608,9 @@ mod tests { // We need a sled ID to get a sled-specific RNG from `rng`; we're not // testing blueprints as a whole here, so steal a blueprint ID and use // it as a sled ID to get reproducibility. - let sled_id = SledUuid::from_untyped_uuid(rng.next_blueprint()); + let sled_id = SledUuid::from_untyped_uuid( + rng.next_blueprint().into_untyped_uuid(), + ); let rng = rng.sled_rng(sled_id); // For each originally-in-service dataset: @@ -705,7 +707,9 @@ mod tests { // We need a sled ID to get a sled-specific RNG from `rng`; we're not // testing blueprints as a whole here, so steal a blueprint ID and use // it as a sled ID to get reproducibility. - let sled_id = SledUuid::from_untyped_uuid(rng.next_blueprint()); + let sled_id = SledUuid::from_untyped_uuid( + rng.next_blueprint().into_untyped_uuid(), + ); let rng = rng.sled_rng(sled_id); // Expunge all datasets on all zpools, by zpool. diff --git a/nexus/reconfigurator/planning/src/planner/rng.rs b/nexus/reconfigurator/planning/src/planner/rng.rs index 474aae18c2..633b05e3aa 100644 --- a/nexus/reconfigurator/planning/src/planner/rng.rs +++ b/nexus/reconfigurator/planning/src/planner/rng.rs @@ -5,6 +5,8 @@ //! RNG for blueprint planning to allow reproducibility (particularly for //! tests). +use omicron_uuid_kinds::BlueprintKind; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::DatasetKind; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::ExternalIpKind; @@ -29,7 +31,7 @@ pub struct PlannerRng { // // In the future, when we switch to typed UUIDs, each of these will be // associated with a specific `TypedUuidKind`. - blueprint_rng: UuidRng, + blueprint_rng: TypedUuidRng, // Each sled gets its own set of RNGs to avoid test changes to one sled // (e.g., adding an extra zone) perturbing all subsequent zone/dataset/etc. // IDs on other sleds. @@ -50,7 +52,8 @@ impl PlannerRng { } pub fn new_from_parent(mut parent: StdRng) -> Self { - let blueprint_rng = UuidRng::from_parent_rng(&mut parent, "blueprint"); + let blueprint_rng = + TypedUuidRng::from_parent_rng(&mut parent, "blueprint"); let clickhouse_rng = UuidRng::from_parent_rng(&mut parent, "clickhouse"); @@ -68,7 +71,7 @@ impl PlannerRng { .or_insert_with(|| SledPlannerRng::new(sled_id, &mut self.parent)) } - pub fn next_blueprint(&mut self) -> Uuid { + pub fn next_blueprint(&mut self) -> BlueprintUuid { self.blueprint_rng.next() } diff --git a/nexus/reconfigurator/preparation/src/lib.rs b/nexus/reconfigurator/preparation/src/lib.rs index c3b66c6e0e..28a19af958 100644 --- a/nexus/reconfigurator/preparation/src/lib.rs +++ b/nexus/reconfigurator/preparation/src/lib.rs @@ -356,14 +356,15 @@ pub async fn reconfigurator_state_load( .blueprints_list(opctx, &p.current_pagparams()) .await .context("listing blueprints")?; - paginator = - p.found_batch(&blueprint_ids, &|b: &BlueprintMetadata| b.id); + paginator = p.found_batch(&blueprint_ids, &|b: &BlueprintMetadata| { + b.id.into_untyped_uuid() + }); blueprint_ids.extend(batch.into_iter()); } let blueprints = futures::stream::iter(blueprint_ids) .filter_map(|bpm| async move { - let blueprint_id = bpm.id; + let blueprint_id = bpm.id.into_untyped_uuid(); let read = datastore .blueprint_read( opctx, diff --git a/nexus/reconfigurator/simulation/src/errors.rs b/nexus/reconfigurator/simulation/src/errors.rs index 571bc90f43..9989f8883b 100644 --- a/nexus/reconfigurator/simulation/src/errors.rs +++ b/nexus/reconfigurator/simulation/src/errors.rs @@ -3,9 +3,9 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. use omicron_common::api::external::{Generation, Name}; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::CollectionUuid; use thiserror::Error; -use uuid::Uuid; /// The caller attempted to insert a duplicate key. #[derive(Clone, Debug, Error)] @@ -23,7 +23,7 @@ impl DuplicateError { Self { id: ObjectId::Collection(id) } } - pub(crate) fn blueprint(id: Uuid) -> Self { + pub(crate) fn blueprint(id: BlueprintUuid) -> Self { Self { id: ObjectId::Blueprint(id) } } @@ -43,7 +43,7 @@ impl DuplicateError { #[derive(Clone, Debug)] pub enum ObjectId { Collection(CollectionUuid), - Blueprint(Uuid), + Blueprint(BlueprintUuid), InternalDns(Generation), ExternalDns(Generation), SiloName(Name), @@ -87,7 +87,7 @@ impl KeyError { Self { id: ObjectId::Collection(id) } } - pub(crate) fn blueprint(id: Uuid) -> Self { + pub(crate) fn blueprint(id: BlueprintUuid) -> Self { Self { id: ObjectId::Blueprint(id) } } diff --git a/nexus/reconfigurator/simulation/src/system.rs b/nexus/reconfigurator/simulation/src/system.rs index ea25f8788d..32d06d7585 100644 --- a/nexus/reconfigurator/simulation/src/system.rs +++ b/nexus/reconfigurator/simulation/src/system.rs @@ -18,8 +18,7 @@ use nexus_types::{ inventory::Collection, }; use omicron_common::{address::IpRange, api::external::Generation}; -use omicron_uuid_kinds::{CollectionUuid, SledUuid}; -use uuid::Uuid; +use omicron_uuid_kinds::{BlueprintUuid, CollectionUuid, SledUuid}; use crate::{ errors::{DuplicateError, KeyError, NonEmptySystemError}, @@ -76,7 +75,7 @@ pub struct SimSystem { /// Blueprints created by the user. /// /// Stored with `Arc` to allow cheap cloning. - blueprints: IndexMap>, + blueprints: IndexMap>, /// Internal DNS configurations. /// @@ -129,7 +128,10 @@ impl SimSystem { self.collections.values().map(|c| &**c) } - pub fn get_blueprint(&self, id: Uuid) -> Result<&Blueprint, KeyError> { + pub fn get_blueprint( + &self, + id: BlueprintUuid, + ) -> Result<&Blueprint, KeyError> { match self.blueprints.get(&id) { Some(b) => Ok(&**b), None => Err(KeyError::blueprint(id)), @@ -226,7 +228,10 @@ impl SimSystemBuilder { } #[inline] - pub fn get_blueprint(&self, id: Uuid) -> Result<&Blueprint, KeyError> { + pub fn get_blueprint( + &self, + id: BlueprintUuid, + ) -> Result<&Blueprint, KeyError> { self.inner.system.get_blueprint(id) } @@ -384,13 +389,13 @@ impl SimSystemBuilder { pub enum SimSystemLogEntry { LoadExample { collection_id: CollectionUuid, - blueprint_id: Uuid, + blueprint_id: BlueprintUuid, internal_dns_version: Generation, external_dns_version: Generation, }, LoadSerialized(LoadSerializedSystemResult), AddCollection(CollectionUuid), - AddBlueprint(Uuid), + AddBlueprint(BlueprintUuid), AddInternalDns(Generation), AddExternalDns(Generation), Wipe, @@ -413,7 +418,7 @@ pub struct LoadSerializedSystemResult { pub collection_ids: Vec, /// The blueprint IDs successfully loaded. - pub blueprint_ids: Vec, + pub blueprint_ids: Vec, /// The service IP pool ranges. pub service_ip_pool_ranges: Vec, diff --git a/nexus/src/app/background/tasks/blueprint_execution.rs b/nexus/src/app/background/tasks/blueprint_execution.rs index db7192d6bf..d5d0fe160c 100644 --- a/nexus/src/app/background/tasks/blueprint_execution.rs +++ b/nexus/src/app/background/tasks/blueprint_execution.rs @@ -193,6 +193,7 @@ mod test { use nexus_types::external_api::views::SledState; use omicron_common::api::external::Generation; use omicron_common::zpool_name::ZpoolName; + use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::OmicronZoneUuid; use omicron_uuid_kinds::PhysicalDiskUuid; @@ -218,7 +219,7 @@ mod test { blueprint_datasets: BTreeMap, dns_version: Generation, ) -> (BlueprintTarget, Blueprint) { - let id = Uuid::new_v4(); + let id = BlueprintUuid::new_v4(); // Assume all sleds are active. let sled_state = blueprint_zones .keys() diff --git a/nexus/src/app/background/tasks/blueprint_load.rs b/nexus/src/app/background/tasks/blueprint_load.rs index 9ce1e89df4..d9342cc4ed 100644 --- a/nexus/src/app/background/tasks/blueprint_load.rs +++ b/nexus/src/app/background/tasks/blueprint_load.rs @@ -197,17 +197,17 @@ mod test { Blueprint, BlueprintTarget, CockroachDbPreserveDowngrade, }; use omicron_common::api::external::Generation; + use omicron_uuid_kinds::BlueprintUuid; use serde::Deserialize; use std::collections::BTreeMap; - use uuid::Uuid; type ControlPlaneTestContext = nexus_test_utils::ControlPlaneTestContext; fn create_blueprint( - parent_blueprint_id: Uuid, + parent_blueprint_id: BlueprintUuid, ) -> (BlueprintTarget, Blueprint) { - let id = Uuid::new_v4(); + let id = BlueprintUuid::new_v4(); ( BlueprintTarget { target_id: id, @@ -237,7 +237,7 @@ mod test { #[derive(Deserialize)] #[allow(unused)] struct TargetUpdate { - pub target_id: Uuid, + pub target_id: BlueprintUuid, pub time_created: chrono::DateTime, pub time_found: Option>, pub status: String, diff --git a/nexus/src/internal_api/http_entrypoints.rs b/nexus/src/internal_api/http_entrypoints.rs index 6fccb6868a..179608601d 100644 --- a/nexus/src/internal_api/http_entrypoints.rs +++ b/nexus/src/internal_api/http_entrypoints.rs @@ -701,7 +701,9 @@ impl NexusInternalApi for NexusInternalApiImpl { Ok(HttpResponseOk(ScanById::results_page( &query, blueprints, - &|_, blueprint: &BlueprintMetadata| blueprint.id, + &|_, blueprint: &BlueprintMetadata| { + blueprint.id.into_untyped_uuid() + }, )?)) }; diff --git a/nexus/test-utils/src/lib.rs b/nexus/test-utils/src/lib.rs index 4991d2eaf9..bb10bb404d 100644 --- a/nexus/test-utils/src/lib.rs +++ b/nexus/test-utils/src/lib.rs @@ -74,6 +74,7 @@ use omicron_common::zpool_name::ZpoolName; use omicron_sled_agent::sim; use omicron_test_utils::dev; use omicron_test_utils::dev::poll::{wait_for_condition, CondCheckError}; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::ExternalIpUuid; use omicron_uuid_kinds::GenericUuid; @@ -140,7 +141,7 @@ pub struct ControlPlaneTestContext { pub external_dns_zone_name: String, pub external_dns: dns_server::TransientServer, pub internal_dns: dns_server::TransientServer, - pub initial_blueprint_id: Uuid, + pub initial_blueprint_id: BlueprintUuid, pub silo_name: Name, pub user_name: UserId, } @@ -328,7 +329,7 @@ pub struct ControlPlaneTestContextBuilder<'a, N: NexusServer> { pub external_dns: Option, pub internal_dns: Option, dns_config: Option, - initial_blueprint_id: Option, + initial_blueprint_id: Option, blueprint_zones: Vec, blueprint_zones2: Vec, @@ -909,7 +910,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { } } Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), blueprint_zones, blueprint_disks, blueprint_datasets, diff --git a/nexus/types/src/deployment.rs b/nexus/types/src/deployment.rs index 33b8e102c5..7d1441177e 100644 --- a/nexus/types/src/deployment.rs +++ b/nexus/types/src/deployment.rs @@ -33,6 +33,7 @@ use omicron_common::disk::DiskIdentity; use omicron_common::disk::OmicronPhysicalDiskConfig; use omicron_common::disk::OmicronPhysicalDisksConfig; use omicron_common::disk::SharedDatasetConfig; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::CollectionUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::OmicronZoneUuid; @@ -49,7 +50,6 @@ use std::net::Ipv6Addr; use std::net::SocketAddrV6; use strum::EnumIter; use strum::IntoEnumIterator; -use uuid::Uuid; mod blueprint_diff; mod blueprint_display; @@ -143,7 +143,7 @@ pub use blueprint_diff::BlueprintDiff; )] pub struct Blueprint { /// unique identifier for this blueprint - pub id: Uuid, + pub id: BlueprintUuid, /// A map of sled id -> desired state of the sled. /// @@ -167,7 +167,7 @@ pub struct Blueprint { pub blueprint_datasets: BTreeMap, /// which blueprint this blueprint is based on - pub parent_blueprint_id: Option, + pub parent_blueprint_id: Option, /// internal DNS version when this blueprint was created // See blueprint execution for more on this. @@ -1077,10 +1077,10 @@ impl BlueprintDatasetConfig { #[derive(Debug, Clone, Eq, PartialEq, JsonSchema, Serialize)] pub struct BlueprintMetadata { /// unique identifier for this blueprint - pub id: Uuid, + pub id: BlueprintUuid, /// which blueprint this blueprint is based on - pub parent_blueprint_id: Option, + pub parent_blueprint_id: Option, /// internal DNS version when this blueprint was created pub internal_dns_version: Generation, /// external DNS version when this blueprint was created @@ -1112,7 +1112,7 @@ impl BlueprintMetadata { #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)] pub struct BlueprintTarget { /// id of the blueprint that the system is trying to make real - pub target_id: Uuid, + pub target_id: BlueprintUuid, /// policy: should the system actively work towards this blueprint /// /// This should generally be left enabled. @@ -1124,7 +1124,7 @@ pub struct BlueprintTarget { /// Specifies what blueprint, if any, the system should be working toward #[derive(Deserialize, JsonSchema)] pub struct BlueprintTargetSet { - pub target_id: Uuid, + pub target_id: BlueprintUuid, pub enabled: bool, } diff --git a/openapi/nexus-internal.json b/openapi/nexus-internal.json index 03350de8f8..f2ea560233 100644 --- a/openapi/nexus-internal.json +++ b/openapi/nexus-internal.json @@ -1967,8 +1967,11 @@ }, "id": { "description": "unique identifier for this blueprint", - "type": "string", - "format": "uuid" + "allOf": [ + { + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" + } + ] }, "internal_dns_version": { "description": "internal DNS version when this blueprint was created", @@ -1981,8 +1984,11 @@ "parent_blueprint_id": { "nullable": true, "description": "which blueprint this blueprint is based on", - "type": "string", - "format": "uuid" + "allOf": [ + { + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" + } + ] }, "sled_state": { "description": "A map of sled id -> desired state of the sled.\n\nA sled is considered part of the control plane cluster iff it has an entry in this map.", @@ -2133,8 +2139,11 @@ }, "id": { "description": "unique identifier for this blueprint", - "type": "string", - "format": "uuid" + "allOf": [ + { + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" + } + ] }, "internal_dns_version": { "description": "internal DNS version when this blueprint was created", @@ -2147,8 +2156,11 @@ "parent_blueprint_id": { "nullable": true, "description": "which blueprint this blueprint is based on", - "type": "string", - "format": "uuid" + "allOf": [ + { + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" + } + ] }, "time_created": { "description": "when this blueprint was generated (for debugging)", @@ -2259,8 +2271,11 @@ }, "target_id": { "description": "id of the blueprint that the system is trying to make real", - "type": "string", - "format": "uuid" + "allOf": [ + { + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" + } + ] }, "time_made_target": { "description": "when this blueprint was made the target", @@ -2282,8 +2297,7 @@ "type": "boolean" }, "target_id": { - "type": "string", - "format": "uuid" + "$ref": "#/components/schemas/TypedUuidForBlueprintKind" } }, "required": [ @@ -5808,6 +5822,10 @@ } } }, + "TypedUuidForBlueprintKind": { + "type": "string", + "format": "uuid" + }, "TypedUuidForDatasetKind": { "type": "string", "format": "uuid" diff --git a/sled-agent/src/rack_setup/service.rs b/sled-agent/src/rack_setup/service.rs index 0c55f261bf..4a378d04be 100644 --- a/sled-agent/src/rack_setup/service.rs +++ b/sled-agent/src/rack_setup/service.rs @@ -108,6 +108,7 @@ use omicron_common::disk::{ }; use omicron_common::ledger::{self, Ledger, Ledgerable}; use omicron_ddm_admin_client::{Client as DdmAdminClient, DdmError}; +use omicron_uuid_kinds::BlueprintUuid; use omicron_uuid_kinds::GenericUuid; use omicron_uuid_kinds::SledUuid; use omicron_uuid_kinds::ZpoolUuid; @@ -135,7 +136,6 @@ use std::net::SocketAddrV6; use std::time::Duration; use thiserror::Error; use tokio::sync::watch; -use uuid::Uuid; /// For tracking the current RSS step and sending notifications about it. pub struct RssProgress { @@ -1617,7 +1617,7 @@ pub(crate) fn build_initial_blueprint_from_sled_configs( } Ok(Blueprint { - id: Uuid::new_v4(), + id: BlueprintUuid::new_v4(), blueprint_zones, blueprint_disks, blueprint_datasets,