Skip to content

Commit 45f5f1c

Browse files
authored
Add clickhouse-cluster-config to omdb blueprint output (#6968)
Print clickhouse cluster config related tables for `blueprint show` and `blueprint diff` omdb commands. A bunch of the complexity and duplication here arises from the fact that we are diffing not only between blueprints that have identical structures, but between blueprints and collections that have drastically different contents. This is useful, but we probably should consider separating the two types of diffs and reworking all the blueprint diff logic to use some sort of semantic diff between types such as https://github.com/distil/diffus as recommended by @sunshowers. In order to make the `cluster_secret` UUID generation deterministic for tests I had use an rng seed in the `BlueprintBuilder`. This required moving creation of the initial `ClickhouseClusterConfig` and it's wrapping `ClickhouseAllocator` from `BlueprintBuilder::new_based_on` to `BlueprintBuilder::build`. Fixes #6941
1 parent e6883f3 commit 45f5f1c

16 files changed

Lines changed: 3399 additions & 228 deletions

nexus/reconfigurator/execution/src/clickhouse.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ mod test {
302302
let num_servers = 2u64;
303303

304304
let mut zones = BTreeMap::new();
305-
let mut config = ClickhouseClusterConfig::new("test".to_string());
305+
let mut config = ClickhouseClusterConfig::new(
306+
"test".to_string(),
307+
"test".to_string(),
308+
);
306309

307310
for keeper_id in 1..=num_keepers {
308311
let sled_id = SledUuid::new_v4();

nexus/reconfigurator/planning/src/blueprint_builder/builder.rs

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,6 @@ pub struct BlueprintBuilder<'a> {
276276
sled_ip_allocators: BTreeMap<SledUuid, IpAllocator>,
277277
external_networking: OnceCell<BuilderExternalNetworking<'a>>,
278278
internal_dns_subnets: OnceCell<DnsSubnetAllocator>,
279-
clickhouse_allocator: Option<ClickhouseAllocator>,
280279

281280
// These fields will become part of the final blueprint. See the
282281
// corresponding fields in `Blueprint`.
@@ -397,43 +396,6 @@ impl<'a> BlueprintBuilder<'a> {
397396
|| commissioned_sled_ids.contains(sled_id)
398397
});
399398

400-
// If we have the clickhouse cluster setup enabled via policy and we
401-
// don't yet have a `ClickhouseClusterConfiguration`, then we must create
402-
// one and feed it to our `ClickhouseAllocator`.
403-
let clickhouse_allocator = if input.clickhouse_cluster_enabled() {
404-
let parent_config = parent_blueprint
405-
.clickhouse_cluster_config
406-
.clone()
407-
.unwrap_or_else(|| {
408-
info!(
409-
log,
410-
concat!(
411-
"Clickhouse cluster enabled by policy: ",
412-
"generating initial 'ClickhouseClusterConfig' ",
413-
"and 'ClickhouseAllocator'"
414-
)
415-
);
416-
ClickhouseClusterConfig::new(OXIMETER_CLUSTER.to_string())
417-
});
418-
Some(ClickhouseAllocator::new(
419-
log.clone(),
420-
parent_config,
421-
inventory.latest_clickhouse_keeper_membership(),
422-
))
423-
} else {
424-
if parent_blueprint.clickhouse_cluster_config.is_some() {
425-
info!(
426-
log,
427-
concat!(
428-
"clickhouse cluster disabled via policy ",
429-
"discarding existing 'ClickhouseAllocator' and ",
430-
"the resulting generated 'ClickhouseClusterConfig"
431-
)
432-
);
433-
}
434-
None
435-
};
436-
437399
Ok(BlueprintBuilder {
438400
log,
439401
parent_blueprint,
@@ -448,7 +410,6 @@ impl<'a> BlueprintBuilder<'a> {
448410
sled_state,
449411
cockroachdb_setting_preserve_downgrade: parent_blueprint
450412
.cockroachdb_setting_preserve_downgrade,
451-
clickhouse_allocator,
452413
creator: creator.to_owned(),
453414
operations: Vec::new(),
454415
comments: Vec::new(),
@@ -533,9 +494,50 @@ impl<'a> BlueprintBuilder<'a> {
533494
.datasets
534495
.into_datasets_map(self.input.all_sled_ids(SledFilter::InService));
535496

497+
// If we have the clickhouse cluster setup enabled via policy and we
498+
// don't yet have a `ClickhouseClusterConfiguration`, then we must create
499+
// one and feed it to our `ClickhouseAllocator`.
500+
let clickhouse_allocator = if self.input.clickhouse_cluster_enabled() {
501+
let parent_config = self
502+
.parent_blueprint
503+
.clickhouse_cluster_config
504+
.clone()
505+
.unwrap_or_else(|| {
506+
info!(
507+
self.log,
508+
concat!(
509+
"Clickhouse cluster enabled by policy: ",
510+
"generating initial 'ClickhouseClusterConfig' ",
511+
"and 'ClickhouseAllocator'"
512+
)
513+
);
514+
ClickhouseClusterConfig::new(
515+
OXIMETER_CLUSTER.to_string(),
516+
self.rng.next_clickhouse().to_string(),
517+
)
518+
});
519+
Some(ClickhouseAllocator::new(
520+
self.log.clone(),
521+
parent_config,
522+
self.collection.latest_clickhouse_keeper_membership(),
523+
))
524+
} else {
525+
if self.parent_blueprint.clickhouse_cluster_config.is_some() {
526+
info!(
527+
self.log,
528+
concat!(
529+
"clickhouse cluster disabled via policy ",
530+
"discarding existing 'ClickhouseAllocator' and ",
531+
"the resulting generated 'ClickhouseClusterConfig"
532+
)
533+
);
534+
}
535+
None
536+
};
537+
536538
// If we have an allocator, use it to generate a new config. If an error
537539
// is returned then log it and carry over the parent_config.
538-
let clickhouse_cluster_config = self.clickhouse_allocator.map(|a| {
540+
let clickhouse_cluster_config = clickhouse_allocator.map(|a| {
539541
match a.plan(&(&blueprint_zones).into()) {
540542
Ok(config) => config,
541543
Err(e) => {

nexus/reconfigurator/planning/src/planner.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,12 @@ mod test {
28332833
.plan()
28342834
.expect("plan");
28352835

2836+
let diff = blueprint2.diff_since_blueprint(&blueprint1);
2837+
assert_contents(
2838+
"tests/output/planner_deploy_all_keeper_nodes_1_2.txt",
2839+
&diff.display().to_string(),
2840+
);
2841+
28362842
// We should see zones for 3 clickhouse keepers, and 2 servers created
28372843
let active_zones: Vec<_> = blueprint2
28382844
.all_omicron_zones(BlueprintZoneFilter::ShouldBeRunning)
@@ -2942,6 +2948,19 @@ mod test {
29422948
.plan()
29432949
.expect("plan");
29442950

2951+
let diff = blueprint4.diff_since_blueprint(&blueprint3);
2952+
assert_contents(
2953+
"tests/output/planner_deploy_all_keeper_nodes_3_4.txt",
2954+
&diff.display().to_string(),
2955+
);
2956+
2957+
let coll_diff = blueprint4.diff_since_collection(&collection);
2958+
println!("coll_diff = {coll_diff:#?}");
2959+
assert_contents(
2960+
"tests/output/planner_deploy_all_keeper_nodes_4_collection.txt",
2961+
&coll_diff.display().to_string(),
2962+
);
2963+
29452964
let bp3_config = blueprint3.clickhouse_cluster_config.as_ref().unwrap();
29462965
let bp4_config = blueprint4.clickhouse_cluster_config.as_ref().unwrap();
29472966
assert_eq!(bp4_config.generation, bp3_config.generation);
@@ -2984,6 +3003,12 @@ mod test {
29843003
.plan()
29853004
.expect("plan");
29863005

3006+
let diff = blueprint5.diff_since_blueprint(&blueprint4);
3007+
assert_contents(
3008+
"tests/output/planner_deploy_all_keeper_nodes_4_5.txt",
3009+
&diff.display().to_string(),
3010+
);
3011+
29873012
let active_zones: Vec<_> = blueprint5
29883013
.all_omicron_zones(BlueprintZoneFilter::ShouldBeRunning)
29893014
.map(|(_, z)| z.clone())
@@ -3025,6 +3050,12 @@ mod test {
30253050
.plan()
30263051
.expect("plan");
30273052

3053+
let diff = blueprint6.diff_since_blueprint(&blueprint5);
3054+
assert_contents(
3055+
"tests/output/planner_deploy_all_keeper_nodes_5_6.txt",
3056+
&diff.display().to_string(),
3057+
);
3058+
30283059
let bp6_config = blueprint6.clickhouse_cluster_config.as_ref().unwrap();
30293060
assert_eq!(bp5_config, bp6_config);
30303061

@@ -3248,6 +3279,12 @@ mod test {
32483279
.plan()
32493280
.expect("plan");
32503281

3282+
let diff = blueprint4.diff_since_blueprint(&blueprint3);
3283+
assert_contents(
3284+
"tests/output/planner_expunge_clickhouse_clusters_3_4.txt",
3285+
&diff.display().to_string(),
3286+
);
3287+
32513288
// The planner should expunge a zone based on the sled being expunged. Since this
32523289
// is a clickhouse keeper zone, the clickhouse keeper configuration should change
32533290
// to reflect this.
@@ -3306,6 +3343,12 @@ mod test {
33063343
.plan()
33073344
.expect("plan");
33083345

3346+
let diff = blueprint6.diff_since_blueprint(&blueprint5);
3347+
assert_contents(
3348+
"tests/output/planner_expunge_clickhouse_clusters_5_6.txt",
3349+
&diff.display().to_string(),
3350+
);
3351+
33093352
let old_config = blueprint5.clickhouse_cluster_config.as_ref().unwrap();
33103353
let config = blueprint6.clickhouse_cluster_config.as_ref().unwrap();
33113354

@@ -3328,7 +3371,7 @@ mod test {
33283371
#[test]
33293372
fn test_expunge_clickhouse_zones_after_policy_is_changed() {
33303373
static TEST_NAME: &str =
3331-
"planner_expunge_clickhouse__zones_after_policy_is_changed";
3374+
"planner_expunge_clickhouse_zones_after_policy_is_changed";
33323375
let logctx = test_setup_log(TEST_NAME);
33333376
let log = logctx.log.clone();
33343377

@@ -3435,6 +3478,12 @@ mod test {
34353478
.plan()
34363479
.expect("plan");
34373480

3481+
let diff = blueprint4.diff_since_blueprint(&blueprint3);
3482+
assert_contents(
3483+
"tests/output/planner_expunge_clickhouse_zones_after_policy_is_changed_3_4.txt",
3484+
&diff.display().to_string(),
3485+
);
3486+
34383487
// All our clickhouse keeper and server zones that we created when we
34393488
// enabled our clickhouse policy should be expunged when we disable it.
34403489
let expunged_zones: Vec<_> = blueprint4
@@ -3456,7 +3505,7 @@ mod test {
34563505
assert_eq!(keeper_zone_ids, expunged_keeper_zone_ids);
34573506
assert_eq!(server_zone_ids, expunged_server_zone_ids);
34583507

3459-
// We should have a new single-node clickhouze zone
3508+
// We should have a new single-node clickhouse zone
34603509
assert_eq!(
34613510
1,
34623511
blueprint4

nexus/reconfigurator/planning/src/planner/rng.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct PlannerRng {
3131
dataset_rng: TypedUuidRng<DatasetKind>,
3232
network_interface_rng: UuidRng,
3333
external_ip_rng: TypedUuidRng<ExternalIpKind>,
34+
clickhouse_rng: UuidRng,
3435
}
3536

3637
impl PlannerRng {
@@ -53,13 +54,16 @@ impl PlannerRng {
5354
UuidRng::from_parent_rng(&mut parent, "network_interface");
5455
let external_ip_rng =
5556
TypedUuidRng::from_parent_rng(&mut parent, "external_ip");
57+
let clickhouse_rng =
58+
UuidRng::from_parent_rng(&mut parent, "clickhouse");
5659

5760
Self {
5861
blueprint_rng,
5962
zone_rng,
6063
dataset_rng,
6164
network_interface_rng,
6265
external_ip_rng,
66+
clickhouse_rng,
6367
}
6468
}
6569

@@ -82,4 +86,8 @@ impl PlannerRng {
8286
pub fn next_external_ip(&mut self) -> ExternalIpUuid {
8387
self.external_ip_rng.next()
8488
}
89+
90+
pub fn next_clickhouse(&mut self) -> Uuid {
91+
self.clickhouse_rng.next()
92+
}
8593
}

0 commit comments

Comments
 (0)