├── include └── .gitkeep ├── test ├── fixtures │ ├── files │ │ ├── empty_pidfile.pid │ │ ├── valid_pidfile.pid │ │ ├── invalid_pidfile.pid │ │ ├── valid_erl_expression.escript │ │ ├── valid_pidfile_with_spaces.pid │ │ ├── invalid_erl_expression.escript │ │ ├── loaded_applications.escript │ │ └── definitions.json │ └── plugins │ │ ├── .gitignore │ │ ├── plugins-subdirectory-04 │ │ └── mock_rabbitmq_plugins_04.ez │ │ ├── plugins-subdirectory-01 │ │ ├── mock_rabbitmq_plugins_01-0.1.0.ez │ │ ├── mock_rabbitmq_plugins_01-0.2.0.ez │ │ └── mock_rabbitmq_plugins_02-0.1.0.ez │ │ ├── plugins-subdirectory-02 │ │ └── mock_rabbitmq_plugins_02-0.2.0.ez │ │ ├── plugins-subdirectory-03 │ │ └── mock_rabbitmq_plugins_03-0.1.0.ez │ │ └── plugins_with_version_requirements │ │ ├── mock_rabbitmq_plugins_01-0.1.0.ez │ │ ├── mock_rabbitmq_plugins_02-0.1.0.ez │ │ ├── mock_rabbitmq_plugin_for_3_7-0.1.0.ez │ │ ├── mock_rabbitmq_plugin_for_3_8-0.1.0.ez │ │ └── mock_rabbitmq_plugin_for_3_8-0.1.0 │ │ └── ebin │ │ ├── mock_rabbitmq_plugins_01_app.beam │ │ ├── mock_rabbitmq_plugins_01_sup.beam │ │ └── mock_rabbitmq_plugin_for_3_8.app ├── ctl │ ├── version_command_test.exs │ ├── list_hashes_command_test.exs │ ├── list_ciphers_command_test.exs │ ├── rotate_logs_command_test.exs │ ├── status_command_test.exs │ ├── force_gc_command_test.exs │ ├── report_command_test.exs │ ├── environment_command_test.exs │ ├── await_online_nodes_command_test.exs │ ├── cluster_status_command_test.exs │ ├── exec_command_test.exs │ ├── stop_app_command_test.exs │ ├── start_app_command_test.exs │ ├── await_startup_command_test.exs │ ├── set_log_level_command_test.exs │ ├── ping_command_test.exs │ ├── autocomplete_command_test.exs │ ├── stop_command_test.exs │ └── shutdown_command_test.exs ├── core │ ├── json_stream_test.exs │ ├── distribution_test.exs │ └── information_unit_test.exs ├── diagnostics │ ├── erlang_cookie_sources_command_test.exs │ ├── observer_command_test.exs │ ├── list_network_interfaces_command_test.exs │ ├── discover_peers_command_test.exs │ ├── list_node_auth_attempt_stats_command_test.exs │ ├── enable_auth_attempt_source_tracking_command_test.exs │ ├── disable_auth_attempt_source_tracking_command_test.exs │ ├── command_line_arguments_command_test.exs │ ├── server_version_command_test.exs │ ├── maybe_stuck_command_test.exs │ ├── erlang_cookie_hash_command_test.exs │ ├── runtime_thread_stats_command_test.exs │ └── check_virtual_hosts_command_test.exs ├── upgrade │ ├── await_online_quorum_plus_one_command_test.exs │ ├── await_online_synchronized_mirror_command_test.exs │ ├── post_upgrade_command_test.exs │ ├── drain_command_test.exs │ └── revive_command_test.exs ├── queues │ ├── check_if_node_is_quorum_critical_command_test.exs │ ├── check_if_node_is_mirror_sync_critical_command_test.exs │ ├── quorum_status_command_test.exs │ └── reclaim_quorum_memory_command_test.exs └── json_formatting.exs ├── .gitignore ├── LICENSE ├── lib ├── rabbitmq │ └── cli │ │ ├── core │ │ ├── feature_flags.ex │ │ ├── merges_no_defaults.ex │ │ ├── merges_default_virtual_host.ex │ │ ├── accepts_default_switches_and_timeout.ex │ │ ├── requires_rabbit_app_running.ex │ │ ├── requires_rabbit_app_stopped.ex │ │ ├── data_coercion.ex │ │ ├── version.ex │ │ ├── accepts_no_positional_arguments.ex │ │ ├── erl_eval.ex │ │ ├── accepts_one_positional_argument.ex │ │ ├── accepts_two_positional_arguments.ex │ │ ├── platform.ex │ │ ├── input.ex │ │ ├── ansi.ex │ │ ├── accepts_one_positive_integer_argument.ex │ │ ├── paths.ex │ │ └── os_pid.ex │ │ ├── formatters │ │ ├── erlang.ex │ │ ├── msacc.ex │ │ ├── string.ex │ │ ├── inspect.ex │ │ ├── string_per_line.ex │ │ └── report.ex │ │ ├── printers │ │ ├── std_io.ex │ │ ├── std_io_raw.ex │ │ └── file.ex │ │ ├── printer_behaviour.ex │ │ ├── ctl │ │ ├── commands │ │ │ ├── start_app_command.ex │ │ │ ├── stop_app_command.ex │ │ │ ├── rotate_logs_command.ex │ │ │ ├── list_ciphers_command.ex │ │ │ ├── list_hashes_command.ex │ │ │ ├── force_gc_command.ex │ │ │ ├── version_command.ex │ │ │ ├── delete_vhost_command.ex │ │ │ ├── environment_command.ex │ │ │ ├── trace_off_command.ex │ │ │ ├── trace_on_command.ex │ │ │ ├── clear_vhost_limits_command.ex │ │ │ ├── reset_command.ex │ │ │ ├── force_reset_command.ex │ │ │ ├── list_users_command.ex │ │ │ ├── set_cluster_name_command.ex │ │ │ ├── clear_global_parameter_command.ex │ │ │ ├── clear_password_command.ex │ │ │ ├── await_startup_command.ex │ │ │ ├── clear_policy_command.ex │ │ │ ├── clear_operator_policy_command.ex │ │ │ ├── list_global_parameters_command.ex │ │ │ ├── set_user_limits_command.ex │ │ │ ├── list_policies_command.ex │ │ │ ├── set_vhost_limits_command.ex │ │ │ ├── cancel_sync_queue_command.ex │ │ │ ├── close_connection_command.ex │ │ │ ├── list_parameters_command.ex │ │ │ ├── resume_listeners_command.ex │ │ │ ├── sync_queue_command.ex │ │ │ ├── list_operator_policies_command.ex │ │ │ ├── list_topic_permissions_command.ex │ │ │ ├── list_permissions_command.ex │ │ │ ├── clear_user_limits_command.ex │ │ │ ├── autocomplete_command.ex │ │ │ ├── suspend_listeners_command.ex │ │ │ ├── list_user_topic_permissions_command.ex │ │ │ ├── set_global_parameter_command.ex │ │ │ ├── delete_user_command.ex │ │ │ ├── enable_feature_flag_command.ex │ │ │ ├── clear_parameter_command.ex │ │ │ ├── force_boot_command.ex │ │ │ └── list_user_permissions_command.ex │ │ └── info_keys.ex │ │ ├── upgrade │ │ └── commands │ │ │ └── post_upgrade_command.ex │ │ ├── time_unit.ex │ │ ├── diagnostics │ │ ├── commands │ │ │ ├── maybe_stuck_command.ex │ │ │ ├── reset_node_auth_attempt_metrics_command.ex │ │ │ ├── discover_peers_command.ex │ │ │ ├── disable_auth_attempt_source_tracking_command.ex │ │ │ ├── enable_auth_attempt_source_tracking_command.ex │ │ │ ├── erlang_cookie_hash_command.ex │ │ │ ├── server_version_command.ex │ │ │ ├── command_line_arguments_command.ex │ │ │ ├── tls_versions_command.ex │ │ │ ├── observer_command.ex │ │ │ ├── log_tail_command.ex │ │ │ ├── certificates_command.ex │ │ │ ├── check_running_command.ex │ │ │ └── log_location_command.ex │ │ └── diagnostics_helpers.ex │ │ ├── formatter_behaviour.ex │ │ ├── queues │ │ └── commands │ │ │ ├── quorum_status_command.ex │ │ │ └── delete_member_command.ex │ │ └── information_unit.ex └── rabbit_common │ └── records.ex ├── .github ├── ISSUE_TEMPLATE.md └── workflows │ └── webhooks.yml ├── config └── config.exs └── .travis.yml /include/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/files/empty_pidfile.pid: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/plugins/.gitignore: -------------------------------------------------------------------------------- 1 | !*.ez 2 | -------------------------------------------------------------------------------- /test/fixtures/files/valid_pidfile.pid: -------------------------------------------------------------------------------- 1 | 13566 2 | -------------------------------------------------------------------------------- /test/fixtures/files/invalid_pidfile.pid: -------------------------------------------------------------------------------- 1 | invalid///& 2 | -------------------------------------------------------------------------------- /test/fixtures/files/valid_erl_expression.escript: -------------------------------------------------------------------------------- 1 | 1 + 1. 2 | -------------------------------------------------------------------------------- /test/fixtures/files/valid_pidfile_with_spaces.pid: -------------------------------------------------------------------------------- 1 | 83777 2 | -------------------------------------------------------------------------------- /test/fixtures/files/invalid_erl_expression.escript: -------------------------------------------------------------------------------- 1 | 1 + . $$$ ///\\\ 2 | -------------------------------------------------------------------------------- /test/fixtures/files/loaded_applications.escript: -------------------------------------------------------------------------------- 1 | application:loaded_applications(). 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /_build 2 | /cover 3 | /deps 4 | /escript 5 | /log 6 | /.erlang.mk/ 7 | /ebin 8 | erl_crash.dump 9 | mix.lock 10 | *.ez 11 | .sw? 12 | .*.sw? 13 | -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-04/mock_rabbitmq_plugins_04.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-04/mock_rabbitmq_plugins_04.ez -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This package is licensed under the MPL 2.0. For the MPL 2.0, please see LICENSE-MPL-RabbitMQ. 2 | 3 | If you have any questions regarding licensing, please contact us at 4 | info@rabbitmq.com. 5 | -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_01-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_01-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_01-0.2.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_01-0.2.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_02-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-01/mock_rabbitmq_plugins_02-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-02/mock_rabbitmq_plugins_02-0.2.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-02/mock_rabbitmq_plugins_02-0.2.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins-subdirectory-03/mock_rabbitmq_plugins_03-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins-subdirectory-03/mock_rabbitmq_plugins_03-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugins_01-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugins_01-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugins_02-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugins_02-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_7-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_7-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0.ez: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0.ez -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0/ebin/mock_rabbitmq_plugins_01_app.beam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0/ebin/mock_rabbitmq_plugins_01_app.beam -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0/ebin/mock_rabbitmq_plugins_01_sup.beam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rabbitmq/rabbitmq-cli/HEAD/test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0/ebin/mock_rabbitmq_plugins_01_sup.beam -------------------------------------------------------------------------------- /test/fixtures/plugins/plugins_with_version_requirements/mock_rabbitmq_plugin_for_3_8-0.1.0/ebin/mock_rabbitmq_plugin_for_3_8.app: -------------------------------------------------------------------------------- 1 | {application, mock_rabbitmq_plugin_for_3_8, [ 2 | {description, "New project"}, 3 | {vsn, "0.1.0"}, 4 | {modules, ['mock_rabbitmq_plugins_01_app','mock_rabbitmq_plugins_01_sup']}, 5 | {registered, [mock_rabbitmq_plugins_01_sup]}, 6 | {applications, [kernel,stdlib,rabbit]}, 7 | {mod, {mock_rabbitmq_plugins_01_app, []}}, 8 | {env, []}, 9 | {broker_version_requirements, ["3.8.0", "3.9.0"]} 10 | ]}. 11 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/feature_flags.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.FeatureFlags do 8 | 9 | # 10 | # API 11 | # 12 | 13 | def feature_flag_lines(feature_flags) do 14 | feature_flags 15 | |> Enum.map(fn %{name: name, state: state} -> 16 | "Flag: #{name}, state: #{state}" 17 | end) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/merges_no_defaults.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.MergesNoDefaults do 10 | defmacro __using__(_) do 11 | quote do 12 | def merge_defaults(args, opts), do: {args, opts} 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/erlang.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Formatters.Erlang do 8 | @behaviour RabbitMQ.CLI.FormatterBehaviour 9 | 10 | def format_output(output, _) do 11 | :io_lib.format("~p", [output]) 12 | |> to_string 13 | end 14 | 15 | def format_stream(stream, options) do 16 | [format_output(Enum.to_list(stream), options)] 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/merges_default_virtual_host.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.MergesDefaultVirtualHost do 10 | defmacro __using__(_) do 11 | quote do 12 | def merge_defaults(args, opts), do: {args, Map.merge(%{vhost: "/"}, opts)} 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/msacc.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Formatters.Msacc do 8 | @behaviour RabbitMQ.CLI.FormatterBehaviour 9 | 10 | def format_output(output, _) do 11 | {:ok, io} = StringIO.open("") 12 | :msacc.print(io, output, %{}) 13 | StringIO.flush(io) 14 | end 15 | 16 | def format_stream(stream, options) do 17 | [format_output(Enum.to_list(stream), options)] 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/accepts_default_switches_and_timeout.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout do 10 | defmacro __using__(_) do 11 | quote do 12 | def switches(), do: [timeout: :integer] 13 | def aliases(), do: [t: :timeout] 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/requires_rabbit_app_running.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be running 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.RequiresRabbitAppRunning do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate_execution_environment(args, opts) do 13 | RabbitMQ.CLI.Core.Validators.rabbit_is_running(args, opts) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/requires_rabbit_app_stopped.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.RequiresRabbitAppStopped do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate_execution_environment(args, opts) do 13 | RabbitMQ.CLI.Core.Validators.rabbit_is_not_running(args, opts) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/data_coercion.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defprotocol RabbitMQ.CLI.Core.DataCoercion do 8 | def to_atom(data) 9 | end 10 | 11 | defimpl RabbitMQ.CLI.Core.DataCoercion, for: Atom do 12 | def to_atom(atom), do: atom 13 | end 14 | 15 | defimpl RabbitMQ.CLI.Core.DataCoercion, for: BitString do 16 | def to_atom(string), do: String.to_atom(string) 17 | end 18 | 19 | defimpl RabbitMQ.CLI.Core.DataCoercion, for: List do 20 | def to_atom(list), do: List.to_atom(list) 21 | end 22 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/printers/std_io.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Printers.StdIO do 8 | @behaviour RabbitMQ.CLI.PrinterBehaviour 9 | 10 | def init(_), do: {:ok, :ok} 11 | def finish(_), do: :ok 12 | 13 | def print_output(nil, _), do: :ok 14 | 15 | def print_output(output, _) when is_list(output) do 16 | for line <- output do 17 | IO.puts(line) 18 | end 19 | end 20 | 21 | def print_output(output, _) do 22 | IO.puts(output) 23 | end 24 | 25 | def print_ok(_) do 26 | :ok 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/printers/std_io_raw.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Printers.StdIORaw do 8 | @behaviour RabbitMQ.CLI.PrinterBehaviour 9 | 10 | def init(_), do: {:ok, :ok} 11 | def finish(_), do: :ok 12 | 13 | def print_output(nil, _), do: :ok 14 | 15 | def print_output(output, _) when is_list(output) do 16 | for line <- output do 17 | IO.write(line) 18 | end 19 | end 20 | 21 | def print_output(output, _) do 22 | IO.write(output) 23 | end 24 | 25 | def print_ok(_) do 26 | :ok 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/version.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.Version do 8 | @default_timeout 30_000 9 | 10 | def local_version do 11 | to_string(:rabbit_misc.version()) 12 | end 13 | 14 | 15 | def remote_version(node_name) do 16 | remote_version(node_name, @default_timeout) 17 | end 18 | def remote_version(node_name, timeout) do 19 | case :rabbit_misc.rpc_call(node_name, :rabbit_misc, :version, [], timeout) do 20 | {:badrpc, _} = err -> err 21 | val -> val 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /test/fixtures/files/definitions.json: -------------------------------------------------------------------------------- 1 | { 2 | "rabbit_version": "3.7.21", 3 | "vhosts": [ 4 | { 5 | "name": "\/" 6 | } 7 | ], 8 | "queues": [ 9 | 10 | ], 11 | "exchanges": [ 12 | { 13 | "name": "project.topic.default", 14 | "vhost": "\/", 15 | "type": "topic", 16 | "durable": true, 17 | "auto_delete": false, 18 | "internal": false, 19 | "arguments": { 20 | 21 | } 22 | } 23 | ], 24 | "bindings": [ 25 | 26 | ], 27 | 28 | "parameters": [ 29 | { 30 | "component": "federation-upstream", 31 | "name": "up-1", 32 | "value": { 33 | "ack-mode": "on-confirm", 34 | "trust-user-id": false, 35 | "uri": "amqp://127.0.0.1:5672" 36 | }, 37 | "vhost": "/" 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for using RabbitMQ. 2 | 3 | **STOP NOW AND READ THIS** BEFORE OPENING A NEW ISSUE ON GITHUB 4 | 5 | Unless you are CERTAIN you have found a reproducible problem in RabbitMQ or 6 | have a **specific, actionable** suggestion for our team, you must first ask 7 | your question or discuss your suspected issue on the mailing list: 8 | 9 | https://groups.google.com/forum/#!forum/rabbitmq-users 10 | 11 | Team RabbitMQ does not use GitHub issues for discussions, investigations, root 12 | cause analysis and so on. 13 | 14 | Please take the time to read the CONTRIBUTING.md document for instructions on 15 | how to effectively ask a question or report a suspected issue: 16 | 17 | https://github.com/rabbitmq/rabbitmq-server/blob/master/CONTRIBUTING.md#github-issues 18 | 19 | Following these rules **will save time** for both you and RabbitMQ's maintainers. 20 | 21 | Thank you. 22 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/accepts_no_positional_arguments.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.AcceptsNoPositionalArguments do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate(args, _) when length(args) > 0 do 13 | {:validation_failure, :too_many_args} 14 | end 15 | 16 | # Note: this will accept everything, so it must be the 17 | # last validation clause defined! 18 | def validate(_, _), do: :ok 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/printer_behaviour.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.PrinterBehaviour do 8 | @callback init(options :: map()) :: {:ok, printer_state :: any} | {:error, error :: any} 9 | @callback finish(printer_state :: any) :: :ok 10 | 11 | @callback print_output(output :: String.t() | [String.t()], printer_state :: any) :: :ok 12 | @callback print_ok(printer_state :: any) :: :ok 13 | 14 | def module_name(nil) do 15 | nil 16 | end 17 | def module_name(printer) do 18 | mod = printer |> String.downcase |> Macro.camelize 19 | String.to_atom("RabbitMQ.CLI.Printers." <> mod) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/string.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | ## Prints values from a command as strings(if possible) 8 | defmodule RabbitMQ.CLI.Formatters.String do 9 | alias RabbitMQ.CLI.Core.Helpers 10 | alias RabbitMQ.CLI.Formatters.FormatterHelpers 11 | 12 | @behaviour RabbitMQ.CLI.FormatterBehaviour 13 | 14 | def format_output(output, _) do 15 | Helpers.string_or_inspect(output) 16 | end 17 | 18 | def format_stream(stream, options) do 19 | Stream.map( 20 | stream, 21 | FormatterHelpers.without_errors_1(fn el -> 22 | format_output(el, options) 23 | end) 24 | ) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/ctl/version_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule VersionCommandTest do 9 | use ExUnit.Case 10 | 11 | @command RabbitMQ.CLI.Ctl.Commands.VersionCommand 12 | 13 | test "merge_defaults: merges no defaults" do 14 | assert @command.merge_defaults([], %{}) == {[], %{}} 15 | end 16 | 17 | test "validate: treats positional arguments as a failure" do 18 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 19 | end 20 | 21 | test "validate: treats empty positional arguments and default switches as a success" do 22 | assert @command.validate([], %{}) == :ok 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/erl_eval.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.ErlEval do 8 | def parse_expr(expr) do 9 | expr_str = to_charlist(expr) 10 | 11 | case :erl_scan.string(expr_str) do 12 | {:ok, scanned, _} -> 13 | case :erl_parse.parse_exprs(scanned) do 14 | {:ok, parsed} -> {:ok, parsed} 15 | {:error, err} -> {:error, format_parse_error(err)} 16 | end 17 | 18 | {:error, err, _} -> 19 | {:error, format_parse_error(err)} 20 | end 21 | end 22 | 23 | defp format_parse_error({_line, mod, err}) do 24 | to_string(:lists.flatten(mod.format_error(err))) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /.github/workflows/webhooks.yml: -------------------------------------------------------------------------------- 1 | # https://help.github.com/en/actions/reference/events-that-trigger-workflows#external-events-repository_dispatch 2 | # https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#example-calling-the-rest-api 3 | # https://developer.github.com/v3/repos/#create-a-repository-dispatch-event 4 | name: Webhook triggers 5 | on: 6 | push: 7 | branches: 8 | - master 9 | jobs: 10 | rabbitmq-server: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: New commit to rabbitmq-cli master branch 14 | run: | 15 | curl --silent --fail --url https://api.github.com/repos/rabbitmq/rabbitmq-server/dispatches \ 16 | --header "Authorization: Bearer ${{ secrets.PERSONAL_ACCESS_TOKEN }}" \ 17 | --header "Content-Type: application/json" \ 18 | --data '{ "event_type": "new-commit-to-dep-release-branch", "client_payload": { "dep": "rabbitmq-cli" } }' 19 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/start_app_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.StartAppCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | use RabbitMQ.CLI.DefaultOutput 10 | 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | 14 | def run([], %{node: node_name}) do 15 | :rabbit_misc.rpc_call(node_name, :rabbit, :start, []) 16 | end 17 | 18 | def usage, do: "start_app" 19 | 20 | def help_section(), do: :node_management 21 | 22 | def description(), do: "Starts the RabbitMQ application but leaves the runtime (Erlang VM) running" 23 | 24 | def banner(_, %{node: node_name}), do: "Starting node #{node_name} ..." 25 | end 26 | -------------------------------------------------------------------------------- /test/core/json_stream_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2019-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule JsonStreamTest do 8 | use ExUnit.Case, async: false 9 | 10 | @formatter RabbitMQ.CLI.Formatters.JsonStream 11 | 12 | test "format_output map with atom keys is converted to JSON object" do 13 | assert @formatter.format_output(%{a: :apple, b: :beer}, %{}) == "{\"a\":\"apple\",\"b\":\"beer\"}" 14 | end 15 | 16 | test "format_output map with binary keys is converted to JSON object" do 17 | assert @formatter.format_output(%{"a" => :apple, "b" => :beer}, %{}) == "{\"a\":\"apple\",\"b\":\"beer\"}" 18 | end 19 | 20 | test "format_output empty binary is converted to empty JSON array" do 21 | assert @formatter.format_output("", %{}) == "" 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/accepts_one_positional_argument.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.AcceptsOnePositionalArgument do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate(args, _) when length(args) == 0 do 13 | {:validation_failure, :not_enough_args} 14 | end 15 | 16 | def validate(args, _) when length(args) > 1 do 17 | {:validation_failure, :too_many_args} 18 | end 19 | 20 | # Note: this will accept everything, so it must be the 21 | # last validation clause defined! 22 | def validate(_, _), do: :ok 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/accepts_two_positional_arguments.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.AcceptsTwoPositionalArguments do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate(args, _) when length(args) < 2 do 13 | {:validation_failure, :not_enough_args} 14 | end 15 | 16 | def validate(args, _) when length(args) > 2 do 17 | {:validation_failure, :too_many_args} 18 | end 19 | 20 | # Note: this will accept everything, so it must be the 21 | # last validation clause defined! 22 | def validate([_, _], _), do: :ok 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/stop_app_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.StopAppCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | use RabbitMQ.CLI.Core.MergesNoDefaults 11 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 12 | 13 | def run([], %{node: node_name}) do 14 | :rabbit_misc.rpc_call(node_name, :rabbit, :stop, []) 15 | end 16 | 17 | use RabbitMQ.CLI.DefaultOutput 18 | 19 | def usage, do: "stop_app" 20 | 21 | def help_section(), do: :node_management 22 | 23 | def description(), do: "Stops the RabbitMQ application, leaving the runtime (Erlang VM) running" 24 | 25 | def banner(_, %{node: node_name}), do: "Stopping rabbit application on node #{node_name} ..." 26 | end 27 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/platform.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.Platform do 8 | def path_separator() do 9 | case :os.type() do 10 | {:unix, _} -> ":" 11 | {:win32, _} -> ";" 12 | end 13 | end 14 | 15 | def line_separator() do 16 | case :os.type() do 17 | {:unix, _} -> "\n" 18 | {:win32, _} -> "\r\n" 19 | end 20 | end 21 | 22 | def os_name({:unix, :linux}) do 23 | "Linux" 24 | end 25 | def os_name({:unix, :darwin}) do 26 | "macOS" 27 | end 28 | def os_name({:unix, :freebsd}) do 29 | "FreeBSD" 30 | end 31 | def os_name({:unix, name}) do 32 | name |> to_string |> String.capitalize 33 | end 34 | def os_name({:win32, _}) do 35 | "Windows" 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/rabbit_common/records.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitCommon.Records do 8 | require Record 9 | import Record, only: [defrecord: 2, extract: 2] 10 | 11 | # Important: amqqueue records must not be used directly since they are versioned 12 | # for mixed version cluster compatibility. Convert records 13 | # to maps on the server end to access the fields of those records. MK. 14 | defrecord :listener, extract(:listener, from_lib: "rabbit_common/include/rabbit.hrl") 15 | defrecord :plugin, extract(:plugin, from_lib: "rabbit_common/include/rabbit.hrl") 16 | defrecord :resource, extract(:resource, from_lib: "rabbit_common/include/rabbit.hrl") 17 | 18 | defrecord :hostent, extract(:hostent, from_lib: "kernel/include/inet.hrl") 19 | end 20 | -------------------------------------------------------------------------------- /test/ctl/list_hashes_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ListHashesCommandTest do 8 | use ExUnit.Case 9 | @command RabbitMQ.CLI.Ctl.Commands.ListHashesCommand 10 | 11 | test "merge_defaults: nothing to do" do 12 | assert @command.merge_defaults([], %{}) == {[], %{}} 13 | end 14 | 15 | test "validate: treats positional arguments as a failure" do 16 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 17 | end 18 | 19 | test "validate: treats empty positional arguments and default switches as a success" do 20 | assert @command.validate([], %{}) == :ok 21 | end 22 | 23 | test "run: lists hashes", _context do 24 | assert match?( 25 | {:ok, _}, 26 | @command.run([], %{}) 27 | ) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/ctl/list_ciphers_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ListCiphersCommandTest do 8 | use ExUnit.Case 9 | @command RabbitMQ.CLI.Ctl.Commands.ListCiphersCommand 10 | 11 | test "merge_defaults: nothing to do" do 12 | assert @command.merge_defaults([], %{}) == {[], %{}} 13 | end 14 | 15 | test "validate: treats positional arguments as a failure" do 16 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 17 | end 18 | 19 | test "validate: treats empty positional arguments and default switches as a success" do 20 | assert @command.validate([], %{}) == :ok 21 | end 22 | 23 | test "run: lists ciphers", _context do 24 | assert match?( 25 | {:ok, _}, 26 | @command.run([], %{}) 27 | ) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/printers/file.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Printers.File do 8 | @behaviour RabbitMQ.CLI.PrinterBehaviour 9 | 10 | def init(options) do 11 | file = options[:file] 12 | 13 | case File.open(file) do 14 | {:ok, io_device} -> {:ok, %{device: io_device}} 15 | {:error, err} -> {:error, err} 16 | end 17 | end 18 | 19 | def finish(%{device: io_device}) do 20 | :ok = File.close(io_device) 21 | end 22 | 23 | def print_output(output, %{device: io_device}) when is_list(output) do 24 | for line <- output do 25 | IO.puts(io_device, line) 26 | end 27 | end 28 | 29 | def print_output(output, %{device: io_device}) do 30 | IO.puts(io_device, output) 31 | end 32 | 33 | def print_ok(_) do 34 | :ok 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/input.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.Input do 8 | alias RabbitMQ.CLI.Core.Config 9 | 10 | def consume_single_line_string_with_prompt(prompt, opts) do 11 | val = case Config.output_less?(opts) do 12 | true -> 13 | IO.read(:stdio, :line) 14 | false -> 15 | IO.puts(prompt) 16 | IO.read(:stdio, :line) 17 | end 18 | 19 | case val do 20 | :eof -> :eof 21 | "" -> :eof 22 | s -> String.trim(s) 23 | end 24 | end 25 | 26 | def consume_multiline_string() do 27 | val = IO.read(:stdio, :all) 28 | 29 | case val do 30 | :eof -> :eof 31 | "" -> :eof 32 | s -> String.trim(s) 33 | end 34 | end 35 | 36 | def infer_password(prompt, opts) do 37 | consume_single_line_string_with_prompt(prompt, opts) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/ansi.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.ANSI do 8 | def bright(string) do 9 | "#{IO.ANSI.bright()}#{string}#{IO.ANSI.reset()}" 10 | end 11 | 12 | def red(string) do 13 | "#{IO.ANSI.red()}#{string}#{IO.ANSI.reset()}" 14 | end 15 | 16 | def yellow(string) do 17 | "#{IO.ANSI.yellow()}#{string}#{IO.ANSI.reset()}" 18 | end 19 | 20 | def magenta(string) do 21 | "#{IO.ANSI.magenta()}#{string}#{IO.ANSI.reset()}" 22 | end 23 | 24 | def bright_red(string) do 25 | "#{IO.ANSI.bright()}#{IO.ANSI.red()}#{string}#{IO.ANSI.reset()}" 26 | end 27 | 28 | def bright_yellow(string) do 29 | "#{IO.ANSI.bright()}#{IO.ANSI.yellow()}#{string}#{IO.ANSI.reset()}" 30 | end 31 | 32 | def bright_magenta(string) do 33 | "#{IO.ANSI.bright()}#{IO.ANSI.magenta()}#{string}#{IO.ANSI.reset()}" 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/rotate_logs_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.RotateLogsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit, :rotate_logs, []) 18 | end 19 | use RabbitMQ.CLI.DefaultOutput 20 | 21 | def usage, do: "rotate_logs" 22 | 23 | def usage_doc_guides() do 24 | [ 25 | DocGuide.logging() 26 | ] 27 | end 28 | 29 | def help_section(), do: :node_management 30 | 31 | def description(), do: "Instructs the RabbitMQ node to perform internal log rotation" 32 | 33 | def banner(_, %{node: node_name}), do: "Rotating logs for node #{node_name} ..." 34 | end 35 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/upgrade/commands/post_upgrade_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Upgrade.Commands.PostUpgradeCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 13 | use RabbitMQ.CLI.Core.MergesNoDefaults 14 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 15 | 16 | def run([], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_amqqueue, :rebalance, [:all, ".*", ".*"]) 18 | end 19 | 20 | use RabbitMQ.CLI.DefaultOutput 21 | 22 | def usage, do: "post_upgrade" 23 | 24 | def usage_doc_guides() do 25 | [ 26 | DocGuide.upgrade() 27 | ] 28 | end 29 | 30 | def help_section, do: :upgrade 31 | 32 | def description, do: "Runs post-upgrade tasks" 33 | 34 | def banner([], _) do 35 | "Executing post upgrade tasks...\n" <> 36 | "Rebalancing queue masters..." 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/time_unit.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.TimeUnit do 8 | require MapSet 9 | 10 | @days_seconds 86400 11 | @weeks_seconds @days_seconds * 7 12 | @months_seconds @days_seconds * (365 / 12) 13 | @years_seconds @days_seconds * 365 14 | 15 | def known_units() do 16 | MapSet.new([ 17 | "days", 18 | "weeks", 19 | "months", 20 | "years" 21 | ]) 22 | end 23 | 24 | def convert(time, unit) do 25 | do_convert(time, String.downcase(unit)) 26 | end 27 | 28 | def known_unit?(val) do 29 | MapSet.member?(known_units(), String.downcase(val)) 30 | end 31 | 32 | defp do_convert(time, "days") do 33 | time * @days_seconds 34 | end 35 | 36 | defp do_convert(time, "weeks") do 37 | time * @weeks_seconds 38 | end 39 | 40 | defp do_convert(time, "months") do 41 | time * @months_seconds 42 | end 43 | 44 | defp do_convert(time, "years") do 45 | time * @years_seconds 46 | end 47 | 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/inspect.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | alias RabbitMQ.CLI.Formatters.FormatterHelpers 7 | 8 | defmodule RabbitMQ.CLI.Formatters.Inspect do 9 | @behaviour RabbitMQ.CLI.FormatterBehaviour 10 | 11 | def format_output(output, _) do 12 | case is_binary(output) do 13 | true -> output 14 | false -> inspect(output) 15 | end 16 | end 17 | 18 | def format_stream(stream, options) do 19 | elements = 20 | Stream.scan( 21 | stream, 22 | :empty, 23 | FormatterHelpers.without_errors_2(fn element, previous -> 24 | separator = 25 | case previous do 26 | :empty -> "" 27 | _ -> "," 28 | end 29 | 30 | format_element(element, separator, options) 31 | end) 32 | ) 33 | 34 | Stream.concat([["["], elements, ["]"]]) 35 | end 36 | 37 | def format_element(val, separator, options) do 38 | separator <> format_output(val, options) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/accepts_one_positive_integer_argument.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Should be used by commands that require rabbit app to be stopped 8 | # but need no other execution environment validators. 9 | defmodule RabbitMQ.CLI.Core.AcceptsOnePositiveIntegerArgument do 10 | defmacro __using__(_) do 11 | quote do 12 | def validate(args, _) when length(args) == 0 do 13 | {:validation_failure, :not_enough_args} 14 | end 15 | 16 | def validate(args, _) when length(args) > 1 do 17 | {:validation_failure, :too_many_args} 18 | end 19 | 20 | def validate([value], _) when is_integer(value) do 21 | :ok 22 | end 23 | 24 | def validate([value], _) do 25 | case Integer.parse(value) do 26 | {n, _} when n >= 1 -> :ok 27 | :error -> {:validation_failure, {:bad_argument, "Argument must be a positive integer"}} 28 | end 29 | end 30 | 31 | def validate(_, _), do: :ok 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/maybe_stuck_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.MaybeStuckCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | use RabbitMQ.CLI.DefaultOutput 10 | 11 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([], %{node: node_name, timeout: timeout}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_diagnostics, :maybe_stuck, [], timeout) 18 | end 19 | 20 | def help_section(), do: :observability_and_health_checks 21 | 22 | def description(), do: "Detects Erlang processes (\"lightweight threads\") potentially not making progress on the target node" 23 | 24 | def usage, do: "maybe_stuck" 25 | 26 | def banner(_, %{node: node_name}) do 27 | "Asking node #{node_name} to detect potentially stuck Erlang processes..." 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_ciphers_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListCiphersCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def scopes(), do: [:ctl, :diagnostics] 14 | 15 | use RabbitMQ.CLI.Core.MergesNoDefaults 16 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 17 | 18 | def distribution(_), do: :none 19 | 20 | def run(_, _) do 21 | {:ok, :rabbit_pbe.supported_ciphers()} 22 | end 23 | 24 | def formatter(), do: RabbitMQ.CLI.Formatters.Erlang 25 | 26 | def usage, do: "list_ciphers" 27 | 28 | def usage_doc_guides() do 29 | [ 30 | DocGuide.configuration(), 31 | DocGuide.tls() 32 | ] 33 | end 34 | 35 | def help_section(), do: :observability_and_health_checks 36 | 37 | def description(), do: "Lists cipher suites supported by encoding commands" 38 | 39 | def banner(_, _), do: "Listing supported ciphers ..." 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_hashes_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListHashesCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def scopes(), do: [:ctl, :diagnostics] 14 | 15 | use RabbitMQ.CLI.Core.MergesNoDefaults 16 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 17 | 18 | def distribution(_), do: :none 19 | 20 | def run(_, _) do 21 | {:ok, :rabbit_pbe.supported_hashes()} 22 | end 23 | 24 | def formatter(), do: RabbitMQ.CLI.Formatters.Erlang 25 | 26 | def usage, do: "list_hashes" 27 | 28 | def usage_doc_guides() do 29 | [ 30 | DocGuide.configuration(), 31 | DocGuide.tls() 32 | ] 33 | end 34 | 35 | def help_section(), do: :observability_and_health_checks 36 | 37 | def description(), do: "Lists hash functions supported by encoding commands" 38 | 39 | def banner(_, _), do: "Listing supported hash algorithms ..." 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/force_gc_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ForceGcCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 15 | 16 | def run([], %{node: node_name, timeout: timeout}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_runtime, :gc_all_processes, [], timeout) 18 | end 19 | 20 | use RabbitMQ.CLI.DefaultOutput 21 | 22 | def usage, do: "force_gc" 23 | 24 | def usage_doc_guides() do 25 | [ 26 | DocGuide.memory_use() 27 | ] 28 | end 29 | 30 | def help_section(), do: :operations 31 | 32 | def description, do: "Makes all Erlang processes on the target node perform/schedule a full sweep garbage collection" 33 | 34 | def banner([], %{node: node_name}), do: "Will ask all processes on node #{node_name} to schedule a full sweep GC" 35 | end 36 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/version_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.VersionCommand do 8 | alias RabbitMQ.CLI.Core.{Validators, Version} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics, :plugins] 13 | 14 | use RabbitMQ.CLI.Core.MergesNoDefaults 15 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 16 | 17 | def validate_execution_environment([] = args, opts) do 18 | Validators.rabbit_is_loaded(args, opts) 19 | end 20 | 21 | def run([], %{formatter: "json"}) do 22 | {:ok, %{version: Version.local_version()}} 23 | end 24 | def run([], %{formatter: "csv"}) do 25 | row = [version: Version.local_version()] 26 | {:ok, [row]} 27 | end 28 | def run([], _opts) do 29 | {:ok, Version.local_version()} 30 | end 31 | use RabbitMQ.CLI.DefaultOutput 32 | 33 | def help_section, do: :help 34 | 35 | def description, do: "Displays CLI tools version" 36 | 37 | def usage, do: "version" 38 | 39 | def banner(_, _), do: nil 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/delete_vhost_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.DeleteVhostCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([arg], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_vhost, :delete, [arg, Helpers.cli_acting_user()]) 18 | end 19 | 20 | use RabbitMQ.CLI.DefaultOutput 21 | 22 | def usage, do: "delete_vhost " 23 | 24 | def usage_additional() do 25 | [ 26 | ["", "Name of the virtual host to delete."] 27 | ] 28 | end 29 | 30 | def usage_doc_guides() do 31 | [ 32 | DocGuide.virtual_hosts() 33 | ] 34 | end 35 | 36 | def help_section(), do: :virtual_hosts 37 | 38 | def description(), do: "Deletes a virtual host" 39 | 40 | def banner([arg], _), do: "Deleting vhost \"#{arg}\" ..." 41 | end 42 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/environment_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.EnvironmentCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | def scopes(), do: [:ctl, :diagnostics] 12 | 13 | use RabbitMQ.CLI.Core.MergesNoDefaults 14 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 15 | 16 | def run([], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit, :environment, []) 18 | end 19 | 20 | use RabbitMQ.CLI.DefaultOutput 21 | 22 | def formatter(), do: RabbitMQ.CLI.Formatters.Erlang 23 | 24 | def usage, do: "environment" 25 | 26 | def usage_doc_guides() do 27 | [ 28 | DocGuide.configuration(), 29 | DocGuide.monitoring() 30 | ] 31 | end 32 | 33 | def help_section(), do: :configuration 34 | 35 | def description(), do: "Displays the name and value of each variable in the application environment for each running application" 36 | 37 | def banner(_, %{node: node_name}), do: "Application environment of node #{node_name} ..." 38 | end 39 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/trace_off_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.TraceOffCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def merge_defaults(_, opts) do 13 | {[], Map.merge(%{vhost: "/"}, opts)} 14 | end 15 | 16 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 17 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 18 | 19 | def run([], %{node: node_name, vhost: vhost}) do 20 | case :rabbit_misc.rpc_call(node_name, :rabbit_trace, :stop, [vhost]) do 21 | :ok -> {:ok, "Trace disabled for vhost #{vhost}"} 22 | other -> other 23 | end 24 | end 25 | 26 | use RabbitMQ.CLI.DefaultOutput 27 | 28 | def usage do 29 | "trace_off [--vhost ]" 30 | end 31 | 32 | def usage_doc_guides() do 33 | [ 34 | DocGuide.firehose(), 35 | DocGuide.virtual_hosts() 36 | ] 37 | end 38 | 39 | def help_section(), do: :virtual_hosts 40 | 41 | def banner(_, %{vhost: vhost}), do: "Stopping tracing for vhost \"#{vhost}\" ..." 42 | end 43 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/trace_on_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.TraceOnCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def merge_defaults(_, opts) do 13 | {[], Map.merge(%{vhost: "/"}, opts)} 14 | end 15 | 16 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 17 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 18 | 19 | def run([], %{node: node_name, vhost: vhost}) do 20 | case :rabbit_misc.rpc_call(node_name, :rabbit_trace, :start, [vhost]) do 21 | :ok -> {:ok, "Trace enabled for vhost #{vhost}"} 22 | other -> other 23 | end 24 | end 25 | 26 | use RabbitMQ.CLI.DefaultOutput 27 | 28 | def usage do 29 | "trace_on [--vhost ]" 30 | end 31 | 32 | def usage_doc_guides() do 33 | [ 34 | DocGuide.firehose(), 35 | DocGuide.virtual_hosts() 36 | ] 37 | end 38 | 39 | def help_section(), do: :virtual_hosts 40 | 41 | def banner(_, %{vhost: vhost}), do: "Starting tracing for vhost \"#{vhost}\" ..." 42 | end 43 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/reset_node_auth_attempt_metrics_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.ResetNodeAuthAttemptMetricsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 14 | 15 | def run([], %{node: node_name}) do 16 | :rabbit_misc.rpc_call(node_name, :rabbit_core_metrics, :reset_auth_attempt_metrics, []) 17 | end 18 | 19 | def usage, do: "reset_node_auth_attempt_metrics" 20 | 21 | def usage_doc_guides() do 22 | [ 23 | DocGuide.access_control(), 24 | DocGuide.monitoring() 25 | ] 26 | end 27 | 28 | def help_section(), do: :configuration 29 | 30 | def description(), do: "Resets auth attempt metrics on the target node" 31 | 32 | def banner([], %{node: node_name}) do 33 | "Reset auth attempt metrics on node #{node_name} ..." 34 | end 35 | 36 | use RabbitMQ.CLI.DefaultOutput 37 | end 38 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/discover_peers_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.DiscoverPeersCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 14 | 15 | def run([], %{node: node_name, timeout: timeout}) do 16 | :rabbit_misc.rpc_call(node_name, :rabbit_peer_discovery, :discover_cluster_nodes, [], timeout) 17 | end 18 | 19 | def output({:ok, {[], _}}, _options) do 20 | {:ok, "No peers discovered"} 21 | end 22 | 23 | def output({:ok, {nodes, _}}, _options) do 24 | {:ok, nodes} 25 | end 26 | 27 | use RabbitMQ.CLI.DefaultOutput 28 | 29 | def help_section(), do: :observability_and_health_checks 30 | 31 | def description(), do: "Performs peer discovery and lists discovered nodes, if any" 32 | 33 | def usage, do: "discover_peers" 34 | 35 | def banner(_, _), do: "Discovering peers nodes ..." 36 | end 37 | -------------------------------------------------------------------------------- /test/ctl/rotate_logs_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule RotateLogsCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.RotateLogsCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname()}} 22 | end 23 | 24 | test "validate: with extra arguments returns an arg count error", context do 25 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 26 | end 27 | 28 | test "run: request to a named, active node succeeds", context do 29 | assert @command.run([], context[:opts]) == :ok 30 | end 31 | 32 | test "run: request to a non-existent node returns a badrpc" do 33 | opts = %{node: :jake@thedog, timeout: 200} 34 | assert match?({:badrpc, _}, @command.run([], opts)) 35 | end 36 | 37 | test "banner", context do 38 | assert @command.banner([], context[:opts]) =~ ~r/Rotating logs for node #{get_rabbit_hostname()}/ 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/ctl/status_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule StatusCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.StatusCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 60_000}} 22 | end 23 | 24 | test "validate: with extra arguments returns an arg count error", context do 25 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 26 | end 27 | 28 | test "run: request to a named, active node succeeds", context do 29 | assert @command.run([], context[:opts])[:pid] != nil 30 | end 31 | 32 | test "run: request to a non-existent node returns a badrpc" do 33 | opts = %{node: :jake@thedog, timeout: 200} 34 | assert match?({:badrpc, _}, @command.run([], opts)) 35 | end 36 | 37 | test "banner", context do 38 | assert @command.banner([], context[:opts]) =~ ~r/Status of node #{get_rabbit_hostname()}/ 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_vhost_limits_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearVhostLimitsCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 18 | 19 | def run([], %{node: node_name, vhost: vhost}) do 20 | :rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :clear, [ 21 | vhost, 22 | Helpers.cli_acting_user() 23 | ]) 24 | end 25 | 26 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 27 | 28 | def usage, do: "clear_vhost_limits [--vhost ]" 29 | 30 | def usage_doc_guides() do 31 | [ 32 | DocGuide.virtual_hosts() 33 | ] 34 | end 35 | 36 | def help_section(), do: :virtual_hosts 37 | 38 | def description(), do: "Clears virtual host limits" 39 | 40 | def banner([], %{vhost: vhost}) do 41 | "Clearing vhost \"#{vhost}\" limits ..." 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/disable_auth_attempt_source_tracking_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.DisableAuthAttemptSourceTrackingCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 14 | 15 | def run([], %{node: node_name}) do 16 | :rabbit_misc.rpc_call(node_name, :application, :set_env, 17 | [:rabbit, :track_auth_attempt_source, :false]) 18 | end 19 | use RabbitMQ.CLI.DefaultOutput 20 | 21 | def usage, do: "disable_track_auth_attempt_source" 22 | 23 | def usage_doc_guides() do 24 | [ 25 | DocGuide.access_control(), 26 | DocGuide.monitoring() 27 | ] 28 | end 29 | 30 | def help_section(), do: :configuration 31 | 32 | def description(), do: "Disables the tracking of peer IP address and username of authentication attempts" 33 | 34 | def banner([], _), do: "Disabling authentication attempt source tracking ..." 35 | end 36 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/diagnostics_helpers.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Helpers do 8 | def test_connection(hostname, port, timeout) do 9 | case :gen_tcp.connect(hostname, port, [], timeout) do 10 | {:error, _} -> :gen_tcp.connect(hostname, port, [:inet6], timeout) 11 | r -> r 12 | end 13 | end 14 | 15 | def check_port_connectivity(port, node_name, timeout) do 16 | regex = Regex.recompile!(~r/^(.+)@/) 17 | hostname = Regex.replace(regex, to_string(node_name), "") |> to_charlist 18 | try do 19 | case test_connection(hostname, port, timeout) do 20 | {:error, _} -> 21 | false 22 | 23 | {:ok, port} -> 24 | :ok = :gen_tcp.close(port) 25 | true 26 | end 27 | 28 | # `gen_tcp:connect/4` will throw if the port is outside of its 29 | # expected domain 30 | catch 31 | :exit, _ -> false 32 | end 33 | end 34 | 35 | def check_listener_connectivity(%{port: port}, node_name, timeout) do 36 | check_port_connectivity(port, node_name, timeout) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/enable_auth_attempt_source_tracking_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.EnableAuthAttemptSourceTrackingCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 14 | 15 | def run([], %{node: node_name}) do 16 | :rabbit_misc.rpc_call(node_name, :application, :set_env, 17 | [:rabbit, :track_auth_attempt_source, :true]) 18 | end 19 | 20 | use RabbitMQ.CLI.DefaultOutput 21 | 22 | def usage, do: "enable_auth_attempt_source_tracking" 23 | 24 | def usage_doc_guides() do 25 | [ 26 | DocGuide.access_control(), 27 | DocGuide.monitoring() 28 | ] 29 | end 30 | 31 | def help_section(), do: :configuration 32 | 33 | def description(), do: "Enables the tracking of peer IP address and username of authentication attempts" 34 | 35 | def banner([], _), do: "Enabling authentication attempt source tracking ..." 36 | end 37 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/erlang_cookie_hash_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.ErlangCookieHashCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | 14 | def run([], %{node: node_name, timeout: timeout}) do 15 | :rabbit_data_coercion.to_binary( 16 | :rabbit_misc.rpc_call(node_name, :rabbit_nodes_common, :cookie_hash, [], timeout)) 17 | end 18 | 19 | def output(result, %{formatter: "json"}) do 20 | {:ok, %{"result" => "ok", "value" => result}} 21 | end 22 | def output(result, _options) when is_bitstring(result) do 23 | {:ok, result} 24 | end 25 | 26 | def help_section(), do: :configuration 27 | 28 | def description(), do: "Displays a hash of the Erlang cookie (shared secret) used by the target node" 29 | 30 | def usage, do: "erlang_cookie_hash" 31 | 32 | def banner([], %{node: node_name}) do 33 | "Asking node #{node_name} its Erlang cookie hash..." 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/server_version_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.ServerVersionCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | 14 | def run([], %{node: node_name, timeout: timeout}) do 15 | :rabbit_data_coercion.to_binary( 16 | :rabbit_misc.rpc_call(node_name, :rabbit_misc, :version, [], timeout)) 17 | end 18 | 19 | def output(result, %{formatter: "json"}) do 20 | {:ok, %{"result" => "ok", "value" => result}} 21 | end 22 | def output(result, _options) when is_bitstring(result) do 23 | {:ok, result} 24 | end 25 | 26 | use RabbitMQ.CLI.DefaultOutput 27 | 28 | def help_section(), do: :observability_and_health_checks 29 | 30 | def description(), do: "Displays server version on the target node" 31 | 32 | def usage, do: "server_version" 33 | 34 | def banner([], %{node: node_name}) do 35 | "Asking node #{node_name} for its RabbitMQ version..." 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/diagnostics/erlang_cookie_sources_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ErlangCookieSourcesCommandTest do 8 | use ExUnit.Case, async: true 9 | 10 | @command RabbitMQ.CLI.Diagnostics.Commands.ErlangCookieSourcesCommand 11 | 12 | setup _context do 13 | {:ok, opts: %{}} 14 | end 15 | 16 | test "merge_defaults: merges no defaults" do 17 | assert @command.merge_defaults([], %{}) == {[], %{}} 18 | end 19 | 20 | test "validate: treats positional arguments as a failure" do 21 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 22 | end 23 | 24 | test "validate: treats empty positional arguments and default switches as a success" do 25 | assert @command.validate([], %{}) == :ok 26 | end 27 | 28 | test "run: returns Erlang cookie sources info", context do 29 | result = @command.run([], context[:opts]) 30 | 31 | assert result[:effective_user] != nil 32 | assert result[:home_dir] != nil 33 | assert result[:cookie_file_path] != nil 34 | assert result[:cookie_file_exists] != nil 35 | assert result[:cookie_file_access] != nil 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/string_per_line.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Formatters.StringPerLine do 8 | @doc """ 9 | Use this to output one stream (collection) element per line, 10 | using the string formatter. Flattens the stream. 11 | """ 12 | 13 | alias RabbitMQ.CLI.Formatters.FormatterHelpers 14 | alias RabbitMQ.CLI.Core.Helpers 15 | import RabbitMQ.CLI.Core.Platform, only: [line_separator: 0] 16 | 17 | @behaviour RabbitMQ.CLI.FormatterBehaviour 18 | 19 | def format_output(output, _) do 20 | Enum.map(output, fn el -> Helpers.string_or_inspect(el) end) 21 | end 22 | 23 | def format_stream(stream, options) do 24 | Stream.scan( 25 | stream, 26 | :empty, 27 | FormatterHelpers.without_errors_2(fn element, previous -> 28 | separator = 29 | case previous do 30 | :empty -> "" 31 | _ -> line_separator() 32 | end 33 | 34 | format_element(element, separator, options) 35 | end) 36 | ) 37 | end 38 | 39 | def format_element(val, separator, options) do 40 | separator <> format_output(val, options) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/reset_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ResetCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppStopped 15 | 16 | def run([], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :reset, []) 18 | end 19 | 20 | def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do 21 | {:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(), 22 | RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)} 23 | end 24 | 25 | use RabbitMQ.CLI.DefaultOutput 26 | 27 | def usage, do: "reset" 28 | 29 | def usage_doc_guides() do 30 | [ 31 | DocGuide.clustering() 32 | ] 33 | end 34 | 35 | def help_section(), do: :node_management 36 | 37 | def description(), do: "Instructs a RabbitMQ node to leave the cluster and return to its virgin state" 38 | 39 | def banner(_, %{node: node_name}), do: "Resetting node #{node_name} ..." 40 | end 41 | -------------------------------------------------------------------------------- /test/core/distribution_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | alias RabbitMQ.CLI.Core.Distribution 8 | 9 | defmodule DistributionTest do 10 | use ExUnit.Case, async: false 11 | 12 | setup_all do 13 | :net_kernel.stop() 14 | :ok 15 | end 16 | 17 | test "set cookie via environment variable" do 18 | on_exit(fn -> 19 | :net_kernel.stop() 20 | System.delete_env("RABBITMQ_ERLANG_COOKIE") 21 | end) 22 | try do 23 | :nocookie = Node.get_cookie() 24 | catch 25 | # one of net_kernel processes is not running ¯\_(ツ)_/¯ 26 | :exit, _ -> :ok 27 | end 28 | System.put_env("RABBITMQ_ERLANG_COOKIE", "mycookie") 29 | opts = %{} 30 | Distribution.start(opts) 31 | :mycookie = Node.get_cookie() 32 | end 33 | 34 | test "set cookie via argument" do 35 | on_exit(fn -> 36 | :net_kernel.stop() 37 | end) 38 | try do 39 | :nocookie = Node.get_cookie() 40 | catch 41 | # one of net_kernel processes is not running ¯\_(ツ)_/¯ 42 | :exit, _ -> :ok 43 | end 44 | opts = %{erlang_cookie: :mycookie} 45 | Distribution.start(opts) 46 | :mycookie = Node.get_cookie() 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/force_reset_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ForceResetCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, ExitCodes} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppStopped 15 | 16 | def run([], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :force_reset, []) 18 | end 19 | 20 | def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do 21 | {:error, ExitCodes.exit_software(), 22 | RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)} 23 | end 24 | 25 | use RabbitMQ.CLI.DefaultOutput 26 | 27 | def usage, do: "force_reset" 28 | 29 | def usage_doc_guides() do 30 | [ 31 | DocGuide.clustering() 32 | ] 33 | end 34 | 35 | def help_section(), do: :cluster_management 36 | 37 | def description(), do: "Forcefully returns a RabbitMQ node to its virgin state" 38 | 39 | def banner(_, %{node: node_name}), do: "Forcefully resetting node #{node_name} ..." 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_users_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListUsersCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{table_headers: true}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([], %{node: node_name, timeout: timeout}) do 23 | :rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :list_users, [], timeout) 24 | end 25 | 26 | use RabbitMQ.CLI.DefaultOutput 27 | 28 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 29 | 30 | def usage, do: "list_users [--no-table-headers]" 31 | 32 | def usage_doc_guides() do 33 | [ 34 | DocGuide.access_control() 35 | ] 36 | end 37 | 38 | def help_section(), do: :user_management 39 | 40 | def description(), do: "List user names and tags" 41 | 42 | def banner(_, _), do: "Listing users ..." 43 | end 44 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatter_behaviour.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | # Formats returned values e.g. to human-readable text or JSON. 8 | defmodule RabbitMQ.CLI.FormatterBehaviour do 9 | alias RabbitMQ.CLI.Core.Helpers 10 | 11 | @callback format_output(any, map()) :: String.t() | [String.t()] 12 | @callback format_stream(Enumerable.t(), map()) :: Enumerable.t() 13 | 14 | @optional_callbacks switches: 0, 15 | aliases: 0 16 | 17 | @callback switches() :: Keyword.t() 18 | @callback aliases() :: Keyword.t() 19 | 20 | def switches(formatter) do 21 | Helpers.apply_if_exported(formatter, :switches, [], []) 22 | end 23 | 24 | def aliases(formatter) do 25 | Helpers.apply_if_exported(formatter, :aliases, [], []) 26 | end 27 | 28 | def module_name(nil) do 29 | nil 30 | end 31 | def module_name(formatter) do 32 | mod = formatter |> String.downcase |> Macro.camelize 33 | Module.safe_concat("RabbitMQ.CLI.Formatters", mod) 34 | end 35 | 36 | def machine_readable?(nil) do 37 | false 38 | end 39 | def machine_readable?(formatter) do 40 | Helpers.apply_if_exported(module_name(formatter), :machine_readable?, [], false) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/set_cluster_name_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SetClusterNameCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([cluster_name], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_nodes, :set_cluster_name, [ 18 | cluster_name, 19 | Helpers.cli_acting_user() 20 | ]) 21 | end 22 | 23 | use RabbitMQ.CLI.DefaultOutput 24 | 25 | def banner([cluster_name], _) do 26 | "Setting cluster name to #{cluster_name} ..." 27 | end 28 | 29 | def usage, do: "set_cluster_name " 30 | 31 | def usage_additional() do 32 | [ 33 | ["", "New cluster name"] 34 | ] 35 | end 36 | 37 | def usage_doc_guides() do 38 | [ 39 | DocGuide.virtual_hosts(), 40 | DocGuide.access_control() 41 | ] 42 | end 43 | 44 | def help_section(), do: :configuration 45 | 46 | def description(), do: "Sets the cluster name" 47 | end 48 | -------------------------------------------------------------------------------- /test/ctl/force_gc_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ForceGcCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.ForceGcCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | reset_vm_memory_high_watermark() 18 | 19 | on_exit([], fn -> 20 | reset_vm_memory_high_watermark() 21 | end) 22 | 23 | :ok 24 | end 25 | 26 | setup do 27 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 200}} 28 | end 29 | 30 | 31 | test "merge_defaults: merge not defaults" do 32 | assert @command.merge_defaults([], %{}) == {[], %{}} 33 | end 34 | 35 | test "validate: with extra arguments returns an error", context do 36 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 37 | end 38 | 39 | test "run: request to a non-existent node returns a badrpc" do 40 | assert match?({:badrpc, _}, @command.run([], %{node: :jake@thedog, timeout: 200})) 41 | end 42 | 43 | test "run: request to a named, active node succeeds", context do 44 | assert @command.run([], context[:opts]) == :ok 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_global_parameter_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearGlobalParameterCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([key], %{node: node_name}) do 17 | :rabbit_misc.rpc_call( 18 | node_name, 19 | :rabbit_runtime_parameters, 20 | :clear_global, 21 | [key, Helpers.cli_acting_user()] 22 | ) 23 | end 24 | 25 | use RabbitMQ.CLI.DefaultOutput 26 | 27 | def usage, do: "clear_global_parameter " 28 | 29 | def usage_additional() do 30 | [ 31 | ["", "parameter name (identifier)"] 32 | ] 33 | end 34 | 35 | def usage_doc_guides() do 36 | [ 37 | DocGuide.parameters() 38 | ] 39 | end 40 | 41 | def help_section(), do: :parameters 42 | 43 | def description(), do: "Clears a global runtime parameter" 44 | 45 | def banner([key], _) do 46 | "Clearing global runtime parameter \"#{key}\" ..." 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/command_line_arguments_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.CommandLineArgumentsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | def scopes(), do: [:diagnostics] 12 | 13 | use RabbitMQ.CLI.Core.MergesNoDefaults 14 | 15 | def validate(_, %{formatter: "json"}) do 16 | {:validation_failure, :unsupported_formatter} 17 | end 18 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 19 | 20 | def run([], %{node: node_name}) do 21 | :rabbit_misc.rpc_call(node_name, :init, :get_arguments, []) 22 | end 23 | use RabbitMQ.CLI.DefaultOutput 24 | 25 | def formatter(), do: RabbitMQ.CLI.Formatters.Erlang 26 | 27 | def usage, do: "command_line_arguments" 28 | 29 | def usage_doc_guides() do 30 | [ 31 | DocGuide.configuration(), 32 | DocGuide.monitoring() 33 | ] 34 | end 35 | 36 | def help_section(), do: :configuration 37 | 38 | def description(), do: "Displays target node's command-line arguments and flags as reported by the runtime" 39 | 40 | def banner(_, %{node: node_name}), do: "Command line arguments of node #{node_name} ..." 41 | end 42 | -------------------------------------------------------------------------------- /test/ctl/report_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ReportTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.ReportCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: :infinity}} 22 | end 23 | 24 | test "validate: with extra arguments, status returns an arg count error", context do 25 | assert @command.validate(["extra"], context[:opts]) == 26 | {:validation_failure, :too_many_args} 27 | end 28 | 29 | test "run: report request to a reachable node succeeds", context do 30 | output = @command.run([], context[:opts]) |> Enum.to_list 31 | 32 | assert_stream_without_errors(output) 33 | end 34 | 35 | test "run: report request on nonexistent RabbitMQ node returns a badrpc" do 36 | opts = %{node: :jake@thedog, timeout: 200} 37 | assert match?({:badrpc, _}, @command.run([], opts)) 38 | end 39 | 40 | test "banner", context do 41 | assert @command.banner([], context[:opts]) 42 | =~ ~r/Reporting server status of node #{get_rabbit_hostname()}/ 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/diagnostics/observer_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ObserverCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.ObserverCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | interval: 5, 24 | timeout: context[:test_timeout] || 15000 25 | }} 26 | end 27 | 28 | test "merge_defaults: injects a default interval of 5s" do 29 | assert @command.merge_defaults([], %{}) == {[], %{interval: 5}} 30 | end 31 | 32 | test "validate: treats positional arguments as a failure" do 33 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 34 | end 35 | 36 | test "validate: treats empty positional arguments and default switches as a success" do 37 | assert @command.validate([], %{}) == :ok 38 | end 39 | 40 | @tag test_timeout: 3000 41 | test "run: targeting an unreachable node throws a badrpc" do 42 | assert match?({:badrpc, _}, @command.run([], %{node: :jake@thedog, interval: 5})) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/diagnostics/list_network_interfaces_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ListNetworkInterfacesCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.ListNetworkInterfacesCommand 12 | setup_all do 13 | RabbitMQ.CLI.Core.Distribution.start() 14 | :ok 15 | end 16 | 17 | setup context do 18 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: context[:test_timeout]}} 19 | end 20 | 21 | test "validate: providing no arguments passes validation", context do 22 | assert @command.validate([], context[:opts]) == :ok 23 | end 24 | 25 | test "validate: providing any arguments fails validation", context do 26 | assert @command.validate(["a"], context[:opts]) == 27 | {:validation_failure, :too_many_args} 28 | end 29 | 30 | @tag test_timeout: 3000 31 | test "run: targeting an unreachable node throws a badrpc", context do 32 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 33 | end 34 | 35 | @tag test_timeout: 15000 36 | test "run: returns a map of interfaces", context do 37 | assert match?(%{}, @command.run([], context[:opts])) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_password_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearPasswordCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([_user] = args, %{node: node_name}) do 17 | :rabbit_misc.rpc_call( 18 | node_name, 19 | :rabbit_auth_backend_internal, 20 | :clear_password, 21 | args ++ [Helpers.cli_acting_user()] 22 | ) 23 | end 24 | 25 | use RabbitMQ.CLI.DefaultOutput 26 | 27 | def usage, do: "clear_password " 28 | 29 | def usage_additional() do 30 | [ 31 | ["", "Name of the user whose password should be cleared"] 32 | ] 33 | end 34 | 35 | def usage_doc_guides() do 36 | [ 37 | DocGuide.access_control() 38 | ] 39 | end 40 | 41 | def help_section(), do: :user_management 42 | 43 | def description(), do: "Clears (resets) password and disables password login for a user" 44 | 45 | def banner([user], _), do: "Clearing password for user \"#{user}\" ..." 46 | end 47 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/tls_versions_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.TlsVersionsCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 11 | use RabbitMQ.CLI.Core.MergesNoDefaults 12 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 13 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 14 | 15 | def run([], %{node: node_name, timeout: timeout} = _opts) do 16 | :rabbit_misc.rpc_call(node_name, :ssl, :versions, [], timeout) 17 | end 18 | 19 | def banner([], %{}), do: "Listing all TLS versions supported by the runtime..." 20 | 21 | def output(result, %{formatter: "json"}) do 22 | vs = Map.new(result) |> Map.get(:available) 23 | 24 | {:ok, %{versions: vs}} 25 | end 26 | 27 | def output(result, _opts) do 28 | vs = Map.new(result) |> Map.get(:available) 29 | {:ok, vs} 30 | end 31 | 32 | def help_section(), do: :observability_and_health_checks 33 | 34 | def description(), do: "Lists TLS versions supported (but not necessarily allowed) on the target node" 35 | 36 | def usage, do: "tls_versions" 37 | 38 | def formatter(), do: RabbitMQ.CLI.Formatters.StringPerLine 39 | end 40 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/await_startup_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.AwaitStartupCommand do 8 | @moduledoc """ 9 | Waits until target node is fully booted. If the node is already running, 10 | returns immediately. 11 | 12 | This command is meant to be used when automating deployments. 13 | See also `AwaitOnlineNodesCommand`. 14 | """ 15 | 16 | import RabbitMQ.CLI.Core.Config, only: [output_less?: 1] 17 | 18 | @behaviour RabbitMQ.CLI.CommandBehaviour 19 | 20 | @default_timeout 300_000 21 | 22 | def merge_defaults(args, opts) do 23 | {args, Map.merge(%{timeout: @default_timeout}, opts)} 24 | end 25 | 26 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 27 | 28 | def run([], %{node: node_name, timeout: timeout} = opts) do 29 | :rabbit_misc.rpc_call(node_name, :rabbit, :await_startup, [ 30 | node_name, 31 | not output_less?(opts), 32 | timeout 33 | ]) 34 | end 35 | 36 | use RabbitMQ.CLI.DefaultOutput 37 | 38 | def usage, do: "await_startup" 39 | 40 | def help_section(), do: :node_management 41 | 42 | def description(), do: "Waits for the RabbitMQ application to start on the target node" 43 | 44 | def banner(_, _), do: nil 45 | end 46 | -------------------------------------------------------------------------------- /test/diagnostics/discover_peers_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule DiscoverPeersCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.DiscoverPeersCommand 12 | setup_all do 13 | RabbitMQ.CLI.Core.Distribution.start() 14 | :ok 15 | end 16 | 17 | setup context do 18 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: context[:test_timeout]}} 19 | end 20 | 21 | test "validate: providing no arguments passes validation", context do 22 | assert @command.validate([], context[:opts]) == :ok 23 | end 24 | 25 | test "validate: providing any arguments fails validation", context do 26 | assert @command.validate(["a"], context[:opts]) == 27 | {:validation_failure, :too_many_args} 28 | end 29 | 30 | @tag test_timeout: 3000 31 | test "run: targeting an unreachable node throws a badrpc", context do 32 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 33 | end 34 | 35 | @tag test_timeout: 15000 36 | test "run: returns a list of nodes when the backend isn't configured", context do 37 | assert match?({:ok, {[], _}}, @command.run([], context[:opts])) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_policy_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearPolicyCommand do 8 | alias RabbitMQ.CLI.Core.{Helpers, DocGuide} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 18 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 19 | 20 | def run([key], %{node: node_name, vhost: vhost}) do 21 | :rabbit_misc.rpc_call(node_name, :rabbit_policy, :delete, [ 22 | vhost, 23 | key, 24 | Helpers.cli_acting_user() 25 | ]) 26 | end 27 | 28 | def usage, do: "clear_policy [--vhost ] " 29 | 30 | def usage_additional() do 31 | [ 32 | ["", "Name of policy to clear (remove)"] 33 | ] 34 | end 35 | 36 | def usage_doc_guides() do 37 | [ 38 | DocGuide.parameters() 39 | ] 40 | end 41 | 42 | def help_section(), do: :policies 43 | 44 | def description(), do: "Clears (removes) a policy" 45 | 46 | def banner([key], %{vhost: vhost}) do 47 | "Clearing policy \"#{key}\" on vhost \"#{vhost}\" ..." 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/diagnostics/list_node_auth_attempt_stats_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ListNodeAuthAttemptStatsCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.ListNodeAuthAttemptStatsCommand 12 | setup_all do 13 | RabbitMQ.CLI.Core.Distribution.start() 14 | :ok 15 | end 16 | 17 | setup context do 18 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: context[:test_timeout], by_source: false}} 19 | end 20 | 21 | test "validate: providing no arguments passes validation", context do 22 | assert @command.validate([], context[:opts]) == :ok 23 | end 24 | 25 | test "validate: providing any arguments fails validation", context do 26 | assert @command.validate(["a"], context[:opts]) == 27 | {:validation_failure, :too_many_args} 28 | end 29 | 30 | @tag test_timeout: 3000 31 | test "run: targeting an unreachable node throws a badrpc", context do 32 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 33 | end 34 | 35 | @tag test_timeout: 15000 36 | test "run: returns auth attempt stats", context do 37 | assert is_list(@command.run([], context[:opts])) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/upgrade/await_online_quorum_plus_one_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule AwaitOnlineQuorumPlusOneCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Upgrade.Commands.AwaitOnlineQuorumPlusOneCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 5000 24 | }} 25 | end 26 | 27 | test "merge_defaults: overrides a timeout" do 28 | assert @command.merge_defaults([], %{}) == {[], %{timeout: 120_000}} 29 | end 30 | 31 | test "validate: accepts no positional arguments" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: succeeds with no positional arguments" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | opts = %{node: :jake@thedog, timeout: 200} 42 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /test/diagnostics/enable_auth_attempt_source_tracking_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule EnableAuthAttemptSourceTrackingCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.EnableAuthAttemptSourceTrackingCommand 12 | setup_all do 13 | RabbitMQ.CLI.Core.Distribution.start() 14 | :ok 15 | end 16 | 17 | setup context do 18 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: context[:test_timeout]}} 19 | end 20 | 21 | test "validate: providing no arguments passes validation", context do 22 | assert @command.validate([], context[:opts]) == :ok 23 | end 24 | 25 | test "validate: providing any arguments fails validation", context do 26 | assert @command.validate(["a"], context[:opts]) == 27 | {:validation_failure, :too_many_args} 28 | end 29 | 30 | @tag test_timeout: 3000 31 | test "run: targeting an unreachable node throws a badrpc", context do 32 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 33 | end 34 | 35 | @tag test_timeout: 15000 36 | test "run: enables source tracking for auth attempt stats", context do 37 | assert :ok = @command.run([], context[:opts]) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/upgrade/await_online_synchronized_mirror_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule AwaitOnlineSynchronizedMirrorsCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Upgrade.Commands.AwaitOnlineSynchronizedMirrorCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 5000 24 | }} 25 | end 26 | 27 | test "merge_defaults: overrides a timeout" do 28 | assert @command.merge_defaults([], %{}) == {[], %{timeout: 120_000}} 29 | end 30 | 31 | test "validate: accepts no positional arguments" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: succeeds with no positional arguments" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | opts = %{node: :jake@thedog, timeout: 200} 42 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_operator_policy_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearOperatorPolicyCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 18 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 19 | 20 | def run([key], %{node: node_name, vhost: vhost}) do 21 | :rabbit_misc.rpc_call(node_name, :rabbit_policy, :delete_op, [ 22 | vhost, 23 | key, 24 | Helpers.cli_acting_user() 25 | ]) 26 | end 27 | 28 | def usage, do: "clear_operator_policy [--vhost ] " 29 | 30 | def usage_additional() do 31 | [ 32 | ["", "policy name (identifier)"] 33 | ] 34 | end 35 | 36 | def usage_doc_guides() do 37 | [ 38 | DocGuide.parameters() 39 | ] 40 | end 41 | 42 | def help_section(), do: :policies 43 | 44 | def description(), do: "Clears an operator policy" 45 | 46 | def banner([key], %{vhost: vhost}) do 47 | "Clearing operator policy \"#{key}\" on vhost \"#{vhost}\" ..." 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/diagnostics/disable_auth_attempt_source_tracking_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule DisbleAuthAttemptSourceTrackingCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.DisableAuthAttemptSourceTrackingCommand 12 | setup_all do 13 | RabbitMQ.CLI.Core.Distribution.start() 14 | :ok 15 | end 16 | 17 | setup context do 18 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: context[:test_timeout]}} 19 | end 20 | 21 | test "validate: providing no arguments passes validation", context do 22 | assert @command.validate([], context[:opts]) == :ok 23 | end 24 | 25 | test "validate: providing any arguments fails validation", context do 26 | assert @command.validate(["a"], context[:opts]) == 27 | {:validation_failure, :too_many_args} 28 | end 29 | 30 | @tag test_timeout: 3000 31 | test "run: targeting an unreachable node throws a badrpc", context do 32 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 33 | end 34 | 35 | @tag test_timeout: 15000 36 | test "run: disables source tracking for auth attempt stats", context do 37 | assert :ok = @command.run([], context[:opts]) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/ctl/environment_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule EnvironmentCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.EnvironmentCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname()}} 22 | end 23 | 24 | test "validate: argument count validates" do 25 | assert @command.validate([], %{}) == :ok 26 | assert @command.validate(["extra"], %{}) == {:validation_failure, :too_many_args} 27 | end 28 | 29 | @tag target: get_rabbit_hostname() 30 | test "run: environment request on a named, active RMQ node is successful", context do 31 | assert @command.run([], context[:opts])[:kernel] != nil 32 | assert @command.run([], context[:opts])[:rabbit] != nil 33 | end 34 | 35 | test "run: environment request on nonexistent RabbitMQ node returns a badrpc" do 36 | opts = %{node: :jake@thedog, timeout: 200} 37 | 38 | assert match?({:badrpc, _}, @command.run([], opts)) 39 | end 40 | 41 | test "banner", context do 42 | assert @command.banner([], context[:opts]) 43 | =~ ~r/Application environment of node #{get_rabbit_hostname()}/ 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_global_parameters_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListGlobalParametersCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | def merge_defaults(args, opts) do 12 | {args, Map.merge(%{table_headers: true}, opts)} 13 | end 14 | 15 | def scopes(), do: [:ctl, :diagnostics] 16 | 17 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 18 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 19 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 20 | 21 | def run([], %{node: node_name, timeout: timeout}) do 22 | :rabbit_misc.rpc_call( 23 | node_name, 24 | :rabbit_runtime_parameters, 25 | :list_global_formatted, 26 | [], 27 | timeout 28 | ) 29 | end 30 | 31 | use RabbitMQ.CLI.DefaultOutput 32 | 33 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 34 | 35 | def usage, do: "list_global_parameters [--no-table-headers]" 36 | 37 | def usage_doc_guides() do 38 | [ 39 | DocGuide.parameters() 40 | ] 41 | end 42 | 43 | def help_section(), do: :parameters 44 | 45 | def description(), do: "Lists global runtime parameters" 46 | 47 | def banner(_, _), do: "Listing global runtime parameters ..." 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/set_user_limits_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SetUserLimitsCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsTwoPositionalArguments 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([username, definition], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :set_user_limits, [ 18 | username, 19 | definition, 20 | Helpers.cli_acting_user() 21 | ]) 22 | end 23 | 24 | use RabbitMQ.CLI.DefaultOutput 25 | 26 | def usage, do: "set_user_limits " 27 | 28 | def usage_additional() do 29 | [ 30 | ["", "Self-explanatory"], 31 | ["", "Limit definitions as a JSON document"] 32 | ] 33 | end 34 | 35 | def usage_doc_guides() do 36 | [ 37 | DocGuide.access_control() 38 | ] 39 | end 40 | 41 | def help_section(), do: :user_management 42 | 43 | def description(), do: "Sets user limits" 44 | 45 | def banner([username, definition], %{}) do 46 | "Setting user limits to \"#{definition}\" for user \"#{username}\" ..." 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | # This file is responsible for configuring your application 9 | # and its dependencies with the aid of the Mix.Config module. 10 | use Mix.Config 11 | 12 | # This configuration is loaded before any dependency and is restricted 13 | # to this project. If another project depends on this project, this 14 | # file won't be loaded nor affect the parent project. For this reason, 15 | # if you want to provide default values for your application for 16 | # 3rd-party users, it should be done in your "mix.exs" file. 17 | 18 | # You can configure for your application as: 19 | # 20 | # config :rabbitmqctl, key: :value 21 | # 22 | # And access this configuration in your application as: 23 | # 24 | # Application.get_env(:rabbitmqctl, :key) 25 | # 26 | # Or configure a 3rd-party app: 27 | # 28 | config :logger, [level: :warn, console: [device: :standard_error]] 29 | # 30 | 31 | # It is also possible to import configuration files, relative to this 32 | # directory. For example, you can emulate configuration per environment 33 | # by uncommenting the line below and defining dev.exs, test.exs and such. 34 | # Configuration from the imported file will override the ones defined 35 | # here (which is why it is important to import them last). 36 | # 37 | # import_config "#{Mix.env}.exs" 38 | -------------------------------------------------------------------------------- /test/queues/check_if_node_is_quorum_critical_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.CheckIfNodeIsQuorumCriticalCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Queues.Commands.CheckIfNodeIsQuorumCriticalCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | :ok 17 | end 18 | 19 | setup context do 20 | {:ok, opts: %{ 21 | node: get_rabbit_hostname(), 22 | timeout: context[:test_timeout] || 30000 23 | }} 24 | end 25 | 26 | test "validate: accepts no positional arguments" do 27 | assert @command.validate([], %{}) == :ok 28 | end 29 | 30 | test "validate: any positional arguments fail validation" do 31 | assert @command.validate(["quorum-queue-a"], %{}) == {:validation_failure, :too_many_args} 32 | assert @command.validate(["quorum-queue-a", "two"], %{}) == {:validation_failure, :too_many_args} 33 | assert @command.validate(["quorum-queue-a", "two", "three"], %{}) == {:validation_failure, :too_many_args} 34 | end 35 | 36 | @tag test_timeout: 3000 37 | test "run: targeting an unreachable node throws a badrpc" do 38 | assert match?({:badrpc, _}, @command.run([], %{node: :jake@thedog, vhost: "/", timeout: 200})) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/upgrade/post_upgrade_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule PostUpgradeCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Upgrade.Commands.PostUpgradeCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 5000 24 | }} 25 | end 26 | 27 | test "merge_defaults: nothing to do" do 28 | assert @command.merge_defaults([], %{}) == {[], %{}} 29 | end 30 | 31 | test "validate: accepts no positional arguments" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: succeeds with no positional arguments" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | opts = %{node: :jake@thedog, timeout: 200} 42 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 43 | end 44 | 45 | test "run: returns an OK", context do 46 | assert match?({:ok, _}, @command.run([], context[:opts])) 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_policies_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListPoliciesCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{vhost: "/", table_headers: true}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do 23 | :rabbit_misc.rpc_call( 24 | node_name, 25 | :rabbit_policy, 26 | :list_formatted, 27 | [vhost], 28 | timeout 29 | ) 30 | end 31 | 32 | use RabbitMQ.CLI.DefaultOutput 33 | 34 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 35 | 36 | def usage, do: "list_policies [--vhost ] [--no-table-headers]" 37 | 38 | def usage_doc_guides() do 39 | [ 40 | DocGuide.parameters() 41 | ] 42 | end 43 | 44 | def help_section(), do: :policies 45 | 46 | def description(), do: "Lists all policies in a virtual host" 47 | 48 | def banner(_, %{vhost: vhost}), do: "Listing policies for vhost \"#{vhost}\" ..." 49 | end 50 | -------------------------------------------------------------------------------- /test/diagnostics/command_line_arguments_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule CommandLineArgumentsCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.CommandLineArgumentsCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: :infinity}} 22 | end 23 | 24 | test "validate: with extra arguments, command line arguments returns an arg count error", context do 25 | assert @command.validate(["extra"], context[:opts]) == 26 | {:validation_failure, :too_many_args} 27 | end 28 | 29 | test "run: command line arguments request to a reachable node succeeds", context do 30 | output = @command.run([], context[:opts]) |> Enum.to_list 31 | 32 | assert_stream_without_errors(output) 33 | end 34 | 35 | test "run: command line arguments request on nonexistent RabbitMQ node returns a badrpc" do 36 | opts = %{node: :jake@thedog, timeout: 200} 37 | assert match?({:badrpc, _}, @command.run([], opts)) 38 | end 39 | 40 | test "banner", context do 41 | assert @command.banner([], context[:opts]) 42 | =~ ~r/Command line arguments of node #{get_rabbit_hostname()}/ 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/queues/check_if_node_is_mirror_sync_critical_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.CheckIfNodeIsMirrorSyncCriticalCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Queues.Commands.CheckIfNodeIsMirrorSyncCriticalCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | :ok 17 | end 18 | 19 | setup context do 20 | {:ok, opts: %{ 21 | node: get_rabbit_hostname(), 22 | timeout: context[:test_timeout] || 30000 23 | }} 24 | end 25 | 26 | test "validate: accepts no positional arguments" do 27 | assert @command.validate([], %{}) == :ok 28 | end 29 | 30 | test "validate: any positional arguments fail validation" do 31 | assert @command.validate(["quorum-queue-a"], %{}) == {:validation_failure, :too_many_args} 32 | assert @command.validate(["quorum-queue-a", "two"], %{}) == {:validation_failure, :too_many_args} 33 | assert @command.validate(["quorum-queue-a", "two", "three"], %{}) == {:validation_failure, :too_many_args} 34 | end 35 | 36 | @tag test_timeout: 3000 37 | test "run: targeting an unreachable node throws a badrpc" do 38 | assert match?({:badrpc, _}, @command.run([], %{node: :jake@thedog, vhost: "/", timeout: 200})) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/set_vhost_limits_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SetVhostLimitsCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def merge_defaults(args, opts) do 13 | {args, Map.merge(%{vhost: "/"}, opts)} 14 | end 15 | 16 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 17 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 18 | 19 | def run([definition], %{node: node_name, vhost: vhost}) do 20 | :rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :parse_set, [ 21 | vhost, 22 | definition, 23 | Helpers.cli_acting_user() 24 | ]) 25 | end 26 | 27 | use RabbitMQ.CLI.DefaultOutput 28 | 29 | def usage, do: "set_vhost_limits [--vhost ] " 30 | 31 | def usage_additional() do 32 | [ 33 | ["", "Limit definitions, must be a valid JSON document"] 34 | ] 35 | end 36 | 37 | def usage_doc_guides() do 38 | [ 39 | DocGuide.virtual_hosts() 40 | ] 41 | end 42 | 43 | def help_section(), do: :virtual_hosts 44 | 45 | def description(), do: "Sets virtual host limits" 46 | 47 | def banner([definition], %{vhost: vhost}) do 48 | "Setting vhost limits to \"#{definition}\" for vhost \"#{vhost}\" ..." 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/cancel_sync_queue_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.CancelSyncQueueCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 18 | 19 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 20 | 21 | def run([queue], %{vhost: vhost, node: node_name}) do 22 | :rpc.call( 23 | node_name, 24 | :rabbit_mirror_queue_misc, 25 | :cancel_sync_queue, 26 | [:rabbit_misc.r(vhost, :queue, queue)], 27 | :infinity 28 | ) 29 | end 30 | 31 | def usage, do: "cancel_sync_queue [--vhost ] " 32 | 33 | def usage_additional() do 34 | [ 35 | ["", "Queue name"] 36 | ] 37 | end 38 | 39 | def usage_doc_guides() do 40 | [ 41 | DocGuide.mirroring() 42 | ] 43 | end 44 | 45 | def help_section(), do: :replication 46 | 47 | def description(), do: "Instructs a synchronising mirrored queue to stop synchronising itself" 48 | 49 | def banner([queue], %{vhost: vhost, node: _node}) do 50 | "Stopping synchronising queue '#{queue}' in vhost '#{vhost}' ..." 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/close_connection_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.CloseConnectionCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsTwoPositionalArguments 14 | 15 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 16 | 17 | def run([pid, explanation], %{node: node_name}) do 18 | :rabbit_misc.rpc_call(node_name, :rabbit_networking, :close_connection, [ 19 | :rabbit_misc.string_to_pid(pid), 20 | explanation 21 | ]) 22 | end 23 | 24 | use RabbitMQ.CLI.DefaultOutput 25 | 26 | def usage, do: "close_connection " 27 | 28 | def usage_additional do 29 | [ 30 | ["", "connection identifier (Erlang PID), see list_connections"], 31 | ["", "reason for connection closure"] 32 | ] 33 | end 34 | 35 | def usage_doc_guides() do 36 | [ 37 | DocGuide.connections() 38 | ] 39 | end 40 | 41 | def help_section(), do: :operations 42 | 43 | def description(), do: "Instructs the broker to close the connection associated with the Erlang process id" 44 | 45 | def banner([pid, explanation], _), do: "Closing connection #{pid}, reason: #{explanation}..." 46 | end 47 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_parameters_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListParametersCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{vhost: "/", table_headers: true}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do 23 | :rabbit_misc.rpc_call( 24 | node_name, 25 | :rabbit_runtime_parameters, 26 | :list_formatted, 27 | [vhost], 28 | timeout 29 | ) 30 | end 31 | 32 | use RabbitMQ.CLI.DefaultOutput 33 | 34 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 35 | 36 | def usage, do: "list_parameters [--vhost ] [--no-table-headers]" 37 | 38 | def usage_doc_guides() do 39 | [ 40 | DocGuide.parameters() 41 | ] 42 | end 43 | 44 | def help_section(), do: :parameters 45 | 46 | def description(), do: "Lists runtime parameters for a virtual host" 47 | 48 | def banner(_, %{vhost: vhost}), do: "Listing runtime parameters for vhost \"#{vhost}\" ..." 49 | end 50 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/resume_listeners_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ResumeListenersCommand do 8 | @moduledoc """ 9 | Resumes all client connection listeners making them accept new client 10 | connections. This command is the opposite of `SuspendListenersCommand`. 11 | 12 | This command is meant to be used when automating upgrades. 13 | See also `SuspendListenersCommand`. 14 | """ 15 | 16 | @behaviour RabbitMQ.CLI.CommandBehaviour 17 | 18 | alias RabbitMQ.CLI.Core.DocGuide 19 | 20 | use RabbitMQ.CLI.Core.MergesNoDefaults 21 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 22 | 23 | def run([], %{node: node_name, timeout: timeout}) do 24 | :rabbit_misc.rpc_call(node_name, :rabbit_maintenance, :resume_all_client_listeners, [], timeout) 25 | end 26 | 27 | use RabbitMQ.CLI.DefaultOutput 28 | 29 | def usage, do: "resume_listeners" 30 | 31 | def usage_doc_guides() do 32 | [ 33 | DocGuide.upgrade() 34 | ] 35 | end 36 | 37 | def help_section(), do: :operations 38 | 39 | def description(), do: "Resumes client connection listeners making them accept client connections again" 40 | 41 | def banner(_, %{node: node_name}) do 42 | "Will resume client connection listeners on node #{node_name}. " 43 | <> "The node will now accept client connections" 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/diagnostics/server_version_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ServerVersionCommandTest do 9 | use ExUnit.Case 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.ServerVersionCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 30000 24 | }} 25 | end 26 | 27 | test "merge_defaults: nothing to do" do 28 | assert @command.merge_defaults([], %{}) == {[], %{}} 29 | end 30 | 31 | test "validate: treats positional arguments as a failure" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: treats empty positional arguments and default switches as a success" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 42 | end 43 | 44 | test "run: returns RabbitMQ version on the target node", context do 45 | res = @command.run([], context[:opts]) 46 | assert is_bitstring(res) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/sync_queue_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SyncQueueCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def merge_defaults(args, opts) do 13 | {args, Map.merge(%{vhost: "/"}, opts)} 14 | end 15 | 16 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 17 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 18 | 19 | def run([queue], %{vhost: vhost, node: node_name}) do 20 | :rpc.call( 21 | node_name, 22 | :rabbit_mirror_queue_misc, 23 | :sync_queue, 24 | [:rabbit_misc.r(vhost, :queue, queue)], 25 | :infinity 26 | ) 27 | end 28 | 29 | use RabbitMQ.CLI.DefaultOutput 30 | 31 | def usage do 32 | "sync_queue [--vhost ] " 33 | end 34 | 35 | def usage_additional() do 36 | [ 37 | ["", "Name of the queue to synchronise"] 38 | ] 39 | end 40 | 41 | def usage_doc_guides() do 42 | [ 43 | DocGuide.mirroring() 44 | ] 45 | end 46 | 47 | def help_section(), do: :replication 48 | 49 | def description(), do: "Instructs a mirrored queue with unsynchronised mirrors (follower replicas) to synchronise them" 50 | 51 | def banner([queue], %{vhost: vhost, node: _node}) do 52 | "Synchronising queue '#{queue}' in vhost '#{vhost}' ..." 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/diagnostics/maybe_stuck_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule MaybeStuckCommandTest do 9 | use ExUnit.Case 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.MaybeStuckCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 15000 24 | }} 25 | end 26 | 27 | test "merge_defaults: returns inputs" do 28 | assert @command.merge_defaults([], %{timeout: 30}) == {[], %{timeout: 30}} 29 | end 30 | 31 | test "validate: treats positional arguments as a failure" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: treats empty positional arguments and default switches as a success" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 42 | end 43 | 44 | @tag test_timeout: 0 45 | test "run: timeout throws a badrpc", context do 46 | assert @command.run([], context[:opts]) == {:badrpc, :timeout} 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_operator_policies_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListOperatorPoliciesCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | def scopes(), do: [:ctl, :diagnostics] 12 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 13 | 14 | def merge_defaults(args, opts) do 15 | {args, Map.merge(%{vhost: "/", table_headers: true}, opts)} 16 | end 17 | 18 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 19 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 20 | 21 | def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do 22 | :rabbit_misc.rpc_call( 23 | node_name, 24 | :rabbit_policy, 25 | :list_formatted_op, 26 | [vhost], 27 | timeout 28 | ) 29 | end 30 | 31 | use RabbitMQ.CLI.DefaultOutput 32 | 33 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 34 | 35 | def usage, do: "list_operator_policies [--vhost ] [--no-table-headers]" 36 | 37 | def usage_doc_guides() do 38 | [ 39 | DocGuide.parameters() 40 | ] 41 | end 42 | 43 | def help_section(), do: :policies 44 | 45 | def description(), do: "Lists operator policy overrides for a virtual host" 46 | 47 | def banner(_, %{vhost: vhost}), 48 | do: "Listing operator policy overrides for vhost \"#{vhost}\" ..." 49 | end 50 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_topic_permissions_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListTopicPermissionsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{vhost: "/", table_headers: true}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do 23 | :rabbit_misc.rpc_call( 24 | node_name, 25 | :rabbit_auth_backend_internal, 26 | :list_vhost_topic_permissions, 27 | [vhost], 28 | timeout 29 | ) 30 | end 31 | 32 | use RabbitMQ.CLI.DefaultOutput 33 | 34 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 35 | 36 | def usage, do: "list_topic_permissions [--vhost ] [--no-table-headers]" 37 | 38 | def usage_doc_guides() do 39 | [ 40 | DocGuide.access_control() 41 | ] 42 | end 43 | 44 | def help_section(), do: :access_control 45 | def description(), do: "Lists topic permissions in a virtual host" 46 | 47 | def banner(_, %{vhost: vhost}), do: "Listing topic permissions for vhost \"#{vhost}\" ..." 48 | end 49 | -------------------------------------------------------------------------------- /test/core/information_unit_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule InformationUnitTest do 9 | use ExUnit.Case, async: true 10 | 11 | alias RabbitMQ.CLI.InformationUnit, as: IU 12 | 13 | test "bytes, MB, GB, TB are known units" do 14 | Enum.each(["bytes", "mb", "MB", "gb", "GB", "tb", "TB"], 15 | fn x -> assert IU.known_unit?(x) end) 16 | end 17 | 18 | test "glip-glops, millibars, gold pressed latinum bars and looney and are not known units" do 19 | Enum.each(["glip-glops", "millibars", "gold pressed latinum bars", "looney"], 20 | fn x -> assert not IU.known_unit?(x) end) 21 | end 22 | 23 | test "conversion to bytes" do 24 | assert IU.convert(0, "bytes") == 0 25 | assert IU.convert(100, "bytes") == 100 26 | assert IU.convert(9988, "bytes") == 9988 27 | end 28 | 29 | test "conversion to MB" do 30 | assert IU.convert(1000000, "mb") == 1.0 31 | assert IU.convert(9500000, "mb") == 9.5 32 | assert IU.convert(97893000, "mb") == 97.893 33 | assert IU.convert(978930000, "mb") == 978.93 34 | end 35 | 36 | test "conversion to GB" do 37 | assert IU.convert(978930000, "gb") == 0.9789 38 | 39 | assert IU.convert(1000000000, "gb") == 1.0 40 | assert IU.convert(9500000000, "gb") == 9.5 41 | assert IU.convert(97893000000, "gb") == 97.893 42 | assert IU.convert(978930000000, "gb") == 978.93 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/ctl/await_online_nodes_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule AwaitOnlineNodesCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.AwaitOnlineNodesCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 300_000}} 18 | end 19 | 20 | setup context do 21 | on_exit(context, fn -> delete_vhost(context[:vhost]) end) 22 | :ok 23 | end 24 | 25 | test "validate: wrong number of arguments results in arg count errors" do 26 | assert @command.validate([], %{}) == {:validation_failure, :not_enough_args} 27 | assert @command.validate(["1", "1"], %{}) == {:validation_failure, :too_many_args} 28 | end 29 | 30 | test "run: a call with node count of 1 with a running RabbitMQ node succeeds", context do 31 | assert @command.run(["1"], context[:opts]) == :ok 32 | end 33 | 34 | test "run: a call to an unreachable RabbitMQ node returns a nodedown" do 35 | opts = %{node: :jake@thedog, timeout: 200} 36 | assert match?({:badrpc, _}, @command.run(["1"], opts)) 37 | end 38 | 39 | test "banner", context do 40 | assert @command.banner(["1"], context[:opts]) 41 | =~ ~r/Will wait for at least 1 nodes to join the cluster of #{context[:opts][:node]}. Timeout: 300 seconds./ 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /test/diagnostics/erlang_cookie_hash_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ErlangCookieHashCommandTest do 9 | use ExUnit.Case 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.ErlangCookieHashCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 5000 24 | }} 25 | end 26 | 27 | test "merge_defaults: nothing to do" do 28 | assert @command.merge_defaults([], %{}) == {[], %{}} 29 | end 30 | 31 | test "validate: treats positional arguments as a failure" do 32 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 33 | end 34 | 35 | test "validate: treats empty positional arguments and default switches as a success" do 36 | assert @command.validate([], %{}) == :ok 37 | end 38 | 39 | @tag test_timeout: 3000 40 | test "run: targeting an unreachable node throws a badrpc", context do 41 | opts = %{node: :jake@thedog, timeout: 200} 42 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 43 | end 44 | 45 | test "run: returns the erlang cookie hash", context do 46 | res = @command.run([], context[:opts]) 47 | assert is_bitstring(res) 48 | end 49 | 50 | end 51 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_permissions_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{vhost: "/", table_headers: true}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do 23 | :rabbit_misc.rpc_call( 24 | node_name, 25 | :rabbit_auth_backend_internal, 26 | :list_vhost_permissions, 27 | [vhost], 28 | timeout 29 | ) 30 | end 31 | 32 | use RabbitMQ.CLI.DefaultOutput 33 | 34 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 35 | 36 | def usage, do: "list_permissions [--vhost ] [--no-table-headers]" 37 | 38 | def usage_doc_guides() do 39 | [ 40 | DocGuide.access_control(), 41 | DocGuide.virtual_hosts() 42 | ] 43 | end 44 | 45 | def help_section(), do: :access_control 46 | def description(), do: "Lists user permissions in a virtual host" 47 | 48 | def banner(_, %{vhost: vhost}), do: "Listing permissions for vhost \"#{vhost}\" ..." 49 | end 50 | -------------------------------------------------------------------------------- /test/ctl/cluster_status_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ClusterStatusCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.ClusterStatusCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 12000}} 22 | end 23 | 24 | test "validate: argument count validates", context do 25 | assert @command.validate([], context[:opts]) == :ok 26 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 27 | end 28 | 29 | test "run: status request to a reachable node returns cluster information", context do 30 | n = context[:opts][:node] 31 | res = @command.run([], context[:opts]) 32 | 33 | assert Enum.member?(res[:nodes][:disc], n) 34 | assert res[:partitions] == [] 35 | assert res[:alarms][n] == [] 36 | end 37 | 38 | test "run: status request on nonexistent RabbitMQ node returns a badrpc" do 39 | opts = %{node: :jake@thedog, timeout: 200} 40 | 41 | assert match?({:badrpc, _}, @command.run([], opts)) 42 | end 43 | 44 | test "banner", context do 45 | s = @command.banner([], context[:opts]) 46 | 47 | assert s =~ ~r/Cluster status of node/ 48 | assert s =~ ~r/#{get_rabbit_hostname()}/ 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # vim:sw=2:et: 2 | 3 | os: linux 4 | dist: xenial 5 | language: elixir 6 | notifications: 7 | email: 8 | recipients: 9 | - alerts@rabbitmq.com 10 | on_success: never 11 | on_failure: always 12 | addons: 13 | apt: 14 | packages: 15 | - awscli 16 | cache: 17 | apt: true 18 | env: 19 | global: 20 | 21 | # $base_rmq_ref is used by rabbitmq-components.mk to select the 22 | # appropriate branch for dependencies. 23 | - base_rmq_ref=master 24 | 25 | jobs: 26 | include: 27 | - elixir: '1.10' 28 | otp_release: '22.3' 29 | - elixir: '1.10' 30 | otp_release: '23.0' 31 | 32 | install: 33 | # This project being an Erlang one (we just set language to Elixir 34 | # to ensure it is installed), we don't want Travis to run mix(1) 35 | # automatically as it will break. 36 | - mix local.rebar --force 37 | 38 | script: 39 | # $current_rmq_ref is also used by rabbitmq-components.mk to select 40 | # the appropriate branch for dependencies. 41 | - make 42 | DEPS_DIR=$PWD/.. 43 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 44 | - | 45 | git clone \ 46 | --branch "$base_rmq_ref" \ 47 | --depth 1 \ 48 | https://github.com/rabbitmq/rabbitmq-server-release.git \ 49 | ../rabbitmq_server_release 50 | make start-background-broker -C ../rabbitmq_server_release \ 51 | DEPS_DIR=$PWD/.. \ 52 | PLUGINS='rabbitmq_federation rabbitmq_stomp' \ 53 | PROJECT_VERSION=3.9.0 \ 54 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 55 | - make tests 56 | DEPS_DIR=$PWD/.. 57 | current_rmq_ref="${TRAVIS_PULL_REQUEST_BRANCH:-${TRAVIS_BRANCH}}" 58 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_user_limits_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearUserLimitsCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | use RabbitMQ.CLI.Core.MergesNoDefaults 14 | use RabbitMQ.CLI.Core.AcceptsTwoPositionalArguments 15 | 16 | def run([username, limit_type], %{node: node_name}) do 17 | :rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :clear_user_limits, [ 18 | username, 19 | limit_type, 20 | Helpers.cli_acting_user() 21 | ]) 22 | end 23 | 24 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 25 | 26 | def usage, do: "clear_user_limits username | all" 27 | 28 | def usage_additional() do 29 | [ 30 | ["", "Limit type, must be max-connections or max-channels"] 31 | ] 32 | end 33 | 34 | def usage_doc_guides() do 35 | [ 36 | DocGuide.access_control() 37 | ] 38 | end 39 | 40 | def help_section(), do: :user_management 41 | 42 | def description(), do: "Clears user connection/channel limits" 43 | 44 | def banner([username, "all"], %{}) do 45 | "Clearing all limits for user \"#{username}\" ..." 46 | end 47 | def banner([username, limit_type], %{}) do 48 | "Clearing \"#{limit_type}\" limit for user \"#{username}\" ..." 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/ctl/exec_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ExecCommandTest do 9 | use ExUnit.Case, async: false 10 | 11 | @command RabbitMQ.CLI.Ctl.Commands.ExecCommand 12 | 13 | setup _ do 14 | {:ok, opts: %{}} 15 | end 16 | 17 | test "validate: providing too few arguments fails validation" do 18 | assert @command.validate([], %{}) == {:validation_failure, :not_enough_args} 19 | end 20 | 21 | test "validate: there should be only one argument" do 22 | assert @command.validate(["foo", "bar"], %{}) == {:validation_failure, :too_many_args} 23 | assert @command.validate(["", "bar"], %{}) == {:validation_failure, :too_many_args} 24 | end 25 | 26 | test "validate: empty expression to exec fails validation" do 27 | assert @command.validate([""], %{}) == {:validation_failure, "Expression must not be blank"} 28 | end 29 | 30 | test "validate: success" do 31 | :ok = @command.validate([":ok"], %{}) 32 | end 33 | 34 | test "run: executes elixir code" do 35 | {:ok, :ok} = @command.run([":ok"], %{}) 36 | node = Node.self() 37 | {:ok, ^node} = @command.run(["Node.self()"], %{}) 38 | {:ok, 3} = @command.run(["1 + 2"], %{}) 39 | end 40 | 41 | test "run: binds options variable" do 42 | opts = %{my: :custom, option: 123} 43 | {:ok, ^opts} = @command.run(["options"], opts) 44 | {:ok, 123} = @command.run(["options[:option]"], opts) 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /test/ctl/stop_app_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule StopAppCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.StopAppCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | start_rabbitmq_app() 18 | 19 | on_exit([], fn -> 20 | start_rabbitmq_app() 21 | end) 22 | 23 | :ok 24 | end 25 | 26 | setup do 27 | {:ok, opts: %{node: get_rabbit_hostname()}} 28 | end 29 | 30 | test "validate: with extra arguments returns an arg count error", context do 31 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 32 | end 33 | 34 | test "run: request to an active node succeeds", context do 35 | node = RabbitMQ.CLI.Core.Helpers.normalise_node(context[:node], :shortnames) 36 | assert :rabbit_misc.rpc_call(node, :rabbit, :is_running, []) 37 | assert @command.run([], context[:opts]) 38 | refute :rabbit_misc.rpc_call(node, :rabbit, :is_running, []) 39 | end 40 | 41 | test "run: request to a non-existent node returns a badrpc" do 42 | opts = %{node: :jake@thedog, timeout: 200} 43 | assert match?({:badrpc, _}, @command.run([], opts)) 44 | end 45 | 46 | test "banner", context do 47 | assert @command.banner([], context[:opts]) =~ ~r/Stopping rabbit application on node #{get_rabbit_hostname()}/ 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/ctl/start_app_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule StartAppCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.StartAppCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | start_rabbitmq_app() 18 | 19 | on_exit([], fn -> 20 | start_rabbitmq_app() 21 | end) 22 | 23 | :ok 24 | end 25 | 26 | setup do 27 | {:ok, opts: %{node: get_rabbit_hostname()}} 28 | end 29 | 30 | test "validate: with extra arguments returns an arg count error", context do 31 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 32 | end 33 | 34 | test "run: request to an active node succeeds", context do 35 | node = RabbitMQ.CLI.Core.Helpers.normalise_node(context[:node], :shortnames) 36 | stop_rabbitmq_app() 37 | refute :rabbit_misc.rpc_call(node, :rabbit, :is_running, []) 38 | assert @command.run([], context[:opts]) 39 | assert :rabbit_misc.rpc_call(node, :rabbit, :is_running, []) 40 | end 41 | 42 | test "run: request to a non-existent node returns a badrpc" do 43 | opts = %{node: :jake@thedog, timeout: 200} 44 | assert match?({:badrpc, _}, @command.run([], opts)) 45 | end 46 | 47 | test "banner", context do 48 | assert @command.banner([], context[:opts]) =~ ~r/Starting node #{get_rabbit_hostname()}/ 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/autocomplete_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2016-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.AutocompleteCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | 10 | alias RabbitMQ.CLI.Core.{Config, DocGuide} 11 | 12 | def scopes(), do: [:ctl, :diagnostics, :plugins, :queues] 13 | 14 | def distribution(_), do: :none 15 | 16 | def merge_defaults(args, opts) do 17 | # enforce --silent as shell completion does not 18 | # expect to receive any additional output, so the command 19 | # is not really interactive 20 | {args, Map.merge(opts, %{silent: true})} 21 | end 22 | 23 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 24 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 25 | 26 | def run(args, %{script_name: script_name}) do 27 | {:stream, RabbitMQ.CLI.AutoComplete.complete(script_name, args)} 28 | end 29 | def run(args, opts) do 30 | script_name = Config.get_system_option(:script_name, opts) 31 | 32 | {:stream, RabbitMQ.CLI.AutoComplete.complete(script_name, args)} 33 | end 34 | use RabbitMQ.CLI.DefaultOutput 35 | 36 | def usage() do 37 | "autocomplete [prefix]" 38 | end 39 | 40 | def banner(_args, _opts) do 41 | nil 42 | end 43 | 44 | def usage_doc_guides() do 45 | [ 46 | DocGuide.cli() 47 | ] 48 | end 49 | 50 | def help_section(), do: :help 51 | 52 | def description(), do: "Provides command name autocomplete variants" 53 | end 54 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/observer_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.ObserverCommand do 8 | @behaviour RabbitMQ.CLI.CommandBehaviour 9 | use RabbitMQ.CLI.DefaultOutput 10 | 11 | def switches(), do: [interval: :integer] 12 | def aliases(), do: [i: :interval] 13 | 14 | def merge_defaults(args, opts) do 15 | {args, Map.merge(%{interval: 5}, opts)} 16 | end 17 | 18 | 19 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 20 | 21 | def run([], %{node: node_name, interval: interval}) do 22 | case :observer_cli.start(node_name, [{:interval, interval * 1000}]) do 23 | # See zhongwencool/observer_cli#54 24 | {:badrpc, _} = err -> err 25 | {:error, _} = err -> err 26 | {:error, _, _} = err -> err 27 | :ok -> {:ok, "Disconnected from #{node_name}."} 28 | :quit -> {:ok, "Disconnected from #{node_name}."} 29 | other -> other 30 | end 31 | end 32 | 33 | def help_section(), do: :observability_and_health_checks 34 | 35 | def description(), do: "Starts a CLI observer interface on the target node" 36 | 37 | def usage, do: "observer [--interval ]" 38 | 39 | def usage_additional() do 40 | [ 41 | ["--interval ", "Update interval to use, in seconds"] 42 | ] 43 | end 44 | 45 | def banner(_, %{node: node_name}) do 46 | "Starting a CLI observer interface on node #{node_name}..." 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /test/diagnostics/runtime_thread_stats_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule RuntimeThreadStatsCommandTest do 9 | use ExUnit.Case 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Diagnostics.Commands.RuntimeThreadStatsCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup context do 21 | {:ok, opts: %{ 22 | node: get_rabbit_hostname(), 23 | timeout: context[:test_timeout] || 10000, 24 | sample_interval: 1 25 | }} 26 | end 27 | 28 | 29 | test "validate: providing no arguments passes validation", context do 30 | assert @command.validate([], context[:opts]) == :ok 31 | end 32 | 33 | test "validate: providing any arguments fails validation", context do 34 | assert @command.validate(["a"], context[:opts]) == 35 | {:validation_failure, :too_many_args} 36 | end 37 | 38 | @tag test_timeout: 2000 39 | test "run: targeting an unreachable node throws a badrpc", context do 40 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 41 | end 42 | 43 | @tag test_timeout: 6000 44 | test "run: returns msacc-formatted output", context do 45 | res = @command.run([], context[:opts]) 46 | # the output is long and its values are environment-specific, 47 | # so we simply assert that it is non-empty. MK. 48 | assert length(res) > 0 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/suspend_listeners_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SuspendListenersCommand do 8 | @moduledoc """ 9 | Suspends all client connection listeners. Suspended listeners will not 10 | accept any new connections but already established ones will not be interrupted. 11 | `ResumeListenersCommand` will undo the effect of this command. 12 | 13 | This command is meant to be used when automating upgrades. 14 | See also `ResumeListenersCommand`. 15 | """ 16 | 17 | @behaviour RabbitMQ.CLI.CommandBehaviour 18 | 19 | alias RabbitMQ.CLI.Core.DocGuide 20 | 21 | use RabbitMQ.CLI.Core.MergesNoDefaults 22 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 23 | 24 | def run([], %{node: node_name, timeout: timeout}) do 25 | :rabbit_misc.rpc_call(node_name, :rabbit_maintenance, :suspend_all_client_listeners, [], timeout) 26 | end 27 | 28 | use RabbitMQ.CLI.DefaultOutput 29 | 30 | def usage, do: "suspend_listeners" 31 | 32 | def usage_doc_guides() do 33 | [ 34 | DocGuide.upgrade() 35 | ] 36 | end 37 | 38 | def help_section(), do: :operations 39 | 40 | def description(), do: "Suspends client connection listeners so that no new client connections are accepted" 41 | 42 | def banner(_, %{node: node_name}) do 43 | "Will suspend client connection listeners on node #{node_name}. " 44 | <> "The node will no longer accept client connections!" 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/paths.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.Paths do 8 | alias RabbitMQ.CLI.Core.Config 9 | import RabbitMQ.CLI.Core.Platform 10 | 11 | def plugins_dir(_, opts) do 12 | plugins_dir(opts) 13 | end 14 | 15 | def plugins_dir(opts) do 16 | case Config.get_option(:plugins_dir, opts) do 17 | nil -> 18 | {:error, :no_plugins_dir} 19 | 20 | dir -> 21 | paths = String.split(to_string(dir), path_separator()) 22 | 23 | case Enum.any?(paths, &File.dir?/1) do 24 | true -> {:ok, dir} 25 | false -> {:error, :plugins_dir_does_not_exist} 26 | end 27 | end 28 | end 29 | 30 | def require_mnesia_dir(opts) do 31 | case Application.get_env(:mnesia, :dir) do 32 | nil -> 33 | case Config.get_option(:mnesia_dir, opts) do 34 | nil -> {:error, :mnesia_dir_not_found} 35 | val -> Application.put_env(:mnesia, :dir, to_charlist(val)) 36 | end 37 | 38 | _ -> 39 | :ok 40 | end 41 | end 42 | 43 | def require_feature_flags_file(opts) do 44 | case Application.get_env(:rabbit, :feature_flags_file) do 45 | nil -> 46 | case Config.get_option(:feature_flags_file, opts) do 47 | nil -> {:error, :feature_flags_file_not_found} 48 | val -> Application.put_env(:rabbit, :feature_flags_file, to_charlist(val)) 49 | end 50 | 51 | _ -> 52 | :ok 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /test/ctl/await_startup_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | # Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule AwaitStartupCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Ctl.Commands.AwaitStartupCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 300_000}} 17 | end 18 | 19 | setup do 20 | {:ok, opts: %{node: get_rabbit_hostname()}} 21 | end 22 | 23 | test "merge_defaults: default timeout is 5 minutes" do 24 | assert @command.merge_defaults([], %{}) == {[], %{timeout: 300_000}} 25 | end 26 | 27 | test "validate: accepts no arguments", context do 28 | assert @command.validate([], context[:opts]) == :ok 29 | end 30 | 31 | test "validate: with extra arguments returns an arg count error", context do 32 | assert @command.validate(["extra"], context[:opts]) == 33 | {:validation_failure, :too_many_args} 34 | end 35 | 36 | test "run: request to a non-existent node returns a badrpc" do 37 | opts = %{node: :jake@thedog, timeout: 200} 38 | assert match?({:badrpc, _}, @command.run([], opts)) 39 | end 40 | 41 | test "run: request to a fully booted node succeeds", context do 42 | # this timeout value is in seconds 43 | assert @command.run([], Map.merge(context[:opts], %{timeout: 5})) == :ok 44 | end 45 | 46 | test "empty banner", context do 47 | nil = @command.banner([], context[:opts]) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/queues/quorum_status_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.QuorumStatusCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Queues.Commands.QuorumStatusCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | :ok 17 | end 18 | 19 | setup context do 20 | {:ok, opts: %{ 21 | node: get_rabbit_hostname(), 22 | timeout: context[:test_timeout] || 30000 23 | }} 24 | end 25 | 26 | 27 | test "validate: treats no arguments as a failure" do 28 | assert @command.validate([], %{}) == {:validation_failure, :not_enough_args} 29 | end 30 | 31 | test "validate: accepts a single positional argument" do 32 | assert @command.validate(["quorum-queue-a"], %{}) == :ok 33 | end 34 | 35 | test "validate: when two or more arguments are provided, returns a failure" do 36 | assert @command.validate(["quorum-queue-a", "one-extra-arg"], %{}) == {:validation_failure, :too_many_args} 37 | assert @command.validate(["quorum-queue-a", "extra-arg", "another-extra-arg"], %{}) == {:validation_failure, :too_many_args} 38 | end 39 | 40 | @tag test_timeout: 3000 41 | test "run: targeting an unreachable node throws a badrpc" do 42 | assert match?({:badrpc, _}, @command.run(["quorum-queue-a"], 43 | %{node: :jake@thedog, vhost: "/", timeout: 200})) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_user_topic_permissions_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListUserTopicPermissionsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | def scopes(), do: [:ctl, :diagnostics] 13 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 14 | 15 | def merge_defaults(args, opts) do 16 | {args, Map.merge(%{table_headers: false}, opts)} 17 | end 18 | 19 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 20 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 21 | 22 | def run([username], %{node: node_name, timeout: timeout}) do 23 | :rabbit_misc.rpc_call( 24 | node_name, 25 | :rabbit_auth_backend_internal, 26 | :list_user_topic_permissions, 27 | [username], 28 | timeout 29 | ) 30 | end 31 | 32 | use RabbitMQ.CLI.DefaultOutput 33 | 34 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 35 | 36 | def usage, do: "list_user_topic_permissions [--no-table-headers] " 37 | 38 | def usage_additional do 39 | [ 40 | ["", "Name of the user"] 41 | ] 42 | end 43 | 44 | def usage_doc_guides() do 45 | [ 46 | DocGuide.access_control() 47 | ] 48 | end 49 | 50 | def help_section(), do: :access_control 51 | def description(), do: "Lists user topic permissions" 52 | 53 | def banner([username], _), do: "Listing topic permissions for user \"#{username}\" ..." 54 | end 55 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/formatters/report.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2017-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Formatters.Report do 8 | alias RabbitMQ.CLI.Formatters.FormatterHelpers 9 | alias RabbitMQ.CLI.Core.{Output, Config} 10 | 11 | @behaviour RabbitMQ.CLI.FormatterBehaviour 12 | def format_output(_, _) do 13 | raise "format_output is not implemented for report formatter" 14 | end 15 | 16 | def format_stream(stream, options) do 17 | quiet = options[:quiet] || options[:silent] || false 18 | 19 | Stream.flat_map( 20 | stream, 21 | FormatterHelpers.without_errors_1(fn 22 | {_command, _banner, {:error, _} = err} -> 23 | err 24 | 25 | {_command, _banner, {:error, _, _} = err} -> 26 | err 27 | 28 | {command, banner, result} -> 29 | case quiet do 30 | true -> 31 | Stream.concat([""], format_result(command, result, options)) 32 | 33 | false -> 34 | Stream.concat(["" | banner_list(banner)], format_result(command, result, options)) 35 | end 36 | end) 37 | ) 38 | end 39 | 40 | def format_result(command, output, options) do 41 | formatter = Config.get_formatter(command, options) 42 | 43 | case Output.format_output(output, formatter, options) do 44 | :ok -> [] 45 | {:ok, val} -> [val] 46 | {:stream, stream} -> stream 47 | end 48 | end 49 | 50 | def banner_list([_ | _] = list), do: list 51 | def banner_list(val), do: [val] 52 | end 53 | -------------------------------------------------------------------------------- /test/queues/reclaim_quorum_memory_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.ReclaimQuorumMemoryCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Queues.Commands.ReclaimQuorumMemoryCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | :ok 17 | end 18 | 19 | setup context do 20 | {:ok, opts: %{ 21 | node: get_rabbit_hostname(), 22 | timeout: context[:test_timeout] || 30000 23 | }} 24 | end 25 | 26 | 27 | test "validate: treats no arguments as a failure" do 28 | assert @command.validate([], %{}) == {:validation_failure, :not_enough_args} 29 | end 30 | 31 | test "validate: accepts a single positional argument" do 32 | assert @command.validate(["quorum-queue-a"], %{}) == :ok 33 | end 34 | 35 | test "validate: when two or more arguments are provided, returns a failure" do 36 | assert @command.validate(["quorum-queue-a", "one-extra-arg"], %{}) == {:validation_failure, :too_many_args} 37 | assert @command.validate(["quorum-queue-a", "extra-arg", "another-extra-arg"], %{}) == {:validation_failure, :too_many_args} 38 | end 39 | 40 | @tag test_timeout: 3000 41 | test "run: targeting an unreachable node throws a badrpc" do 42 | assert match?({:badrpc, _}, @command.run(["quorum-queue-a"], 43 | %{node: :jake@thedog, vhost: "/", timeout: 200})) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/set_global_parameter_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.SetGlobalParameterCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | 14 | def validate(args, _) when length(args) < 2 do 15 | {:validation_failure, :not_enough_args} 16 | end 17 | def validate(args, _) when length(args) > 2 do 18 | {:validation_failure, :too_many_args} 19 | end 20 | def validate(_, _), do: :ok 21 | 22 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 23 | 24 | def run([name, value], %{node: node_name}) do 25 | :rabbit_misc.rpc_call( 26 | node_name, 27 | :rabbit_runtime_parameters, 28 | :parse_set_global, 29 | [name, value, Helpers.cli_acting_user()] 30 | ) 31 | end 32 | 33 | use RabbitMQ.CLI.DefaultOutput 34 | 35 | def usage, do: "set_global_parameter " 36 | 37 | def usage_additional() do 38 | [ 39 | ["", "global parameter name (identifier)"], 40 | ["", "parameter value"] 41 | ] 42 | end 43 | 44 | def usage_doc_guides() do 45 | [ 46 | DocGuide.parameters() 47 | ] 48 | end 49 | 50 | def help_section(), do: :parameters 51 | 52 | def description(), do: "Sets a runtime parameter." 53 | 54 | def banner([name, value], _) do 55 | "Setting global runtime parameter \"#{name}\" to \"#{value}\" ..." 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/ctl/set_log_level_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule SetLogLevelCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Ctl.Commands.SetLogLevelCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | {:ok, 16 | log_level: "debug", 17 | opts: %{node: get_rabbit_hostname()}} 18 | end 19 | 20 | test "validate: with a single known level succeeds", context do 21 | assert @command.validate([context[:log_level]], context[:opts]) == :ok 22 | end 23 | 24 | test "validate: with a single unsupported level fails", context do 25 | assert match?({:error, _}, @command.validate(["lolwut"], context[:opts])) 26 | end 27 | 28 | test "validate: with extra arguments returns an arg count error", context do 29 | assert @command.validate([context[:log_level], "whoops"], context[:opts]) == {:validation_failure, :too_many_args} 30 | end 31 | 32 | test "run: request to a named, active node succeeds", context do 33 | assert @command.run([context[:log_level]], context[:opts]) == :ok 34 | end 35 | 36 | test "run: request to a non-existent node returns a badrpc", context do 37 | opts = %{node: :jake@thedog, timeout: 200} 38 | assert match?({:badrpc, _}, @command.run([context[:log_level]], opts)) 39 | end 40 | 41 | test "banner", context do 42 | assert @command.banner([context[:log_level]], context[:opts]) == "Setting log level to \"debug\" ..." 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/log_tail_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2019-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.LogTailCommand do 8 | @moduledoc """ 9 | Displays standard log file location on the target node 10 | """ 11 | @behaviour RabbitMQ.CLI.CommandBehaviour 12 | 13 | alias RabbitMQ.CLI.Core.LogFiles 14 | 15 | def switches, do: [number: :integer, timeout: :integer] 16 | def aliases, do: ['N': :number, t: :timeout] 17 | 18 | def merge_defaults(args, opts) do 19 | {args, Map.merge(%{number: 50}, opts)} 20 | end 21 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 22 | 23 | def run([], %{node: node_name, timeout: timeout, number: n}) do 24 | case LogFiles.get_default_log_location(node_name, timeout) do 25 | {:ok, file} -> 26 | :rabbit_misc.rpc_call(node_name, 27 | :rabbit_log_tail, :tail_n_lines, [file, n], 28 | timeout) 29 | error -> error 30 | end 31 | end 32 | 33 | use RabbitMQ.CLI.DefaultOutput 34 | 35 | def help_section(), do: :observability_and_health_checks 36 | 37 | def description(), do: "Prints the last N lines of the log on the node" 38 | 39 | def usage, do: "log_tail [--number|-N ]" 40 | 41 | def usage_additional do 42 | [ 43 | ["", "number of lines to print. Defaults to 50"] 44 | ] 45 | end 46 | 47 | def banner([], %{node: node_name, number: n}) do 48 | "Last #{n} log lines on node #{node_name} ..." 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/queues/commands/quorum_status_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.QuorumStatusCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | def scopes(), do: [:diagnostics, :queues] 12 | 13 | def merge_defaults(args, opts), do: {args, Map.merge(%{vhost: "/"}, opts)} 14 | 15 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 16 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 17 | 18 | def run([name] = _args, %{node: node_name, vhost: vhost}) do 19 | case :rabbit_misc.rpc_call(node_name, :rabbit_quorum_queue, :status, [vhost, name]) do 20 | {:error, :classic_queue_not_supported} -> 21 | {:error, "Cannot get quorum status of a classic queue"} 22 | 23 | other -> 24 | other 25 | end 26 | end 27 | 28 | use RabbitMQ.CLI.DefaultOutput 29 | 30 | def formatter(), do: RabbitMQ.CLI.Formatters.PrettyTable 31 | 32 | def usage() do 33 | "quorum_status [--vhost ] " 34 | end 35 | 36 | def usage_additional do 37 | [ 38 | ["", "Name of the queue"] 39 | ] 40 | end 41 | 42 | def usage_doc_guides() do 43 | [ 44 | DocGuide.quorum_queues() 45 | ] 46 | end 47 | 48 | def help_section(), do: :observability_and_health_checks 49 | 50 | def description(), do: "Displays quorum status of a quorum queue" 51 | 52 | def banner([name], %{node: node_name}), 53 | do: "Status of quorum queue #{name} on node #{node_name} ..." 54 | end 55 | -------------------------------------------------------------------------------- /test/upgrade/drain_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule DrainCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Upgrade.Commands.DrainCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | revive_node() 17 | 18 | on_exit(fn -> 19 | revive_node() 20 | end) 21 | 22 | :ok 23 | end 24 | 25 | setup context do 26 | {:ok, opts: %{ 27 | node: get_rabbit_hostname(), 28 | timeout: context[:test_timeout] || 5000 29 | }} 30 | end 31 | 32 | test "merge_defaults: nothing to do" do 33 | assert @command.merge_defaults([], %{}) == {[], %{}} 34 | end 35 | 36 | test "validate: accepts no positional arguments" do 37 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 38 | end 39 | 40 | test "validate: succeeds with no positional arguments" do 41 | assert @command.validate([], %{}) == :ok 42 | end 43 | 44 | @tag test_timeout: 3000 45 | test "run: targeting an unreachable node throws a badrpc", context do 46 | opts = %{node: :jake@thedog, timeout: 200} 47 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 48 | end 49 | 50 | test "run: puts target node into maintenance mode", context do 51 | assert not is_draining_node() 52 | assert :ok == @command.run([], context[:opts]) 53 | 54 | await_condition(fn -> is_draining_node() end, 7000) 55 | revive_node() 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/ctl/ping_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule PingCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.PingCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | reset_vm_memory_high_watermark() 18 | 19 | on_exit([], fn -> 20 | reset_vm_memory_high_watermark() 21 | end) 22 | 23 | :ok 24 | end 25 | 26 | setup do 27 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 200}} 28 | end 29 | 30 | test "validate: with extra arguments returns an arg count error", context do 31 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 32 | end 33 | 34 | test "validate: with no arguments succeeds", _context do 35 | assert @command.validate([], []) == :ok 36 | end 37 | 38 | test "validate: with a named, active node argument succeeds", context do 39 | assert @command.validate([], context[:opts]) == :ok 40 | end 41 | 42 | test "run: request to a named, active node succeeds", context do 43 | assert @command.run([], context[:opts]) 44 | end 45 | 46 | test "run: request to a non-existent node returns a badrpc" do 47 | assert match?({:error, _}, @command.run([], %{node: :jake@thedog, timeout: 200})) 48 | end 49 | 50 | test "banner", context do 51 | banner = @command.banner([], context[:opts]) 52 | 53 | assert banner =~ ~r/Will ping/ 54 | assert banner =~ ~r/#{get_rabbit_hostname()}/ 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/certificates_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.CertificatesCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | import RabbitMQ.CLI.Core.Listeners 12 | 13 | use RabbitMQ.CLI.Core.MergesNoDefaults 14 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 15 | 16 | def run([], %{node: node_name, timeout: timeout}) do 17 | case :rabbit_misc.rpc_call(node_name, :rabbit_networking, :active_listeners, [], timeout) do 18 | {:error, _} = err -> 19 | err 20 | 21 | {:error, _, _} = err -> 22 | err 23 | 24 | xs when is_list(xs) -> 25 | listeners = listeners_with_certificates(listeners_on(xs, node_name)) 26 | 27 | case listeners do 28 | [] -> %{} 29 | _ -> Enum.map(listeners, &listener_certs/1) 30 | end 31 | 32 | other -> 33 | other 34 | end 35 | end 36 | 37 | use RabbitMQ.CLI.DefaultOutput 38 | 39 | def formatter(), do: RabbitMQ.CLI.Formatters.Erlang 40 | 41 | def usage, do: "certificates" 42 | 43 | def usage_doc_guides() do 44 | [ 45 | DocGuide.configuration(), 46 | DocGuide.tls() 47 | ] 48 | end 49 | 50 | def help_section(), do: :configuration 51 | 52 | def description(), do: "Displays certificates (public keys) for every listener on target node that is configured to use TLS" 53 | 54 | def banner(_, %{node: node_name}), do: "Certificates of node #{node_name} ..." 55 | end 56 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/queues/commands/delete_member_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Queues.Commands.DeleteMemberCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | import RabbitMQ.CLI.Core.DataCoercion 10 | 11 | @behaviour RabbitMQ.CLI.CommandBehaviour 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | use RabbitMQ.CLI.Core.AcceptsTwoPositionalArguments 18 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 19 | 20 | def run([name, node] = _args, %{vhost: vhost, node: node_name}) do 21 | case :rabbit_misc.rpc_call(node_name, :rabbit_quorum_queue, :delete_member, [ 22 | vhost, 23 | name, 24 | to_atom(node) 25 | ]) do 26 | {:error, :classic_queue_not_supported} -> 27 | {:error, "Cannot add members to a classic queue"} 28 | 29 | other -> 30 | other 31 | end 32 | end 33 | 34 | use RabbitMQ.CLI.DefaultOutput 35 | 36 | def usage, do: "delete_member [--vhost ] " 37 | 38 | def usage_additional do 39 | [ 40 | ["", "quorum queue name"], 41 | ["", "node to remove a new replica on"] 42 | ] 43 | end 44 | 45 | def usage_doc_guides() do 46 | [ 47 | DocGuide.quorum_queues() 48 | ] 49 | end 50 | 51 | def help_section, do: :replication 52 | 53 | def description, do: "Removes a quorum queue member (replica) on the given node." 54 | 55 | def banner([name, node], _) do 56 | "Removing a replica of queue #{name} on node #{node}..." 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /test/diagnostics/check_virtual_hosts_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule CheckVirtualHostsCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Diagnostics.Commands.CheckVirtualHostsCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | :ok 17 | end 18 | 19 | setup context do 20 | {:ok, opts: %{ 21 | node: get_rabbit_hostname(), 22 | timeout: context[:test_timeout] || 30000 23 | }} 24 | end 25 | 26 | test "merge_defaults: is a no-op" do 27 | assert @command.merge_defaults([], %{}) == {[], %{}} 28 | end 29 | 30 | test "validate: treats positional arguments as a failure" do 31 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 32 | end 33 | 34 | test "validate: treats empty positional arguments and default switches as a success" do 35 | assert @command.validate([], %{}) == :ok 36 | end 37 | 38 | @tag test_timeout: 3000 39 | test "run: targeting an unreachable node throws a badrpc", context do 40 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))) 41 | end 42 | 43 | test "output: when all virtual hosts are reported as up, returns a success", context do 44 | assert match?({:ok, _}, @command.output([], context[:opts])) 45 | end 46 | 47 | test "output: when target node reports a virtual host as down, returns a failure", context do 48 | assert match?({:error, _}, @command.output(["a-down-vhost"], context[:opts])) 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/upgrade/revive_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule ReviveCommandTest do 8 | use ExUnit.Case, async: false 9 | import TestHelper 10 | 11 | @command RabbitMQ.CLI.Upgrade.Commands.ReviveCommand 12 | 13 | setup_all do 14 | RabbitMQ.CLI.Core.Distribution.start() 15 | 16 | revive_node() 17 | 18 | on_exit(fn -> 19 | revive_node() 20 | end) 21 | 22 | :ok 23 | end 24 | 25 | setup context do 26 | {:ok, opts: %{ 27 | node: get_rabbit_hostname(), 28 | timeout: context[:test_timeout] || 5000 29 | }} 30 | end 31 | 32 | test "merge_defaults: nothing to do" do 33 | assert @command.merge_defaults([], %{}) == {[], %{}} 34 | end 35 | 36 | test "validate: accepts no positional arguments" do 37 | assert @command.validate(["extra-arg"], %{}) == {:validation_failure, :too_many_args} 38 | end 39 | 40 | test "validate: succeeds with no positional arguments" do 41 | assert @command.validate([], %{}) == :ok 42 | end 43 | 44 | @tag test_timeout: 3000 45 | test "run: targeting an unreachable node throws a badrpc", context do 46 | opts = %{node: :jake@thedog, timeout: 200} 47 | assert match?({:badrpc, _}, @command.run([], Map.merge(context[:opts], opts))) 48 | end 49 | 50 | test "run: puts target node into regular operating mode", context do 51 | assert not is_draining_node() 52 | drain_node() 53 | await_condition(fn -> is_draining_node() end, 7000) 54 | assert :ok == @command.run([], context[:opts]) 55 | await_condition(fn -> not is_draining_node() end, 7000) 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/core/os_pid.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Core.OsPid do 8 | @external_process_check_interval 1000 9 | 10 | @pid_regex ~r/^\s*(?\d+)/ 11 | 12 | # 13 | # API 14 | # 15 | 16 | def wait_for_os_process_death(pid) do 17 | case :rabbit_misc.is_os_process_alive(pid) do 18 | true -> 19 | :timer.sleep(@external_process_check_interval) 20 | wait_for_os_process_death(pid) 21 | 22 | false -> 23 | :ok 24 | end 25 | end 26 | 27 | def read_pid_from_file(pidfile_path, should_wait) do 28 | case {:file.read_file(pidfile_path), should_wait} do 29 | {{:ok, contents}, _} -> 30 | pid_regex = Regex.recompile!(@pid_regex) 31 | 32 | case Regex.named_captures(pid_regex, contents)["pid"] do 33 | # e.g. the file is empty 34 | nil -> 35 | {:error, :could_not_read_pid_from_file, {:contents, contents}} 36 | 37 | pid_string -> 38 | try do 39 | {pid, _remainder} = Integer.parse(pid_string) 40 | pid 41 | rescue 42 | _e in ArgumentError -> 43 | {:error, {:could_not_read_pid_from_file, {:contents, contents}}} 44 | end 45 | end 46 | 47 | # file does not exist, wait and re-check 48 | {{:error, :enoent}, true} -> 49 | :timer.sleep(@external_process_check_interval) 50 | read_pid_from_file(pidfile_path, should_wait) 51 | 52 | {{:error, details}, _} -> 53 | {:error, :could_not_read_pid_from_file, details} 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/delete_user_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.DeleteUserCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, ExitCodes, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument 14 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 15 | 16 | def run([username], %{node: node_name}) do 17 | :rabbit_misc.rpc_call( 18 | node_name, 19 | :rabbit_auth_backend_internal, 20 | :delete_user, 21 | [username, Helpers.cli_acting_user()] 22 | ) 23 | end 24 | 25 | def output({:error, {:no_such_user, username}}, %{node: node_name, formatter: "json"}) do 26 | {:error, %{"result" => "error", "node" => node_name, "message" => "User #{username} does not exists"}} 27 | end 28 | def output({:error, {:no_such_user, username}}, _) do 29 | {:error, ExitCodes.exit_nouser(), "User \"#{username}\" does not exist"} 30 | end 31 | use RabbitMQ.CLI.DefaultOutput 32 | 33 | def usage, do: "delete_user " 34 | 35 | def usage_additional() do 36 | [ 37 | ["", "Name of the user to delete."] 38 | ] 39 | end 40 | 41 | def usage_doc_guides() do 42 | [ 43 | DocGuide.access_control() 44 | ] 45 | end 46 | 47 | def help_section(), do: :user_management 48 | 49 | def description(), do: "Removes a user from the internal database. Has no effect on users provided by external backends such as LDAP" 50 | 51 | def banner([arg], _), do: "Deleting user \"#{arg}\" ..." 52 | end 53 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/check_running_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckRunningCommand do 8 | @moduledoc """ 9 | Exits with a non-zero code if the RabbitMQ app on the target node is not running. 10 | 11 | This command is meant to be used in health checks. 12 | """ 13 | 14 | @behaviour RabbitMQ.CLI.CommandBehaviour 15 | 16 | use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout 17 | use RabbitMQ.CLI.Core.MergesNoDefaults 18 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 19 | 20 | def run([], %{node: node_name, timeout: timeout}) do 21 | # Note: we use is_booted/1 over is_running/1 to avoid 22 | # returning a positive result when the node is still booting 23 | :rabbit_misc.rpc_call(node_name, :rabbit, :is_booted, [node_name], timeout) 24 | end 25 | 26 | def output(true, %{node: node_name} = _options) do 27 | {:ok, "RabbitMQ on node #{node_name} is fully booted and running"} 28 | end 29 | 30 | def output(false, %{node: node_name} = _options) do 31 | {:error, 32 | "RabbitMQ on node #{node_name} is not running or has not fully booted yet (check with is_booting)"} 33 | end 34 | 35 | use RabbitMQ.CLI.DefaultOutput 36 | 37 | def help_section(), do: :observability_and_health_checks 38 | 39 | def description(), do: "Health check that exits with a non-zero code if the RabbitMQ app on the target node is not running" 40 | 41 | def usage, do: "check_running" 42 | 43 | def banner([], %{node: node_name}) do 44 | "Checking if RabbitMQ is running on node #{node_name} ..." 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /test/ctl/autocomplete_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule AutocompleteCommandTest do 9 | use ExUnit.Case, async: true 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.AutocompleteCommand 13 | setup do 14 | {:ok, opts: %{ 15 | script_name: "rabbitmqctl", 16 | node: get_rabbit_hostname() 17 | }} 18 | end 19 | 20 | test "shows up in help" do 21 | s = @command.usage() 22 | assert s =~ ~r/autocomplete/ 23 | end 24 | 25 | test "enforces --silent" do 26 | assert @command.merge_defaults(["list_"], %{}) == {["list_"], %{silent: true}} 27 | end 28 | 29 | test "validate: providing no arguments fails validation" do 30 | assert @command.validate([], %{}) == {:validation_failure, :not_enough_args} 31 | end 32 | 33 | test "validate: providing two or more arguments fails validation" do 34 | assert @command.validate(["list_", "extra"], %{}) == {:validation_failure, :too_many_args} 35 | end 36 | 37 | test "validate: providing a single argument passes validation" do 38 | assert @command.validate(["list_c"], %{}) == :ok 39 | end 40 | 41 | test "run: lists completion options", context do 42 | {:stream, completion_options} = @command.run(["list_c"], context[:opts]) 43 | 44 | assert Enum.member?(completion_options, "list_channels") 45 | assert Enum.member?(completion_options, "list_connections") 46 | assert Enum.member?(completion_options, "list_consumers") 47 | end 48 | 49 | test "banner shows that the name is being set", context do 50 | assert @command.banner(["list_"], context[:opts]) == nil 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/diagnostics/commands/log_location_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2019-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Diagnostics.Commands.LogLocationCommand do 8 | @moduledoc """ 9 | Displays standard log file location on the target node 10 | """ 11 | @behaviour RabbitMQ.CLI.CommandBehaviour 12 | 13 | alias RabbitMQ.CLI.Core.LogFiles 14 | 15 | def switches, do: [all: :boolean, timeout: :integer] 16 | def aliases, do: [a: :all, t: :timeout] 17 | 18 | def merge_defaults(args, opts) do 19 | {args, Map.merge(%{all: false}, opts)} 20 | end 21 | 22 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 23 | 24 | def run([], %{node: node_name, timeout: timeout, all: all}) do 25 | case all do 26 | true -> LogFiles.get_log_locations(node_name, timeout); 27 | false -> LogFiles.get_default_log_location(node_name, timeout) 28 | end 29 | end 30 | 31 | def output({:ok, location}, %{node: node_name, formatter: "json"}) do 32 | {:ok, %{ 33 | "result" => "ok", 34 | "node_name" => node_name, 35 | "paths" => [location] 36 | }} 37 | end 38 | def output(locations, %{node: node_name, formatter: "json"}) do 39 | {:ok, %{ 40 | "result" => "ok", 41 | "node_name" => node_name, 42 | "paths" => locations 43 | }} 44 | end 45 | use RabbitMQ.CLI.DefaultOutput 46 | 47 | def help_section(), do: :configuration 48 | 49 | def description(), do: "Shows log file location(s) on target node" 50 | 51 | def usage, do: "log_location [--all|-a]" 52 | 53 | def banner([], %{node: node_name}) do 54 | "Log file location(s) on node #{node_name} ..." 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /test/json_formatting.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule JSONFormattingTest do 9 | use ExUnit.Case, async: false 10 | import ExUnit.CaptureIO 11 | import RabbitMQ.CLI.Core.ExitCodes 12 | import TestHelper 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | set_scope(:all) 18 | 19 | :ok 20 | end 21 | 22 | test "JSON output of status" do 23 | set_scope(:ctl) 24 | 25 | node = to_string(get_rabbit_hostname()) 26 | command = ["status", "-n", node, "--formatter=json"] 27 | output = capture_io(:stdio, fn -> 28 | error_check(command, exit_ok()) 29 | end) 30 | {:ok, doc} = JSON.decode(output) 31 | 32 | assert Map.has_key?(doc, "memory") 33 | assert Map.has_key?(doc, "file_descriptors") 34 | assert Map.has_key?(doc, "listeners") 35 | assert Map.has_key?(doc, "processes") 36 | assert Map.has_key?(doc, "os") 37 | assert Map.has_key?(doc, "pid") 38 | assert Map.has_key?(doc, "rabbitmq_version") 39 | 40 | assert doc["alarms"] == [] 41 | end 42 | 43 | test "JSON output of cluster_status" do 44 | set_scope(:ctl) 45 | 46 | node = to_string(get_rabbit_hostname()) 47 | command = ["cluster_status", "-n", node, "--formatter=json"] 48 | output = capture_io(:stdio, fn -> 49 | error_check(command, exit_ok()) 50 | end) 51 | {:ok, doc} = JSON.decode(output) 52 | 53 | assert Enum.member?(doc["disk_nodes"], node) 54 | assert Map.has_key?(doc["listeners"], node) 55 | assert Map.has_key?(doc["versions"], node) 56 | assert doc["alarms"] == [] 57 | assert doc["partitions"] == %{} 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/enable_feature_flag_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2018-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule RabbitMQ.CLI.Ctl.Commands.EnableFeatureFlagCommand do 9 | @behaviour RabbitMQ.CLI.CommandBehaviour 10 | 11 | def merge_defaults(args, opts), do: {args, opts} 12 | 13 | def validate([], _), do: {:validation_failure, :not_enough_args} 14 | def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args} 15 | def validate([""], _), do: {:validation_failure, {:bad_argument, "feature_flag cannot be an empty string."}} 16 | def validate([_], _), do: :ok 17 | 18 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 19 | 20 | def run([feature_flag], %{node: node_name}) do 21 | case :rabbit_misc.rpc_call(node_name, :rabbit_feature_flags, :enable, [String.to_atom(feature_flag)]) do 22 | # Server does not support feature flags, consider none are available. 23 | # See rabbitmq/rabbitmq-cli#344 for context. MK. 24 | {:badrpc, {:EXIT, {:undef, _}}} -> {:error, :unsupported} 25 | {:badrpc, _} = err -> err 26 | other -> other 27 | end 28 | end 29 | 30 | def output({:error, :unsupported}, %{node: node_name}) do 31 | {:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage, "This feature flag is not supported by node #{node_name}"} 32 | end 33 | use RabbitMQ.CLI.DefaultOutput 34 | 35 | def usage, do: "enable_feature_flag " 36 | 37 | def help_section(), do: :feature_flags 38 | 39 | def description(), do: "Enables a feature flag on target node" 40 | 41 | def banner([feature_flag], _), do: "Enabling feature flag \"#{feature_flag}\" ..." 42 | end 43 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/information_unit.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.InformationUnit do 8 | require MapSet 9 | 10 | @kilobyte_bytes 1000 11 | @megabyte_bytes @kilobyte_bytes * 1000 12 | @gigabyte_bytes @megabyte_bytes * 1000 13 | @terabyte_bytes @gigabyte_bytes * 1000 14 | 15 | def known_units() do 16 | MapSet.new([ 17 | "bytes", 18 | "kb", 19 | "kilobytes", 20 | "mb", 21 | "megabytes", 22 | "gb", 23 | "gigabytes", 24 | "tb", 25 | "terabytes" 26 | ]) 27 | end 28 | 29 | def parse(val) do 30 | :rabbit_resource_monitor_misc.parse_information_unit(val) 31 | end 32 | 33 | def convert(bytes, "bytes") do 34 | bytes 35 | end 36 | 37 | def convert(bytes, unit) do 38 | do_convert(bytes, String.downcase(unit)) 39 | end 40 | 41 | def known_unit?(val) do 42 | MapSet.member?(known_units(), String.downcase(val)) 43 | end 44 | 45 | defp do_convert(bytes, "kb") do 46 | Float.round(bytes / @kilobyte_bytes, 4) 47 | end 48 | 49 | defp do_convert(bytes, "kilobytes"), do: do_convert(bytes, "kb") 50 | 51 | defp do_convert(bytes, "mb") do 52 | Float.round(bytes / @megabyte_bytes, 4) 53 | end 54 | 55 | defp do_convert(bytes, "megabytes"), do: do_convert(bytes, "mb") 56 | 57 | defp do_convert(bytes, "gb") do 58 | Float.round(bytes / @gigabyte_bytes, 4) 59 | end 60 | 61 | defp do_convert(bytes, "gigabytes"), do: do_convert(bytes, "gb") 62 | 63 | defp do_convert(bytes, "tb") do 64 | Float.round(bytes / @terabyte_bytes, 4) 65 | end 66 | 67 | defp do_convert(bytes, "terabytes"), do: do_convert(bytes, "tb") 68 | end 69 | -------------------------------------------------------------------------------- /test/ctl/stop_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule StopCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.StopCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), 22 | idempotent: false}} 23 | end 24 | 25 | test "validate accepts no arguments", context do 26 | assert @command.validate([], context[:opts]) == :ok 27 | end 28 | 29 | test "validate accepts a PID file path", context do 30 | assert @command.validate(["/path/to/pidfile.pid"], context[:opts]) == :ok 31 | end 32 | 33 | test "validate: with extra arguments returns an arg count error", context do 34 | assert @command.validate(["/path/to/pidfile.pid", "extra"], context[:opts]) == {:validation_failure, :too_many_args} 35 | end 36 | 37 | # NB: as this commands shuts down the Erlang vm it isn't really practical to test it here 38 | 39 | test "run: request to a non-existent node with --idempotent=false returns a badrpc" do 40 | opts = %{node: :jake@thedog, idempotent: false, timeout: 200} 41 | assert match?({:badrpc, _}, @command.run([], opts)) 42 | end 43 | 44 | test "run: request to a non-existent node with --idempotent returns ok" do 45 | opts = %{node: :jake@thedog, idempotent: true, timeout: 200} 46 | assert match?({:ok, _}, @command.run([], opts)) 47 | end 48 | 49 | test "banner", context do 50 | assert @command.banner([], context[:opts]) =~ ~r/Stopping and halting node #{get_rabbit_hostname()}/ 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/info_keys.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.InfoKeys do 8 | import RabbitCommon.Records 9 | alias RabbitMQ.CLI.Core.DataCoercion 10 | 11 | def validate_info_keys(args, valid_keys) do 12 | info_keys = prepare_info_keys(args) 13 | 14 | case invalid_info_keys(info_keys, Enum.map(valid_keys, &DataCoercion.to_atom/1)) do 15 | [_ | _] = bad_info_keys -> 16 | {:validation_failure, {:bad_info_key, bad_info_keys}} 17 | 18 | [] -> 19 | {:ok, info_keys} 20 | end 21 | end 22 | 23 | def prepare_info_keys(args) do 24 | args 25 | |> Enum.flat_map(fn arg -> String.split(arg, ",", trim: true) end) 26 | |> Enum.map(fn s -> String.replace(s, ",", "") end) 27 | |> Enum.map(&String.trim/1) 28 | |> Enum.map(&String.to_atom/1) 29 | |> Enum.uniq() 30 | end 31 | 32 | def with_valid_info_keys(args, valid_keys, fun) do 33 | case validate_info_keys(args, valid_keys) do 34 | {:ok, info_keys} -> fun.(info_keys) 35 | err -> err 36 | end 37 | end 38 | 39 | defp invalid_info_keys(info_keys, valid_keys) do 40 | MapSet.new(info_keys) 41 | |> MapSet.difference(MapSet.new(valid_keys)) 42 | |> MapSet.to_list() 43 | end 44 | 45 | def info_for_keys(item, []) do 46 | item 47 | end 48 | 49 | def info_for_keys([{_, _} | _] = item, info_keys) do 50 | item 51 | |> Enum.filter(fn {k, _} -> Enum.member?(info_keys, k) end) 52 | |> Enum.map(fn {k, v} -> {k, format_info_item(v)} end) 53 | end 54 | 55 | defp format_info_item(resource(name: name)) do 56 | name 57 | end 58 | 59 | defp format_info_item(any) do 60 | any 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/clear_parameter_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ClearParameterCommand do 8 | alias RabbitMQ.CLI.Core.{DocGuide, Helpers} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def merge_defaults(args, opts) do 14 | {args, Map.merge(%{vhost: "/"}, opts)} 15 | end 16 | 17 | def validate(args, _) when is_list(args) and length(args) < 2 do 18 | {:validation_failure, :not_enough_args} 19 | end 20 | 21 | def validate([_ | _] = args, _) when length(args) > 2 do 22 | {:validation_failure, :too_many_args} 23 | end 24 | 25 | def validate([_, _], _), do: :ok 26 | 27 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 28 | 29 | def run([component_name, key], %{node: node_name, vhost: vhost}) do 30 | :rabbit_misc.rpc_call( 31 | node_name, 32 | :rabbit_runtime_parameters, 33 | :clear, 34 | [vhost, component_name, key, Helpers.cli_acting_user()] 35 | ) 36 | end 37 | 38 | def usage, do: "clear_parameter [--vhost ] " 39 | 40 | def usage_additional() do 41 | [ 42 | ["", "component name"], 43 | ["", "parameter name (identifier)"] 44 | ] 45 | end 46 | 47 | def usage_doc_guides() do 48 | [ 49 | DocGuide.parameters() 50 | ] 51 | end 52 | 53 | def help_section(), do: :parameters 54 | 55 | def description(), do: "Clears a runtime parameter." 56 | 57 | def banner([component_name, key], %{vhost: vhost}) do 58 | "Clearing runtime parameter \"#{key}\" for component \"#{component_name}\" on vhost \"#{vhost}\" ..." 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/force_boot_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ForceBootCommand do 8 | alias RabbitMQ.CLI.Core.{Config, DocGuide} 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | 12 | use RabbitMQ.CLI.Core.MergesNoDefaults 13 | use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments 14 | 15 | ## 16 | def validate_execution_environment(args, opts) do 17 | ## We don't use RequiresRabbitAppStopped helper because we don't want to fail 18 | ## the validation if the node is not running. 19 | case RabbitMQ.CLI.Core.Validators.rabbit_is_not_running(args, opts) do 20 | :ok -> :ok 21 | {:validation_failure, _} = failure -> failure 22 | _other -> RabbitMQ.CLI.Core.Validators.node_is_not_running(args, opts) 23 | end 24 | end 25 | 26 | def run([], %{node: node_name} = opts) do 27 | case :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :force_load_next_boot, []) do 28 | {:badrpc, :nodedown} -> 29 | case Config.get_option(:mnesia_dir, opts) do 30 | nil -> 31 | {:error, :mnesia_dir_not_found} 32 | 33 | dir -> 34 | File.write(Path.join(dir, "force_load"), "") 35 | end 36 | 37 | _ -> 38 | :ok 39 | end 40 | end 41 | 42 | use RabbitMQ.CLI.DefaultOutput 43 | 44 | def usage, do: "force_boot" 45 | 46 | def usage_doc_guides() do 47 | [ 48 | DocGuide.clustering() 49 | ] 50 | end 51 | 52 | def help_section(), do: :cluster_management 53 | 54 | def description(), do: "Forces node to start even if it cannot contact or rejoin any of its previously known peers" 55 | 56 | def banner(_, _), do: nil 57 | end 58 | -------------------------------------------------------------------------------- /lib/rabbitmq/cli/ctl/commands/list_user_permissions_command.ex: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | defmodule RabbitMQ.CLI.Ctl.Commands.ListUserPermissionsCommand do 8 | alias RabbitMQ.CLI.Core.DocGuide 9 | 10 | @behaviour RabbitMQ.CLI.CommandBehaviour 11 | use RabbitMQ.CLI.DefaultOutput 12 | 13 | def formatter(), do: RabbitMQ.CLI.Formatters.Table 14 | 15 | def scopes(), do: [:ctl, :diagnostics] 16 | def switches(), do: [timeout: :integer] 17 | def aliases(), do: [t: :timeout] 18 | 19 | def merge_defaults(args, opts) do 20 | {args, Map.merge(%{table_headers: true}, opts)} 21 | end 22 | 23 | def validate([], _), do: {:validation_failure, :not_enough_args} 24 | def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args} 25 | def validate([_], _), do: :ok 26 | 27 | use RabbitMQ.CLI.Core.RequiresRabbitAppRunning 28 | 29 | def run([username], %{node: node_name, timeout: timeout}) do 30 | :rabbit_misc.rpc_call( 31 | node_name, 32 | :rabbit_auth_backend_internal, 33 | :list_user_permissions, 34 | [username], 35 | timeout 36 | ) 37 | end 38 | 39 | def usage, do: "list_user_permissions [--no-table-headers] " 40 | 41 | def usage_additional do 42 | [ 43 | ["", "Name of the user"] 44 | ] 45 | end 46 | 47 | def usage_doc_guides() do 48 | [ 49 | DocGuide.access_control(), 50 | DocGuide.virtual_hosts() 51 | ] 52 | end 53 | 54 | def help_section(), do: :access_control 55 | def description(), do: "Lists permissions of a user across all virtual hosts" 56 | 57 | def banner([username], _), do: "Listing permissions for user \"#{username}\" ..." 58 | end 59 | -------------------------------------------------------------------------------- /test/ctl/shutdown_command_test.exs: -------------------------------------------------------------------------------- 1 | ## This Source Code Form is subject to the terms of the Mozilla Public 2 | ## License, v. 2.0. If a copy of the MPL was not distributed with this 3 | ## file, You can obtain one at https://mozilla.org/MPL/2.0/. 4 | ## 5 | ## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. 6 | 7 | 8 | defmodule ShutdownCommandTest do 9 | use ExUnit.Case, async: false 10 | import TestHelper 11 | 12 | @command RabbitMQ.CLI.Ctl.Commands.ShutdownCommand 13 | 14 | setup_all do 15 | RabbitMQ.CLI.Core.Distribution.start() 16 | 17 | :ok 18 | end 19 | 20 | setup do 21 | {:ok, opts: %{node: get_rabbit_hostname(), timeout: 15}} 22 | end 23 | 24 | test "validate: accepts no arguments", context do 25 | assert @command.validate([], context[:opts]) == :ok 26 | end 27 | 28 | test "validate: with extra arguments returns an arg count error", context do 29 | assert @command.validate(["extra"], context[:opts]) == {:validation_failure, :too_many_args} 30 | end 31 | 32 | test "validate: in wait mode, checks if local and target node hostnames match" do 33 | assert match?({:validation_failure, {:unsupported_target, _}}, 34 | @command.validate([], %{wait: true, node: :'rabbit@some.remote.hostname'})) 35 | end 36 | 37 | test "validate: in wait mode, always assumes @localhost nodes are local" do 38 | assert @command.validate([], %{wait: true, node: :rabbit@localhost}) == :ok 39 | end 40 | 41 | test "validate: in no wait mode, passes unconditionally", context do 42 | assert @command.validate([], Map.merge(%{wait: false}, context[:opts])) == :ok 43 | end 44 | 45 | test "run: request to a non-existent node returns a badrpc" do 46 | opts = %{node: :jake@thedog, wait: false, timeout: 200} 47 | assert match?({:badrpc, _}, @command.run([], opts)) 48 | end 49 | 50 | test "empty banner", context do 51 | nil = @command.banner([], context[:opts]) 52 | end 53 | end 54 | --------------------------------------------------------------------------------