Skip to content

Commit 5a60421

Browse files
authored
[35/n] [reconfigurator] add add_zones_with_mupdate_override chicken switch (#8648)
Add a chicken switch to enable testing mupdate/update logic for r16 while not affecting customer systems. Required a few changes but should hopefully be relatively easy to understand. As part of this, added: * omdb and reconfigurator-cli logic * displayers for both chicken switches and their diffs (using daft) * db storage and migrations
1 parent e770728 commit 5a60421

File tree

33 files changed

+728
-133
lines changed

33 files changed

+728
-133
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

clients/nexus-client/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ progenitor::generate_api!(
5454
OximeterReadMode = nexus_types::deployment::OximeterReadMode,
5555
OximeterReadPolicy = nexus_types::deployment::OximeterReadPolicy,
5656
PendingMgsUpdate = nexus_types::deployment::PendingMgsUpdate,
57+
PlannerChickenSwitches = nexus_types::deployment::PlannerChickenSwitches,
58+
ReconfiguratorChickenSwitches = nexus_types::deployment::ReconfiguratorChickenSwitches,
59+
ReconfiguratorChickenSwitchesParam = nexus_types::deployment::ReconfiguratorChickenSwitchesParam,
60+
ReconfiguratorChickenSwitchesView = nexus_types::deployment::ReconfiguratorChickenSwitchesView,
5761
RecoverySiloConfig = nexus_sled_agent_shared::recovery_silo::RecoverySiloConfig,
5862
Srv = nexus_types::internal_api::params::Srv,
5963
TypedUuidForBlueprintKind = omicron_uuid_kinds::BlueprintUuid,

dev-tools/omdb/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ gateway-types.workspace = true
3434
http.workspace = true
3535
humantime.workspace = true
3636
iddqd.workspace = true
37+
indent_write.workspace = true
3738
internal-dns-resolver.workspace = true
3839
internal-dns-types.workspace = true
3940
itertools.workspace = true

dev-tools/omdb/src/bin/omdb/nexus/chicken_switches.rs

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ use clap::ArgAction;
1010
use clap::Args;
1111
use clap::Subcommand;
1212
use http::StatusCode;
13-
use nexus_client::types::{
14-
ReconfiguratorChickenSwitches, ReconfiguratorChickenSwitchesParam,
15-
};
13+
use indent_write::io::IndentWriter;
14+
use nexus_types::deployment::PlannerChickenSwitches;
15+
use nexus_types::deployment::ReconfiguratorChickenSwitches;
16+
use nexus_types::deployment::ReconfiguratorChickenSwitchesParam;
17+
use std::io;
18+
use std::io::Write;
1619
use std::num::ParseIntError;
1720
use std::str::FromStr;
1821

@@ -34,8 +37,58 @@ pub enum ChickenSwitchesCommands {
3437

3538
#[derive(Debug, Clone, Args)]
3639
pub struct ChickenSwitchesSetArgs {
37-
#[clap(long, action=ArgAction::Set)]
38-
planner_enabled: bool,
40+
#[clap(flatten)]
41+
switches: ChickenSwitchesOpts,
42+
}
43+
44+
// Define the switches separately so we can use `group(required = true, multiple
45+
// = true).`
46+
#[derive(Debug, Clone, Args)]
47+
#[group(required = true, multiple = true)]
48+
pub struct ChickenSwitchesOpts {
49+
#[clap(long, action = ArgAction::Set)]
50+
planner_enabled: Option<bool>,
51+
52+
#[clap(long, action = ArgAction::Set)]
53+
add_zones_with_mupdate_override: Option<bool>,
54+
}
55+
56+
impl ChickenSwitchesOpts {
57+
/// Returns an updated `ReconfiguratorChickenSwitchesParam` regardless of
58+
/// whether any switches were modified.
59+
fn update(
60+
&self,
61+
current: &ReconfiguratorChickenSwitches,
62+
) -> ReconfiguratorChickenSwitches {
63+
ReconfiguratorChickenSwitches {
64+
planner_enabled: self
65+
.planner_enabled
66+
.unwrap_or(current.planner_enabled),
67+
planner_switches: PlannerChickenSwitches {
68+
add_zones_with_mupdate_override: self
69+
.add_zones_with_mupdate_override
70+
.unwrap_or(
71+
current
72+
.planner_switches
73+
.add_zones_with_mupdate_override,
74+
),
75+
},
76+
}
77+
}
78+
79+
/// Returns an updated `ReconfiguratorChickenSwitchesParam` if any
80+
/// switches were modified, or `None` if no changes were made.
81+
fn update_if_modified(
82+
&self,
83+
current: &ReconfiguratorChickenSwitches,
84+
next_version: u32,
85+
) -> Option<ReconfiguratorChickenSwitchesParam> {
86+
let new = self.update(current);
87+
(&new != current).then(|| ReconfiguratorChickenSwitchesParam {
88+
version: next_version,
89+
switches: new,
90+
})
91+
}
3992
}
4093

4194
#[derive(Debug, Clone, Copy, Args)]
@@ -92,15 +145,12 @@ async fn chicken_switches_show(
92145

93146
match res {
94147
Ok(switches) => {
95-
let ReconfiguratorChickenSwitches {
96-
version,
97-
planner_enabled,
98-
time_modified,
99-
} = switches.into_inner();
100-
println!("Reconfigurator Chicken Switches: ");
101-
println!(" version: {version}");
102-
println!(" modified time: {time_modified}");
103-
println!(" planner enabled: {planner_enabled}");
148+
println!("Reconfigurator chicken switches:");
149+
let stdout = io::stdout();
150+
let mut indented = IndentWriter::new(" ", stdout.lock());
151+
// No need for writeln! here because .display() adds its own
152+
// newlines.
153+
write!(indented, "{}", switches.display()).unwrap();
104154
}
105155
Err(err) => {
106156
if err.status() == Some(StatusCode::NOT_FOUND) {
@@ -124,7 +174,7 @@ async fn chicken_switches_set(
124174
.await
125175
{
126176
Ok(switches) => {
127-
let Some(version) = switches.version.checked_add(1) else {
177+
let Some(next_version) = switches.version.checked_add(1) else {
128178
eprintln!(
129179
"ERROR: Failed to update chicken switches. Max version reached."
130180
);
@@ -133,30 +183,23 @@ async fn chicken_switches_set(
133183
let switches = switches.into_inner();
134184
// Future switches should use the following pattern, and only update
135185
// the current switch values if a setting changed.
136-
//
137-
// We may want to use `Options` in `args` to allow defaulting to
138-
// the current setting rather than forcing the user to update all
139-
// settings if the number of switches grows significantly. However,
140-
// this will not play nice with the `NOT_FOUND` case below.
141-
let mut modified = false;
142-
if args.planner_enabled != switches.planner_enabled {
143-
modified = true;
144-
}
145-
if modified {
146-
ReconfiguratorChickenSwitchesParam {
147-
version,
148-
planner_enabled: args.planner_enabled,
149-
}
150-
} else {
186+
let Some(switches) = args
187+
.switches
188+
.update_if_modified(&switches.switches, next_version)
189+
else {
151190
println!("No modifications made to current switch values");
152191
return Ok(());
153-
}
192+
};
193+
switches
154194
}
155195
Err(err) => {
156196
if err.status() == Some(StatusCode::NOT_FOUND) {
197+
let default_switches = ReconfiguratorChickenSwitches::default();
198+
// In this initial case, the operator expects that we always set
199+
// switches.
157200
ReconfiguratorChickenSwitchesParam {
158201
version: 1,
159-
planner_enabled: args.planner_enabled,
202+
switches: args.switches.update(&default_switches),
160203
}
161204
} else {
162205
eprintln!("error: {:#}", err);

dev-tools/omdb/src/bin/omdb/reconfigurator.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ use nexus_db_queries::db::datastore::SQL_BATCH_SIZE;
2424
use nexus_db_queries::db::pagination::Paginator;
2525
use nexus_types::deployment::Blueprint;
2626
use nexus_types::deployment::BlueprintMetadata;
27+
use nexus_types::deployment::PlannerChickenSwitches;
2728
use nexus_types::deployment::ReconfiguratorChickenSwitches;
29+
use nexus_types::deployment::ReconfiguratorChickenSwitchesView;
2830
use nexus_types::deployment::UnstableReconfiguratorState;
2931
use omicron_common::api::external::Error;
3032
use omicron_common::api::external::LookupType;
@@ -403,20 +405,30 @@ async fn cmd_reconfigurator_chicken_switches_history(
403405
struct SwitchesRow {
404406
version: String,
405407
planner_enabled: String,
408+
add_zones_with_mupdate_override: String,
406409
time_modified: String,
407410
}
408411

409412
let rows: Vec<_> = history
410413
.into_iter()
411414
.map(|s| {
412-
let ReconfiguratorChickenSwitches {
415+
let ReconfiguratorChickenSwitchesView {
413416
version,
414-
planner_enabled,
417+
switches:
418+
ReconfiguratorChickenSwitches {
419+
planner_enabled,
420+
planner_switches:
421+
PlannerChickenSwitches {
422+
add_zones_with_mupdate_override,
423+
},
424+
},
415425
time_modified,
416426
} = s;
417427
SwitchesRow {
418428
version: version.to_string(),
419429
planner_enabled: planner_enabled.to_string(),
430+
add_zones_with_mupdate_override:
431+
add_zones_with_mupdate_override.to_string(),
420432
time_modified: time_modified.to_string(),
421433
}
422434
})

dev-tools/omdb/tests/successes.out

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,47 @@ task: "webhook_deliverator"
13981398
stderr:
13991399
note: using Nexus URL http://127.0.0.1:REDACTED_PORT/
14001400
=============================================
1401+
EXECUTING COMMAND: omdb ["nexus", "chicken-switches", "show", "current"]
1402+
termination: Exited(0)
1403+
---------------------------------------------
1404+
stdout:
1405+
No chicken switches enabled
1406+
---------------------------------------------
1407+
stderr:
1408+
note: using Nexus URL http://127.0.0.1:REDACTED_PORT/
1409+
=============================================
1410+
EXECUTING COMMAND: omdb ["-w", "nexus", "chicken-switches", "set", "--planner-enabled", "true"]
1411+
termination: Exited(0)
1412+
---------------------------------------------
1413+
stdout:
1414+
Chicken switches updated at version 1
1415+
---------------------------------------------
1416+
stderr:
1417+
note: using Nexus URL http://127.0.0.1:REDACTED_PORT/
1418+
=============================================
1419+
EXECUTING COMMAND: omdb ["-w", "nexus", "chicken-switches", "set", "--add-zones-with-mupdate-override", "false"]
1420+
termination: Exited(0)
1421+
---------------------------------------------
1422+
stdout:
1423+
Chicken switches updated at version 2
1424+
---------------------------------------------
1425+
stderr:
1426+
note: using Nexus URL http://127.0.0.1:REDACTED_PORT/
1427+
=============================================
1428+
EXECUTING COMMAND: omdb ["nexus", "chicken-switches", "show", "current"]
1429+
termination: Exited(0)
1430+
---------------------------------------------
1431+
stdout:
1432+
Reconfigurator chicken switches:
1433+
version: 2
1434+
modified time: <REDACTED_TIMESTAMP>
1435+
planner enabled: true
1436+
planner switches:
1437+
add zones with mupdate override: false
1438+
---------------------------------------------
1439+
stderr:
1440+
note: using Nexus URL http://127.0.0.1:REDACTED_PORT/
1441+
=============================================
14011442
EXECUTING COMMAND: omdb ["nexus", "sagas", "list"]
14021443
termination: Exited(0)
14031444
---------------------------------------------

dev-tools/omdb/tests/test_all_output.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,27 @@ async fn test_omdb_success_cases(cptestctx: &ControlPlaneTestContext) {
203203
&["nexus", "background-tasks", "show", "dns_internal"],
204204
&["nexus", "background-tasks", "show", "dns_external"],
205205
&["nexus", "background-tasks", "show", "all"],
206+
// chicken switches: show and set
207+
&["nexus", "chicken-switches", "show", "current"],
208+
&[
209+
"-w",
210+
"nexus",
211+
"chicken-switches",
212+
"set",
213+
"--planner-enabled",
214+
"true",
215+
],
216+
&[
217+
"-w",
218+
"nexus",
219+
"chicken-switches",
220+
"set",
221+
"--add-zones-with-mupdate-override",
222+
"false",
223+
],
224+
// After the set commands above, we should see chicken switches
225+
// populated.
226+
&["nexus", "chicken-switches", "show", "current"],
206227
&["nexus", "sagas", "list"],
207228
&["--destructive", "nexus", "sagas", "demo-create"],
208229
&["nexus", "sagas", "list"],

dev-tools/reconfigurator-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ camino.workspace = true
1717
chrono.workspace = true
1818
clap.workspace = true
1919
colored.workspace = true
20+
daft.workspace = true
2021
humantime.workspace = true
2122
iddqd.workspace = true
2223
indent_write.workspace = true

0 commit comments

Comments
 (0)