rabbitmq / rabbitmq-cli Goto Github PK
View Code? Open in Web Editor NEWCommand line tools for RabbitMQ
License: Other
Command line tools for RabbitMQ
License: Other
Currently, you get the full usage message whenever you use an invalid command string, even if it's a recognized command with the wrong number of arguments. We already define a usage string in each command module; it shouldn't be too hard to create a more targeted usage message for errors generated by the wrong number of arguments.
Now that rabbitmq/rabbitmq-server#683 is merged, we should port the changes to this project.
Following the implemention of #62, there could be need to introduce some level of control to the rate at which information is returned and displayed when rabbitmqctl
list_*
commands are executed.
For example during troubleshooting, controlled monitoring and inspection of a node's metadata like queues and bindings in real time, while the node is subject to other factors like queue declarations, publishes, e.t.c.
AS A RabbitMQ developer
I WANT the CLI tests to run in a Docker container
SO THAT I don't have to install Elixir when I'm not working on the CLI
NOTE: This may be very slow relative to the actual tests. We may ultimately want a flag in there to let you run tests locally if you have Elixir installed.
The CLI tests currently require a RabbitMQ server to be started separately; let's start a server as part of the test suite.
A lot of the outputs in rabbitmqctl status
are currently given in bytes, kilobytes or microseconds. Applying some scaling would make them more human-readable.
Some commands have specific error messages returned from run
, which is not handled properly by rabbitmqctl
module.
This messages should be handled by function in command module. Something like report_error
or report_output
.
Fill in the functionality for the rabbitmqctl status
command as a way to drive out some program structure.
Option switches for parsing command line arguments are provided in parser
module.
Commands can be able to add their own command line options, so they should be added to switches when parsing arguments.
The spec for the list_users
command intermittently fails with the following message:
1) test On a successful query, return an array of lists of tuples (ListUsersCommandTest)
test/list_users_command_test.exs:55
Expected truthy, got false
code: Enum.all?(matches_found, fn user -> Enum.find(context[:std_result], fn found -> found == user end) end)
stacktrace:
test/list_users_command_test.exs:59: anonymous fn/1 in ListUsersCommandTest.test On a successful query, return an array of lists of tuples/1
(ex_unit) lib/ex_unit/capture_io.ex:146: ExUnit.CaptureIO.do_capture_io/2
(ex_unit) lib/ex_unit/capture_io.ex:119: ExUnit.CaptureIO.do_capture_io/3
test/list_users_command_test.exs:56
..
2) test sufficiently long timeouts don't interfere with results (ListUsersCommandTest)
test/list_users_command_test.exs:72
Expected truthy, got false
code: Enum.all?(matches_found, fn user -> Enum.find(context[:std_result], fn found -> found == user end) end)
stacktrace:
test/list_users_command_test.exs:77: anonymous fn/1 in ListUsersCommandTest.test sufficiently long timeouts don't interfere with results/1
(ex_unit) lib/ex_unit/capture_io.ex:146: ExUnit.CaptureIO.do_capture_io/2
(ex_unit) lib/ex_unit/capture_io.ex:119: ExUnit.CaptureIO.do_capture_io/3
test/list_users_command_test.exs:74
A request from @dumbbell, this would allow us to set command aliases using a configuration file. Useful if we want to hand people some code for debugging purposes, but don't want them to have to use eval
.
The Elixir.Code
module makes it fairly easy to generate and evaluate strings as function calls. If we use this in RabbitMQCtl.main/1
, we can just define one module per subcommand (e.g., EnvironmentCommand
for rabbitmqctl env
) instead of making one handler in main
for each subcommand. As long as we're consistent with the structure of these modules, we can do this fairly simply.
Currently we use module names such as Parser
(top-level). This repository is meant to have multiple tools and inevitably a small shared library they will use. We should namespace all modules under RabbitMQ.CLI
, e.g. RabbitMQ.CLI.RabbitMQCtl
, RabbitMQ.CLI.Distribution
, RabbitMQ.CLI.RabbitMQCtl.Parser
and so on.
README section for adding commands no longer corresponds with command behaviour since #45 have been merged. Needs to be updated.
Stable branch is way behind master. Maybe it's time to make it up-to-date and start merging there.
We are going to need separate master soon, since there will be changes in reporting API
Implement the following commands:
./rabbitmqctl --nope foo clear_permissions -q foo
Error: invalid options for this command.
Given:
--nope foo clear_permissions -q foo
** (SyntaxError) nofile:1: syntax error before: '.'
(elixir) lib/code.ex:168: Code.eval_string/3
(rabbitmqctl) lib/rabbitmqctl.ex:65: RabbitMQCtl.command_usage/1
(rabbitmqctl) lib/rabbitmqctl.ex:112: RabbitMQCtl.print_standard_messages/2
(rabbitmqctl) lib/rabbitmqctl.ex:33: RabbitMQCtl.main/1
(elixir) lib/kernel/cli.ex:76: anonymous fn/3 in Kernel.CLI.exec_fun/2
This should just fail and print an error message.
RABBITMQ_HOME="/path/to/umbrella.git/deps/rabbit/" RABBITMQ_MNESIA_DIR="/var/folders/6v/nzn6gr5d6k31r39x57fddtpm0000gp/T//rabbitmq-test-instances/rabbit/mnesia/rabbit" ./rabbitmqctl forget_cluster_node -n rabbit@mercurio hare@mercurio --offline
"Removing node hare@mercurio from the cluster"
* Impersonating node: rabbit@mercurio...
done
* Mnesia directory: /var/folders/6v/nzn6gr5d6k31r39x57fddtpm0000gp/T/rabbitmq-test-instances/rabbit/mnesia/rabbit...
08:34:49.359 [info] Application mnesia exited: :stopped
** (UndefinedFunctionError) function :lager_config.get/2 is undefined (module :lager_config is not available)
:lager_config.get({:rabbit_log_lager_event, :loglevel}, {0, []})
(rabbit) src/rabbit_mnesia.erl:308: :rabbit_mnesia.forget_cluster_node/2
(rabbit) src/rabbit_mnesia.erl:333: :rabbit_mnesia.remove_node_offline_node/1
(rabbitmqctl) lib/rabbitmqctl.ex:95: anonymous fn/4 in RabbitMQCtl.run_command/2
(rabbitmqctl) lib/rabbitmqctl.ex:49: RabbitMQCtl.main/1
(elixir) lib/kernel/cli.ex:76: anonymous fn/3 in Kernel.CLI.exec_fun/2
merge_defaults
in most commands is implemented like Map.merge(opts, default_opts)
, which always rewrites opts
with default_opts
making impossible to set custom vhost
or other params.
There should be tests for merge_defaults
.
Example test:
test "merge_defaults: default vhost is '/'" do
assert @command.merge_defaults([], %{}) == {[], %{vhost: "/"}}
assert @command.merge_defaults([], %{vhost: "non_default"}) == {[], %{vhost: "non_default"}}
end
** (FunctionClauseError) no function clause matching in ListBindingsCommand.banner/2
(rabbitmqctl) lib/list_bindings_command.ex:66: ListBindingsCommand.banner(["source_name", "source_kind", "destination_name", "destination_kind", "routing_key", "arguments"], %{node: :rabbit@snowman, timeout: :infinity, vhost: "/"})
(rabbitmqctl) lib/rabbitmqctl.ex:79: RabbitMQCtl.print_banner/3
(rabbitmqctl) lib/rabbitmqctl.ex:63: anonymous fn/4 in RabbitMQCtl.run_command/2
(rabbitmqctl) lib/rabbitmqctl.ex:32: RabbitMQCtl.main/1
(elixir) lib/kernel/cli.ex:76: anonymous fn/3 in Kernel.CLI.exec_fun/2```
From a testing perspective it makes sense to tackle them together.
Our CLI tools should be able to output multiple formats for both humans and machines consumption.
The simplest use case is the combination with Unix commands, such as cut(1) or awk(1). Lists and tables should formatted with easy integration with those tools in mind.
A more advanced example is what is done with libxo: it is used by standard Unix tools to format XML, JSON or HTML, in addition to the expected human-readable output.
Finally, on Windows, PowerShell offers commands the possibility to exchange "objects", skipping parsing entirely if I understand correctly. I have no idea how it works but it seems powerful.
Implement the following commands:
The -q
flag is does not currently suppress the info message for the clear_permissions
command:
./rabbitmqctl clear_permissions sandwich -q
Clearing permissions for user "sandwich" in vhost "/" ...
:ok
print_usage
is currently just a stub.
Implement rabbitmq-plugins
commands (in RabbitMQ.CLI.Plugins
namespace)
To avoid duplication across all command modules.
running mix test
after upgrading to elixir 1.3.1 yields:
.....** (exit) exited in: :gen_server.call(#PID<3.256.0>, {:get_cached_env, 0}, 30000)
** (EXIT) no connection to nonode@nohost
(stdlib) gen_server.erl:212: :gen_server.call/3
test/list_queues_command_test.exs:49: (module)
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/code.ex:363: Code.require_file/2
(elixir) lib/kernel/parallel_require.ex:56: anonymous fn/2 in Kernel.ParallelRequire.spawn_requires/5
Add option to show usage for specific command only.
Show node and timeout argument usage in specific command usages.
We've been having a lot of command modules pass their tests, but crash when you try to run them from a compiled CLI. This means we need more in-depth integration testing.
Ideally the solution here will respect the goal of self-contained command code and testing, but with integration tests there may not be a clean way.
Currently the -p
option is called param
. Since it's only used for vhost name, it shoud be named vhost
Currently the main module is vulnerable to unusual error returns (e.g. :error_string
instead of :error
). This could be dealt with via an error parser that checks the output and runs a simple conversion on any returns it doesn't understand: ```{:strange_code, } -> {:error, {:strange_code, }}`. Many commands already follow this format already, so the CLI knows how to handle it.
A request from @hairyhum, this would be a bash-level auto-complete feature for the basic rabbitmqctl
commands.
Currently it's not possible to run two rabbitmqctl
instances at the same time (e.g. sync_queue
and another one to test cancel_sync_queue
) because all instances use the same name.
This issue is not as trivial as it may seem and it took a few iterations in the current rabbitmqctl
, see rabbitmq/rabbitmq-server#549 for the most recent one.
I have 2 vhosts in the RabbitMQ node I run mix test
against and it looks like some tests assume there's a single vhost:
9) test valid user returns a list of permissions (ListUserPermissionsCommandTest)
test/list_user_permissions_command_test.exs:78
Assertion with == failed
code: ListUserPermissionsCommand.list_user_permissions([context[:username]], context[:opts]) == context[:result]
lhs: [[vhost: "bunny_testbed", configure: ".*", write: ".*", read: ".*"], [vhost: "/", configure: ".*", write: ".*", read: ".*"]]
rhs: [[vhost: "/", configure: ".*", write: ".*", read: ".*"]]
stacktrace:
test/list_user_permissions_command_test.exs:79
10) test long user-defined timeout doesn't interfere with operation (ListUserPermissionsCommandTest)
test/list_user_permissions_command_test.exs:100
Assertion with == failed
code: ListUserPermissionsCommand.list_user_permissions([context[:username]], context[:opts]) == context[:result]
lhs: [[vhost: "bunny_testbed", configure: ".*", write: ".*", read: ".*"], [vhost: "/", configure: ".*", write: ".*", read: ".*"]]
rhs: [[vhost: "/", configure: ".*", write: ".*", read: ".*"]]
stacktrace:
test/list_user_permissions_command_test.exs:101
Currently the status
command prints all numerical units as-is, with no units associated. We should get some units associated with the output.
NOTE: this may be best accomplished by in-lining transformations to the raw result
rather than directly modifying the printing code.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.