Format with `gmake format`

This commit is contained in:
Michael Klishin 2019-01-30 22:20:29 +03:00
parent d29850caef
commit 94b55d71fa
147 changed files with 3158 additions and 2079 deletions

View File

@ -19,6 +19,6 @@ defmodule RabbitCommon.Records do
defrecord :amqqueue, extract(:amqqueue, from_lib: "rabbit_common/include/rabbit.hrl")
defrecord :listener, extract(:listener, from_lib: "rabbit_common/include/rabbit.hrl")
defrecord :plugin, extract(:plugin, from_lib: "rabbit_common/include/rabbit.hrl")
defrecord :plugin, extract(:plugin, from_lib: "rabbit_common/include/rabbit.hrl")
defrecord :resource, extract(:resource, from_lib: "rabbit_common/include/rabbit.hrl")
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defprotocol Rabbitmq.Atom.Coerce do
def to_atom(data)
end

View File

@ -13,19 +13,20 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule Rabbitmq.CLI.AutoComplete do
alias RabbitMQ.CLI.Core.{CommandModules, Parser}
@spec complete(String.t, [String.t]) :: [String.t]
@spec complete(String.t(), [String.t()]) :: [String.t()]
def complete(_, []) do
[]
end
def complete(script_name, args) do
case Parser.parse_global(args) do
{_, %{script_name: _args_script_name}, _} ->
complete(args);
_ ->
complete(args)
_ ->
complete(["--script-name", script_name | args])
end
end
@ -33,45 +34,53 @@ defmodule Rabbitmq.CLI.AutoComplete do
defp complete(tokens) do
{command, command_name, _, _, _} = Parser.parse(tokens)
last_token = List.last(tokens)
case {command, command_name} do
## No command provided
{_, ""} -> complete_default_opts(last_token);
{_, ""} ->
complete_default_opts(last_token)
## Command is not found/incomplete
{:no_command, command_name} ->
complete_command_name(command_name);
complete_command_name(command_name)
{{:suggest, _}, command_name} ->
complete_command_name(command_name);
complete_command_name(command_name)
## Command is found
{command, _} ->
complete_command_opts(command, last_token)
end
|> Enum.sort
|> Enum.sort()
end
defp complete_default_opts(opt) do
Parser.default_switches
|> Keyword.keys
|> Enum.map(fn(sw) -> "--" <> to_string(sw) end)
Parser.default_switches()
|> Keyword.keys()
|> Enum.map(fn sw -> "--" <> to_string(sw) end)
|> select_starts_with(opt)
|> format_options
end
defp complete_command_name(command_name) do
module_map = CommandModules.module_map
module_map = CommandModules.module_map()
case module_map[command_name] do
nil ->
module_map
|> Map.keys
|> Map.keys()
|> select_starts_with(command_name)
_ ->
command_name
end
end
defp complete_command_opts(command, <<"-", _ :: binary>> = opt) do
switches = command.switches
|> Keyword.keys
|> Enum.map(fn(sw) -> "--" <> to_string(sw) end)
defp complete_command_opts(command, <<"-", _::binary>> = opt) do
switches =
command.switches
|> Keyword.keys()
|> Enum.map(fn sw -> "--" <> to_string(sw) end)
# aliases = command.aliases
# |> Keyword.keys
@ -79,16 +88,17 @@ defmodule Rabbitmq.CLI.AutoComplete do
select_starts_with(switches, opt)
|> format_options
end
defp complete_command_opts(_, _) do
[]
end
defp select_starts_with(list, prefix) do
Enum.filter(list, fn(el) -> String.starts_with?(el, prefix) end)
Enum.filter(list, fn el -> String.starts_with?(el, prefix) end)
end
defp format_options(options) do
options
|> Enum.map(fn(opt) -> String.replace(opt, "_", "-") end)
|> Enum.map(fn opt -> String.replace(opt, "_", "-") end)
end
end

View File

@ -13,19 +13,21 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.CommandBehaviour do
@callback usage() :: String.t | [String.t]
@callback usage() :: String.t() | [String.t()]
# validates CLI arguments
@callback validate(list(), map()) :: :ok | {:validation_failure, atom() | {atom(), String.t}}
@callback validate(list(), map()) :: :ok | {:validation_failure, atom() | {atom(), String.t()}}
@callback merge_defaults(list(), map()) :: {list(), map()}
@callback banner(list(), map()) :: [String.t] | String.t | nil
@callback banner(list(), map()) :: [String.t()] | String.t() | nil
@callback run(list(), map()) :: any
# Coerces run/2 return value into the standard command output form
# that is then formatted, printed and returned as an exit code.
# There is a default implementation for this callback in DefaultOutput module
@callback output(any, map()) :: :ok | {:ok, any} | {:stream, Enum.t} |
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_code, [String.t]}
@callback output(any, map()) ::
:ok
| {:ok, any}
| {:stream, Enum.t()}
| {:error, RabbitMQ.CLI.Core.ExitCodes.exit_code(), [String.t()]}
@optional_callbacks formatter: 0,
scopes: 0,
usage_additional: 0,
@ -36,16 +38,17 @@ defmodule RabbitMQ.CLI.CommandBehaviour do
validate_execution_environment: 2,
distribution: 1
@callback validate_execution_environment(list(), map()) :: :ok | {:validation_failure, atom() | {atom(), any}}
@callback switches() :: Keyword.t
@callback aliases() :: Keyword.t
@callback validate_execution_environment(list(), map()) ::
:ok | {:validation_failure, atom() | {atom(), any}}
@callback switches() :: Keyword.t()
@callback aliases() :: Keyword.t()
@callback formatter() :: atom()
@callback scopes() :: [atom()]
@callback usage_additional() :: String.t | [String.t]
@callback usage_additional() :: String.t() | [String.t()]
## Erlang distribution control
## :cli - default rabbitmqctl generated node name
## :none - disable erlang distribution
## {:fun, fun} - use a custom function to start distribution
@callback distribution(map()) :: :cli | :none | {:fun, ((map()) -> :ok | {:error, any()})}
@callback distribution(map()) :: :cli | :none | {:fun, (map() -> :ok | {:error, any()})}
end

View File

@ -19,8 +19,9 @@ defmodule RabbitMQ.CLI.Core.AcceptsNoPositionalArguments do
defmacro __using__(_) do
quote do
def validate(args, _) when length(args) > 0 do
{:validation_failure, :too_many_args}
{:validation_failure, :too_many_args}
end
# Note: this will accept everything, so it must be the
# last validation clause defined!
def validate(_, _), do: :ok

View File

@ -19,11 +19,13 @@ defmodule RabbitMQ.CLI.Core.AcceptsOnePositionalArgument do
defmacro __using__(_) do
quote do
def validate(args, _) when length(args) == 0 do
{:validation_failure, :not_enough_args}
{:validation_failure, :not_enough_args}
end
def validate(args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
{:validation_failure, :too_many_args}
end
# Note: this will accept everything, so it must be the
# last validation clause defined!
def validate(_, _), do: :ok

View File

@ -19,21 +19,24 @@ defmodule RabbitMQ.CLI.Core.AcceptsOnePositiveIntegerArgument do
defmacro __using__(_) do
quote do
def validate(args, _) when length(args) == 0 do
{:validation_failure, :not_enough_args}
{:validation_failure, :not_enough_args}
end
def validate(args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
{:validation_failure, :too_many_args}
end
def validate([value], _) when is_integer(value) do
:ok
end
def validate([value], _) do
case Integer.parse(value) do
{n, _} when n >= 1 -> :ok
:error -> {:validation_failure,
{:bad_argument, "Argument must be a positive integer"}}
end
case Integer.parse(value) do
{n, _} when n >= 1 -> :ok
:error -> {:validation_failure, {:bad_argument, "Argument must be a positive integer"}}
end
end
def validate(_, _), do: :ok
end
end

View File

@ -60,25 +60,31 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
def plugin_modules(opts) do
Helpers.require_rabbit(opts)
enabled_plugins =
try do
PluginsHelpers.read_enabled(opts)
catch err ->
{:ok, enabled_plugins_file} = PluginsHelpers.enabled_plugins_file(opts)
require Logger
Logger.warn("Unable to read the enebled plugins file.\n" <>
" Reason: #{inspect(err)}\n" <>
" Commands provided by plugins will not be available.\n" <>
" Please make sure your user has sufficient permissions to read to\n" <>
" #{enabled_plugins_file}")
[]
catch
err ->
{:ok, enabled_plugins_file} = PluginsHelpers.enabled_plugins_file(opts)
require Logger
Logger.warn(
"Unable to read the enebled plugins file.\n" <>
" Reason: #{inspect(err)}\n" <>
" Commands provided by plugins will not be available.\n" <>
" Please make sure your user has sufficient permissions to read to\n" <>
" #{enabled_plugins_file}"
)
[]
end
partitioned =
Enum.group_by(enabled_plugins, fn(app) ->
Enum.group_by(enabled_plugins, fn app ->
case Application.load(app) do
:ok -> :loaded;
{:error, {:already_loaded, ^app}} -> :loaded;
:ok -> :loaded
{:error, {:already_loaded, ^app}} -> :loaded
_ -> :not_found
end
end)
@ -87,36 +93,37 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
missing = partitioned[:not_found] || []
## If plugins are not in ERL_LIBS, they should be loaded from plugins_dir
case missing do
[] -> :ok;
_ ->
[] ->
:ok
_ ->
Helpers.add_plugins_to_load_path(opts)
Enum.each(missing, fn(app) -> Application.load(app) end)
Enum.each(missing, fn app -> Application.load(app) end)
end
Enum.flat_map(loaded ++ missing, fn(app) ->
Enum.flat_map(loaded ++ missing, fn app ->
Application.spec(app, :modules) || []
end)
end
defp make_module_map(modules, scope) do
commands_ns = Regex.recompile!(@commands_ns)
modules
|> Enum.filter(fn(mod) ->
to_string(mod) =~ commands_ns
and
module_exists?(mod)
and
implements_command_behaviour?(mod)
and
command_in_scope(mod, scope)
end)
|> Enum.filter(fn mod ->
to_string(mod) =~ commands_ns and
module_exists?(mod) and
implements_command_behaviour?(mod) and
command_in_scope(mod, scope)
end)
|> Enum.map(&command_tuple/1)
|> Map.new
|> Map.new()
end
defp module_exists?(nil) do
false
end
defp module_exists?(mod) do
Code.ensure_loaded?(mod)
end
@ -124,9 +131,12 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
defp implements_command_behaviour?(nil) do
false
end
defp implements_command_behaviour?(module) do
Enum.member?(module.module_info(:attributes)[:behaviour] || [],
RabbitMQ.CLI.CommandBehaviour)
Enum.member?(
module.module_info(:attributes)[:behaviour] || [],
RabbitMQ.CLI.CommandBehaviour
)
end
def module_to_command(mod) do
@ -144,16 +154,16 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
def strip_namespace(str) do
str
|> String.split(".")
|> List.last
|> List.last()
end
def to_snake_case(<<c, str :: binary>>) do
def to_snake_case(<<c, str::binary>>) do
tail = for <<c <- str>>, into: "", do: snake(c)
<<to_lower_char(c), tail :: binary >>
<<to_lower_char(c), tail::binary>>
end
defp snake(c) do
if (c >= ?A) and (c <= ?Z) do
if c >= ?A and c <= ?Z do
<<"_", c + 32>>
else
<<c>>
@ -161,7 +171,7 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
end
defp to_lower_char(c) do
if (c >= ?A) and (c <= ?Z) do
if c >= ?A and c <= ?Z do
c + 32
else
c
@ -171,21 +181,23 @@ defmodule RabbitMQ.CLI.Core.CommandModules do
defp command_in_scope(_cmd, :all) do
true
end
defp command_in_scope(cmd, scope) do
Enum.member?(command_scopes(cmd), scope)
end
defp command_scopes(cmd) do
case :erlang.function_exported(cmd, :scopes, 0) do
true ->
true ->
cmd.scopes()
false ->
Regex.recompile!(@commands_ns)
|> Regex.run(to_string(cmd), capture: :all_but_first)
|> List.first
|> List.first()
|> to_snake_case
|> String.to_atom
|> List.wrap
|> String.to_atom()
|> List.wrap()
end
end
end

View File

@ -14,15 +14,16 @@
## Copyright (c) 2016-2017 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Core.Config do
#
# Environment
#
def get_option(name, opts \\ %{}) do
raw_option = opts[name] ||
get_system_option(name) ||
default(name)
raw_option =
opts[name] ||
get_system_option(name) ||
default(name)
normalise(name, raw_option)
end
@ -31,46 +32,51 @@ defmodule RabbitMQ.CLI.Core.Config do
end
def normalise(:node, nil), do: nil
def normalise(:node, node) when not is_atom(node) do
Rabbitmq.Atom.Coerce.to_atom(node)
end
def normalise(:erlang_cookie, nil), do: nil
def normalise(:erlang_cookie, c) when not is_atom(c) do
Rabbitmq.Atom.Coerce.to_atom(c)
end
def normalise(:longnames, true), do: :longnames
def normalise(:longnames, "true"), do: :longnames
def normalise(:longnames, 'true'), do: :longnames
def normalise(:longnames, true), do: :longnames
def normalise(:longnames, "true"), do: :longnames
def normalise(:longnames, 'true'), do: :longnames
def normalise(:longnames, "\"true\""), do: :longnames
def normalise(:longnames, _val), do: :shortnames
def normalise(_, value), do: value
def normalise(:longnames, _val), do: :shortnames
def normalise(_, value), do: value
def system_env_variable(name) do
case name do
:longnames -> "RABBITMQ_USE_LONGNAME";
:rabbitmq_home -> "RABBITMQ_HOME";
:mnesia_dir -> "RABBITMQ_MNESIA_DIR";
:plugins_dir -> "RABBITMQ_PLUGINS_DIR";
:plugins_expand_dir -> "RABBITMQ_PLUGINS_EXPAND_DIR";
:enabled_plugins_file -> "RABBITMQ_ENABLED_PLUGINS_FILE";
:node -> "RABBITMQ_NODENAME";
:aliases_file -> "RABBITMQ_CLI_ALIASES_FILE";
:erlang_cookie -> "RABBITMQ_ERLANG_COOKIE";
:longnames -> "RABBITMQ_USE_LONGNAME"
:rabbitmq_home -> "RABBITMQ_HOME"
:mnesia_dir -> "RABBITMQ_MNESIA_DIR"
:plugins_dir -> "RABBITMQ_PLUGINS_DIR"
:plugins_expand_dir -> "RABBITMQ_PLUGINS_EXPAND_DIR"
:enabled_plugins_file -> "RABBITMQ_ENABLED_PLUGINS_FILE"
:node -> "RABBITMQ_NODENAME"
:aliases_file -> "RABBITMQ_CLI_ALIASES_FILE"
:erlang_cookie -> "RABBITMQ_ERLANG_COOKIE"
_ -> ""
end
end
def get_system_option(:script_name) do
Path.basename(:escript.script_name())
|> Path.rootname
|> String.to_atom
|> Path.rootname()
|> String.to_atom()
end
def get_system_option(name) do
System.get_env(system_env_variable(name))
end
def default(:script_name), do: :rabbitmqctl
def default(:node), do: :rabbit
def default(:node), do: :rabbit
def default(_), do: nil
#
@ -79,22 +85,26 @@ defmodule RabbitMQ.CLI.Core.Config do
def get_formatter(command, %{formatter: formatter}) do
module_name = Module.safe_concat("RabbitMQ.CLI.Formatters", Macro.camelize(formatter))
case Code.ensure_loaded(module_name) do
{:module, _} -> module_name;
{:module, _} -> module_name
{:error, :nofile} -> default_formatter(command)
end
end
def get_formatter(command, _) do
default_formatter(command)
end
def get_printer(%{printer: printer}) do
module_name = String.to_atom("RabbitMQ.CLI.Printers." <> Macro.camelize(printer))
case Code.ensure_loaded(module_name) do
{:module, _} -> module_name;
{:module, _} -> module_name
{:error, :nofile} -> default_printer()
end
end
def get_printer(_) do
default_printer()
end
@ -105,9 +115,8 @@ defmodule RabbitMQ.CLI.Core.Config do
def default_formatter(command) do
case function_exported?(command, :formatter, 0) do
true -> command.formatter;
true -> command.formatter
false -> RabbitMQ.CLI.Formatters.String
end
end
end

View File

@ -37,25 +37,24 @@ defmodule RabbitMQ.CLI.Core.ExitCodes do
def exit_tempfail, do: @exit_tempfail
def exit_config, do: @exit_config
def exit_code_for({:validation_failure, :not_enough_args}), do: exit_usage()
def exit_code_for({:validation_failure, :too_many_args}), do: exit_usage()
def exit_code_for({:validation_failure, :not_enough_args}), do: exit_usage()
def exit_code_for({:validation_failure, :too_many_args}), do: exit_usage()
def exit_code_for({:validation_failure, {:not_enough_args, _}}), do: exit_usage()
def exit_code_for({:validation_failure, {:too_many_args, _}}), do: exit_usage()
def exit_code_for({:validation_failure, {:bad_argument, _}}), do: exit_dataerr()
def exit_code_for({:validation_failure, :bad_argument}), do: exit_dataerr()
def exit_code_for({:validation_failure, :eperm}), do: exit_dataerr()
def exit_code_for({:validation_failure, {:bad_option, _}}), do: exit_usage()
def exit_code_for({:validation_failure, _}), do: exit_usage()
def exit_code_for({:validation_failure, {:too_many_args, _}}), do: exit_usage()
def exit_code_for({:validation_failure, {:bad_argument, _}}), do: exit_dataerr()
def exit_code_for({:validation_failure, :bad_argument}), do: exit_dataerr()
def exit_code_for({:validation_failure, :eperm}), do: exit_dataerr()
def exit_code_for({:validation_failure, {:bad_option, _}}), do: exit_usage()
def exit_code_for({:validation_failure, _}), do: exit_usage()
# a special case of bad_argument
def exit_code_for({:no_such_vhost, _}), do: exit_dataerr()
def exit_code_for({:badrpc_multi, :timeout, _}), do: exit_tempfail()
def exit_code_for({:badrpc, :timeout}), do: exit_tempfail()
def exit_code_for({:badrpc, {:timeout, _}}), do: exit_tempfail()
def exit_code_for({:badrpc, {:timeout, _, _}}), do: exit_tempfail()
def exit_code_for(:timeout), do: exit_tempfail()
def exit_code_for({:timeout, _}), do: exit_tempfail()
def exit_code_for({:badrpc_multi, :nodedown, _}), do: exit_unavailable()
def exit_code_for({:badrpc, :nodedown}), do: exit_unavailable()
def exit_code_for({:error, _}), do: exit_unavailable()
def exit_code_for({:no_such_vhost, _}), do: exit_dataerr()
def exit_code_for({:badrpc_multi, :timeout, _}), do: exit_tempfail()
def exit_code_for({:badrpc, :timeout}), do: exit_tempfail()
def exit_code_for({:badrpc, {:timeout, _}}), do: exit_tempfail()
def exit_code_for({:badrpc, {:timeout, _, _}}), do: exit_tempfail()
def exit_code_for(:timeout), do: exit_tempfail()
def exit_code_for({:timeout, _}), do: exit_tempfail()
def exit_code_for({:badrpc_multi, :nodedown, _}), do: exit_unavailable()
def exit_code_for({:badrpc, :nodedown}), do: exit_unavailable()
def exit_code_for({:error, _}), do: exit_unavailable()
end

View File

@ -45,10 +45,11 @@ defmodule RabbitMQ.CLI.Core.Helpers do
def validate_step(:ok, step) do
case step.() do
{:error, err} -> {:validation_failure, err};
_ -> :ok
{:error, err} -> {:validation_failure, err}
_ -> :ok
end
end
def validate_step({:validation_failure, err}, _) do
{:validation_failure, err}
end
@ -57,31 +58,32 @@ defmodule RabbitMQ.CLI.Core.Helpers do
["k", "kiB", "M", "MiB", "G", "GiB", "kB", "MB", "GB", ""]
end
def memory_unit_absolute(num, unit) when is_number(num) and num < 0, do: {:bad_argument, [num, unit]}
def memory_unit_absolute(num, unit) when is_number(num) and num < 0,
do: {:bad_argument, [num, unit]}
def memory_unit_absolute(num, "k") when is_number(num), do: power_as_int(num, 2, 10)
def memory_unit_absolute(num, "k") when is_number(num), do: power_as_int(num, 2, 10)
def memory_unit_absolute(num, "kiB") when is_number(num), do: power_as_int(num, 2, 10)
def memory_unit_absolute(num, "M") when is_number(num), do: power_as_int(num, 2, 20)
def memory_unit_absolute(num, "M") when is_number(num), do: power_as_int(num, 2, 20)
def memory_unit_absolute(num, "MiB") when is_number(num), do: power_as_int(num, 2, 20)
def memory_unit_absolute(num, "G") when is_number(num), do: power_as_int(num, 2, 30)
def memory_unit_absolute(num, "G") when is_number(num), do: power_as_int(num, 2, 30)
def memory_unit_absolute(num, "GiB") when is_number(num), do: power_as_int(num, 2, 30)
def memory_unit_absolute(num, "kB") when is_number(num), do: power_as_int(num, 10, 3)
def memory_unit_absolute(num, "MB") when is_number(num), do: power_as_int(num, 10, 6)
def memory_unit_absolute(num, "GB") when is_number(num), do: power_as_int(num, 10, 9)
def memory_unit_absolute(num, "kB") when is_number(num), do: power_as_int(num, 10, 3)
def memory_unit_absolute(num, "MB") when is_number(num), do: power_as_int(num, 10, 6)
def memory_unit_absolute(num, "GB") when is_number(num), do: power_as_int(num, 10, 9)
def memory_unit_absolute(num, "") when is_number(num), do: num
def memory_unit_absolute(num, unit) when is_number(num), do: {:bad_argument, [unit]}
def memory_unit_absolute(num, unit), do: {:bad_argument, [num, unit]}
def power_as_int(num, x, y), do: round(num * (:math.pow(x, y)))
def power_as_int(num, x, y), do: round(num * :math.pow(x, y))
def nodes_in_cluster(node, timeout \\ :infinity) do
with_nodes_in_cluster(node, fn(nodes) -> nodes end, timeout)
with_nodes_in_cluster(node, fn nodes -> nodes end, timeout)
end
def with_nodes_in_cluster(node, fun, timeout \\ :infinity) do
case :rpc.call(node, :rabbit_mnesia, :cluster_nodes, [:running], timeout) do
{:badrpc, _} = err -> err
value -> fun.(value)
value -> fun.(value)
end
end
@ -91,11 +93,14 @@ defmodule RabbitMQ.CLI.Core.Helpers do
def plugins_dir(opts) do
case Config.get_option(:plugins_dir, opts) do
nil -> {:error, :no_plugins_dir};
nil ->
{:error, :no_plugins_dir}
dir ->
paths = String.split(to_string(dir), path_separator())
case Enum.any?(paths, &File.dir?/1) do
true -> {:ok, dir};
true -> {:ok, dir}
false -> {:error, :plugins_dir_does_not_exist}
end
end
@ -117,19 +122,24 @@ defmodule RabbitMQ.CLI.Core.Helpers do
def require_rabbit(opts) do
home = Config.get_option(:rabbitmq_home, opts)
case home do
nil ->
{:error, {:unable_to_load_rabbit, :rabbitmq_home_is_undefined}};
_ ->
{:error, {:unable_to_load_rabbit, :rabbitmq_home_is_undefined}}
_ ->
path = Path.join(home, "ebin")
Code.append_path(path)
case Application.load(:rabbit) do
:ok ->
Code.ensure_loaded(:rabbit_plugins)
:ok;
:ok
{:error, {:already_loaded, :rabbit}} ->
Code.ensure_loaded(:rabbit_plugins)
:ok;
:ok
{:error, err} ->
{:error, {:unable_to_load_rabbit, err}}
end
@ -138,7 +148,7 @@ defmodule RabbitMQ.CLI.Core.Helpers do
def rabbit_app_running?(%{node: node, timeout: timeout}) do
case :rabbit_misc.rpc_call(node, :rabbit, :is_running, [], timeout) do
true -> true
true -> true
false -> false
other -> {:error, other}
end
@ -149,32 +159,34 @@ defmodule RabbitMQ.CLI.Core.Helpers do
end
def add_plugins_to_load_path(opts) do
with {:ok, plugins_dir} <- plugins_dir(opts)
do
with {:ok, plugins_dir} <- plugins_dir(opts) do
String.split(to_string(plugins_dir), path_separator())
|>
Enum.map(&add_directory_plugins_to_load_path/1)
|> Enum.map(&add_directory_plugins_to_load_path/1)
:ok
end
end
def add_directory_plugins_to_load_path(directory_with_plugins_inside_it) do
with {:ok, files} <- File.ls(directory_with_plugins_inside_it)
do
Enum.map(files,
fn(filename) ->
with {:ok, files} <- File.ls(directory_with_plugins_inside_it) do
Enum.map(
files,
fn filename ->
cond do
String.ends_with?(filename, [".ez"]) ->
Path.join([directory_with_plugins_inside_it, filename])
|> String.to_charlist
|> add_archive_code_path();
|> String.to_charlist()
|> add_archive_code_path()
File.dir?(filename) ->
Path.join([directory_with_plugins_inside_it, filename])
|> add_dir_code_path();
|> add_dir_code_path()
true ->
{:error, {:not_a_plugin, filename}}
end
end)
end
)
end
end
@ -182,22 +194,29 @@ defmodule RabbitMQ.CLI.Core.Helpers do
case :erl_prim_loader.list_dir(ez_dir) do
{:ok, [app_dir]} ->
app_in_ez = :filename.join(ez_dir, app_dir)
add_dir_code_path(app_in_ez);
_ -> {:error, :no_app_dir}
add_dir_code_path(app_in_ez)
_ ->
{:error, :no_app_dir}
end
end
defp add_dir_code_path(app_dir_0) do
app_dir = to_charlist(app_dir_0)
case :erl_prim_loader.list_dir(app_dir) do
{:ok, list} ->
case Enum.member?(list, 'ebin') do
true ->
ebin_dir = :filename.join(app_dir, 'ebin')
Code.append_path(ebin_dir)
false -> {:error, :no_ebin}
end;
_ -> {:error, :app_dir_empty}
false ->
{:error, :no_ebin}
end
_ ->
{:error, :app_dir_empty}
end
end
@ -205,10 +224,12 @@ defmodule RabbitMQ.CLI.Core.Helpers do
case Application.get_env(:mnesia, :dir) do
nil ->
case Config.get_option(:mnesia_dir, opts) do
nil -> {:error, :mnesia_dir_not_found};
nil -> {:error, :mnesia_dir_not_found}
val -> Application.put_env(:mnesia, :dir, to_charlist(val))
end
_ -> :ok
_ ->
:ok
end
end
@ -218,7 +239,7 @@ defmodule RabbitMQ.CLI.Core.Helpers do
# Convert function to stream
def defer(fun) do
Stream.iterate(:ok, fn(_) -> fun.() end)
Stream.iterate(:ok, fn _ -> fun.() end)
|> Stream.drop(1)
|> Stream.take(1)
end
@ -230,18 +251,18 @@ defmodule RabbitMQ.CLI.Core.Helpers do
# to then next function, or {:ok, val, output} where
# val will be passed and output will be put into the stream
def stream_until_error_parametrised(funs, init) do
Stream.transform(
funs, {:just, init},
fn(f, {:just, val}) ->
case f.(val) do
{:error, _} = err -> {[err], :nothing};
:ok -> {[], {:just, val}};
{:ok, new_val} -> {[], {:just, new_val}};
{:ok, new_val, out} -> {[out], {:just, new_val}}
end;
(_, :nothing) ->
{:halt, :nothing}
end)
Stream.transform(funs, {:just, init}, fn
f, {:just, val} ->
case f.(val) do
{:error, _} = err -> {[err], :nothing}
:ok -> {[], {:just, val}}
{:ok, new_val} -> {[], {:just, new_val}}
{:ok, new_val, out} -> {[out], {:just, new_val}}
end
_, :nothing ->
{:halt, :nothing}
end)
end
# Streamify function sequence.
@ -251,35 +272,37 @@ defmodule RabbitMQ.CLI.Core.Helpers do
stream_until_error_parametrised(
Enum.map(
funs,
fn(fun) ->
fn(:no_param) ->
fn fun ->
fn :no_param ->
case fun.() do
{:error, _} = err -> err;
other -> {:ok, :no_param, other}
{:error, _} = err -> err
other -> {:ok, :no_param, other}
end
end
end),
:no_param)
end
),
:no_param
)
end
def apply_if_exported(mod, fun, args, default) do
case function_exported?(mod, fun, length(args)) do
true -> apply(mod, fun, args);
true -> apply(mod, fun, args)
false -> default
end
end
def path_separator() do
case :os.type do
{:unix, _} -> ":"
{:win32, _} -> ";"
case :os.type() do
{:unix, _} -> ":"
{:win32, _} -> ";"
end
end
def line_separator() do
case :os.type do
{:unix, _} -> "\n"
{:win32, _} -> "\r\n"
case :os.type() do
{:unix, _} -> "\n"
{:win32, _} -> "\r\n"
end
end
@ -287,18 +310,22 @@ defmodule RabbitMQ.CLI.Core.Helpers do
def string_or_inspect(val) do
case String.Chars.impl_for(val) do
nil -> inspect(val);
_ ->
try do to_string(val)
catch _, _ -> inspect(val)
nil ->
inspect(val)
_ ->
try do
to_string(val)
catch
_, _ -> inspect(val)
end
end
end
def evaluate_input_as_term(input) do
{:ok,tokens,_end_line} = :erl_scan.string(to_charlist(input <> "."))
{:ok,abs_form} = :erl_parse.parse_exprs(tokens)
{:value,term_value,_bs} = :erl_eval.exprs(abs_form, :erl_eval.new_bindings())
term_value
{:ok, tokens, _end_line} = :erl_scan.string(to_charlist(input <> "."))
{:ok, abs_form} = :erl_parse.parse_exprs(tokens)
{:value, term_value, _bs} = :erl_eval.exprs(abs_form, :erl_eval.new_bindings())
term_value
end
end

View File

@ -24,9 +24,10 @@ defmodule RabbitMQ.CLI.Core.OsPid do
def wait_for_os_process_death(pid) do
case :rabbit_misc.is_os_process_alive(pid) do
true ->
true ->
:timer.sleep(@external_process_check_interval)
wait_for_os_process_death(pid);
wait_for_os_process_death(pid)
false ->
:ok
end
@ -36,9 +37,12 @@ defmodule RabbitMQ.CLI.Core.OsPid do
case {:file.read_file(pidfile_path), should_wait} do
{{:ok, contents}, _} ->
pid_regex = Regex.recompile!(@pid_regex)
case Regex.named_captures(pid_regex, contents)["pid"] do
# e.g. the file is empty
nil -> {:error, :could_not_read_pid_from_file, {:contents, contents}};
nil ->
{:error, :could_not_read_pid_from_file, {:contents, contents}}
pid_string ->
try do
{pid, _remainder} = Integer.parse(pid_string)
@ -48,10 +52,12 @@ defmodule RabbitMQ.CLI.Core.OsPid do
{:error, {:could_not_read_pid_from_file, {:contents, contents}}}
end
end
# file does not exist, wait and re-check
{{:error, :enoent}, true} ->
:timer.sleep(@external_process_check_interval)
read_pid_from_file(pidfile_path, should_wait);
read_pid_from_file(pidfile_path, should_wait)
{{:error, details}, _} ->
{:error, :could_not_read_pid_from_file, details}
end

View File

@ -13,22 +13,24 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Core.Output do
def format_output(:ok, _, _) do
:ok
end
# the command intends to produce no output
def format_output({:ok, nil}, _, _) do
:ok
end
def format_output({:ok, :check_passed}, _, _) do
:ok
end
def format_output({:ok, output}, formatter, options) do
{:ok, formatter.format_output(output, options)}
end
def format_output({:stream, stream}, formatter, options) do
{:stream, formatter.format_stream(stream, options)}
end
@ -44,33 +46,36 @@ defmodule RabbitMQ.CLI.Core.Output do
printer.print_ok(printer_state)
:ok
end
# the command intends to produce no output
def print_output_0({:ok, nil}, _printer, _printer_state) do
:ok
end
def print_output_0({:ok, :check_passed}, _printer, _printer_state) do
:ok
end
def print_output_0({:ok, single_value}, printer, printer_state) do
printer.print_output(single_value, printer_state)
:ok
end
def print_output_0({:stream, stream}, printer, printer_state) do
case print_output_stream(stream, printer, printer_state) do
:ok -> :ok;
:ok -> :ok
{:error, _} = err -> err
end
end
def print_output_stream(stream, printer, printer_state) do
Enum.reduce_while(stream, :ok,
fn
({:error, err}, _) ->
Enum.reduce_while(stream, :ok, fn
{:error, err}, _ ->
{:halt, {:error, err}}
(val, _) ->
val, _ ->
printer.print_output(val, printer_state)
{:cont, :ok}
end)
end)
end
end

View File

@ -20,11 +20,10 @@ defmodule RabbitMQ.CLI.Core.Parser do
# the English language is 5.
@levenshtein_distance_limit 5
@spec parse([String.t]) :: {command :: :no_command | atom() | {:suggest, String.t},
command_name :: String.t,
arguments :: [String.t],
options :: map(),
invalid :: [{String.t, String.t | nil}]}
@spec parse([String.t()]) ::
{command :: :no_command | atom() | {:suggest, String.t()}, command_name :: String.t(),
arguments :: [String.t()], options :: map(),
invalid :: [{String.t(), String.t() | nil}]}
def parse(input) do
{parsed_args, options, invalid} = parse_global(input)
@ -32,16 +31,21 @@ defmodule RabbitMQ.CLI.Core.Parser do
case command_module do
nil ->
{:no_command, command_name, arguments, options, invalid};
{:no_command, command_name, arguments, options, invalid}
{:suggest, _} = suggest ->
{suggest, command_name, arguments, options, invalid};
{suggest, command_name, arguments, options, invalid}
{:alias, alias_module, alias_content} ->
{[_alias_command_name | cmd_arguments], cmd_options, cmd_invalid} =
parse_alias(input, command_name, alias_module, alias_content, options)
{alias_module, command_name, cmd_arguments, cmd_options, cmd_invalid};
{alias_module, command_name, cmd_arguments, cmd_options, cmd_invalid}
command_module when is_atom(command_module) ->
{[^command_name | cmd_arguments], cmd_options, cmd_invalid} =
parse_command_specific(input, command_module, options)
{command_module, command_name, cmd_arguments, cmd_options, cmd_invalid}
end
end
@ -53,17 +57,24 @@ defmodule RabbitMQ.CLI.Core.Parser do
## Most of the time a command will be from rabbitmqctl application
## so there is not point in scanning plugins for potential commands
CommandModules.load_core(options)
core_commands = CommandModules.module_map_core
command = case core_commands[cmd_name] do
nil ->
CommandModules.load(options)
module_map = CommandModules.module_map
module_map[cmd_name] ||
command_alias(cmd_name, module_map, options) ||
command_suggestion(cmd_name, module_map);
c -> c
end
core_commands = CommandModules.module_map_core()
command =
case core_commands[cmd_name] do
nil ->
CommandModules.load(options)
module_map = CommandModules.module_map()
module_map[cmd_name] ||
command_alias(cmd_name, module_map, options) ||
command_suggestion(cmd_name, module_map)
c ->
c
end
{cmd_name, command, arguments}
[] ->
{"", nil, []}
end
@ -71,11 +82,14 @@ defmodule RabbitMQ.CLI.Core.Parser do
defp command_alias(cmd_name, module_map, options) do
aliases = load_aliases(options)
case aliases[cmd_name] do
nil -> nil;
nil ->
nil
[alias_cmd_name | _] = alias_content ->
case module_map[alias_cmd_name] do
nil -> nil;
nil -> nil
module -> {:alias, module, alias_content}
end
end
@ -83,20 +97,27 @@ defmodule RabbitMQ.CLI.Core.Parser do
defp load_aliases(options) do
aliases_file = Config.get_option(:aliases_file, options)
case aliases_file && File.read(aliases_file) do
## No aliases file
nil -> %{};
nil ->
%{}
{:ok, content} ->
String.split(content, "\n")
|> Enum.reduce(%{},
fn(str, acc) ->
case String.split(str, "=", parts: 2) do
[alias_name, alias_string] ->
Map.put(acc, String.trim(alias_name), OptionParser.split(alias_string))
_ ->
acc
end
end);
|> Enum.reduce(
%{},
fn str, acc ->
case String.split(str, "=", parts: 2) do
[alias_name, alias_string] ->
Map.put(acc, String.trim(alias_name), OptionParser.split(alias_string))
_ ->
acc
end
end
)
{:error, err} ->
IO.puts(:stderr, "Error reading aliases file #{aliases_file}: #{err}")
%{}
@ -106,16 +127,20 @@ defmodule RabbitMQ.CLI.Core.Parser do
defp command_suggestion(_cmd_name, empty) when empty == %{} do
nil
end
defp command_suggestion(cmd_name, module_map) do
suggestion = module_map
|> Map.keys
|> Enum.map(fn(cmd) ->
{cmd, Simetric.Levenshtein.compare(cmd, cmd_name)}
end)
|> Enum.min_by(fn({_,distance}) -> distance end)
suggestion =
module_map
|> Map.keys()
|> Enum.map(fn cmd ->
{cmd, Simetric.Levenshtein.compare(cmd, cmd_name)}
end)
|> Enum.min_by(fn {_, distance} -> distance end)
case suggestion do
{cmd, distance} when distance <= @levenshtein_distance_limit ->
{:suggest, cmd};
{:suggest, cmd}
_ ->
nil
end
@ -141,6 +166,7 @@ defmodule RabbitMQ.CLI.Core.Parser do
def parse_global_head(input) do
switches = default_switches()
aliases = default_aliases()
{options, tail, invalid} =
OptionParser.parse_head(
input,
@ -148,7 +174,8 @@ defmodule RabbitMQ.CLI.Core.Parser do
aliases: aliases,
allow_nonexistent_atoms: true
)
norm_options = normalize_options(options, switches) |> Map.new
norm_options = normalize_options(options, switches) |> Map.new()
{norm_options, tail, invalid}
end
@ -159,74 +186,85 @@ defmodule RabbitMQ.CLI.Core.Parser do
end
defp parse_generic(input, switches, aliases) do
{options, args, invalid} = OptionParser.parse(
input,
strict: switches,
aliases: aliases,
allow_nonexistent_atoms: true
)
norm_options = normalize_options(options, switches) |> Map.new
{options, args, invalid} =
OptionParser.parse(
input,
strict: switches,
aliases: aliases,
allow_nonexistent_atoms: true
)
norm_options = normalize_options(options, switches) |> Map.new()
{args, norm_options, invalid}
end
def default_switches() do
[node: :atom,
quiet: :boolean,
silent: :boolean,
dry_run: :boolean,
vhost: :string,
# for backwards compatibility,
# not all commands support timeouts
timeout: :integer,
longnames: :boolean,
formatter: :string,
printer: :string,
file: :string,
script_name: :atom,
rabbitmq_home: :string,
mnesia_dir: :string,
plugins_dir: :string,
enabled_plugins_file: :string,
aliases_file: :string,
erlang_cookie: :atom
[
node: :atom,
quiet: :boolean,
silent: :boolean,
dry_run: :boolean,
vhost: :string,
# for backwards compatibility,
# not all commands support timeouts
timeout: :integer,
longnames: :boolean,
formatter: :string,
printer: :string,
file: :string,
script_name: :atom,
rabbitmq_home: :string,
mnesia_dir: :string,
plugins_dir: :string,
enabled_plugins_file: :string,
aliases_file: :string,
erlang_cookie: :atom
]
end
def default_aliases() do
[p: :vhost,
n: :node,
q: :quiet,
s: :silent,
l: :longnames,
# for backwards compatibility,
# not all commands support timeouts
t: :timeout]
[
p: :vhost,
n: :node,
q: :quiet,
s: :silent,
l: :longnames,
# for backwards compatibility,
# not all commands support timeouts
t: :timeout
]
end
defp build_switches(default, command, formatter) do
command_switches = apply_if_exported(command, :switches, [], [])
formatter_switches = apply_if_exported(formatter, :switches, [], [])
assert_no_conflict(command, command_switches, formatter_switches,
:redefining_formatter_switches)
merge_if_different(default, formatter_switches,
{:formatter_invalid,
{formatter, {:redefining_global_switches,
default,
formatter_switches}}})
|> merge_if_different(command_switches,
{:command_invalid,
{command, {:redefining_global_switches,
default,
command_switches}}})
assert_no_conflict(
command,
command_switches,
formatter_switches,
:redefining_formatter_switches
)
merge_if_different(
default,
formatter_switches,
{:formatter_invalid,
{formatter, {:redefining_global_switches, default, formatter_switches}}}
)
|> merge_if_different(
command_switches,
{:command_invalid, {command, {:redefining_global_switches, default, command_switches}}}
)
end
defp assert_no_conflict(command, command_fields, formatter_fields, err) do
merge_if_different(formatter_fields, command_fields,
{:command_invalid,
{command, {err, formatter_fields, command_fields}}})
merge_if_different(
formatter_fields,
command_fields,
{:command_invalid, {command, {err, formatter_fields, command_fields}}}
)
:ok
end
@ -234,40 +272,43 @@ defmodule RabbitMQ.CLI.Core.Parser do
command_aliases = apply_if_exported(command, :aliases, [], [])
formatter_aliases = apply_if_exported(formatter, :aliases, [], [])
assert_no_conflict(command, command_aliases, formatter_aliases,
:redefining_formatter_aliases)
assert_no_conflict(command, command_aliases, formatter_aliases, :redefining_formatter_aliases)
merge_if_different(default, formatter_aliases,
{:formatter_invalid,
{command, {:redefining_global_aliases,
default,
formatter_aliases}}})
|> merge_if_different(command_aliases,
{:command_invalid,
{command, {:redefining_global_aliases,
default,
command_aliases}}})
merge_if_different(
default,
formatter_aliases,
{:formatter_invalid, {command, {:redefining_global_aliases, default, formatter_aliases}}}
)
|> merge_if_different(
command_aliases,
{:command_invalid, {command, {:redefining_global_aliases, default, command_aliases}}}
)
end
defp apply_if_exported(mod, fun, args, default) do
Code.ensure_loaded(mod)
case function_exported?(mod, fun, length(args)) do
true -> apply(mod, fun, args);
true -> apply(mod, fun, args)
false -> default
end
end
defp merge_if_different(default, specific, error) do
case keyword_intersect(default, specific) do
[] -> Keyword.merge(default, specific);
[] ->
Keyword.merge(default, specific)
conflicts ->
# if all conflicting keys are of the same type,
# that's acceptable
case Enum.all?(conflicts,
fn(c) ->
Keyword.get(default, c) == Keyword.get(specific, c)
end) do
true -> Keyword.merge(default, specific);
case Enum.all?(
conflicts,
fn c ->
Keyword.get(default, c) == Keyword.get(specific, c)
end
) do
true -> Keyword.merge(default, specific)
false -> exit(error)
end
end
@ -277,24 +318,27 @@ defmodule RabbitMQ.CLI.Core.Parser do
one_keys = MapSet.new(Keyword.keys(one))
two_keys = MapSet.new(Keyword.keys(two))
intersection = MapSet.intersection(one_keys, two_keys)
case Enum.empty?(intersection) do
true -> [];
true -> []
false -> MapSet.to_list(intersection)
end
end
defp normalize_options(options, switches) do
Enum.map(options,
fn({key, option}) ->
{key, normalize_type(option, switches[key])}
end)
Enum.map(
options,
fn {key, option} ->
{key, normalize_type(option, switches[key])}
end
)
end
defp normalize_type(value, :atom) when is_binary(value) do
String.to_atom(value)
end
defp normalize_type(value, _type) do
value
end
end

View File

@ -19,73 +19,74 @@ defmodule RabbitMQ.CLI.Core.Validators do
def chain([validator | rest], args) do
case apply(validator, args) do
:ok -> chain(rest, args)
{:ok, _} -> chain(rest, args)
:ok -> chain(rest, args)
{:ok, _} -> chain(rest, args)
{:validation_failure, err} -> {:validation_failure, err}
{:error, err} -> {:validation_failure, err}
{:error, err} -> {:validation_failure, err}
end
end
def chain([], _) do
:ok
end
def node_is_not_running(_, %{node: node_name}) do
case Helpers.node_running?(node_name) do
true -> {:validation_failure, :node_running};
true -> {:validation_failure, :node_running}
false -> :ok
end
end
def node_is_running(_, %{node: node_name}) do
case Helpers.node_running?(node_name) do
false -> {:validation_failure, :node_not_running};
true -> :ok
false -> {:validation_failure, :node_not_running}
true -> :ok
end
end
def mnesia_dir_is_set(_, opts) do
case Helpers.require_mnesia_dir(opts) do
:ok -> :ok;
:ok -> :ok
{:error, err} -> {:validation_failure, err}
end
end
def rabbit_is_loaded(_, opts) do
case Helpers.require_rabbit(opts) do
:ok -> :ok;
:ok -> :ok
{:error, err} -> {:validation_failure, err}
end
end
def rabbit_is_running(args, opts) do
case rabbit_app_state(args, opts) do
:running -> :ok;
:stopped -> {:validation_failure, :rabbit_app_is_stopped};
other -> other
:running -> :ok
:stopped -> {:validation_failure, :rabbit_app_is_stopped}
other -> other
end
end
def rabbit_is_running_or_offline_flag_used(_args, %{offline: true}) do
:ok
end
def rabbit_is_running_or_offline_flag_used(args, opts) do
rabbit_is_running(args, opts)
end
def rabbit_is_not_running(args, opts) do
case rabbit_app_state(args, opts) do
:running -> {:validation_failure, :rabbit_app_is_running};
:stopped -> :ok;
other -> other
:running -> {:validation_failure, :rabbit_app_is_running}
:stopped -> :ok
other -> other
end
end
def rabbit_app_state(_, opts) do
case Helpers.rabbit_app_running?(opts) do
true -> :running;
false -> :stopped;
true -> :running
false -> :stopped
{:error, err} -> {:error, err}
end
end
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.AddUserCommand do
alias RabbitMQ.CLI.Core.{ExitCodes, Helpers}
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -34,14 +32,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AddUserCommand do
{:validation_failure, {:bad_argument, "user cannot be empty string."}}
end
def validate([_,_], _), do: :ok
def validate([_, _], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_, _] = args, %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:add_user, args ++ [Helpers.cli_acting_user()])
:add_user,
args ++ [Helpers.cli_acting_user()]
)
end
def usage, do: "add_user <username> <password>"
@ -51,5 +52,6 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AddUserCommand do
def output({:error, {:user_already_exists, username}}, _) do
{:error, ExitCodes.exit_software(), "User \"#{username}\" already exists"}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.AddVhostCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -24,7 +22,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AddVhostCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.AuthenticateUserCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -21,12 +20,13 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AuthenticateUserCommand do
def validate(args, _) when length(args) < 2, do: {:validation_failure, :not_enough_args}
def validate(args, _) when length(args) > 2, do: {:validation_failure, :too_many_args}
def validate([_,_], _), do: :ok
def validate([_, _], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([user, password], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_access_control,
:check_user_pass_login,
[user, password]
@ -38,12 +38,14 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AuthenticateUserCommand do
def banner([username, _password], _), do: "Authenticating user \"#{username}\" ..."
def output({:refused, user, msg, args}, _) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_dataerr,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_dataerr(),
"Error: failed to authenticate user \"#{user}\"\n" <>
to_string(:io_lib.format(msg, args))}
to_string(:io_lib.format(msg, args))}
end
def output({:ok, _user}, _) do
{:ok, "Success"}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,18 +13,19 @@
## The Initial Developer of the Original Code is Pivotal Software, Inc.
## Copyright (c) 2016-2018 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.AwaitOnlineNodesCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@default_timeout 300_000
def merge_defaults(args, opts) do
timeout = case opts[:timeout] do
nil -> @default_timeout;
:infinity -> @default_timeout;
other -> other
end
timeout =
case opts[:timeout] do
nil -> @default_timeout
:infinity -> @default_timeout
other -> other
end
{args, Map.merge(opts, %{timeout: timeout})}
end
@ -34,8 +35,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AwaitOnlineNodesCommand do
def run([count], %{node: node_name, timeout: timeout}) do
{n, _} = Integer.parse(count)
:rabbit_misc.rpc_call(node_name,
:rabbit_nodes, :await_running_count, [n, timeout])
:rabbit_misc.rpc_call(node_name, :rabbit_nodes, :await_running_count, [n, timeout])
end
def usage() do
@ -43,15 +43,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AwaitOnlineNodesCommand do
end
def banner([count], %{node: node_name, timeout: timeout}) when is_number(timeout) do
"Will wait for at least #{count} nodes to join the cluster of #{node_name}. Timeout: #{trunc(timeout / 1000)} seconds."
"Will wait for at least #{count} nodes to join the cluster of #{node_name}. Timeout: #{
trunc(timeout / 1000)
} seconds."
end
def banner([count], %{node: node_name, timeout: _timeout}) do
"Will wait for at least #{count} nodes to join the cluster of #{node_name}."
end
def output({:error, :timeout}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"Error: timed out while waiting. Not enough nodes joined #{node_name}'s cluster."}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -35,9 +35,13 @@ defmodule RabbitMQ.CLI.Ctl.Commands.AwaitStartupCommand do
use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments
def run([], %{node: node_name, timeout: timeout} = opts) do
:rabbit_misc.rpc_call(node_name, :rabbit, :await_startup,
[node_name, not output_less?(opts), timeout])
:rabbit_misc.rpc_call(node_name, :rabbit, :await_startup, [
node_name,
not output_less?(opts),
timeout
])
end
use RabbitMQ.CLI.DefaultOutput
def usage, do: "await_startup"

View File

@ -23,14 +23,15 @@ defmodule RabbitMQ.CLI.Ctl.Commands.CancelSyncQueueCommand do
def usage, do: "cancel_sync_queue [-p <vhost>] queue"
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([queue], %{vhost: vhost, node: node_name}) do
:rpc.call(node_name,
:rpc.call(
node_name,
:rabbit_mirror_queue_misc,
:cancel_sync_queue,
[:rabbit_misc.r(vhost, :queue, queue)],

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is Pivotal Software, Inc.
## Copyright (c) 2016-2017 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ChangeClusterNodeTypeCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -21,27 +20,32 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ChangeClusterNodeTypeCommand do
{args, opts}
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
# node type
def validate(["disc"], _), do: :ok
def validate(["disk"], _), do: :ok
def validate(["ram"], _), do: :ok
def validate(["ram"], _), do: :ok
def validate([_], _), do: {:validation_failure, {:bad_argument, "The node type must be either disc or ram."}}
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate([_], _),
do: {:validation_failure, {:bad_argument, "The node type must be either disc or ram."}}
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppStopped
def run([node_type_arg], %{node: node_name}) do
normalized_type = normalize_type(String.to_atom(node_type_arg))
current_type = :rabbit_misc.rpc_call(node_name,
:rabbit_mnesia, :node_type, [])
current_type = :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :node_type, [])
case current_type do
^normalized_type -> {:ok, "Node type is already #{normalized_type}"};
^normalized_type ->
{:ok, "Node type is already #{normalized_type}"}
_ ->
:rabbit_misc.rpc_call(node_name,
:rabbit_mnesia, :change_cluster_node_type, [normalized_type])
:rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :change_cluster_node_type, [
normalized_type
])
end
end
@ -54,17 +58,20 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ChangeClusterNodeTypeCommand do
end
def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)}
end
use RabbitMQ.CLI.DefaultOutput
defp normalize_type(:ram) do
:ram
end
defp normalize_type(:disc) do
:disc
end
defp normalize_type(:disk) do
:disc
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ChangePasswordCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -23,18 +21,21 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ChangePasswordCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate(args, _) when length(args) < 2, do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 2, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 2, do: {:validation_failure, :too_many_args}
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_user, _] = args, %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal, :change_password, args ++ [Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:change_password,
args ++ [Helpers.cli_acting_user()]
)
end
def usage, do: "change_password <username> <password>"
def banner([user| _], _), do: "Changing password for user \"#{user}\" ..."
def banner([user | _], _), do: "Changing password for user \"#{user}\" ..."
end

View File

@ -13,13 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearGlobalParameterCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, opts}
end
@ -27,18 +26,22 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearGlobalParameterCommand do
def validate(args, _) when is_list(args) and length(args) < 1 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([key], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:clear_global,
[key, Helpers.cli_acting_user()])
[key, Helpers.cli_acting_user()]
)
end
def usage, do: "clear_global_parameter <key>"

View File

@ -13,13 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearOperatorPolicyCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{vhost: "/"}, opts)}
end
@ -27,21 +26,25 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearOperatorPolicyCommand do
def validate([], _) do
{:validation_failure, :not_enough_args}
end
def validate([_,_|_], _) do
def validate([_, _ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([key], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_policy, :delete_op, [vhost, key, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_policy, :delete_op, [
vhost,
key,
Helpers.cli_acting_user()
])
end
def usage, do: "clear_operator_policy [-p <vhost>] <key>"
def banner([key], %{vhost: vhost}) do
"Clearing operator policy \"#{key}\" on vhost \"#{vhost}\" ..."
end

View File

@ -13,13 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearParameterCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{vhost: "/"}, opts)}
end
@ -27,23 +26,26 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearParameterCommand do
def validate(args, _) when is_list(args) and length(args) < 2 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 2 do
def validate([_ | _] = args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
end
def validate([_,_], _), do: :ok
def validate([_, _], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([component_name, key], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:clear,
[vhost, component_name, key, Helpers.cli_acting_user()])
[vhost, component_name, key, Helpers.cli_acting_user()]
)
end
def usage, do: "clear_parameter [-p <vhost>] <component_name> <key>"
def banner([component_name, key], %{vhost: vhost}) do
"Clearing runtime parameter \"#{key}\" for component \"#{component_name}\" on vhost \"#{vhost}\" ..."
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPasswordCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -24,18 +22,21 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearPasswordCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_user] = args, %{node: node_name}) do
:rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :clear_password,
args ++ [Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:clear_password,
args ++ [Helpers.cli_acting_user()]
)
end
def usage, do: "clear_password <username>"
def banner([user], _), do: "Clearing password for user \"#{user}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPermissionsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,18 +27,23 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearPermissionsCommand do
def validate([], _) do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
def run([username], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal, :clear_permissions, [username, vhost, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :clear_permissions, [
username,
vhost,
Helpers.cli_acting_user()
])
end
def usage, do: "clear_permissions [-p vhost] <username>"
def banner([username], %{vhost: vhost}), do: "Clearing permissions for user \"#{username}\" in vhost \"#{vhost}\" ..."
def banner([username], %{vhost: vhost}),
do: "Clearing permissions for user \"#{username}\" in vhost \"#{vhost}\" ..."
end

View File

@ -13,12 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPolicyCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{vhost: "/"}, opts)}
end
@ -26,21 +26,25 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearPolicyCommand do
def validate([], _) do
{:validation_failure, :not_enough_args}
end
def validate([_,_|_], _) do
def validate([_, _ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([key], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_policy, :delete, [vhost, key, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_policy, :delete, [
vhost,
key,
Helpers.cli_acting_user()
])
end
def usage, do: "clear_policy [-p <vhost>] <key>"
def banner([key], %{vhost: vhost}) do
"Clearing policy \"#{key}\" on vhost \"#{vhost}\" ..."
end

View File

@ -13,13 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearTopicPermissionsCommand do
alias RabbitMQ.CLI.Core.Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{vhost: "/"}, opts)}
end
@ -27,25 +26,39 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearTopicPermissionsCommand do
def validate([], _) do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 2 do
def validate([_ | _] = args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
def validate([_, _], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([username], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal, :clear_topic_permissions, [username, vhost, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :clear_topic_permissions, [
username,
vhost,
Helpers.cli_acting_user()
])
end
def run([username, exchange], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal, :clear_topic_permissions, [username, vhost, exchange, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_auth_backend_internal, :clear_topic_permissions, [
username,
vhost,
exchange,
Helpers.cli_acting_user()
])
end
def usage, do: "clear_topic_permissions [-p vhost] <username> [<exchange>]"
def banner([username], %{vhost: vhost}), do: "Clearing topic permissions for user \"#{username}\" in vhost \"#{vhost}\" ..."
def banner([username, exchange], %{vhost: vhost}), do: "Clearing topic permissions on \"#{exchange}\" for user \"#{username}\" in vhost \"#{vhost}\" ..."
def banner([username], %{vhost: vhost}),
do: "Clearing topic permissions for user \"#{username}\" in vhost \"#{vhost}\" ..."
def banner([username, exchange], %{vhost: vhost}),
do:
"Clearing topic permissions on \"#{exchange}\" for user \"#{username}\" in vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClearVhostLimitsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -32,12 +31,15 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClearVhostLimitsCommand do
{:validation_failure, :too_many_args}
end
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
def run([], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :clear, [vhost, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :clear, [
vhost,
Helpers.cli_acting_user()
])
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.CloseAllConnectionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
def merge_defaults(args, opts) do
@ -26,22 +25,37 @@ defmodule RabbitMQ.CLI.Ctl.Commands.CloseAllConnectionsCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([explanation], %{node: node_name, vhost: vhost, global: global_opt,
per_connection_delay: delay, limit: limit}) do
conns = case global_opt do
false ->
per_vhost = :rabbit_misc.rpc_call(node_name, :rabbit_connection_tracking, :list, [vhost])
apply_limit(per_vhost, limit)
true ->
:rabbit_misc.rpc_call(node_name, :rabbit_connection_tracking,
:list_on_node, [node_name])
end
def run([explanation], %{
node: node_name,
vhost: vhost,
global: global_opt,
per_connection_delay: delay,
limit: limit
}) do
conns =
case global_opt do
false ->
per_vhost =
:rabbit_misc.rpc_call(node_name, :rabbit_connection_tracking, :list, [vhost])
apply_limit(per_vhost, limit)
true ->
:rabbit_misc.rpc_call(node_name, :rabbit_connection_tracking, :list_on_node, [node_name])
end
case conns do
{:badrpc, _} = err ->
err
_ ->
:rabbit_misc.rpc_call(node_name, :rabbit_connection_tracking_handler,
:close_connections, [conns, explanation, delay])
:rabbit_misc.rpc_call(
node_name,
:rabbit_connection_tracking_handler,
:close_connections,
[conns, explanation, delay]
)
{:ok, "Closed #{length(conns)} connections"}
end
end
@ -49,25 +63,31 @@ defmodule RabbitMQ.CLI.Ctl.Commands.CloseAllConnectionsCommand do
defp apply_limit(conns, 0) do
conns
end
defp apply_limit(conns, number) do
:lists.sublist(conns, number)
end
def output({:stream, stream}, _opts) do
{:stream, Stream.filter(stream, fn(x) -> x != :ok end)}
{:stream, Stream.filter(stream, fn x -> x != :ok end)}
end
use RabbitMQ.CLI.DefaultOutput
def switches(), do: [global: :boolean, per_connection_delay: :integer, limit: :integer]
def usage, do: "close_all_connections [-p <vhost> --limit <limit>] [-n <node> --global] [--per-connection-delay <delay>] <explanation>"
def usage,
do:
"close_all_connections [-p <vhost> --limit <limit>] [-n <node> --global] [--per-connection-delay <delay>] <explanation>"
def banner([explanation], %{node: node_name, global: true}) do
"Closing all connections to node #{node_name} (across all vhosts), reason: #{explanation}..."
end
def banner([explanation], %{vhost: vhost, limit: 0}) do
"Closing all connections in vhost #{vhost}, reason: #{explanation}..."
end
def banner([explanation], %{vhost: vhost, limit: limit}) do
"Closing #{limit} connections in vhost #{vhost}, reason: #{explanation}..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.CloseConnectionCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -21,14 +20,15 @@ defmodule RabbitMQ.CLI.Ctl.Commands.CloseConnectionCommand do
def validate(args, _) when length(args) > 2, do: {:validation_failure, :too_many_args}
def validate(args, _) when length(args) < 2, do: {:validation_failure, :not_enough_args}
def validate([_,_], _), do: :ok
def validate([_, _], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([pid, explanation], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name, :rabbit_networking,
:close_connection,
[:rabbit_misc.string_to_pid(pid), explanation])
:rabbit_misc.rpc_call(node_name, :rabbit_networking, :close_connection, [
:rabbit_misc.string_to_pid(pid),
explanation
])
end
def usage, do: "close_connection <connectionpid> <explanation>"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ClusterStatusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,12 +28,15 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ClusterStatusCommand do
case :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :status, []) do
{:badrpc, _} = err ->
err
status ->
case :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :cluster_nodes, [:running]) do
{:badrpc, _} = err ->
err
{:error, {:corrupt_or_missing_cluster_files, _, _}} ->
{:error, "Could not read mnesia files containing cluster status"}
nodes ->
alarms_by_node = Enum.map(nodes, &alarms_by_node/1)
status ++ [{:alarms, alarms_by_node}]

View File

@ -20,56 +20,76 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DecodeCommand do
use RabbitMQ.CLI.DefaultOutput
def switches() do
[
cipher: :atom,
hash: :atom,
iterations: :integer
]
[
cipher: :atom,
hash: :atom,
iterations: :integer
]
end
def distribution(_), do: :none
def merge_defaults(args, opts) do
{args, Map.merge(%{
cipher: :rabbit_pbe.default_cipher(),
hash: :rabbit_pbe.default_hash(),
iterations: :rabbit_pbe.default_iterations()
}, opts)
}
{args,
Map.merge(
%{
cipher: :rabbit_pbe.default_cipher(),
hash: :rabbit_pbe.default_hash(),
iterations: :rabbit_pbe.default_iterations()
},
opts
)}
end
def validate(args, _) when length(args) < 2 do
{:validation_failure,
{:bad_argument, "Please provide a value to decode and a passphrase."}}
{:validation_failure, {:bad_argument, "Please provide a value to decode and a passphrase."}}
end
def validate(args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
{:validation_failure, :too_many_args}
end
def validate(args, opts) when length(args) === 2 do
case {supports_cipher(opts.cipher), supports_hash(opts.hash), opts.iterations > 0} do
{false, _, _} -> {:validation_failure, {:bad_argument, "The requested cipher is not supported."}}
{_, false, _} -> {:validation_failure, {:bad_argument, "The requested hash is not supported"}}
{_, _, false} -> {:validation_failure, {:bad_argument, "The requested number of iterations is incorrect (must be a positive integer)"}}
{true, true, true} -> :ok
{false, _, _} ->
{:validation_failure, {:bad_argument, "The requested cipher is not supported."}}
{_, false, _} ->
{:validation_failure, {:bad_argument, "The requested hash is not supported"}}
{_, _, false} ->
{:validation_failure,
{:bad_argument,
"The requested number of iterations is incorrect (must be a positive integer)"}}
{true, true, true} ->
:ok
end
end
def run([value, passphrase], %{cipher: cipher, hash: hash, iterations: iterations}) do
try do
term_value = Helpers.evaluate_input_as_term(value)
term_to_decrypt = case term_value do
{:encrypted, encrypted_term} -> encrypted_term
_ -> term_value
end
term_to_decrypt =
case term_value do
{:encrypted, encrypted_term} -> encrypted_term
_ -> term_value
end
result = :rabbit_pbe.decrypt_term(cipher, hash, iterations, passphrase, term_to_decrypt)
{:ok, result}
catch _, _ ->
{:error, "Failed to decrypt the value. Things to check: is the passphrase correct? Are the cipher and hash algorithms the same as those used for encryption?"}
catch
_, _ ->
{:error,
"Failed to decrypt the value. Things to check: is the passphrase correct? Are the cipher and hash algorithms the same as those used for encryption?"}
end
end
def formatter(), do: RabbitMQ.CLI.Formatters.Erlang
def usage, do: "decode value passphrase [--cipher cipher] [--hash hash] [--iterations iterations]"
def usage,
do: "decode value passphrase [--cipher cipher] [--hash hash] [--iterations iterations]"
def banner([_, _], _) do
"Decrypting value ..."
@ -78,5 +98,4 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DecodeCommand do
defp supports_cipher(cipher), do: Enum.member?(:rabbit_pbe.supported_ciphers(), cipher)
defp supports_hash(hash), do: Enum.member?(:rabbit_pbe.supported_hashes(), hash)
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.DeleteQueueCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -22,17 +21,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DeleteQueueCommand do
def usage(), do: "delete_queue queue_name [--if_empty|-e] [--if_unused|-u]"
def banner([qname], %{vhost: vhost,
if_empty: if_empty,
if_unused: if_unused}) do
if_empty_str = case if_empty do
true -> ["if queue is empty "]
false -> []
end
if_unused_str = case if_unused do
true -> ["if queue is unused "]
false -> []
end
def banner([qname], %{vhost: vhost, if_empty: if_empty, if_unused: if_unused}) do
if_empty_str =
case if_empty do
true -> ["if queue is empty "]
false -> []
end
if_unused_str =
case if_unused do
true -> ["if queue is unused "]
false -> []
end
"Deleting queue '#{qname}' on vhost '#{vhost}' " <>
Enum.join(Enum.concat([if_empty_str, if_unused_str]), "and ") <> "..."
end
@ -50,48 +51,64 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DeleteQueueCommand do
def validate([], _options) do
{:validation_failure, :not_enough_args}
end
def validate([_,_|_], _options) do
def validate([_, _ | _], _options) do
{:validation_failure, :too_many_args}
end
def validate([""], _options) do
{
:validation_failure,
{:bad_argument, "queue name cannot be empty string."}
}
end
def validate([_], _options) do
:ok
end
def run([qname], %{node: node, vhost: vhost,
if_empty: if_empty, if_unused: if_unused,
timeout: timeout}) do
def run([qname], %{
node: node,
vhost: vhost,
if_empty: if_empty,
if_unused: if_unused,
timeout: timeout
}) do
## Generate queue resource name from queue name and vhost
queue_resource = :rabbit_misc.r(vhost, :queue, qname)
## Lookup a queue on broker node using resource name
case :rabbit_misc.rpc_call(node, :rabbit_amqqueue, :lookup,
[queue_resource]) do
case :rabbit_misc.rpc_call(node, :rabbit_amqqueue, :lookup, [queue_resource]) do
{:ok, queue} ->
## Delete queue
:rabbit_misc.rpc_call(node, :rabbit_amqqueue, :delete,
[queue, if_unused, if_empty, "cli_user"],
timeout);
{:error, _} = error -> error
:rabbit_misc.rpc_call(
node,
:rabbit_amqqueue,
:delete,
[queue, if_unused, if_empty, "cli_user"],
timeout
)
{:error, _} = error ->
error
end
end
def output({:error, :not_found}, _options) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage, "Queue not found"}
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage(), "Queue not found"}
end
def output({:error, :not_empty}, _options) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage, "Queue is not empty"}
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage(), "Queue is not empty"}
end
def output({:error, :in_use}, _options) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage, "Queue is in use"}
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_usage(), "Queue is in use"}
end
def output({:ok, qlen}, _options) do
{:ok, "Queue was successfully deleted with #{qlen} messages"}
end
## Use default output for all non-special case outputs
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.DeleteUserCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -29,7 +28,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DeleteUserCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([username], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:delete_user,
[username, Helpers.cli_acting_user()]
@ -39,5 +39,4 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DeleteUserCommand do
def usage, do: "delete_user <username>"
def banner([arg], _), do: "Deleting user \"#{arg}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.DeleteVhostCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -23,7 +22,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.DeleteVhostCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning

View File

@ -30,26 +30,38 @@ defmodule RabbitMQ.CLI.Ctl.Commands.EncodeCommand do
def distribution(_), do: :none
def merge_defaults(args, opts) do
{args, Map.merge(%{
cipher: :rabbit_pbe.default_cipher(),
hash: :rabbit_pbe.default_hash(),
iterations: :rabbit_pbe.default_iterations()
}, opts)
}
{args,
Map.merge(
%{
cipher: :rabbit_pbe.default_cipher(),
hash: :rabbit_pbe.default_hash(),
iterations: :rabbit_pbe.default_iterations()
},
opts
)}
end
def validate(args, _) when length(args) < 2 do
{:validation_failure,
{:bad_argument, "Please provide a value to decode and a passphrase."}}
{:validation_failure, {:bad_argument, "Please provide a value to decode and a passphrase."}}
end
def validate(args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
{:validation_failure, :too_many_args}
end
def validate(args, opts) when length(args) === 2 do
case {supports_cipher(opts.cipher), supports_hash(opts.hash), opts.iterations > 0} do
{false, _, _} -> {:validation_failure, {:bad_argument, "The requested cipher is not supported."}}
{_, false, _} -> {:validation_failure, {:bad_argument, "The requested hash is not supported"}}
{_, _, false} -> {:validation_failure, {:bad_argument, "The requested number of iterations is incorrect"}}
{true, true, true} -> :ok
{false, _, _} ->
{:validation_failure, {:bad_argument, "The requested cipher is not supported."}}
{_, false, _} ->
{:validation_failure, {:bad_argument, "The requested hash is not supported"}}
{_, _, false} ->
{:validation_failure, {:bad_argument, "The requested number of iterations is incorrect"}}
{true, true, true} ->
:ok
end
end
@ -58,14 +70,16 @@ defmodule RabbitMQ.CLI.Ctl.Commands.EncodeCommand do
term_value = Helpers.evaluate_input_as_term(value)
result = :rabbit_pbe.encrypt_term(cipher, hash, iterations, passphrase, term_value)
{:ok, {:encrypted, result}}
catch _, _ ->
{:error, "Error during cipher operation."}
catch
_, _ ->
{:error, "Error during cipher operation."}
end
end
def formatter(), do: RabbitMQ.CLI.Formatters.Erlang
def usage, do: "encode value passphrase [--cipher cipher] [--hash hash] [--iterations iterations]"
def usage,
do: "encode value passphrase [--cipher cipher] [--hash hash] [--iterations iterations]"
def banner([_, _], _) do
"Encrypting value ..."

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.EnvironmentCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -24,7 +23,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.EnvironmentCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_], _), do: {:validation_failure, :too_many_args}
def validate([_ | _], _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: :ok
def run([], %{node: node_name}) do

View File

@ -29,17 +29,18 @@ defmodule RabbitMQ.CLI.Ctl.Commands.EvalCommand do
def validate([expr | _], _) do
case parse_expr(expr) do
{:ok, _} -> :ok;
{:ok, _} -> :ok
{:error, err} -> {:validation_failure, err}
end
end
def run([expr | arguments], %{node: node_name} = opts) do
def run([expr | arguments], %{node: node_name} = opts) do
{:ok, parsed} = parse_expr(expr)
bindings = make_bindings(arguments, opts)
case :rabbit_misc.rpc_call(node_name, :erl_eval, :exprs, [parsed, bindings]) do
{:value, value, _} -> {:ok, value};
err -> err
{:value, value, _} -> {:ok, value}
err -> err
end
end
@ -51,23 +52,26 @@ defmodule RabbitMQ.CLI.Ctl.Commands.EvalCommand do
defp make_bindings(arguments, opts) do
Enum.with_index(arguments, 1)
|> Enum.map(fn({val, index}) -> {String.to_atom("_#{index}"), val} end)
|> Enum.map(fn {val, index} -> {String.to_atom("_#{index}"), val} end)
|> Enum.concat(option_bindings(opts))
end
defp option_bindings(opts) do
Enum.to_list(opts)
|> Enum.map(fn({key, val}) -> {String.to_atom("_#{key}"), val} end)
|> Enum.map(fn {key, val} -> {String.to_atom("_#{key}"), val} end)
end
defp parse_expr(expr) do
expr_str = to_charlist(expr)
case :erl_scan.string(expr_str) do
{:ok, scanned, _} ->
case :erl_parse.parse_exprs(scanned) do
{:ok, parsed} -> {:ok, parsed};
{:ok, parsed} -> {:ok, parsed}
{:error, err} -> {:error, format_parse_error(err)}
end;
{:error, err, _} ->
end
{:error, err, _} ->
{:error, format_parse_error(err)}
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ExecCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -44,6 +43,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ExecCommand do
rescue
ex in SyntaxError ->
{:validation_failure, "SyntaxError: " <> Exception.message(ex)}
_ ->
:ok
end
@ -53,8 +53,9 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ExecCommand do
try do
{val, _} = Code.eval_string(expr, [options: opts], __ENV__)
{:ok, val}
rescue ex ->
{:error, Exception.message(ex)}
rescue
ex ->
{:error, Exception.message(ex)}
end
end

View File

@ -24,6 +24,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForceBootCommand do
def validate(args, _) when length(args) > 0 do
{:validation_failure, :too_many_args}
end
def validate([], %{}), do: :ok
##
@ -38,21 +39,22 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForceBootCommand do
end
def run([], %{node: node_name} = opts) do
case :rabbit_misc.rpc_call(node_name,
:rabbit_mnesia, :force_load_next_boot, []) do
case :rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :force_load_next_boot, []) do
{:badrpc, :nodedown} ->
case Config.get_option(:mnesia_dir, opts) do
nil ->
{:error, :mnesia_dir_not_found};
nil ->
{:error, :mnesia_dir_not_found}
dir ->
File.write(Path.join(dir, "force_load"), "")
end;
_ -> :ok
end
_ ->
:ok
end
end
def usage, do: "force_boot"
def banner(_, _), do: nil
end

View File

@ -13,13 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ForceResetCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppStopped
@ -30,12 +29,12 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForceResetCommand do
def usage, do: "force_reset"
def banner(_, %{node: node_name}), do: "Forcefully resetting node #{node_name} ..."
def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -26,17 +26,21 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForgetClusterNodeCommand do
{args, Map.merge(%{offline: false}, opts)}
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_,_|_], _), do: {:validation_failure, :too_many_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_, _ | _], _), do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
def validate_execution_environment([_node_to_remove] = args, %{offline: true} = opts) do
Validators.chain([&Validators.node_is_not_running/2,
&Validators.mnesia_dir_is_set/2,
&Validators.rabbit_is_loaded/2],
[args, opts])
Validators.chain(
[
&Validators.node_is_not_running/2,
&Validators.mnesia_dir_is_set/2,
&Validators.rabbit_is_loaded/2
],
[args, opts]
)
end
def validate_execution_environment([_], %{offline: false}) do
:ok
end
@ -44,16 +48,18 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForgetClusterNodeCommand do
def run([node_to_remove], %{node: node_name, offline: true} = opts) do
Stream.concat([
become(node_name, opts),
RabbitMQ.CLI.Core.Helpers.defer(fn() ->
RabbitMQ.CLI.Core.Helpers.defer(fn ->
:rabbit_event.start_link()
:rabbit_mnesia.forget_cluster_node(to_atom(node_to_remove), true)
end)])
end)
])
end
def run([node_to_remove], %{node: node_name, offline: false}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_mnesia, :forget_cluster_node,
[to_atom(node_to_remove), false])
:rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :forget_cluster_node, [
to_atom(node_to_remove),
false
])
end
def usage() do
@ -64,22 +70,27 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForgetClusterNodeCommand do
"Removing node #{node_to_remove} from the cluster"
end
defp become(node_name, opts) do
:error_logger.tty(false)
case :net_adm.ping(node_name) do
:pong -> exit({:node_running, node_name});
:pang -> :ok = :net_kernel.stop()
Stream.concat([
[" * Impersonating node: #{node_name}..."],
RabbitMQ.CLI.Core.Helpers.defer(fn() ->
{:ok, _} = Distribution.start_as(node_name, opts)
" done"
end),
RabbitMQ.CLI.Core.Helpers.defer(fn() ->
dir = :mnesia.system_info(:directory)
" * Mnesia directory: #{dir}..."
end)])
:pong ->
exit({:node_running, node_name})
:pang ->
:ok = :net_kernel.stop()
Stream.concat([
[" * Impersonating node: #{node_name}..."],
RabbitMQ.CLI.Core.Helpers.defer(fn ->
{:ok, _} = Distribution.start_as(node_name, opts)
" done"
end),
RabbitMQ.CLI.Core.Helpers.defer(fn ->
dir = :mnesia.system_info(:directory)
" * Mnesia directory: #{dir}..."
end)
])
end
end
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.HelpCommand do
alias RabbitMQ.CLI.Core.{CommandModules, Config, ExitCodes}
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -30,27 +28,34 @@ defmodule RabbitMQ.CLI.Ctl.Commands.HelpCommand do
def switches(), do: [list_commands: :boolean]
def run([command_name|_], opts) do
def run([command_name | _], opts) do
CommandModules.load(opts)
case CommandModules.module_map[command_name] do
case CommandModules.module_map()[command_name] do
nil ->
all_usage(opts);
all_usage(opts)
command ->
Enum.join([base_usage(command, opts)] ++
options_usage() ++
additional_usage(command), "\n\n")
Enum.join(
[base_usage(command, opts)] ++
options_usage() ++
additional_usage(command),
"\n\n"
)
end
end
def run(_, opts) do
CommandModules.load(opts)
case opts[:list_commands] do
true -> commands();
_ -> all_usage(opts)
true -> commands()
_ -> all_usage(opts)
end
end
def output(result, _) do
{:error, ExitCodes.exit_ok, result}
{:error, ExitCodes.exit_ok(), result}
end
def program_name(opts) do
@ -58,35 +63,46 @@ defmodule RabbitMQ.CLI.Ctl.Commands.HelpCommand do
end
def all_usage(opts) do
Enum.join(tool_usage(program_name(opts)) ++
options_usage() ++
[Enum.join(["Commands:"] ++ commands(), "\n")] ++
additional_usage(), "\n\n")
Enum.join(
tool_usage(program_name(opts)) ++
options_usage() ++
[Enum.join(["Commands:"] ++ commands(), "\n")] ++
additional_usage(),
"\n\n"
)
end
def usage(), do: "help (<command> | [--list-commands])"
defp tool_usage(tool_name) do
["\nUsage:\n" <>
"#{tool_name} [-n <node>] [-t <timeout>] [-l] [-q] <command> [<command options>]"]
[
"\nUsage:\n" <>
"#{tool_name} [-n <node>] [-t <timeout>] [-l] [-q] <command> [<command options>]"
]
end
def base_usage(command, opts) do
tool_name = program_name(opts)
maybe_timeout = case command_supports_timeout(command) do
true -> " [-t <timeout>]"
false -> ""
end
Enum.join(["\nUsage:\n",
"#{tool_name} [-n <node>] [-l] [-q] " <>
flatten_string(command.usage(), maybe_timeout)])
maybe_timeout =
case command_supports_timeout(command) do
true -> " [-t <timeout>]"
false -> ""
end
Enum.join([
"\nUsage:\n",
"#{tool_name} [-n <node>] [-l] [-q] " <>
flatten_string(command.usage(), maybe_timeout)
])
end
defp flatten_string(list, additional) when is_list(list) do
list
|> Enum.map(fn(line) -> line <> additional end)
|> Enum.map(fn line -> line <> additional end)
|> Enum.join("\n")
end
defp flatten_string(str, additional) when is_binary(str) do
str <> additional
end
@ -125,36 +141,43 @@ to display results. The default value is \"/\"."]
def commands() do
# Enum.map obtains the usage string for each command module.
# Enum.each prints them all.
CommandModules.module_map
|> Map.values
|> Enum.sort
|> Enum.map( fn(cmd) ->
maybe_timeout = case command_supports_timeout(cmd) do
true -> " [-t <timeout>]"
false -> ""
end
case cmd.usage() do
bin when is_binary(bin) ->
bin <> maybe_timeout;
list when is_list(list) ->
Enum.map(list, fn(line) -> line <> maybe_timeout end)
end
end)
|> List.flatten
|> Enum.sort
|> Enum.map(fn(cmd_usage) -> " #{cmd_usage}" end)
CommandModules.module_map()
|> Map.values()
|> Enum.sort()
|> Enum.map(fn cmd ->
maybe_timeout =
case command_supports_timeout(cmd) do
true -> " [-t <timeout>]"
false -> ""
end
case cmd.usage() do
bin when is_binary(bin) ->
bin <> maybe_timeout
list when is_list(list) ->
Enum.map(list, fn line -> line <> maybe_timeout end)
end
end)
|> List.flatten()
|> Enum.sort()
|> Enum.map(fn cmd_usage -> " #{cmd_usage}" end)
end
defp additional_usage(command) do
if :erlang.function_exported(command, :usage_additional, 0) do
case command.usage_additional() do
list when is_list(list) -> ["<timeout> - operation timeout in seconds. Default is \"infinity\"." | list];
bin when is_binary(bin) -> ["<timeout> - operation timeout in seconds. Default is \"infinity\".", bin]
list when is_list(list) ->
["<timeout> - operation timeout in seconds. Default is \"infinity\"." | list]
bin when is_binary(bin) ->
["<timeout> - operation timeout in seconds. Default is \"infinity\".", bin]
end
else
case command_supports_timeout(command) do
true ->
["<timeout> - operation timeout in seconds. Default is \"infinity\"."];
["<timeout> - operation timeout in seconds. Default is \"infinity\"."]
false ->
[]
end
@ -162,20 +185,22 @@ to display results. The default value is \"/\"."]
end
defp additional_usage() do
["<timeout> - operation timeout in seconds. Default is \"infinity\".",
CommandModules.module_map
|> Map.values
|> Enum.filter(&:erlang.function_exported(&1, :usage_additional, 0))
|> Enum.map(&(&1.usage_additional))
|> Enum.join("\n\n")]
[
"<timeout> - operation timeout in seconds. Default is \"infinity\".",
CommandModules.module_map()
|> Map.values()
|> Enum.filter(&:erlang.function_exported(&1, :usage_additional, 0))
|> Enum.map(& &1.usage_additional)
|> Enum.join("\n\n")
]
end
defp command_supports_timeout(command) do
case :erlang.function_exported(command, :switches, 0) do
true -> nil != command.switches[:timeout];
true -> nil != command.switches[:timeout]
false -> false
end
end
def banner(_,_), do: nil
def banner(_, _), do: nil
end

View File

@ -31,29 +31,37 @@ defmodule RabbitMQ.CLI.Ctl.Commands.HipeCompileCommand do
def usage, do: "hipe_compile <directory>"
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([target_dir], opts) do
:ok
|> Helpers.validate_step(fn() ->
|> Helpers.validate_step(fn ->
case acceptable_path?(target_dir) do
true -> :ok
true -> :ok
false -> {:error, {:bad_argument, "Target directory path cannot be blank"}}
end
end)
|> Helpers.validate_step(fn() ->
|> Helpers.validate_step(fn ->
case File.dir?(target_dir) do
true -> :ok
true ->
:ok
false ->
case File.mkdir_p(target_dir) do
:ok -> :ok
:ok ->
:ok
{:error, perm} when perm == :eperm or perm == :eacces ->
{:error, {:bad_argument, "Cannot create target directory #{target_dir}: insufficient permissions"}}
{:error,
{:bad_argument,
"Cannot create target directory #{target_dir}: insufficient permissions"}}
end
end
end)
|> Helpers.validate_step(fn() -> Helpers.require_rabbit(opts) end)
|> Helpers.validate_step(fn -> Helpers.require_rabbit(opts) end)
end
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: {:validation_failure, :too_many_args}
def run([target_dir], _opts) do
Code.ensure_loaded(:rabbit_hipe)
@ -77,10 +85,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.HipeCompileCommand do
case :rabbit_hipe.can_hipe_compile() do
true ->
case :rabbit_hipe.compile_to_directory(target_dir) do
{:ok, _, _} -> :ok
{:ok, _, _} -> :ok
{:ok, :already_compiled} -> {:ok, "already compiled"}
{:error, message} -> {:error, message}
{:error, message} -> {:error, message}
end
false ->
{:error, "HiPE compilation is not supported"}
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is Pivotal Software, Inc.
## Copyright (c) 2016-2017 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.JoinClusterCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -31,27 +30,30 @@ defmodule RabbitMQ.CLI.Ctl.Commands.JoinClusterCommand do
end
def validate(_, %{disc: true, ram: true}) do
{:validation_failure,
{:bad_argument, "The node type must be either disc or ram."}}
{:validation_failure, {:bad_argument, "The node type must be either disc or ram."}}
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppStopped
def run([target_node], %{node: node_name, ram: ram, disc: disc}) do
node_type = case {ram, disc} do
{true, false} -> :ram
{false, true} -> :disc
## disc is default
{false, false} -> :disc
end
:rabbit_misc.rpc_call(node_name,
:rabbit_mnesia,
:join_cluster,
[Helpers.normalise_node(target_node), node_type]
)
node_type =
case {ram, disc} do
{true, false} -> :ram
{false, true} -> :disc
## disc is default
{false, false} -> :disc
end
:rabbit_misc.rpc_call(
node_name,
:rabbit_mnesia,
:join_cluster,
[Helpers.normalise_node(target_node), node_type]
)
end
def usage() do
@ -65,13 +67,16 @@ defmodule RabbitMQ.CLI.Ctl.Commands.JoinClusterCommand do
def output({:ok, :already_member}, _) do
{:ok, "The node is already a member of this cluster"}
end
def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)}
end
def output({:error, :cannot_cluster_node_with_itself}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"Error: cannot cluster node with itself: #{node_name}"}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListBindingsCommand do
alias RabbitMQ.CLI.Ctl.{InfoKeys, RpcStream}
@ -35,42 +34,48 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListBindingsCommand do
merge_defaults(
~w(source_name source_kind
destination_name destination_kind
routing_key arguments), opts)
routing_key arguments),
opts
)
end
def merge_defaults(args, opts) do
{args, Map.merge(default_opts(), opts)}
end
def validate(args, _) do
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_|_] = args, %{node: node_name, timeout: timeout, vhost: vhost}) do
info_keys = InfoKeys.prepare_info_keys(args)
def run([_ | _] = args, %{node: node_name, timeout: timeout, vhost: vhost}) do
info_keys = InfoKeys.prepare_info_keys(args)
RpcStream.receive_list_items(node_name, :rabbit_binding, :info_all,
[vhost, info_keys],
timeout,
info_keys)
RpcStream.receive_list_items(
node_name,
:rabbit_binding,
:info_all,
[vhost, info_keys],
timeout,
info_keys
)
end
def usage() do
"list_bindings [-p <vhost>] [--no-table-headers] [<bindinginfoitem> ...]"
"list_bindings [-p <vhost>] [--no-table-headers] [<bindinginfoitem> ...]"
end
def usage_additional() do
"<bindinginfoitem> must be a member of the list [" <>
"<bindinginfoitem> must be a member of the list [" <>
Enum.join(@info_keys, ", ") <> "]."
end
defp default_opts() do
%{vhost: "/",
table_headers: true}
%{vhost: "/", table_headers: true}
end
def banner(_, %{vhost: vhost}), do: "Listing bindings for vhost #{vhost}..."

View File

@ -14,7 +14,6 @@
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
##
defmodule RabbitMQ.CLI.Ctl.Commands.ListChannelsCommand do
alias RabbitMQ.CLI.Core.Helpers
alias RabbitMQ.CLI.Ctl.{InfoKeys, RpcStream}
@ -37,41 +36,46 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListChannelsCommand do
def merge_defaults([], opts) do
merge_defaults(~w(pid user consumer_count messages_unacknowledged), opts)
end
def merge_defaults(args, opts) do
{args, Map.merge(%{table_headers: true}, opts)}
end
def validate(args, _) do
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], opts) do
run(~w(pid user consumer_count messages_unacknowledged), opts)
run(~w(pid user consumer_count messages_unacknowledged), opts)
end
def run([_|_] = args, %{node: node_name, timeout: timeout}) do
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn(nodes) ->
RpcStream.receive_list_items(node_name,
:rabbit_channel, :emit_info_all,
[nodes, info_keys],
timeout,
info_keys,
Kernel.length(nodes))
end)
def run([_ | _] = args, %{node: node_name, timeout: timeout}) do
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn nodes ->
RpcStream.receive_list_items(
node_name,
:rabbit_channel,
:emit_info_all,
[nodes, info_keys],
timeout,
info_keys,
Kernel.length(nodes)
)
end)
end
def usage() do
"list_channels [--no-table-headers] [<channelinfoitem> ...]"
"list_channels [--no-table-headers] [<channelinfoitem> ...]"
end
def usage_additional() do
"<channelinfoitem> must be a member of the list [" <>
"<channelinfoitem> must be a member of the list [" <>
Enum.join(@info_keys, ", ") <> "]."
end

View File

@ -20,10 +20,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListCiphersCommand do
def merge_defaults(args, opts) do
{args, opts}
end
def validate(args, _) when length(args) > 0 do
{:validation_failure,
{:bad_argument, :too_many_args}}
{:validation_failure, {:bad_argument, :too_many_args}}
end
def validate(_, _), do: :ok
def distribution(_), do: :none
@ -37,5 +38,4 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListCiphersCommand do
def usage, do: "list_ciphers"
def banner(_, _), do: "Listing supported ciphers ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListConnectionsCommand do
alias RabbitMQ.CLI.Core.Helpers
alias RabbitMQ.CLI.Ctl.{InfoKeys, RpcStream}
@ -39,38 +38,42 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConnectionsCommand do
def merge_defaults([], opts) do
merge_defaults(~w(user peer_host peer_port state), opts)
end
def merge_defaults(args, opts) do
{args, Map.merge(%{table_headers: true}, opts)}
end
def validate(args, _) do
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_|_] = args, %{node: node_name, timeout: timeout}) do
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn(nodes) ->
RpcStream.receive_list_items(node_name,
:rabbit_networking,
:emit_connection_info_all,
[nodes, info_keys],
timeout,
info_keys,
Kernel.length(nodes))
end)
def run([_ | _] = args, %{node: node_name, timeout: timeout}) do
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn nodes ->
RpcStream.receive_list_items(
node_name,
:rabbit_networking,
:emit_connection_info_all,
[nodes, info_keys],
timeout,
info_keys,
Kernel.length(nodes)
)
end)
end
def usage() do
"list_connections [--no-table-headers] [<connectioninfoitem> ...]"
"list_connections [--no-table-headers] [<connectioninfoitem> ...]"
end
def usage_additional() do
"<connectioninfoitem> must be a member of the list [" <>
"<connectioninfoitem> must be a member of the list [" <>
Enum.join(@info_keys, ", ") <> "]."
end

View File

@ -32,7 +32,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConsumersCommand do
def info_keys(), do: @info_keys
def merge_defaults([], opts) do
{Enum.map(@info_keys -- [:activity_status], &Atom.to_string/1), Map.merge(%{vhost: "/", table_headers: true}, opts)}
{Enum.map(@info_keys -- [:activity_status], &Atom.to_string/1),
Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def merge_defaults(args, opts) do
@ -50,6 +51,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConsumersCommand do
def run([_ | _] = args, %{node: node_name, timeout: timeout, vhost: vhost}) do
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn nodes ->
RpcStream.receive_list_items(
node_name,

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListExchangesCommand do
alias RabbitMQ.CLI.Ctl.{InfoKeys, RpcStream}
@ -39,30 +38,35 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListExchangesCommand do
end
def validate(args, _) do
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
case InfoKeys.validate_info_keys(args, @info_keys) do
{:ok, _} -> :ok
err -> err
end
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_|_] = args, %{node: node_name, timeout: timeout, vhost: vhost}) do
info_keys = InfoKeys.prepare_info_keys(args)
RpcStream.receive_list_items(node_name, :rabbit_exchange, :info_all,
[vhost, info_keys],
timeout,
info_keys)
def run([_ | _] = args, %{node: node_name, timeout: timeout, vhost: vhost}) do
info_keys = InfoKeys.prepare_info_keys(args)
RpcStream.receive_list_items(
node_name,
:rabbit_exchange,
:info_all,
[vhost, info_keys],
timeout,
info_keys
)
end
def usage() do
"list_exchanges [-p <vhost>] [--no-table-headers] [<exchangeinfoitem> ...]"
"list_exchanges [-p <vhost>] [--no-table-headers] [<exchangeinfoitem> ...]"
end
def usage_additional() do
"<exchangeinfoitem> must be a member of the list [" <>
"<exchangeinfoitem> must be a member of the list [" <>
Enum.join(@info_keys, ", ") <> "]."
end
def banner(_,%{vhost: vhost}), do: "Listing exchanges for vhost #{vhost} ..."
def banner(_, %{vhost: vhost}), do: "Listing exchanges for vhost #{vhost} ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListGlobalParametersCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -28,23 +27,25 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListGlobalParametersCommand do
def switches(), do: [timeout: :integer, table_headers: :boolean]
def aliases(), do: [t: :timeout]
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:list_global_formatted,
[],
timeout)
timeout
)
end
def usage, do: "list_global_parameters [--no-table-headers]"
def banner(_, _), do: "Listing global runtime parameters ..."
end

View File

@ -20,10 +20,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListHashesCommand do
def merge_defaults(args, opts) do
{args, opts}
end
def validate(args, _) when length(args) > 0 do
{:validation_failure,
{:bad_argument, :too_many_args}}
{:validation_failure, {:bad_argument, :too_many_args}}
end
def validate(_, _), do: :ok
def distribution(_), do: :none
@ -37,5 +38,4 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListHashesCommand do
def usage, do: "list_hashes"
def banner(_, _), do: "Listing supported hash algorithms ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListOperatorPoliciesCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -28,23 +27,26 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListOperatorPoliciesCommand do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_policy,
:list_formatted_op,
[vhost],
timeout)
timeout
)
end
def usage, do: "list_operator_policies [-p <vhost>] [--no-table-headers]"
def banner(_, %{vhost: vhost}), do: "Listing operator policy overrides for vhost \"#{vhost}\" ..."
def banner(_, %{vhost: vhost}),
do: "Listing operator policy overrides for vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListParametersCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,17 +28,20 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListParametersCommand do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:list_formatted,
[vhost],
timeout)
timeout
)
end
def usage, do: "list_parameters [-p <vhost>] [--no-table-headers]"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -28,15 +27,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:list_vhost_permissions,
[vhost],
@ -47,5 +48,4 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand do
def usage, do: "list_permissions [-p <vhost>] [--no-table-headers]"
def banner(_, %{vhost: vhost}), do: "Listing permissions for vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListPoliciesCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -28,19 +27,22 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListPoliciesCommand do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_policy,
:list_formatted,
[vhost],
timeout)
timeout
)
end
def usage, do: "list_policies [-p <vhost>] [--no-table-headers]"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListQueuesCommand do
require RabbitMQ.CLI.Ctl.InfoKeys
require RabbitMQ.CLI.Ctl.RpcStream
@ -40,27 +39,36 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListQueuesCommand do
def scopes(), do: [:ctl, :diagnostics]
def switches(), do: [offline: :boolean, online: :boolean, local: :boolean, timeout: :integer,
table_headers: :boolean]
def switches(),
do: [
offline: :boolean,
online: :boolean,
local: :boolean,
timeout: :integer,
table_headers: :boolean
]
def aliases(), do: [t: :timeout]
defp default_opts() do
%{vhost: "/",
offline: false,
online: false,
local: false,
table_headers: true}
%{vhost: "/", offline: false, online: false, local: false, table_headers: true}
end
def merge_defaults([_|_] = args, opts) do
timeout = case opts[:timeout] do
nil -> @default_timeout;
:infinity -> @default_timeout;
other -> other
end
{args, Map.merge(default_opts(),
Map.merge(opts, %{timeout: timeout}))}
def merge_defaults([_ | _] = args, opts) do
timeout =
case opts[:timeout] do
nil -> @default_timeout
:infinity -> @default_timeout
other -> other
end
{args,
Map.merge(
default_opts(),
Map.merge(opts, %{timeout: timeout})
)}
end
def merge_defaults([], opts) do
merge_defaults(~w(name messages), opts)
end
@ -76,30 +84,47 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListQueuesCommand do
# it lists queues with unavailable masters
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_|_] = args, %{node: node_name, timeout: timeout, vhost: vhost,
online: online_opt, offline: offline_opt,
local: local_opt}) do
{online, offline} = case {online_opt, offline_opt} do
{false, false} -> {true, true};
other -> other
end
def run([_ | _] = args, %{
node: node_name,
timeout: timeout,
vhost: vhost,
online: online_opt,
offline: offline_opt,
local: local_opt
}) do
{online, offline} =
case {online_opt, offline_opt} do
{false, false} -> {true, true}
other -> other
end
info_keys = InfoKeys.prepare_info_keys(args)
Helpers.with_nodes_in_cluster(node_name, fn(nodes) ->
Helpers.with_nodes_in_cluster(node_name, fn nodes ->
offline_mfa = {:rabbit_amqqueue, :emit_info_down, [vhost, info_keys]}
local_mfa = {:rabbit_amqqueue, :emit_info_local, [vhost, info_keys]}
online_mfa = {:rabbit_amqqueue, :emit_info_all, [nodes, vhost, info_keys]}
{chunks, mfas} = case {local_opt, offline, online} do
# Local takes precedence
{true, _, _} -> {1, [local_mfa]};
{_, true, true} -> {Kernel.length(nodes) + 1, [offline_mfa, online_mfa]};
{_, false, true} -> {Kernel.length(nodes), [online_mfa]};
{_, true, false} -> {1, [offline_mfa]}
end
RpcStream.receive_list_items_with_fun(node_name, mfas, timeout, info_keys, chunks,
fn({{:error, {:badrpc, {:timeout, to}}}, :finished}) ->
{{:error, {:badrpc, {:timeout, to, "Some queue(s) are unresponsive, use list_unresponsive_queues command."}}}, :finished};
(any) -> any
end)
online_mfa = {:rabbit_amqqueue, :emit_info_all, [nodes, vhost, info_keys]}
{chunks, mfas} =
case {local_opt, offline, online} do
# Local takes precedence
{true, _, _} -> {1, [local_mfa]}
{_, true, true} -> {Kernel.length(nodes) + 1, [offline_mfa, online_mfa]}
{_, false, true} -> {Kernel.length(nodes), [online_mfa]}
{_, true, false} -> {1, [offline_mfa]}
end
RpcStream.receive_list_items_with_fun(node_name, mfas, timeout, info_keys, chunks, fn
{{:error, {:badrpc, {:timeout, to}}}, :finished} ->
{{:error,
{:badrpc,
{:timeout, to,
"Some queue(s) are unresponsive, use list_unresponsive_queues command."}}},
:finished}
any ->
any
end)
end)
end
@ -111,8 +136,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListQueuesCommand do
["<queueinfoitem> must be a member of the list [" <> Enum.join(@info_keys, ", ") <> "]."]
end
def banner(_,%{vhost: vhost, timeout: timeout}) do
["Timeout: #{timeout / 1000} seconds ...",
"Listing queues for vhost #{vhost} ..."]
def banner(_, %{vhost: vhost, timeout: timeout}) do
["Timeout: #{timeout / 1000} seconds ...", "Listing queues for vhost #{vhost} ..."]
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListTopicPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -28,15 +27,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListTopicPermissionsCommand do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:list_vhost_topic_permissions,
[vhost],

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListUnresponsiveQueuesCommand do
require RabbitMQ.CLI.Ctl.InfoKeys
require RabbitMQ.CLI.Ctl.RpcStream
@ -33,17 +32,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUnresponsiveQueuesCommand do
def scopes(), do: [:ctl, :diagnostics]
def switches(), do: [queue_timeout: :integer, local: :boolean, timeout: :integer,
table_headers: :boolean]
def switches(),
do: [queue_timeout: :integer, local: :boolean, timeout: :integer, table_headers: :boolean]
def aliases(), do: [t: :timeout]
defp default_opts() do
%{vhost: "/", local: false, queue_timeout: 15, table_headers: true}
end
def merge_defaults([_|_] = args, opts) do
def merge_defaults([_ | _] = args, opts) do
{args, Map.merge(default_opts(), opts)}
end
def merge_defaults([], opts) do
merge_defaults(~w(name), opts)
end
@ -57,19 +58,28 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUnresponsiveQueuesCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run(args, %{node: node_name, vhost: vhost, timeout: timeout,
queue_timeout: qtimeout, local: local_opt}) do
def run(args, %{
node: node_name,
vhost: vhost,
timeout: timeout,
queue_timeout: qtimeout,
local: local_opt
}) do
info_keys = InfoKeys.prepare_info_keys(args)
queue_timeout = qtimeout * 1000
Helpers.with_nodes_in_cluster(node_name, fn(nodes) ->
local_mfa = {:rabbit_amqqueue, :emit_unresponsive_local, [vhost, info_keys, queue_timeout]}
all_mfa = {:rabbit_amqqueue, :emit_unresponsive, [nodes, vhost, info_keys, queue_timeout]}
{chunks, mfas} = case local_opt do
true -> {1, [local_mfa]};
Helpers.with_nodes_in_cluster(node_name, fn nodes ->
local_mfa = {:rabbit_amqqueue, :emit_unresponsive_local, [vhost, info_keys, queue_timeout]}
all_mfa = {:rabbit_amqqueue, :emit_unresponsive, [nodes, vhost, info_keys, queue_timeout]}
{chunks, mfas} =
case local_opt do
true -> {1, [local_mfa]}
false -> {Kernel.length(nodes), [all_mfa]}
end
RpcStream.receive_list_items(node_name, mfas, timeout, info_keys, chunks)
end)
RpcStream.receive_list_items(node_name, mfas, timeout, info_keys, chunks)
end)
end
def usage() do
@ -77,9 +87,9 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUnresponsiveQueuesCommand do
end
def usage_additional() do
"<unresponsive_queueinfoitem> must be a member of the list [" <>
"<unresponsive_queueinfoitem> must be a member of the list [" <>
Enum.join(@info_keys, ", ") <> "]."
end
def banner(_,%{vhost: vhost}), do: "Listing unresponsive queues for vhost #{vhost} ..."
def banner(_, %{vhost: vhost}), do: "Listing unresponsive queues for vhost #{vhost} ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListUserPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,18 +28,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUserPermissionsCommand do
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([username], %{node: node_name, timeout: time_out}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal,
:list_user_permissions,
[username],
time_out
)
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:list_user_permissions,
[username],
time_out
)
end
def usage, do: "list_user_permissions [--no-table-headers] <username>"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListUserTopicPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,18 +28,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUserTopicPermissionsCommand do
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([username], %{node: node_name, timeout: time_out}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_auth_backend_internal,
:list_user_topic_permissions,
[username],
time_out
)
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:list_user_topic_permissions,
[username],
time_out
)
end
def usage, do: "list_user_topic_permissions [--no-table-headers] <username>"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListUsersCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -24,13 +23,14 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListUsersCommand do
def switches(), do: [timeout: :integer, table_headers: :boolean]
def aliases(), do: [t: :timeout]
def merge_defaults(args, opts) do
def merge_defaults(args, opts) do
{args, Map.merge(%{table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
@ -41,5 +41,5 @@ def merge_defaults(args, opts) do
def usage, do: "list_users [--no-table-headers]"
def banner(_,_), do: "Listing users ..."
def banner(_, _), do: "Listing users ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostLimitsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -25,24 +24,32 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostLimitsCommand do
def merge_defaults(args, %{global: true} = opts) do
{args, Map.merge(%{table_headers: true}, opts)}
end
def merge_defaults(args, opts) do
{args, Map.merge(%{vhost: "/", table_headers: true}, opts)}
end
def validate([_|_], _) do
def validate([_ | _], _) do
{:validation_failure, :too_many_args}
end
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, global: true}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :list, []) do
[] -> []
{:error, err} -> {:error, err}
{:badrpc, node} -> {:badrpc, node}
val ->
Enum.map(val, fn({vhost, val}) ->
[] ->
[]
{:error, err} ->
{:error, err}
{:badrpc, node} ->
{:badrpc, node}
val ->
Enum.map(val, fn {vhost, val} ->
{:ok, val_encoded} = JSON.encode(Map.new(val))
[vhost: vhost, limits: val_encoded]
end)
@ -51,10 +58,16 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostLimitsCommand do
def run([], %{node: node_name, vhost: vhost}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :list, [vhost]) do
[] -> []
{:error, err} -> {:error, err}
{:badrpc, node} -> {:badrpc, node}
val when is_list(val) or is_map(val) ->
[] ->
[]
{:error, err} ->
{:error, err}
{:badrpc, node} ->
{:badrpc, node}
val when is_list(val) or is_map(val) ->
JSON.encode(Map.new(val))
end
end
@ -64,6 +77,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostLimitsCommand do
def banner([], %{global: true}) do
"Listing limits for all vhosts ..."
end
def banner([], %{vhost: vhost}) do
"Listing limits for vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
alias RabbitMQ.CLI.Ctl.InfoKeys
@ -33,6 +32,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
def merge_defaults([], opts) do
merge_defaults(["name"], opts)
end
def merge_defaults(args, opts) do
{args, Map.merge(%{table_headers: true}, opts)}
end
@ -46,7 +46,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([_|_] = args, %{node: node_name, timeout: time_out}) do
def run([_ | _] = args, %{node: node_name, timeout: time_out}) do
:rabbit_misc.rpc_call(node_name, :rabbit_vhost, :info_all, [], time_out)
|> filter_by_arg(args)
end
@ -61,17 +61,16 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
vhosts
end
defp filter_by_arg(vhosts, [_|_] = args) do
defp filter_by_arg(vhosts, [_ | _] = args) do
symbol_args = InfoKeys.prepare_info_keys(args)
vhosts
|> Enum.map(
fn(vhost) ->
symbol_args
|> Enum.filter(fn(arg) -> vhost[arg] != nil end)
|> Enum.map(fn(arg) -> {arg, vhost[arg]} end)
end
)
|> Enum.map(fn vhost ->
symbol_args
|> Enum.filter(fn arg -> vhost[arg] != nil end)
|> Enum.map(fn arg -> {arg, vhost[arg]} end)
end)
end
def banner(_,_), do: "Listing vhosts ..."
def banner(_, _), do: "Listing vhosts ..."
end

View File

@ -23,11 +23,13 @@ defmodule RabbitMQ.CLI.Ctl.Commands.NodeHealthCheckCommand do
def aliases(), do: [t: :timeout]
def merge_defaults(args, opts) do
timeout = case opts[:timeout] do
nil -> @default_timeout;
:infinity -> @default_timeout;
other -> other
end
timeout =
case opts[:timeout] do
nil -> @default_timeout
:infinity -> @default_timeout
other -> other
end
{args, Map.merge(opts, %{timeout: timeout})}
end
@ -38,17 +40,22 @@ defmodule RabbitMQ.CLI.Ctl.Commands.NodeHealthCheckCommand do
def run([], %{node: node_name, timeout: timeout}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_health_check, :node, [node_name, timeout]) do
:ok ->
:ok ->
:ok
true ->
true ->
:ok
{:badrpc, _} = err ->
{:badrpc, _} = err ->
err
{:error_string, error_message} ->
{:error_string, error_message} ->
{:healthcheck_failed, error_message}
{:node_is_ko, error_message, _exit_code} ->
{:healthcheck_failed, error_message}
other ->
other ->
other
end
end
@ -56,16 +63,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.NodeHealthCheckCommand do
def output(:ok, _) do
{:ok, "Health check passed"}
end
def output({:healthcheck_failed, message}, _) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"Error: healthcheck failed. Message: #{message}"}
end
use RabbitMQ.CLI.DefaultOutput
def usage, do: "node_health_check"
def banner(_, %{node: node_name, timeout: timeout}) do
["Timeout: #{trunc(timeout / 1000)} seconds ...",
"Checking health of node #{node_name} ..."]
["Timeout: #{trunc(timeout / 1000)} seconds ...", "Checking health of node #{node_name} ..."]
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is Pivotal Software, Inc.
## Copyright (c) 2016-2018 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.PingCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@ -22,11 +21,13 @@ defmodule RabbitMQ.CLI.Ctl.Commands.PingCommand do
def scopes(), do: [:ctl, :diagnostics]
def merge_defaults(args, opts) do
timeout = case opts[:timeout] do
nil -> @default_timeout;
:infinity -> @default_timeout;
other -> other
end
timeout =
case opts[:timeout] do
nil -> @default_timeout
:infinity -> @default_timeout
other -> other
end
{args, Map.merge(opts, %{timeout: timeout})}
end
@ -40,20 +41,27 @@ defmodule RabbitMQ.CLI.Ctl.Commands.PingCommand do
# this is very similar to what net_adm:ping/1 does reimplemented with support for custom timeouts
# and error values that are used by CLI commands
msg = "Failed to connect and authenticate to #{node_name} in #{timeout} ms"
try do
case :gen.call({:net_kernel, node_name}, :'$gen_call', {:is_auth, node()}, timeout) do
:ok -> :ok
{:ok, _} -> :ok
_ ->
case :gen.call({:net_kernel, node_name}, :"$gen_call", {:is_auth, node()}, timeout) do
:ok ->
:ok
{:ok, _} ->
:ok
_ ->
:erlang.disconnect_node(node_name)
{:error, msg}
end
catch :exit, _ ->
:erlang.disconnect_node(node_name)
{:error, msg}
_ ->
:erlang.disconnect_node(node_name)
{:error, msg}
catch
:exit, _ ->
:erlang.disconnect_node(node_name)
{:error, msg}
_ ->
:erlang.disconnect_node(node_name)
{:error, msg}
end
end
@ -62,8 +70,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.PingCommand do
end
def banner([], %{node: node_name, timeout: timeout}) when is_number(timeout) do
"Will ping #{node_name}. This only checks if the OS process is running and registered with epmd. Timeout: #{timeout} ms."
"Will ping #{node_name}. This only checks if the OS process is running and registered with epmd. Timeout: #{
timeout
} ms."
end
def banner([], %{node: node_name, timeout: _timeout}) do
"Will ping #{node_name}. This only checks if the OS process is running and registered with epmd."
end
@ -71,9 +82,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.PingCommand do
def output(:ok, _) do
{:ok, "Ping succeeded"}
end
def output({:error, :timeout}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"Error: timed out while waiting for a response from #{node_name}."}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.PurgeQueueCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -38,20 +37,27 @@ defmodule RabbitMQ.CLI.Ctl.Commands.PurgeQueueCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([queue], %{node: node_name, vhost: vhost, timeout: timeout}) do
res = :rabbit_misc.rpc_call(node_name,
:rabbit_amqqueue, :lookup, [:rabbit_misc.r(vhost, :queue, queue)], timeout)
res =
:rabbit_misc.rpc_call(
node_name,
:rabbit_amqqueue,
:lookup,
[:rabbit_misc.r(vhost, :queue, queue)],
timeout
)
case res do
{:ok, q} -> purge(node_name, q, timeout)
_ -> res
_ -> res
end
end
defp purge(node_name, q, timeout) do
res = :rabbit_misc.rpc_call(node_name, :rabbit_amqqueue, :purge, [q], timeout)
case res do
{:ok, _message_count} -> :ok
_ -> res
_ -> res
end
end

View File

@ -13,9 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.QuorumStatusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,10 +27,12 @@ defmodule RabbitMQ.CLI.Ctl.Commands.QuorumStatusCommand do
def merge_defaults(args, opts), do: {args, Map.merge(default_opts(), opts)}
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
def validate([_], _), do: :ok
def validate([], _) do
{:validation_failure, :not_enough_args}
end
@ -42,7 +42,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.QuorumStatusCommand do
def run([name] = _args, %{node: node_name, vhost: vhost}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_quorum_queue, :status, [vhost, name]) do
{:error, :classic_queue_not_supported} ->
{:error, "Cannot get quorum status of a classic queue"};
{:error, "Cannot get quorum status of a classic queue"}
other ->
other
end
@ -52,5 +53,6 @@ defmodule RabbitMQ.CLI.Ctl.Commands.QuorumStatusCommand do
"quorum_status [-p <vhost>] <queuename>"
end
def banner([name], %{node: node_name}), do: "Status of quorum queue #{name} on node #{node_name} ..."
def banner([name], %{node: node_name}),
do: "Status of quorum queue #{name} on node #{node_name} ..."
end

View File

@ -24,36 +24,44 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RenameClusterNodeCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_], _), do: {:validation_failure, :not_enough_args}
def validate(_, _) do
:ok
end
def validate_execution_environment(args, opts) do
Validators.chain([&validate_args_count_even/2,
&Validators.node_is_not_running/2,
&Validators.mnesia_dir_is_set/2,
&Validators.rabbit_is_loaded/2],
[args, opts])
Validators.chain(
[
&validate_args_count_even/2,
&Validators.node_is_not_running/2,
&Validators.mnesia_dir_is_set/2,
&Validators.rabbit_is_loaded/2
],
[args, opts]
)
end
def run(nodes, %{node: node_name}) do
node_pairs = make_node_pairs(nodes)
try do
:rabbit_mnesia_rename.rename(node_name, node_pairs)
catch _, reason ->
{:rename_failed, reason}
catch
_, reason ->
{:rename_failed, reason}
end
end
defp validate_args_count_even(args, _) do
case agrs_count_even?(args) do
true -> :ok;
true ->
:ok
false ->
{:validation_failure,
{:bad_argument, "Argument list should contain even number of nodes"}}
{:bad_argument, "Argument list should contain even number of nodes"}}
end
end
@ -64,6 +72,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RenameClusterNodeCommand do
defp make_node_pairs([]) do
[]
end
defp make_node_pairs([from, to | rest]) do
[{to_atom(from), to_atom(to)} | make_node_pairs(rest)]
end
@ -73,9 +82,13 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RenameClusterNodeCommand do
end
def banner(args, _) do
["Renaming cluster nodes: \n ",
for {node_from, node_to} <- make_node_pairs(args) do "#{node_from} -> #{node_to} \n" end]
|> List.flatten
|> Enum.join
[
"Renaming cluster nodes: \n ",
for {node_from, node_to} <- make_node_pairs(args) do
"#{node_from} -> #{node_to} \n"
end
]
|> List.flatten()
|> Enum.join()
end
end

View File

@ -13,12 +13,21 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
alias RabbitMQ.CLI.Ctl.Commands.{ClusterStatusCommand, EnvironmentCommand,
ListBindingsCommand, ListChannelsCommand, ListConnectionsCommand,
ListExchangesCommand, ListGlobalParametersCommand, ListParametersCommand,
ListPermissionsCommand, ListPoliciesCommand, ListQueuesCommand, StatusCommand}
alias RabbitMQ.CLI.Ctl.Commands.{
ClusterStatusCommand,
EnvironmentCommand,
ListBindingsCommand,
ListChannelsCommand,
ListConnectionsCommand,
ListExchangesCommand,
ListGlobalParametersCommand,
ListParametersCommand,
ListPermissionsCommand,
ListPoliciesCommand,
ListQueuesCommand,
StatusCommand
}
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -29,13 +38,16 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) != 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) != 0,
do: {:validation_failure, :too_many_args}
def validate([], %{formatter: formatter}) do
case formatter do
"report" -> :ok
_other -> {:validation_failure, "Only report formatter is supported"}
_other -> {:validation_failure, "Only report formatter is supported"}
end
end
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
@ -44,26 +56,32 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
case :rabbit_misc.rpc_call(node_name, :rabbit_vhost, :list, []) do
{:badrpc, _} = err ->
err
vhosts ->
data =
[run_command(StatusCommand, [], opts),
run_command(ClusterStatusCommand, [], opts),
run_command(EnvironmentCommand, [], opts),
run_command(ListConnectionsCommand, info_keys(ListConnectionsCommand), opts),
run_command(ListChannelsCommand, info_keys(ListChannelsCommand), opts)]
data = [
run_command(StatusCommand, [], opts),
run_command(ClusterStatusCommand, [], opts),
run_command(EnvironmentCommand, [], opts),
run_command(ListConnectionsCommand, info_keys(ListConnectionsCommand), opts),
run_command(ListChannelsCommand, info_keys(ListChannelsCommand), opts)
]
vhost_data =
vhosts
|> Enum.flat_map(fn v ->
opts = Map.put(opts, :vhost, v)
[run_command(ListQueuesCommand, info_keys(ListQueuesCommand), opts),
run_command(ListExchangesCommand, info_keys(ListExchangesCommand), opts),
run_command(ListBindingsCommand, info_keys(ListBindingsCommand), opts),
run_command(ListPermissionsCommand, [], opts),
run_command(ListPoliciesCommand, [], opts),
run_command(ListGlobalParametersCommand, [], opts),
run_command(ListParametersCommand, [], opts)]
end)
vhosts
|> Enum.flat_map(fn v ->
opts = Map.put(opts, :vhost, v)
[
run_command(ListQueuesCommand, info_keys(ListQueuesCommand), opts),
run_command(ListExchangesCommand, info_keys(ListExchangesCommand), opts),
run_command(ListBindingsCommand, info_keys(ListBindingsCommand), opts),
run_command(ListPermissionsCommand, [], opts),
run_command(ListPoliciesCommand, [], opts),
run_command(ListGlobalParametersCommand, [], opts),
run_command(ListParametersCommand, [], opts)
]
end)
data ++ vhost_data
end
end
@ -75,7 +93,6 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
{command, banner, command_result}
end
defp info_keys(command) do
command.info_keys()
|> Enum.map(&Atom.to_string/1)
@ -83,5 +100,5 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
def usage, do: "report"
def banner(_,%{node: node_name}), do: "Reporting server status of node #{node_name} ..."
def banner(_, %{node: node_name}), do: "Reporting server status of node #{node_name} ..."
end

View File

@ -13,30 +13,28 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ResetCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppStopped
def run([], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name, :rabbit_mnesia, :reset, [])
end
def usage, do: "reset"
def banner(_, %{node: node_name}), do: "Resetting node #{node_name} ..."
def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -23,8 +23,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RestartVhostCommand do
def merge_defaults(args, opts), do: {args, Map.merge(%{vhost: "/"}, opts)}
def validate([], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
@ -34,20 +34,22 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RestartVhostCommand do
def usage, do: "restart_vhost [-p <vhost>]"
def banner(_,%{node: node_name, vhost: vhost}) do
def banner(_, %{node: node_name, vhost: vhost}) do
"Trying to restart vhost '#{vhost}' on node '#{node_name}' ..."
end
def output({:ok, _pid}, %{vhost: vhost, node: node_name}) do
{:ok, "Successfully restarted vhost '#{vhost}' on node '#{node_name}'"}
end
def output({:error, {:already_started, _pid}}, %{vhost: vhost, node: node_name}) do
{:ok, "Vhost '#{vhost}' is already running on node '#{node_name}'"}
end
def output({:error, err}, %{vhost: vhost, node: node_name}) do
{:error, ExitCodes.exit_software(),
["Failed to start vhost '#{vhost}' on node '#{node_name}'",
"Reason: #{inspect(err)}"]}
["Failed to start vhost '#{vhost}' on node '#{node_name}'", "Reason: #{inspect(err)}"]}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,14 +13,13 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.RotateLogsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetClusterNameCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -35,8 +34,10 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetClusterNameCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([cluster_name], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_nodes, :set_cluster_name, [cluster_name, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_nodes, :set_cluster_name, [
cluster_name,
Helpers.cli_acting_user()
])
end
def banner([cluster_name], _) do

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -35,13 +34,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
def validate([limit], _) do
case Integer.parse(limit) do
{_, ""} -> :ok
{_, ""} ->
:ok
{limit_val, units} ->
case Helpers.memory_unit_absolute(limit_val, units) do
scaled_limit when is_integer(scaled_limit) -> :ok
_ -> {:validation_failure, :bad_argument}
end
_ -> {:validation_failure, :bad_argument}
_ ->
{:validation_failure, :bad_argument}
end
end
@ -52,7 +55,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
end
end
def validate([_|rest], _) when length(rest) > 0 do
def validate([_ | rest], _) when length(rest) > 0 do
{:validation_failure, :too_many_args}
end
@ -62,11 +65,10 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
set_disk_free_limit_relative(args, opts)
end
def run([limit], %{node: _} = opts) when is_binary(limit) do
case Integer.parse(limit) do
{limit_val, ""} -> set_disk_free_limit_absolute([limit_val], opts)
{limit_val, units} -> set_disk_free_limit_in_units([limit_val, units], opts)
{limit_val, ""} -> set_disk_free_limit_absolute([limit_val], opts)
{limit_val, units} -> set_disk_free_limit_in_units([limit_val, units], opts)
end
end
@ -77,17 +79,17 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
## ----------------------- Memory-Relative Call ----------------------------
defp set_disk_free_limit_relative(["mem_relative", fraction], %{node: node_name})
when is_float(fraction) do
when is_float(fraction) do
make_rpc_call(node_name, [{:mem_relative, fraction}])
end
defp set_disk_free_limit_relative(["mem_relative", integer_input], %{node: node_name})
when is_integer(integer_input) do
when is_integer(integer_input) do
make_rpc_call(node_name, [{:mem_relative, integer_input * 1.0}])
end
defp set_disk_free_limit_relative(["mem_relative", fraction_str], %{node: _} = opts)
when is_binary(fraction_str) do
when is_binary(fraction_str) do
{fraction_val, ""} = Float.parse(fraction_str)
set_disk_free_limit_relative(["mem_relative", fraction_val], opts)
end
@ -99,7 +101,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
end
defp set_disk_free_limit_absolute([limit], %{node: _} = opts) when is_float(limit) do
set_disk_free_limit_absolute([limit |> Float.floor |> round], opts)
set_disk_free_limit_absolute([limit |> Float.floor() |> round], opts)
end
defp set_disk_free_limit_in_units([limit_val, units], opts) do
@ -119,8 +121,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
"Setting disk free limit on #{node_name} to #{arg} times the total RAM ..."
end
def banner([arg], %{node: node_name}), do: "Setting disk free limit on #{node_name} to #{arg} bytes ..."
def banner([arg], %{node: node_name}),
do: "Setting disk free limit on #{node_name} to #{arg} bytes ..."
def usage, do: "set_disk_free_limit <disk_limit>\nset_disk_free_limit mem_relative <fraction>"
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetGlobalParameterCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,11 +27,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetGlobalParameterCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 2 do
def validate([_ | _] = args, _) when length(args) < 2 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 2 do
def validate([_ | _] = args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
end
@ -41,7 +40,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetGlobalParameterCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([name, value], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:parse_set_global,
[name, value, Helpers.cli_acting_user()]

View File

@ -15,16 +15,30 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetLogLevelCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
@known_levels ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency", "none"]
@known_levels [
"debug",
"info",
"notice",
"warning",
"error",
"critical",
"alert",
"emergency",
"none"
]
def merge_defaults(args, opts), do: {args, opts}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([level], _) do
case Enum.member?(@known_levels, level) do
true -> :ok
false -> {:error, "level #{level} is not supported. Try one of debug, info, warning, error, none"}
true ->
:ok
false ->
{:error, "level #{level} is not supported. Try one of debug, info, warning, error, none"}
end
end
@ -40,8 +54,9 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetLogLevelCommand do
def banner([log_level], _), do: "Setting log level to \"#{log_level}\" ..."
def output({:error, {:invalid_log_level, level}}, _opts) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"level #{level} is not supported. Try one of debug, info, warning, error, none"}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetOperatorPolicyCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -30,11 +29,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetOperatorPolicyCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 3 do
def validate([_ | _] = args, _) when length(args) < 3 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 3 do
def validate([_ | _] = args, _) when length(args) > 3 do
{:validation_failure, :too_many_args}
end
@ -42,25 +41,27 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetOperatorPolicyCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([name, pattern, definition], %{node: node_name,
vhost: vhost,
priority: priority,
apply_to: apply_to}) do
:rabbit_misc.rpc_call(node_name,
def run([name, pattern, definition], %{
node: node_name,
vhost: vhost,
priority: priority,
apply_to: apply_to
}) do
:rabbit_misc.rpc_call(
node_name,
:rabbit_policy,
:parse_set_op,
[vhost,
name,
pattern,
definition,
priority,
apply_to,
Helpers.cli_acting_user()])
[vhost, name, pattern, definition, priority, apply_to, Helpers.cli_acting_user()]
)
end
def usage, do: "set_operator_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>"
def usage,
do:
"set_operator_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>"
def banner([name, pattern, definition], %{vhost: vhost, priority: priority}) do
"Setting operator policy override \"#{name}\" for pattern \"#{pattern}\" to \"#{definition}\" with priority \"#{priority}\" for vhost \"#{vhost}\" ..."
"Setting operator policy override \"#{name}\" for pattern \"#{pattern}\" to \"#{definition}\" with priority \"#{
priority
}\" for vhost \"#{vhost}\" ..."
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetParameterCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,11 +27,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetParameterCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 3 do
def validate([_ | _] = args, _) when length(args) < 3 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 3 do
def validate([_ | _] = args, _) when length(args) > 3 do
{:validation_failure, :too_many_args}
end
@ -41,7 +40,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetParameterCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([component_name, name, value], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_runtime_parameters,
:parse_set,
[vhost, component_name, name, value, Helpers.cli_acting_user()]
@ -51,6 +51,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetParameterCommand do
def usage, do: "set_parameter [-p <vhost>] <component_name> <name> <value>"
def banner([component_name, name, value], %{vhost: vhost}) do
"Setting runtime parameter \"#{component_name}\" for component \"#{name}\" to \"#{value}\" in vhost \"#{vhost}\" ..."
"Setting runtime parameter \"#{component_name}\" for component \"#{name}\" to \"#{value}\" in vhost \"#{
vhost
}\" ..."
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetPermissionsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,19 +27,21 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetPermissionsCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 4 do
def validate([_ | _] = args, _) when length(args) < 4 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 4 do
def validate([_ | _] = args, _) when length(args) > 4 do
{:validation_failure, :too_many_args}
end
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([user, conf, write, read], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:set_permissions,
[user, vhost, conf, write, read, Helpers.cli_acting_user()]
@ -49,5 +50,6 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetPermissionsCommand do
def usage, do: "set_permissions [-p <vhost>] <username> <conf> <write> <read>"
def banner([user|_], %{vhost: vhost}), do: "Setting permissions for user \"#{user}\" in vhost \"#{vhost}\" ..."
def banner([user | _], %{vhost: vhost}),
do: "Setting permissions for user \"#{user}\" in vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetPolicyCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -30,11 +29,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetPolicyCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 3 do
def validate([_ | _] = args, _) when length(args) < 3 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 3 do
def validate([_ | _] = args, _) when length(args) > 3 do
{:validation_failure, :too_many_args}
end
@ -42,25 +41,27 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetPolicyCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([name, pattern, definition], %{node: node_name,
vhost: vhost,
priority: priority,
apply_to: apply_to}) do
:rabbit_misc.rpc_call(node_name,
def run([name, pattern, definition], %{
node: node_name,
vhost: vhost,
priority: priority,
apply_to: apply_to
}) do
:rabbit_misc.rpc_call(
node_name,
:rabbit_policy,
:parse_set,
[vhost,
name,
pattern,
definition,
priority,
apply_to,
Helpers.cli_acting_user()])
[vhost, name, pattern, definition, priority, apply_to, Helpers.cli_acting_user()]
)
end
def usage, do: "set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>"
def usage,
do:
"set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition>"
def banner([name, pattern, definition], %{vhost: vhost, priority: priority}) do
"Setting policy \"#{name}\" for pattern \"#{pattern}\" to \"#{definition}\" with priority \"#{priority}\" for vhost \"#{vhost}\" ..."
"Setting policy \"#{name}\" for pattern \"#{pattern}\" to \"#{definition}\" with priority \"#{
priority
}\" for vhost \"#{vhost}\" ..."
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetTopicPermissionsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -27,26 +26,32 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetTopicPermissionsCommand do
def validate([], _) do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) < 4 do
def validate([_ | _] = args, _) when length(args) < 4 do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 4 do
def validate([_ | _] = args, _) when length(args) > 4 do
{:validation_failure, :too_many_args}
end
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([user, exchange, write_pattern, read_pattern], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:set_topic_permissions,
[user, vhost, exchange, write_pattern, read_pattern, Helpers.cli_acting_user()]
)
end
def usage, do: "set_topic_permissions [-p <vhost>] <username> <exchange> <write_pattern> <read_pattern>"
def usage,
do: "set_topic_permissions [-p <vhost>] <username> <exchange> <write_pattern> <read_pattern>"
def banner([user, exchange, _, _], %{vhost: vhost}), do: "Setting topic permissions on \"#{exchange}\" for user \"#{user}\" in vhost \"#{vhost}\" ..."
def banner([user, exchange, _, _], %{vhost: vhost}),
do:
"Setting topic permissions on \"#{exchange}\" for user \"#{user}\" in vhost \"#{vhost}\" ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetUserTagsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,7 +27,8 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetUserTagsCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([user | tags], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:rabbit_auth_backend_internal,
:set_tags,
[user, tags, Helpers.cli_acting_user()]

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetVhostLimitsCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -28,7 +27,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetVhostLimitsCommand do
{:validation_failure, :not_enough_args}
end
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
@ -37,8 +36,11 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetVhostLimitsCommand do
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([definition], %{node: node_name, vhost: vhost}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_vhost_limit, :parse_set, [vhost, definition, Helpers.cli_acting_user()])
:rabbit_misc.rpc_call(node_name, :rabbit_vhost_limit, :parse_set, [
vhost,
definition,
Helpers.cli_acting_user()
])
end
def usage, do: "set_vhost_limits [-p <vhost>] <definition>"

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.SetVmMemoryHighWatermarkCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -30,54 +29,70 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetVmMemoryHighWatermarkCommand do
{:validation_failure, :not_enough_args}
end
def validate(["absolute"|_] = args, _) when length(args) > 2 do
def validate(["absolute" | _] = args, _) when length(args) > 2 do
{:validation_failure, :too_many_args}
end
def validate(["absolute", arg], _) do
case Integer.parse(arg) do
:error -> {:validation_failure, :bad_argument}
:error ->
{:validation_failure, :bad_argument}
{_, rest} ->
case Enum.member?(Helpers.memory_units, rest) do
true -> :ok
false -> case Float.parse(arg) do
{_, orest} when orest == rest ->
{:validation_failure, {:bad_argument, "Invalid units."}}
_ ->
{:validation_failure, {:bad_argument, "The threshold should be an integer."}}
end
case Enum.member?(Helpers.memory_units(), rest) do
true ->
:ok
false ->
case Float.parse(arg) do
{_, orest} when orest == rest ->
{:validation_failure, {:bad_argument, "Invalid units."}}
_ ->
{:validation_failure, {:bad_argument, "The threshold should be an integer."}}
end
end
end
end
def validate([_|_] = args, _) when length(args) > 1 do
def validate([_ | _] = args, _) when length(args) > 1 do
{:validation_failure, :too_many_args}
end
def validate([arg], _) when is_number(arg) and (arg < 0.0 or arg > 1.0) do
{:validation_failure, {:bad_argument, "The threshold should be a fraction between 0.0 and 1.0"}}
{:validation_failure,
{:bad_argument, "The threshold should be a fraction between 0.0 and 1.0"}}
end
def validate([arg], %{}) when is_binary(arg) do
case Float.parse(arg) do
{arg, ""} when is_number(arg) and (arg < 0.0 or arg > 1.0) ->
{:validation_failure, {:bad_argument, "The threshold should be a fraction between 0.0 and 1.0"}}
{_, ""} -> :ok
_ -> {:validation_failure, :bad_argument}
{:validation_failure,
{:bad_argument, "The threshold should be a fraction between 0.0 and 1.0"}}
{_, ""} ->
:ok
_ ->
{:validation_failure, :bad_argument}
end
end
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run(["absolute", arg], opts) do
case Integer.parse(arg) do
{num, rest} -> valid_units = rest in Helpers.memory_units
set_vm_memory_high_watermark_absolute({num, rest}, valid_units, opts)
{num, rest} ->
valid_units = rest in Helpers.memory_units()
set_vm_memory_high_watermark_absolute({num, rest}, valid_units, opts)
end
end
def run([arg], %{node: node_name}) when is_number(arg) and arg >= 0.0 do
:rabbit_misc.rpc_call(node_name,
:rabbit_misc.rpc_call(
node_name,
:vm_memory_monitor,
:set_vm_memory_high_watermark,
[arg]
@ -86,20 +101,31 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetVmMemoryHighWatermarkCommand do
def run([arg], %{} = opts) when is_binary(arg) do
case Float.parse(arg) do
{num, ""} -> run([num], opts)
{num, ""} -> run([num], opts)
end
end
defp set_vm_memory_high_watermark_absolute({num, rest}, true, %{node: node_name}) when num > 0 do
val = Helpers.memory_unit_absolute(num, rest)
:rabbit_misc.rpc_call(node_name,
:vm_memory_monitor,
:set_vm_memory_high_watermark,
[{:absolute, val}])
defp set_vm_memory_high_watermark_absolute({num, rest}, true, %{node: node_name})
when num > 0 do
val = Helpers.memory_unit_absolute(num, rest)
:rabbit_misc.rpc_call(
node_name,
:vm_memory_monitor,
:set_vm_memory_high_watermark,
[{:absolute, val}]
)
end
def usage, do: ["set_vm_memory_high_watermark <fraction>", "set_vm_memory_high_watermark absolute <value>"]
def usage,
do: [
"set_vm_memory_high_watermark <fraction>",
"set_vm_memory_high_watermark absolute <value>"
]
def banner(["absolute", arg], %{node: node_name}), do: "Setting memory threshold on #{node_name} to #{arg} bytes ..."
def banner([arg], %{node: node_name}), do: "Setting memory threshold on #{node_name} to #{arg} ..."
def banner(["absolute", arg], %{node: node_name}),
do: "Setting memory threshold on #{node_name} to #{arg} bytes ..."
def banner([arg], %{node: node_name}),
do: "Setting memory threshold on #{node_name} to #{arg} ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.ShutdownCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
alias RabbitMQ.CLI.Core.OsPid
@ -25,26 +24,30 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ShutdownCommand do
case :rabbit_misc.rpc_call(node_name, :os, :getpid, []) do
pid when is_list(pid) ->
shutdown_node_and_wait_pid_to_stop(node_name, pid)
other -> other
other ->
other
end
end
def shutdown_node_and_wait_pid_to_stop(node_name, pid) do
{:stream,
RabbitMQ.CLI.Core.Helpers.stream_until_error([
fn() -> "Shutting down RabbitMQ node #{node_name} running at PID #{pid}" end,
fn() ->
res = :rabbit_misc.rpc_call(node_name, :rabbit, :stop_and_halt, [])
case res do
:ok -> "Waiting for PID #{pid} to terminate";
{:badrpc, err} -> {:error, err}
{:error, _} = err -> err
end
end,
fn() ->
OsPid.wait_for_os_process_death(pid)
"RabbitMQ node #{node_name} running at PID #{pid} successfully shut down"
end])}
RabbitMQ.CLI.Core.Helpers.stream_until_error([
fn -> "Shutting down RabbitMQ node #{node_name} running at PID #{pid}" end,
fn ->
res = :rabbit_misc.rpc_call(node_name, :rabbit, :stop_and_halt, [])
case res do
:ok -> "Waiting for PID #{pid} to terminate"
{:badrpc, err} -> {:error, err}
{:error, _} = err -> err
end
end,
fn ->
OsPid.wait_for_os_process_death(pid)
"RabbitMQ node #{node_name} running at PID #{pid} successfully shut down"
end
])}
end
use RabbitMQ.CLI.DefaultOutput

View File

@ -13,14 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.StartAppCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
def run([], %{node: node_name}) do

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.StatusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -22,7 +21,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.StatusCommand do
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
def run([], %{node: node_name}) do

View File

@ -13,14 +13,12 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.StopAppCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts), do: {args, opts}
def validate([_|_] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 0, do: {:validation_failure, :too_many_args}
def validate([], _), do: :ok
def run([], %{node: node_name}) do
@ -29,6 +27,5 @@ defmodule RabbitMQ.CLI.Ctl.Commands.StopAppCommand do
def usage, do: "stop_app"
def banner(_, %{node: node_name}), do: "Stopping rabbit application on node #{node_name} ..."
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.StopCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -27,27 +26,33 @@ defmodule RabbitMQ.CLI.Ctl.Commands.StopCommand do
def validate([], _), do: :ok
def validate([_pidfile_path], _), do: :ok
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def run([], %{node: node_name, idempotent: true}) do
case :rabbit_misc.rpc_call(node_name, :rabbit, :stop_and_halt, []) do
{:badrpc, :nodedown} -> {:ok, "Node #{node_name} is no longer running"};
any -> any
{:badrpc, :nodedown} -> {:ok, "Node #{node_name} is no longer running"}
any -> any
end
end
def run([], %{node: node_name, idempotent: false}) do
:rabbit_misc.rpc_call(node_name, :rabbit, :stop_and_halt, [])
end
def run([pidfile_path], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name, :rabbit, :stop_and_halt, [])
case OsPid.read_pid_from_file(pidfile_path, true) do
{:error, details} -> {:error, "could not read pid from file #{pidfile_path}. Error: #{details}"};
{:error, :could_not_read_pid_from_file,
{:contents, s}} -> {:error, "could not read pid from file #{pidfile_path}. File contents: #{s}"};
{:error, :could_not_read_pid_from_file,
details} -> {:error, "could not read pid from file #{pidfile_path}. Error: #{details}"};
pid ->
{:error, details} ->
{:error, "could not read pid from file #{pidfile_path}. Error: #{details}"}
{:error, :could_not_read_pid_from_file, {:contents, s}} ->
{:error, "could not read pid from file #{pidfile_path}. File contents: #{s}"}
{:error, :could_not_read_pid_from_file, details} ->
{:error, "could not read pid from file #{pidfile_path}. Error: #{details}"}
pid ->
OsPid.wait_for_os_process_death(pid)
{:ok, "process #{pid} (take from pid file #{pidfile_path}) is no longer running"}
end
@ -58,5 +63,6 @@ defmodule RabbitMQ.CLI.Ctl.Commands.StopCommand do
def banner([pidfile_path], %{node: node_name}) do
"Stopping and halting node #{node_name} (will monitor pid file #{pidfile_path}) ..."
end
def banner(_, %{node: node_name}), do: "Stopping and halting node #{node_name} ..."
end

View File

@ -23,14 +23,15 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SyncQueueCommand do
{args, Map.merge(default_opts(), opts)}
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([queue], %{vhost: vhost, node: node_name}) do
:rpc.call(node_name,
:rpc.call(
node_name,
:rabbit_mirror_queue_misc,
:sync_queue,
[:rabbit_misc.r(vhost, :queue, queue)],

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.TraceOffCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -22,14 +21,14 @@ defmodule RabbitMQ.CLI.Ctl.Commands.TraceOffCommand do
{[], Map.merge(%{vhost: "/"}, opts)}
end
def validate([_|_], _), do: {:validation_failure, :too_many_args}
def validate([_ | _], _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, vhost: vhost}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_trace, :stop, [vhost]) do
:ok -> {:ok, "Trace disabled for vhost #{vhost}"};
:ok -> {:ok, "Trace disabled for vhost #{vhost}"}
other -> other
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.TraceOnCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@ -22,14 +21,14 @@ defmodule RabbitMQ.CLI.Ctl.Commands.TraceOnCommand do
{[], Map.merge(%{vhost: "/"}, opts)}
end
def validate([_|_], _), do: {:validation_failure, :too_many_args}
def validate([_ | _], _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: :ok
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, vhost: vhost}) do
case :rabbit_misc.rpc_call(node_name, :rabbit_trace, :start, [vhost]) do
:ok -> {:ok, "Trace enabled for vhost #{vhost}"};
:ok -> {:ok, "Trace enabled for vhost #{vhost}"}
other -> other
end
end

View File

@ -13,7 +13,6 @@
## The Initial Developer of the Original Code is Pivotal Software, Inc.
## Copyright (c) 2016-2017 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Ctl.Commands.UpdateClusterNodesCommand do
alias RabbitMQ.CLI.Core.Helpers
@ -23,18 +22,19 @@ defmodule RabbitMQ.CLI.Ctl.Commands.UpdateClusterNodesCommand do
{args, opts}
end
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_], _), do: :ok
def validate(_, _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: {:validation_failure, :too_many_args}
use RabbitMQ.CLI.Core.RequiresRabbitAppStopped
def run([seed_node], %{node: node_name}) do
:rabbit_misc.rpc_call(node_name,
:rabbit_mnesia,
:update_cluster_nodes,
[Helpers.normalise_node(seed_node)]
)
:rabbit_misc.rpc_call(
node_name,
:rabbit_mnesia,
:update_cluster_nodes,
[Helpers.normalise_node(seed_node)]
)
end
def usage() do
@ -46,12 +46,14 @@ defmodule RabbitMQ.CLI.Ctl.Commands.UpdateClusterNodesCommand do
end
def output({:error, :mnesia_unexpectedly_running}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
RabbitMQ.CLI.DefaultOutput.mnesia_running_error(node_name)}
end
def output({:error, :cannot_cluster_node_with_itself}, %{node: node_name}) do
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software,
{:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(),
"Error: cannot cluster node with itself: #{node_name}"}
end
use RabbitMQ.CLI.DefaultOutput
end

View File

@ -21,23 +21,25 @@ defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
def switches(), do: [pid: :integer, timeout: :integer]
def aliases(), do: ['P': :pid, t: :timeout]
def aliases(), do: [P: :pid, t: :timeout]
def scopes(), do: [:ctl, :diagnostics]
def merge_defaults(args, opts) do
timeout = case opts[:timeout] do
nil -> @default_timeout;
:infinity -> @default_timeout;
val -> val
end
{args, Map.put(opts, :timeout, timeout)}
end
timeout =
case opts[:timeout] do
nil -> @default_timeout
:infinity -> @default_timeout
val -> val
end
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
{args, Map.put(opts, :timeout, timeout)}
end
def validate([_ | _] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}
def validate([_], %{pid: _}), do: {:validation_failure, "Cannot specify both pid and pidfile"}
def validate([], %{pid: _} = opts), do: Validators.rabbit_is_loaded([], opts)
def validate([], _), do: {:validation_failure, "No pid or pidfile specified"}
def validate([], %{pid: _} = opts), do: Validators.rabbit_is_loaded([], opts)
def validate([], _), do: {:validation_failure, "No pid or pidfile specified"}
def validate([_], opts), do: Validators.rabbit_is_loaded([], opts)
def run([pid_file], %{node: node_name, timeout: timeout} = opts) do
@ -47,45 +49,58 @@ defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
Helpers.stream_until_error_parametrised(
[
log("Waiting for pid file '#{pid_file}' to appear", quiet),
fn(_) -> wait_for_pid_file(pid_file, timeout) end,
log_param(fn(pid) -> "pid is #{pid}" end, quiet),
]
++
wait_for_pid_funs(node_name, app_names, timeout, quiet),
:init)
fn _ -> wait_for_pid_file(pid_file, timeout) end,
log_param(fn pid -> "pid is #{pid}" end, quiet)
] ++
wait_for_pid_funs(node_name, app_names, timeout, quiet),
:init
)
end
def run([], %{node: node_name, pid: pid, timeout: timeout} = opts) do
app_names = :rabbit_and_plugins
quiet = opts[:quiet] || false
Helpers.stream_until_error_parametrised(
wait_for_pid_funs(node_name, app_names, timeout, quiet),
pid)
pid
)
end
defp wait_for_pid_funs(node_name, app_names, timeout, quiet) do
app_names_formatted = :io_lib.format('~p', [app_names])
[
log_param(fn(pid) -> "Waiting for erlang distribution on node '#{node_name}' while OS process '#{pid}' is running" end, quiet),
fn(pid) -> wait_for_erlang_distribution(pid, node_name, timeout) end,
log("Waiting for applications '#{app_names_formatted}' to start on node '#{node_name}'", quiet),
fn(_) -> wait_for_application(node_name, app_names) end,
log_param(
fn pid ->
"Waiting for erlang distribution on node '#{node_name}' while OS process '#{pid}' is running"
end,
quiet
),
fn pid -> wait_for_erlang_distribution(pid, node_name, timeout) end,
log(
"Waiting for applications '#{app_names_formatted}' to start on node '#{node_name}'",
quiet
),
fn _ -> wait_for_application(node_name, app_names) end,
log("Applications '#{app_names_formatted}' are running on node '#{node_name}'", quiet)
]
end
defp log(_string, _quiet = true) do
fn(val) -> {:ok, val} end
fn val -> {:ok, val} end
end
defp log(string, _quiet = false) do
fn(val) -> {:ok, val, string} end
fn val -> {:ok, val, string} end
end
defp log_param(_fun, _quiet = true) do
fn(val) -> {:ok, val} end
fn val -> {:ok, val} end
end
defp log_param(fun, _quiet = false) do
fn(val) -> {:ok, val, fun.(val)} end
fn val -> {:ok, val, fun.(val)} end
end
def usage, do: "wait [<pid_file>] [--pid|-P <pid>]"
@ -95,53 +110,62 @@ defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
def output({:error, err}, _opts) do
case format_error(err) do
:undefined -> RabbitMQ.CLI.DefaultOutput.output({:error, err});
error_str -> {:error, RabbitMQ.CLI.Core.ExitCodes.exit_software, error_str}
:undefined -> RabbitMQ.CLI.DefaultOutput.output({:error, err})
error_str -> {:error, RabbitMQ.CLI.Core.ExitCodes.exit_software(), error_str}
end
end
def output({:stream, stream}, _opts) do
{:stream,
Stream.map(stream, fn
({:error, err}) ->
{:error,
case format_error(err) do
:undefined -> err;
error_str -> error_str
end};
(other) -> other
end)}
{:error, err} ->
{:error,
case format_error(err) do
:undefined -> err
error_str -> error_str
end}
other ->
other
end)}
end
use RabbitMQ.CLI.DefaultOutput
defp format_error(:process_not_running) do
"Error: process is not running."
end
defp format_error({:garbage_in_pid_file, _}) do
"Error: garbage in pid file."
end
defp format_error({:could_not_read_pid, err}) do
"Error: could not read pid. Detail: #{err}"
end
defp format_error(_) do
:undefined
end
defp wait_for_application(node_name, :rabbit_and_plugins) do
case :rabbit.await_startup(node_name) do
{:badrpc, err} -> {:error, {:badrpc, err}};
other -> other
{:badrpc, err} -> {:error, {:badrpc, err}}
other -> other
end
end
defp wait_for_erlang_distribution(pid, node_name, timeout) do
wait_for(timeout,
fn() ->
wait_for(
timeout,
fn ->
case check_distribution(pid, node_name) do
# Loop while node is available.
{:error, :pang} -> {:error, :loop};
other -> other
{:error, :pang} -> {:error, :loop}
other -> other
end
end)
end
)
end
defp check_distribution(pid, node_name) do
@ -150,8 +174,10 @@ defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
case Node.ping(node_name) do
:pong -> :ok
:pang -> {:error, :pang}
end;
false -> {:error, :process_not_running}
end
false ->
{:error, :process_not_running}
end
end
@ -160,50 +186,69 @@ defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
end
defp wait_for_pid_file(pid_file, timeout) do
wait_for(timeout,
fn() ->
wait_for(
timeout,
fn ->
case :file.read_file(pid_file) do
{:ok, bin} ->
case Integer.parse(bin) do
:error ->
{:error, {:garbage_in_pid_file, pid_file}}
{int, _} -> {:ok, int}
{int, _} ->
{:ok, int}
end
{:error, :enoent} ->
{:error, :loop};
{:error, :loop}
{:error, err} ->
{:error, {:could_not_read_pid, err}}
end
end)
end
)
end
def wait_for(timeout, fun) do
def wait_for(timeout, fun) do
sleep = round(timeout / 10)
case wait_for_loop(timeout, sleep, fun) do
{:error, :timeout} -> {:error, {:timeout, timeout}}
other -> other
other -> other
end
end
def wait_for_loop(timeout, _, _) when timeout <= 0 do
{:error, :timeout}
end
def wait_for_loop(timeout, sleep, fun) do
time = :erlang.system_time(:milli_seconds)
time = :erlang.system_time(:milli_seconds)
case fun.() do
{:error, :loop} ->
time_to_fun = :erlang.system_time(:milli_seconds) - time
time_taken = case {time_to_fun > timeout, time_to_fun > sleep} do
## The function took longer than timeout
{true, _} -> time_to_fun;
## The function took longer than sleep
{false, true} -> time_to_fun;
## We need to sleep
{false, false} -> :timer.sleep(sleep)
time_to_fun + sleep
end
wait_for_loop(timeout - time_taken, sleep, fun);
other -> other
time_taken =
case {time_to_fun > timeout, time_to_fun > sleep} do
## The function took longer than timeout
{true, _} ->
time_to_fun
## The function took longer than sleep
{false, true} ->
time_to_fun
## We need to sleep
{false, false} ->
:timer.sleep(sleep)
time_to_fun + sleep
end
wait_for_loop(timeout - time_taken, sleep, fun)
other ->
other
end
end
end

View File

@ -18,19 +18,22 @@ defmodule RabbitMQ.CLI.Ctl.InfoKeys do
def validate_info_keys(args, valid_keys) do
info_keys = prepare_info_keys(args)
case invalid_info_keys(info_keys, valid_keys) do
[_|_] = bad_info_keys ->
[_ | _] = bad_info_keys ->
{:validation_failure, {:bad_info_key, bad_info_keys}}
[] -> {:ok, info_keys}
[] ->
{:ok, info_keys}
end
end
def prepare_info_keys(args) do
args
|> Enum.flat_map(fn(arg) -> String.split(arg, ",", [trim: true]) end)
|> Enum.flat_map(fn arg -> String.split(arg, ",", trim: true) end)
|> Enum.map(&String.trim/1)
|> Enum.map(&String.to_atom/1)
|> Enum.uniq
|> Enum.uniq()
end
def with_valid_info_keys(args, valid_keys, fun) do
@ -43,17 +46,17 @@ defmodule RabbitMQ.CLI.Ctl.InfoKeys do
defp invalid_info_keys(info_keys, valid_keys) do
MapSet.new(info_keys)
|> MapSet.difference(MapSet.new(valid_keys))
|> MapSet.to_list
|> MapSet.to_list()
end
def info_for_keys(item, []) do
item
end
def info_for_keys([{_,_}|_] = item, info_keys) do
def info_for_keys([{_, _} | _] = item, info_keys) do
item
|> Enum.filter(fn({k, _}) -> Enum.member?(info_keys, k) end)
|> Enum.map(fn({k, v}) -> {k, format_info_item(v)} end)
|> Enum.filter(fn {k, _} -> Enum.member?(info_keys, k) end)
|> Enum.map(fn {k, v} -> {k, format_info_item(v)} end)
end
defp format_info_item(resource(name: name)) do

Some files were not shown because too many files have changed in this diff Show More