Skip to content

Commit 5bdc275

Browse files
New command group: bindings, closes #64
1 parent 12fbcbb commit 5bdc275

File tree

5 files changed

+199
-4
lines changed

5 files changed

+199
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Enhancements
66

7+
* `bindings` is a new command group for operations on bindings
78
* `exchanges` is a new command group for operations on exchanges
89
* `global_parameters` is a new command group for operations on [global runtime parameters](https://www.rabbitmq.com/docs/parameters)
910
* `nodes` is a new command group for operations on nodes

src/cli.rs

+83
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ pub fn parser(pre_flight_settings: PreFlightSettings) -> Command {
4545
GITHUB_REPOSITORY_URL
4646
);
4747

48+
let bindings_group = Command::new("bindings")
49+
.about("Operations on bindings")
50+
.infer_subcommands(pre_flight_settings.infer_subcommands)
51+
.infer_long_args(pre_flight_settings.infer_long_options)
52+
.subcommand_value_name("binding")
53+
.subcommands(binding_subcommands(pre_flight_settings.clone()));
4854
let close_group = Command::new("close")
4955
.about("Closes connections")
5056
.infer_subcommands(pre_flight_settings.infer_subcommands)
@@ -275,6 +281,7 @@ pub fn parser(pre_flight_settings: PreFlightSettings) -> Command {
275281
.subcommands(vhosts_subcommands(pre_flight_settings.clone()));
276282

277283
let command_groups = [
284+
bindings_group,
278285
close_group,
279286
declare_group,
280287
definitions_group,
@@ -1248,6 +1255,82 @@ fn purge_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 1] {
12481255
[queue_cmd].map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
12491256
}
12501257

1258+
fn binding_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 3] {
1259+
let declare_cmd = Command::new("declare")
1260+
.about("Creates a binding between a source exchange and a destination (a queue or an exchange)")
1261+
.arg(
1262+
Arg::new("source")
1263+
.long("source")
1264+
.help("source exchange")
1265+
.required(true),
1266+
)
1267+
.arg(
1268+
Arg::new("destination_type")
1269+
.long("destination-type")
1270+
.help("destination type: exchange or queue")
1271+
.required(true)
1272+
.value_parser(value_parser!(BindingDestinationType)),
1273+
)
1274+
.arg(
1275+
Arg::new("destination")
1276+
.long("destination")
1277+
.help("destination exchange/queue name")
1278+
.required(true),
1279+
)
1280+
.arg(
1281+
Arg::new("routing_key")
1282+
.long("routing-key")
1283+
.help("routing key")
1284+
.required(true),
1285+
)
1286+
.arg(
1287+
Arg::new("arguments")
1288+
.long("arguments")
1289+
.help("additional arguments")
1290+
.required(false)
1291+
.default_value("{}")
1292+
.value_parser(value_parser!(String)),
1293+
);
1294+
let delete_cmd = Command::new("delete")
1295+
.about("Deletes a binding")
1296+
.arg(
1297+
Arg::new("source")
1298+
.long("source")
1299+
.help("source exchange")
1300+
.required(true),
1301+
)
1302+
.arg(
1303+
Arg::new("destination_type")
1304+
.long("destination-type")
1305+
.help("destination type: exchange or queue")
1306+
.required(true),
1307+
)
1308+
.arg(
1309+
Arg::new("destination")
1310+
.long("destination")
1311+
.help("destination exchange/queue name")
1312+
.required(true),
1313+
)
1314+
.arg(
1315+
Arg::new("routing_key")
1316+
.long("routing-key")
1317+
.help("routing key")
1318+
.required(true),
1319+
)
1320+
.arg(
1321+
Arg::new("arguments")
1322+
.long("arguments")
1323+
.help("additional arguments")
1324+
.required(false)
1325+
.default_value("{}")
1326+
.value_parser(value_parser!(String)),
1327+
);
1328+
let list_cmd = Command::new("list").long_about("Lists bindings");
1329+
1330+
[declare_cmd, delete_cmd, list_cmd]
1331+
.map(|cmd| cmd.infer_long_args(pre_flight_settings.infer_long_options))
1332+
}
1333+
12511334
fn queues_subcommands(pre_flight_settings: PreFlightSettings) -> [Command; 5] {
12521335
let declare_cmd = Command::new("declare")
12531336
.about("Declares a queue or a stream")

src/main.rs

+12
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,18 @@ fn dispatch_common_subcommand(
279279
res_handler: &mut ResultHandler,
280280
) -> ExitCode {
281281
match &pair {
282+
("bindings", "declare") => {
283+
let result = commands::declare_binding(client, &vhost, second_level_args);
284+
res_handler.no_output_on_success(result);
285+
}
286+
("bindings", "delete") => {
287+
let result = commands::delete_binding(client, &vhost, second_level_args);
288+
res_handler.no_output_on_success(result);
289+
}
290+
("bindings", "list") => {
291+
let result = commands::list_bindings(client);
292+
res_handler.tabular_result(result)
293+
}
282294
("close", "connection") => {
283295
let result = commands::close_connection(client, second_level_args);
284296
res_handler.no_output_on_success(result);

tests/bindings_tests.rs

+101-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::test_helpers::*;
1818

1919
#[test]
2020
fn test_list_bindings() -> Result<(), Box<dyn std::error::Error>> {
21-
let vh1 = "bindings_vhost_1";
22-
let vh2 = "bindings_vhost_2";
21+
let vh1 = "test_list_bindings_1";
22+
let vh2 = "test_list_bindings_2";
2323
let q1 = "new_queue_1";
2424
let q2 = "new_queue_2";
2525

@@ -100,3 +100,102 @@ fn test_list_bindings() -> Result<(), Box<dyn std::error::Error>> {
100100

101101
Ok(())
102102
}
103+
104+
#[test]
105+
fn test_bindings_list() -> Result<(), Box<dyn std::error::Error>> {
106+
let vh1 = "test_bindings_list_1";
107+
let vh2 = "test_bindings_list_2";
108+
let q1 = "new_queue_1";
109+
let q2 = "new_queue_2";
110+
111+
delete_vhost(vh1).expect("failed to delete a virtual host");
112+
delete_vhost(vh2).expect("failed to delete a virtual host");
113+
114+
// declare vhost 1
115+
run_succeeds(["vhosts", "declare", "--name", vh1]);
116+
117+
// declare vhost 2
118+
run_succeeds(["vhosts", "declare", "--name", vh2]);
119+
120+
// declare a new queue in vhost 1
121+
run_succeeds([
122+
"-V", vh1, "queues", "declare", "--name", q1, "--type", "classic",
123+
]);
124+
125+
// declare a new queue in vhost 2
126+
run_succeeds([
127+
"-V", vh2, "queues", "declare", "--name", q2, "--type", "quorum",
128+
]);
129+
130+
// bind the queue -> a pre-existing exchange
131+
run_succeeds([
132+
"-V",
133+
vh1,
134+
"bindings",
135+
"declare",
136+
"--source",
137+
"amq.direct",
138+
"--destination-type",
139+
"queue",
140+
"--destination",
141+
q1,
142+
"--routing-key",
143+
"routing_key_queue",
144+
]);
145+
146+
// declare an exchange -> exchange binding
147+
run_succeeds([
148+
"-V",
149+
vh1,
150+
"bindings",
151+
"declare",
152+
"--source",
153+
"amq.direct",
154+
"--destination-type",
155+
"exchange",
156+
"--destination",
157+
"amq.topic",
158+
"--routing-key",
159+
"routing_key_exchange",
160+
]);
161+
162+
await_queue_metric_emission();
163+
164+
// list bindings in vhost 1
165+
run_succeeds(["-V", vh1, "list", "bindings"]).stdout(
166+
predicate::str::contains("new_queue_1")
167+
.and(predicate::str::contains("routing_key_queue"))
168+
.and(predicate::str::contains("routing_key_exchange")),
169+
);
170+
171+
// delete a binding
172+
// declare an exchange -> exchange binding
173+
run_succeeds([
174+
"-V",
175+
vh1,
176+
"bindings",
177+
"declare",
178+
"--source",
179+
"amq.direct",
180+
"--destination-type",
181+
"queue",
182+
"--destination",
183+
q1,
184+
"--routing-key",
185+
"routing_key_queue",
186+
]);
187+
188+
// ensure that the deleted binding is no longer listed
189+
run_succeeds(["-V", vh1, "list", "bindings"]).stdout(
190+
predicate::str::contains("new_queue_1")
191+
.not()
192+
.and(predicate::str::contains("routing_key_queue"))
193+
.not()
194+
.and(predicate::str::contains("routing_key_exchange")),
195+
);
196+
197+
delete_vhost(vh1).expect("failed to delete a virtual host");
198+
delete_vhost(vh2).expect("failed to delete a virtual host");
199+
200+
Ok(())
201+
}

tests/exchanges_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ fn test_exchanges_bind_and_unbind() -> Result<(), Box<dyn std::error::Error>> {
276276
await_queue_metric_emission();
277277

278278
// list bindings in vhost 1
279-
run_succeeds(["-V", "bindings_vhost_1", "list", "bindings"]).stdout(
279+
run_succeeds(["-V", vh2, "list", "bindings"]).stdout(
280280
predicate::str::contains("new_queue_1")
281281
.and(predicate::str::contains("routing_key_queue"))
282282
.and(predicate::str::contains("routing_key_exchange")),
@@ -298,7 +298,7 @@ fn test_exchanges_bind_and_unbind() -> Result<(), Box<dyn std::error::Error>> {
298298
"routing_key_queue",
299299
]);
300300

301-
run_succeeds(["-V", "bindings_vhost_1", "list", "bindings"]).stdout(
301+
run_succeeds(["-V", vh1, "list", "bindings"]).stdout(
302302
predicate::str::contains("new_queue_1")
303303
.not()
304304
.and(predicate::str::contains("routing_key_queue"))

0 commit comments

Comments
 (0)