Skip to content

Commit e99233b

Browse files
Make sure that all deletion commands support --idempotently
1 parent 4f13e21 commit e99233b

File tree

10 files changed

+671
-48
lines changed

10 files changed

+671
-48
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,27 @@
3636

3737
**Important**: this command should **only** be used to undo incorrect shovel destination URIs (see above).
3838

39+
* All `delete_*` and `clear_*` commands now support the `--idempotently` flag (previously it was just a few):
40+
- `bindings delete`
41+
- `close connection`
42+
- `close user_connections`
43+
- `connections close`
44+
- `connections close_of_user`
45+
- `exchanges delete`
46+
- `exchanges unbind`
47+
- `federation delete_upstream`
48+
- `global_parameters clear`
49+
- `operator_policies delete`
50+
- `parameters clear`
51+
- `policies delete`
52+
- `queues delete`
53+
- `shovels delete`
54+
- `streams delete`
55+
- `users delete`
56+
- `vhosts delete`
57+
58+
* Updated `delete_binding` to use the new `BindingDeletionParams` struct API
59+
3960
## v2.11.0 (Sep 22, 2025)
4061

4162
### Enhancements

src/cli.rs

Lines changed: 109 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,8 @@ fn delete_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 13] {
12061206
.required(false)
12071207
.default_value("{}")
12081208
.value_parser(value_parser!(String)),
1209-
);
1209+
)
1210+
.arg(idempotently_arg.clone());
12101211
let parameter_cmd = Command::new("parameter")
12111212
.about("Clears a runtime parameter")
12121213
.arg(
@@ -1220,21 +1221,26 @@ fn delete_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 13] {
12201221
.long("component")
12211222
.help("component (eg. federation-upstream)")
12221223
.required(true),
1223-
);
1224-
let policy_cmd = Command::new("policy").about("Deletes a policy").arg(
1225-
Arg::new("name")
1226-
.long("name")
1227-
.help("policy name")
1228-
.required(true),
1229-
);
1224+
)
1225+
.arg(idempotently_arg.clone());
1226+
let policy_cmd = Command::new("policy")
1227+
.about("Deletes a policy")
1228+
.arg(
1229+
Arg::new("name")
1230+
.long("name")
1231+
.help("policy name")
1232+
.required(true),
1233+
)
1234+
.arg(idempotently_arg.clone());
12301235
let operator_policy_cmd = Command::new("operator_policy")
12311236
.about("Deletes an operator policy")
12321237
.arg(
12331238
Arg::new("name")
12341239
.long("name")
12351240
.help("operator policy name")
12361241
.required(true),
1237-
);
1242+
)
1243+
.arg(idempotently_arg.clone());
12381244
let vhost_limit_cmd = Command::new("vhost_limit")
12391245
.about("delete a vhost limit")
12401246
.arg(
@@ -1297,6 +1303,13 @@ fn purge_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 1] {
12971303
}
12981304

12991305
fn binding_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 3] {
1306+
let idempotently_arg = Arg::new("idempotently")
1307+
.long("idempotently")
1308+
.value_parser(value_parser!(bool))
1309+
.action(ArgAction::SetTrue)
1310+
.help("do not consider 404 Not Found API responses to be errors")
1311+
.required(false);
1312+
13001313
let declare_cmd = Command::new("declare")
13011314
.about("Creates a binding between a source exchange and a destination (a queue or an exchange)")
13021315
.arg(
@@ -1365,7 +1378,8 @@ fn binding_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 3] {
13651378
.required(false)
13661379
.default_value("{}")
13671380
.value_parser(value_parser!(String)),
1368-
);
1381+
)
1382+
.arg(idempotently_arg.clone());
13691383
let list_cmd = Command::new("list").long_about("Lists bindings");
13701384

13711385
[declare_cmd, delete_cmd, list_cmd]
@@ -1507,6 +1521,13 @@ fn streams_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 3] {
15071521
}
15081522

15091523
fn parameters_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 5] {
1524+
let idempotently_arg = Arg::new("idempotently")
1525+
.long("idempotently")
1526+
.value_parser(value_parser!(bool))
1527+
.action(ArgAction::SetTrue)
1528+
.help("do not consider 404 Not Found API responses to be errors")
1529+
.required(false);
1530+
15101531
let list_all_cmd = Command::new("list_all")
15111532
.long_about("Lists all runtime parameters across all virtual hosts")
15121533
.after_help(color_print::cformat!(
@@ -1578,13 +1599,21 @@ fn parameters_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 5
15781599
.long("component")
15791600
.help("component (eg. federation-upstream)")
15801601
.required(true),
1581-
);
1602+
)
1603+
.arg(idempotently_arg.clone());
15821604

15831605
[clear_cmd, list_all_cmd, list_cmd, list_in_cmd, set_cmd]
15841606
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
15851607
}
15861608

15871609
fn global_parameters_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 3] {
1610+
let idempotently_arg = Arg::new("idempotently")
1611+
.long("idempotently")
1612+
.value_parser(value_parser!(bool))
1613+
.action(ArgAction::SetTrue)
1614+
.help("do not consider 404 Not Found API responses to be errors")
1615+
.required(false);
1616+
15881617
let list_cmd = Command::new("list")
15891618
.long_about("Lists global runtime parameters")
15901619
.after_help(color_print::cformat!(
@@ -1620,13 +1649,21 @@ fn global_parameters_subcommands(pre_flight_settings: PreFlightSettings) -> [Com
16201649
.long("name")
16211650
.help("parameter's name")
16221651
.required(true),
1623-
);
1652+
)
1653+
.arg(idempotently_arg.clone());
16241654

16251655
[clear_cmd, list_cmd, set_cmd]
16261656
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
16271657
}
16281658

16291659
fn operator_policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 10] {
1660+
let idempotently_arg = Arg::new("idempotently")
1661+
.long("idempotently")
1662+
.value_parser(value_parser!(bool))
1663+
.action(ArgAction::SetTrue)
1664+
.help("do not consider 404 Not Found API responses to be errors")
1665+
.required(false);
1666+
16301667
let declare_cmd = Command::new("declare")
16311668
.visible_aliases(vec!["update", "set"])
16321669
.about("Creates or updates an operator policy")
@@ -1679,7 +1716,8 @@ fn operator_policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Com
16791716
.long("name")
16801717
.help("policy name")
16811718
.required(true),
1682-
);
1719+
)
1720+
.arg(idempotently_arg.clone());
16831721

16841722
let delete_definition_key_cmd = Command::new("delete_definition_keys")
16851723
.about("Deletes definition keys from an operator policy, unless it is the only key")
@@ -1800,6 +1838,13 @@ fn operator_policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Com
18001838
}
18011839

18021840
fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 12] {
1841+
let idempotently_arg = Arg::new("idempotently")
1842+
.long("idempotently")
1843+
.value_parser(value_parser!(bool))
1844+
.action(ArgAction::SetTrue)
1845+
.help("do not consider 404 Not Found API responses to be errors")
1846+
.required(false);
1847+
18031848
let declare_cmd = Command::new("declare")
18041849
.visible_aliases(vec!["update", "set"])
18051850
.about("Creates or updates a policy")
@@ -1889,12 +1934,15 @@ fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 12]
18891934
POLICY_GUIDE_URL
18901935
));
18911936

1892-
let delete_cmd = Command::new("delete").about("Deletes a policy").arg(
1893-
Arg::new("name")
1894-
.long("name")
1895-
.help("policy name")
1896-
.required(true),
1897-
);
1937+
let delete_cmd = Command::new("delete")
1938+
.about("Deletes a policy")
1939+
.arg(
1940+
Arg::new("name")
1941+
.long("name")
1942+
.help("policy name")
1943+
.required(true),
1944+
)
1945+
.arg(idempotently_arg.clone());
18981946

18991947
let delete_definition_keys_cmd = Command::new("delete_definition_keys")
19001948
.about("Deletes a definition key from a policy, unless it is the only key")
@@ -2088,14 +2136,22 @@ fn rebalance_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 1]
20882136
}
20892137

20902138
fn close_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 2] {
2139+
let idempotently_arg = Arg::new("idempotently")
2140+
.long("idempotently")
2141+
.value_parser(value_parser!(bool))
2142+
.action(ArgAction::SetTrue)
2143+
.help("do not consider 404 Not Found API responses to be errors")
2144+
.required(false);
2145+
20912146
let close_connection = Command::new("connection")
20922147
.about("Closes a client connection")
20932148
.arg(
20942149
Arg::new("name")
20952150
.long("name")
20962151
.help("connection name (identifying string)")
20972152
.required(true),
2098-
);
2153+
)
2154+
.arg(idempotently_arg.clone());
20992155
let close_user_connections = Command::new("user_connections")
21002156
.about("Closes all connections that authenticated with a specific username")
21012157
.arg(
@@ -2104,7 +2160,8 @@ fn close_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 2] {
21042160
.long("username")
21052161
.help("Name of the user whose connections to close")
21062162
.required(true),
2107-
);
2163+
)
2164+
.arg(idempotently_arg.clone());
21082165
[close_connection, close_user_connections]
21092166
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
21102167
}
@@ -2121,14 +2178,22 @@ fn channels_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 1]
21212178
}
21222179

21232180
fn connections_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 4] {
2181+
let idempotently_arg = Arg::new("idempotently")
2182+
.long("idempotently")
2183+
.value_parser(value_parser!(bool))
2184+
.action(ArgAction::SetTrue)
2185+
.help("do not consider 404 Not Found API responses to be errors")
2186+
.required(false);
2187+
21242188
let close_connection = Command::new("close")
21252189
.about("Closes a client connection")
21262190
.arg(
21272191
Arg::new("name")
21282192
.long("name")
21292193
.help("connection name (identifying string)")
21302194
.required(true),
2131-
);
2195+
)
2196+
.arg(idempotently_arg.clone());
21322197
let close_user_connections = Command::new("close_of_user")
21332198
.about("Closes all connections that are authenticated with a specific username")
21342199
.arg(
@@ -2137,7 +2202,8 @@ fn connections_subcommands(pre_flight_settings: PreFlightSettings) -> [Command;
21372202
.long("username")
21382203
.help("Name of the user whose connections should be closed")
21392204
.required(true),
2140-
);
2205+
)
2206+
.arg(idempotently_arg.clone());
21412207
let list_cmd = Command::new("list")
21422208
.long_about("Lists client connections")
21432209
.after_help(color_print::cformat!(
@@ -2467,7 +2533,8 @@ fn exchanges_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 5]
24672533
.required(false)
24682534
.default_value("{}")
24692535
.value_parser(value_parser!(String)),
2470-
);
2536+
)
2537+
.arg(idempotently_arg.clone());
24712538
[bind_cmd, declare_cmd, delete_cmd, list_cmd, unbind_cmd]
24722539
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
24732540
}
@@ -2893,6 +2960,13 @@ pub fn get_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 1] {
28932960
}
28942961

28952962
pub fn shovel_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7] {
2963+
let idempotently_arg = Arg::new("idempotently")
2964+
.long("idempotently")
2965+
.value_parser(value_parser!(bool))
2966+
.action(ArgAction::SetTrue)
2967+
.help("do not consider 404 Not Found API responses to be errors")
2968+
.required(false);
2969+
28962970
let list_all_cmd = Command::new("list_all")
28972971
.long_about("Lists shovels in all virtual hosts")
28982972
.after_help(color_print::cformat!(
@@ -3039,7 +3113,8 @@ pub fn shovel_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7
30393113
.long("name")
30403114
.help("shovel name (identifier)")
30413115
.required(true),
3042-
);
3116+
)
3117+
.arg(idempotently_arg.clone());
30433118

30443119
let disable_tls_peer_verification_cmd = Command::new("disable_tls_peer_verification_for_all_source_uris")
30453120
// shorter, displayed in the shovels group's help
@@ -3084,6 +3159,13 @@ pub fn shovel_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 7
30843159
}
30853160

30863161
fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 8] {
3162+
let idempotently_arg = Arg::new("idempotently")
3163+
.long("idempotently")
3164+
.value_parser(value_parser!(bool))
3165+
.action(ArgAction::SetTrue)
3166+
.help("do not consider 404 Not Found API responses to be errors")
3167+
.required(false);
3168+
30873169
let list_all_upstreams = Command::new("list_all_upstreams")
30883170
.long_about("Lists federation upstreams in all virtual hosts")
30893171
.after_help(color_print::cformat!(
@@ -3400,7 +3482,8 @@ fn federation_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 8
34003482
.long("name")
34013483
.help("upstream name (identifier)")
34023484
.required(true),
3403-
);
3485+
)
3486+
.arg(idempotently_arg.clone());
34043487

34053488
let list_all_links = Command::new("list_all_links")
34063489
.long_about("List federation links in all virtual hosts")

0 commit comments

Comments
 (0)