@@ -241,17 +241,15 @@ mod tests {
241241 use httptest:: responders:: status_code;
242242 use nexus_db_queries:: db:: pub_test_utils:: TestDatabase ;
243243 use nexus_reconfigurator_planning:: blueprint_builder:: BlueprintBuilder ;
244- use nexus_sled_agent_shared:: inventory:: OmicronZoneDataset ;
245- use nexus_types:: deployment:: BlueprintZoneConfig ;
244+ use nexus_reconfigurator_planning:: example:: ExampleSystemBuilder ;
245+ use nexus_reconfigurator_planning:: planner:: PlannerRng ;
246+ use nexus_types:: deployment:: BlueprintSource ;
246247 use nexus_types:: deployment:: BlueprintZoneDisposition ;
247248 use nexus_types:: deployment:: BlueprintZoneImageSource ;
248249 use omicron_common:: api:: external:: Generation ;
249- use omicron_common:: zpool_name:: ZpoolName ;
250250 use omicron_test_utils:: dev;
251- use omicron_uuid_kinds:: SledUuid ;
252- use omicron_uuid_kinds:: ZpoolUuid ;
253251 use std:: collections:: BTreeMap ;
254- use std:: iter ;
252+ use std:: collections :: BTreeSet ;
255253 use std:: net:: SocketAddr ;
256254
257255 // The `CockroachAdminFromBlueprintViaFixedPort` type above is the standard
@@ -260,109 +258,83 @@ mod tests {
260258 // can _write_ that test), so test it in isolation here.
261259 #[ test]
262260 fn test_default_cockroach_admin_addrs_from_blueprint ( ) {
263- // Construct an empty blueprint with one sled.
264- let sled_id = SledUuid :: new_v4 ( ) ;
265- let mut blueprint = BlueprintBuilder :: build_empty_with_sleds (
266- iter:: once ( sled_id) ,
267- "test" ,
268- ) ;
269- let bp_sled = & mut blueprint
270- . sleds
271- . get_mut ( & sled_id)
272- . expect ( "found entry for test sled" ) ;
273-
274- let zpool_id = ZpoolUuid :: new_v4 ( ) ;
275- let make_crdb_zone_config =
276- |disposition, id, addr : SocketAddrV6 | BlueprintZoneConfig {
277- disposition,
278- id,
279- filesystem_pool : ZpoolName :: new_external ( zpool_id) ,
280- zone_type : BlueprintZoneType :: CockroachDb (
281- blueprint_zone_type:: CockroachDb {
282- address : addr,
283- dataset : OmicronZoneDataset {
284- pool_name : format ! ( "oxp_{}" , zpool_id)
285- . parse ( )
286- . unwrap ( ) ,
287- } ,
288- } ,
289- ) ,
290- image_source : BlueprintZoneImageSource :: InstallDataset ,
291- } ;
292-
293- // Add three CRDB zones with known addresses; the first and third are
294- // in service, and the second is expunged. Only the first and third
295- // should show up when we ask for addresses below.
296- let crdb_id1 = OmicronZoneUuid :: new_v4 ( ) ;
297- let crdb_id2 = OmicronZoneUuid :: new_v4 ( ) ;
298- let crdb_id3 = OmicronZoneUuid :: new_v4 ( ) ;
299- let crdb_addr1: SocketAddrV6 = "[2001:db8::1]:1111" . parse ( ) . unwrap ( ) ;
300- let crdb_addr2: SocketAddrV6 = "[2001:db8::2]:1234" . parse ( ) . unwrap ( ) ;
301- let crdb_addr3: SocketAddrV6 = "[2001:db8::3]:1234" . parse ( ) . unwrap ( ) ;
302- bp_sled
303- . zones
304- . insert_unique ( make_crdb_zone_config (
305- BlueprintZoneDisposition :: InService ,
306- crdb_id1,
307- crdb_addr1,
308- ) )
309- . expect ( "freshly generated zone IDs are unique" ) ;
310- bp_sled
311- . zones
312- . insert_unique ( make_crdb_zone_config (
313- BlueprintZoneDisposition :: Expunged {
261+ const TEST_NAME : & str =
262+ "test_default_cockroach_admin_addrs_from_blueprint" ;
263+ let logctx = dev:: test_setup_log ( TEST_NAME ) ;
264+ let log = & logctx. log ;
265+
266+ // Build an example system with one sled.
267+ let ( example_system, bp0) =
268+ ExampleSystemBuilder :: new ( log, TEST_NAME ) . nsleds ( 1 ) . build ( ) ;
269+ let input = example_system. input ;
270+
271+ // `ExampleSystemBuilder` doesn't place any cockroach nodes; assert so
272+ // we bail out early if that changes.
273+ let ncockroach = bp0
274+ . all_omicron_zones ( BlueprintZoneDisposition :: is_in_service)
275+ . filter ( |( _, z) | z. zone_type . is_cockroach ( ) )
276+ . count ( ) ;
277+ assert_eq ! ( ncockroach, 0 ) ;
278+
279+ // This blueprint has no cockroach zones, so should have no admin addrs
280+ // either.
281+ let admin_addrs = CockroachAdminFromBlueprintViaFixedPort
282+ . cockroach_admin_addrs ( & bp0)
283+ . collect :: < Vec < _ > > ( ) ;
284+ assert_eq ! ( admin_addrs, Vec :: new( ) ) ;
285+
286+ // Add 5 cockroach zones to our sled.
287+ let mut builder = BlueprintBuilder :: new_based_on (
288+ log,
289+ & bp0,
290+ & input,
291+ TEST_NAME ,
292+ PlannerRng :: from_entropy ( ) ,
293+ )
294+ . expect ( "constructed builder" ) ;
295+ let sled_id = bp0. sleds ( ) . next ( ) . expect ( "1 sled" ) ;
296+ for _ in 0 ..5 {
297+ builder
298+ . sled_add_zone_cockroachdb (
299+ sled_id,
300+ BlueprintZoneImageSource :: InstallDataset ,
301+ )
302+ . expect ( "added cockroach" ) ;
303+ }
304+ let mut bp1 = builder. build ( BlueprintSource :: Test ) ;
305+
306+ // Mutate this blueprint: expunge 2 of the 5 zones. Record the expected
307+ // admin addrs from the other three.
308+ let mut expected = BTreeSet :: new ( ) ;
309+ let sled_config = bp1. sleds . get_mut ( & sled_id) . unwrap ( ) ;
310+ let mut seen = 0 ;
311+ for mut zone in sled_config. zones . iter_mut ( ) {
312+ if !zone. zone_type . is_cockroach ( ) {
313+ continue ;
314+ }
315+ // Keep even; expunge odd.
316+ if seen % 2 == 0 {
317+ let ip = zone. underlay_ip ( ) ;
318+ let addr = SocketAddrV6 :: new ( ip, COCKROACH_ADMIN_PORT , 0 , 0 ) ;
319+ expected. insert ( ( zone. id , addr) ) ;
320+ } else {
321+ zone. disposition = BlueprintZoneDisposition :: Expunged {
314322 as_of_generation : Generation :: new ( ) ,
315323 ready_for_cleanup : false ,
316- } ,
317- crdb_id2,
318- crdb_addr2,
319- ) )
320- . expect ( "freshly generated zone IDs are unique" ) ;
321- bp_sled
322- . zones
323- . insert_unique ( make_crdb_zone_config (
324- BlueprintZoneDisposition :: InService ,
325- crdb_id3,
326- crdb_addr3,
327- ) )
328- . expect ( "freshly generated zone IDs are unique" ) ;
329-
330- // Also add a non-CRDB zone to ensure it's filtered out.
331- bp_sled
332- . zones
333- . insert_unique ( BlueprintZoneConfig {
334- disposition : BlueprintZoneDisposition :: InService ,
335- id : OmicronZoneUuid :: new_v4 ( ) ,
336- filesystem_pool : ZpoolName :: new_external ( ZpoolUuid :: new_v4 ( ) ) ,
337- zone_type : BlueprintZoneType :: CruciblePantry (
338- blueprint_zone_type:: CruciblePantry {
339- address : "[::1]:0" . parse ( ) . unwrap ( ) ,
340- } ,
341- ) ,
342- image_source : BlueprintZoneImageSource :: InstallDataset ,
343- } )
344- . expect ( "freshly generated zone IDs are unique" ) ;
345-
346- // We expect to see CRDB zones 1 and 3 with their IPs but the ports
347- // changed to `COCKROACH_ADMIN_PORT`.
348- let mut expected = vec ! [
349- (
350- crdb_id1,
351- SocketAddrV6 :: new( * crdb_addr1. ip( ) , COCKROACH_ADMIN_PORT , 0 , 0 ) ,
352- ) ,
353- (
354- crdb_id3,
355- SocketAddrV6 :: new( * crdb_addr3. ip( ) , COCKROACH_ADMIN_PORT , 0 , 0 ) ,
356- ) ,
357- ] ;
358- // We sort starting with zone id, since the original zones are sorted
359- // that way in a map.
360- expected. sort_unstable ( ) ;
324+ } ;
325+ }
326+ seen += 1 ;
327+ }
328+ assert_eq ! ( seen, 5 ) ;
329+ assert_eq ! ( expected. len( ) , 3 ) ;
361330
331+ // Confirm we only see the three expected addrs.
362332 let admin_addrs = CockroachAdminFromBlueprintViaFixedPort
363- . cockroach_admin_addrs ( & blueprint )
364- . collect :: < Vec < _ > > ( ) ;
333+ . cockroach_admin_addrs ( & bp1 )
334+ . collect :: < BTreeSet < _ > > ( ) ;
365335 assert_eq ! ( expected, admin_addrs) ;
336+
337+ logctx. cleanup_successful ( ) ;
366338 }
367339
368340 #[ tokio:: test]
0 commit comments