Skip to content

Commit f7e54fd

Browse files
'policies patch', a new command for partial policy definition updates
1 parent a214cd6 commit f7e54fd

File tree

5 files changed

+94
-1
lines changed

5 files changed

+94
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
### Enhancements
66

7+
* `policies set` and `policies update` are two new aliases for `policies declare`. The former follows the naming
8+
used by `rabbitmqctl` and the latter reflects the fact that the command can be used to update an existing policy,
9+
in particular, to override its definition
10+
* `policies patch` is a new command that updates a policy definition by merging the provided definition with the existing one
711
* `parameters list_all` is a new command that lists all runtime parameters across all virtual hosts
812
* `parameters list_in` is a new command that lists runtime parameters of a given component (type)
913
in a specific virtual host

src/cli.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1585,8 +1585,9 @@ fn global_parameters_subcommands(pre_flight_settings: PreFlightSettings) -> [Com
15851585
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
15861586
}
15871587

1588-
fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 9] {
1588+
fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 10] {
15891589
let declare_cmd = Command::new("declare")
1590+
.visible_aliases(vec!["update", "set"])
15901591
.about("Creates or updates a policy")
15911592
.after_help(color_print::cformat!("<bold>Doc guide:</bold>: {}", POLICY_GUIDE_URL))
15921593
.arg(
@@ -1684,6 +1685,20 @@ fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 9]
16841685
.help("target type, one of 'queues', 'streams', 'exchanges'"),
16851686
);
16861687

1688+
let patch_cmd = Command::new("patch")
1689+
.about("Merges a set of keys into existing policy definitions")
1690+
.arg(
1691+
Arg::new("name")
1692+
.long("name")
1693+
.help("policy name")
1694+
.required(true),
1695+
)
1696+
.arg(
1697+
Arg::new("definition")
1698+
.long("definition")
1699+
.help("policy definition changes to merge into the existing ones"),
1700+
);
1701+
16871702
let update_cmd = Command::new("update_definition")
16881703
.about("Updates a policy definition key")
16891704
.arg(
@@ -1728,6 +1743,7 @@ fn policies_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 9]
17281743
list_cmd,
17291744
list_in_cmd,
17301745
list_matching_cmd,
1746+
patch_cmd,
17311747
update_cmd,
17321748
update_all_in_cmd,
17331749
]

src/commands.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,31 @@ pub fn update_policy_definition(
10521052
update_policy_definition_with(&client, vhost, &name, &key, &parsed_value)
10531053
}
10541054

1055+
pub fn patch_policy_definition(
1056+
client: APIClient,
1057+
vhost: &str,
1058+
command_args: &ArgMatches,
1059+
) -> ClientResult<()> {
1060+
let name = command_args.get_one::<String>("name").cloned().unwrap();
1061+
let value = command_args
1062+
.get_one::<String>("definition")
1063+
.cloned()
1064+
.unwrap();
1065+
let parsed_value = serde_json::from_str::<serde_json::Value>(&value).unwrap_or_else(|err| {
1066+
eprintln!("`{}` is not a valid JSON value: {}", value, err);
1067+
process::exit(1);
1068+
});
1069+
1070+
let mut pol = client.get_policy(vhost, &name)?;
1071+
let patch = parsed_value.as_object().unwrap();
1072+
for (k, v) in patch.iter() {
1073+
pol.insert_definition_key(k.clone(), v.clone());
1074+
}
1075+
1076+
let params = PolicyParams::from(&pol);
1077+
client.declare_policy(&params)
1078+
}
1079+
10551080
pub fn update_all_policy_definitions_in(
10561081
client: APIClient,
10571082
vhost: &str,

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ fn dispatch_common_subcommand(
683683
let result = commands::list_matching_policies_in(client, &vhost, &name, typ);
684684
res_handler.tabular_result(result)
685685
}
686+
("policies", "patch") => {
687+
let result = commands::patch_policy_definition(client, &vhost, second_level_args);
688+
res_handler.no_output_on_success(result);
689+
}
686690
("policies", "update_definition") => {
687691
let result = commands::update_policy_definition(client, &vhost, second_level_args);
688692
res_handler.no_output_on_success(result);

tests/policies_tests.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,3 +513,47 @@ fn test_policies_bulk_policy_key_manipulation() -> Result<(), Box<dyn std::error
513513

514514
Ok(())
515515
}
516+
517+
#[test]
518+
fn test_policies_patch_definition() -> Result<(), Box<dyn std::error::Error>> {
519+
let policy_name = "test_policies_patch_definition";
520+
521+
run_succeeds([
522+
"policies",
523+
"declare",
524+
"--name",
525+
policy_name,
526+
"--pattern",
527+
"foo-.*",
528+
"--apply-to",
529+
"queues",
530+
"--priority",
531+
"123",
532+
"--definition",
533+
"{\"max-length\": 20, \"max-length-bytes\": 99999999}",
534+
]);
535+
run_succeeds(["policies", "list"])
536+
.stdout(predicate::str::contains(policy_name).and(predicate::str::contains("20")));
537+
538+
run_succeeds([
539+
"policies",
540+
"patch",
541+
"--name",
542+
policy_name,
543+
"--definition",
544+
"{\"max-length\": 29, \"max-length-bytes\": 8888888888}",
545+
]);
546+
547+
run_succeeds(["policies", "list"]).stdout(
548+
predicate::str::contains(policy_name)
549+
.and(predicate::str::contains("8888888888"))
550+
.and(predicate::str::contains("29")),
551+
);
552+
553+
run_succeeds(["policies", "list"]).stdout(predicate::str::contains("99999999").not());
554+
555+
run_succeeds(["policies", "delete", "--name", policy_name]);
556+
run_succeeds(["policies", "list"]).stdout(predicate::str::contains(policy_name).not());
557+
558+
Ok(())
559+
}

0 commit comments

Comments
 (0)