Default output formatting and exit code selection. Inspect printer

This commit is contained in:
Daniil Fedotov 2016-08-18 14:56:21 +01:00
parent a79602a77c
commit 35fc3d12cd
65 changed files with 281 additions and 109 deletions

View File

@ -23,4 +23,5 @@ defmodule RabbitMQ.CLI.CommandBehaviour do
@callback run(List.t, Map.t) :: any
@callback switches() :: Keyword.t
@callback aliases() :: Keyword.t
@callback output(any, Map.t) :: :ok | {:ok, any} | {:stream, Enum.t} | {:error, ExitCodes.exit_code, [String.t]}
end

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.AddUserCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.AddVhostCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([], _), do: {:validation_failure, :not_enough_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.AuthenticateUserCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate(args, _) when length(args) < 2, do: {:validation_failure, :not_enough_args}

View File

@ -15,6 +15,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.CancelSyncQueueCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults([_|_] = args, opts) do
{args, Map.merge(default_opts, opts)}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ChangeClusterNodeTypeCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def flags, do: []
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ChangePasswordCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ClearParameterCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPasswordCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([], _), do: {:validation_failure, :not_enough_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def merge_defaults(args, opts) do

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ClearPolicyCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.CloseConnectionCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ClusterStatusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.DeleteUserCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate(args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.DeleteVhostCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.EnvironmentCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([_|_], _), do: {:validation_failure, :too_many_args}
def validate(_, _), do: :ok

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.EvalCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ForceBootCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ForceResetCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -20,6 +20,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ForgetClusterNodeCommand do
import RabbitMQ.CLI.Coerce
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def flags, do: [:offline]
def switches(), do: [offline: :boolean]

View File

@ -20,6 +20,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.HelpCommand do
alias RabbitMQ.CLI.ExitCodes, as: ExitCodes
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate(_, _), do: :ok
def merge_defaults(args, opts), do: {args, opts}

View File

@ -18,6 +18,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.JoinClusterCommand do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [
:disc, # --disc is accepted for consistency's sake.
:ram

View File

@ -19,6 +19,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListBindingsCommand do
alias RabbitMQ.CLI.Ctl.RpcStream, as: RpcStream
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(source_name source_kind destination_name destination_kind routing_key arguments)a

View File

@ -21,6 +21,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListChannelsCommand do
alias RabbitMQ.CLI.Ctl.InfoKeys, as: InfoKeys
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(pid connection name number user vhost transactional
confirm consumer_count messages_unacknowledged

View File

@ -20,6 +20,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConnectionsCommand do
alias RabbitMQ.CLI.Ctl.RpcStream, as: RpcStream
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(pid name port host peer_port peer_host ssl ssl_protocol
ssl_key_exchange ssl_cipher ssl_hash peer_cert_subject

View File

@ -20,6 +20,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConsumersCommand do
alias RabbitMQ.CLI.Ctl.RpcStream, as: RpcStream
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(queue_name channel_pid consumer_tag
ack_required prefetch_count arguments)a

View File

@ -19,6 +19,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListExchangesCommand do
alias RabbitMQ.CLI.Ctl.RpcStream, as: RpcStream
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(name type durable auto_delete internal arguments policy)a

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ListParametersCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def merge_defaults([], opts) do
{[], Map.merge(%{vhost: "/"}, opts)}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def merge_defaults(args, opts) do

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ListPoliciesCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def switches(), do: []

View File

@ -23,6 +23,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListQueuesCommand do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@info_keys ~w(name durable auto_delete
arguments policy pid owner_pid exclusive exclusive_consumer_pid

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ListUserPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def validate([], _), do: {:validation_failure, :not_enough_args}
def validate([_|_] = args, _) when length(args) > 1, do: {:validation_failure, :too_many_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ListUsersCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -18,6 +18,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListVhostsCommand do
alias RabbitMQ.CLI.Ctl.InfoKeys, as: InfoKeys
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
@info_keys ~w(name tracing)a

View File

@ -15,6 +15,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.NodeHealthCheckCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
defp default_opts() do
%{timeout: 70000}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.PurgeQueueCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def flags, do: []

View File

@ -21,6 +21,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.RenameClusterNodeCommand do
import RabbitMQ.CLI.Coerce
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def flags, do: [:mnesia_dir, :rabbitmq_home]
def switches(), do: [mnesia_dir: :string, rabbitmq_home: :string]

View File

@ -26,6 +26,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ReportCommand do
alias RabbitMQ.CLI.Ctl.Commands.ListPermissionsCommand, as: ListPermissionsCommand
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.ResetCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.RotateLogsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetClusterNameCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def switches(), do: []

View File

@ -18,6 +18,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetDiskFreeLimitCommand do
import RabbitMQ.CLI.Ctl.Helpers, only: [memory_unit_absolute: 2]
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetParameterCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetPermissionsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def merge_defaults(args, opts) do

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetPolicyCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def switches(), do: [priority: :integer, apply_to: :string]
def aliases(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SetUserTagsCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -18,6 +18,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.SetVmMemoryHighWatermarkCommand do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.StartAppCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.StatusCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.StopAppCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.StopCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -15,6 +15,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.SyncQueueCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults([_|_] = args, opts) do
{args, Map.merge(default_opts, opts)}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.TraceOffCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def validate([_|_], _), do: {:validation_failure, :too_many_args}

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.TraceOnCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags [:vhost]
def validate([_|_], _), do: {:validation_failure, :too_many_args}

View File

@ -18,6 +18,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.UpdateClusterNodesCommand do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def flags, do: []
def switches(), do: []

View File

@ -16,6 +16,7 @@
defmodule RabbitMQ.CLI.Ctl.Commands.WaitCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
@flags []
def merge_defaults(args, opts), do: {args, opts}

View File

@ -0,0 +1,71 @@
## The contents of this file are subject to the Mozilla Public License
## Version 1.1 (the "License"); you may not use this file except in
## compliance with the License. You may obtain a copy of the License
## at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS IS"
## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
## the License for the specific language governing rights and
## limitations under the License.
##
## The Original Code is RabbitMQ.
##
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.DefaultOutput do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
alias RabbitMQ.CLI.ExitCodes, as: ExitCodes
defmacro __using__(_opts) do
quote do
def normalize_output(:ok), do: :ok
def normalize_output({:ok, _} = input), do: input
def normalize_output({:badrpc, :nodedown} = input), do: input
def normalize_output({:badrpc, :timeout} = input), do: input
def normalize_output({:refused, _, _, _} = input), do: input
def normalize_output({:bad_option, _} = input), do: input
def normalize_output({:error, _} = input), do: input
def normalize_output(unknown) when is_atom(unknown), do: {:error, unknown}
def normalize_output({unknown, _} = input) when is_atom(unknown), do: {:error, input}
def normalize_output(result) when not is_atom(result), do: {:ok, result}
def output(result, opts) do
result
|> normalize_output()
|> format_output(opts)
end
defp format_output({:badrpc, :nodedown} = result, opts) do
{:error, ExitCodes.exit_code_for(result),
["Error: unable to connect to node '#{opts[:node]}': nodedown"]}
end
defp format_output({:badrpc, :timeout} = result, opts) do
{:error, ExitCodes.exit_code_for(result),
["Error: {timeout, #{opts[:timeout]}}"]}
end
defp format_output({:error, err} = result, _) do
string_err = string_or_inspect(err)
{:error, ExitCodes.exit_code_for(result), ["Error:\n#{string_err}"]}
end
defp format_output(:ok) do
:ok
end
defp format_output({:ok, output}, _) do
case Enumerable.impl_for(output) do
nil -> {:ok, output};
_ -> {:stream, output}
end
end
defp string_or_inspect(val) do
case String.Chars.impl_for(val) do
nil -> inspect(val);
_ -> to_string(val)
end
end
end
end
end

View File

@ -21,10 +21,29 @@ defmodule RabbitMQ.CLI.ExitCodes do
@exit_software 70
@exit_tempfail 75
@type exit_code :: integer
def exit_ok, do: @exit_ok
def exit_usage, do: @exit_usage
def exit_dataerr, do: @exit_dataerr
def exit_unavailable, do: @exit_unavailable
def exit_software, do: @exit_software
def exit_tempfail, do: @exit_tempfail
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, {:bad_option, _}}), do: exit_usage
def exit_code_for({:validation_failure, _}), do: exit_usage
def exit_code_for({:badrpc, :timeout}), do: exit_tempfail
def exit_code_for({:badrpc, :nodedown}), do: exit_unavailable
def exit_code_for({:refused, _, _, _}), do: exit_dataerr
def exit_code_for({:healthcheck_failed, _}), do: exit_software
def exit_code_for({:join_cluster_failed, _}), do: exit_software
def exit_code_for({:reset_failed, _}), do: exit_software
def exit_code_for({:error, _}), do: exit_software
end

View File

@ -19,6 +19,7 @@ defmodule RabbitMQ.CLI.Plugins.Commands.DisableCommand do
alias RabbitMQ.CLI.Plugins.Helpers, as: PluginHelpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}

View File

@ -19,6 +19,7 @@ defmodule RabbitMQ.CLI.Plugins.Commands.EnableCommand do
alias RabbitMQ.CLI.Plugins.Helpers, as: PluginHelpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}

View File

@ -21,6 +21,7 @@ defmodule RabbitMQ.CLI.Plugins.Commands.ListCommand do
alias RabbitMQ.CLI.Plugins.Helpers, as: PluginHelpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults([], opts), do: merge_defaults([".*"], opts)
def merge_defaults(args, opts), do: {args, Map.merge(default_opts, opts)}

View File

@ -19,6 +19,7 @@ defmodule RabbitMQ.CLI.Plugins.Commands.SetCommand do
alias RabbitMQ.CLI.Plugins.Helpers, as: PluginHelpers
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def merge_defaults(args, %{offline: false, online: false} = opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}

View File

@ -0,0 +1,32 @@
## The contents of this file are subject to the Mozilla Public License
## Version 1.1 (the "License"); you may not use this file except in
## compliance with the License. You may obtain a copy of the License
## at http://www.mozilla.org/MPL/
##
## Software distributed under the License is distributed on an "AS IS"
## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
## the License for the specific language governing rights and
## limitations under the License.
##
## The Original Code is RabbitMQ.
##
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
defmodule RabbitMQ.CLI.Printers.InspectPrinter do
def start_collection(_), do: :ok
def finish_collection(_), do: :ok
def print_error(err, _) do
IO.inspect({:error, err})
end
def print_output(output, _) do
IO.inspect(output)
end
def print_ok(_) do
:ok
end
end

View File

@ -16,7 +16,6 @@
defmodule RabbitMQCtl do
alias RabbitMQ.CLI.Distribution, as: Distribution
alias RabbitMQ.CLI.StandardCodes, as: StandardCodes
alias RabbitMQ.CLI.Ctl.Commands.HelpCommand, as: HelpCommand
@ -32,24 +31,83 @@ defmodule RabbitMQCtl do
end
def main(unparsed_command) do
{parsed_cmd, options, invalid} = parse(unparsed_command)
{printer, print_options} = get_printer(options)
case try_run_command(parsed_cmd, options, invalid) do
{:validation_failure, _} = invalid ->
error_strings = validation_error(invalid, unparsed_command)
{:error, exit_code_for(invalid), error_strings}
cmd_result -> cmd_result
end
|> print_output(printer, print_options)
|> exit_program
end
def get_printer(%{printer: printer} = opts) do
module_name = String.to_atom("RabbitMQ.CLI.Printers." <>
Mix.Utils.camelize(printer))
printer = case Code.ensure_loaded(module_name) do
{:module, _} -> module_name;
{:error, :nofile} -> default_printer
end
{printer, opts}
end
def get_printer(opts) do
{default_printer, opts}
end
def default_printer() do
RabbitMQ.CLI.Printers.InspectPrinter
end
def print_output({:exit, exit_code, strings}, printer, print_options) do
printer.print_error(Enum.join(strings, "\n"), print_options)
exit_code
end
def print_output(:ok, printer, print_options) do
printer.print_ok(print_options)
exit_ok
end
def print_output({:ok, single_value}, printer, print_options) do
printer.print_output(single_value, print_options)
exit_ok
end
def print_output({:stream, stream}, printer, print_options) do
printer.start_collection(print_options)
exit_code = case print_output_stream(stream, printer, print_options) do
:ok -> exit_ok;
{:error, _} = err -> exit_code_for(err)
end
printer.finish_collection(print_options)
exit_code
end
def print_output_stream(stream, printer, print_options) do
Enum.reduce_while(stream, :ok,
fn
({:error, err}, _) ->
printer.print_error(err, print_options)
{:halt, {:error, err}};
(val, _) ->
printer.print_output(val, print_options)
{:cont, :ok}
end)
end
def try_run_command(parsed_cmd, options, invalid) do
case {is_command?(parsed_cmd), invalid} do
## No such command
{false, _} ->
HelpCommand.all_usage() |> handle_exit(exit_usage);
{:ok, strings} = HelpCommand.all_usage()
{:error, exit_usage, strings};
## Invalid options
{_, [_|_]} ->
print_standard_messages({:bad_option, invalid}, unparsed_command)
|> handle_exit
{:validation_failure, {:bad_option, invalid}};
## Command valid
{true, []} ->
effective_options = options |> merge_all_defaults |> normalize_node
Distribution.start(effective_options)
effective_options
|> run_command(parsed_cmd)
|> StandardCodes.map_to_standard_code
|> print_standard_messages(unparsed_command)
|> handle_exit
run_command(effective_options, parsed_cmd)
end
end
@ -92,10 +150,12 @@ defmodule RabbitMQCtl do
:ok ->
print_banner(command, arguments, options)
maybe_connect_to_rabbitmq(command_name, options[:node])
execute_command(command, arguments, options)
command.run(arguments, options)
|> command.output(options)
err -> err
end
result -> {:bad_option, result}
result -> {:validation_failure, {:bad_option, result}}
end
end)
end
@ -112,43 +172,6 @@ defmodule RabbitMQCtl do
end
end
defp execute_command(command, arguments, options) do
command.run(arguments, options)
end
defp print_standard_messages({:badrpc, :nodedown} = result, unparsed_command) do
{_, options, _} = parse(unparsed_command)
IO.puts "Error: unable to connect to node '#{options[:node]}': nodedown"
result
end
defp print_standard_messages({:badrpc, :timeout} = result, unparsed_command) do
{_, options, _} = parse(unparsed_command)
IO.puts "Error: {timeout, #{options[:timeout]}}"
result
end
defp print_standard_messages({:too_many_args, _} = result, unparsed_command) do
{[cmd | _], _, _} = parse(unparsed_command)
IO.puts "Error: too many arguments."
IO.puts "Given:\n\t#{unparsed_command |> Enum.join(" ")}"
HelpCommand.run([cmd], %{})
result
end
defp print_standard_messages({:not_enough_args, _} = result, unparsed_command) do
{[cmd | _], _, _} = parse(unparsed_command)
IO.puts "Error: not enough arguments."
IO.puts "Given:\n\t#{unparsed_command |> Enum.join(" ")}"
HelpCommand.run([cmd], %{})
result
end
defp print_standard_messages({:refused, user, _, _} = result, _) do
IO.puts "Error: failed to authenticate user \"#{user}\""
result
@ -183,52 +206,23 @@ defmodule RabbitMQCtl do
result
end
defp print_standard_messages({:error, err} = result, _) do
IO.puts "Error:"
IO.inspect err
result
end
defp print_standard_messages({:healthcheck_failed, message} = result, _) do
IO.puts "Error: healthcheck failed. Message: #{message}"
result
end
defp print_standard_messages({:bad_option, opt} = result, unparsed_command) do
case parse(unparsed_command) do
{[cmd | _], _, _} ->
IO.puts "Error: invalid options for this command."
IO.puts "Given:\n\t#{unparsed_command |> Enum.join(" ")}"
HelpCommand.run([cmd], %{})
result;
_ ->
IO.puts "Error: invalid options"
IO.inspect opt
HelpCommand.all_usage()
result
end
end
defp print_standard_messages({:validation_failure, err_detail} = result, unparsed_command) do
defp validation_error({:validation_failure, err_detail}, unparsed_command) do
{[command_name | _], _, _} = parse(unparsed_command)
err = format_validation_error(err_detail) # TODO format the error better
IO.puts "Error: #{err}"
IO.puts "Given:\n\t#{unparsed_command |> Enum.join(" ")}"
base_error = ["Error: #{err}", "Given:\n\t#{unparsed_command |> Enum.join(" ")}"]
case is_command?(command_name) do
true ->
command = commands[command_name]
HelpCommand.print_base_usage(HelpCommand.program_name(), command)
base_error ++ HelpCommand.print_base_usage(HelpCommand.program_name(), command)
false ->
HelpCommand.all_usage()
exit_usage
base_error ++ HelpCommand.all_usage()
end
result
end
defp print_standard_messages(result, _) do
result
end
defp format_validation_error(:not_enough_args), do: "not enough arguments."
@ -237,38 +231,27 @@ defmodule RabbitMQCtl do
defp format_validation_error({:too_many_args, detail}), do: "too many arguments. #{detail}"
defp format_validation_error(:bad_argument), do: "Bad argument."
defp format_validation_error({:bad_argument, detail}), do: "Bad argument. #{detail}"
defp format_validation_error({:bad_option, opts}) do
Enum.join(["Invalid options:" | for {key, val} <- opts do "#{key} : #{val}" end], "\n")
end
defp format_validation_error(err), do: inspect err
defp handle_exit({:validation_failure, :not_enough_args}), do: exit_program(exit_usage)
defp handle_exit({:validation_failure, :too_many_args}), do: exit_program(exit_usage)
defp handle_exit({:validation_failure, {:not_enough_args, _}}), do: exit_program(exit_usage)
defp handle_exit({:validation_failure, {:too_many_args, _}}), do: exit_program(exit_usage)
defp handle_exit({:validation_failure, {:bad_argument, _}}), do: exit_program(exit_dataerr)
defp handle_exit({:validation_failure, :bad_argument}), do: exit_program(exit_dataerr)
defp handle_exit({:validation_failure, _}), do: exit_program(exit_usage)
defp handle_exit({:bad_option, _} = _err), do: exit_program(exit_usage)
defp handle_exit({:badrpc, :timeout}), do: exit_program(exit_tempfail)
defp handle_exit({:badrpc, :nodedown}), do: exit_program(exit_unavailable)
defp handle_exit({:refused, _, _, _}), do: exit_program(exit_dataerr)
defp handle_exit({:healthcheck_failed, _}), do: exit_program(exit_software)
defp handle_exit({:join_cluster_failed, _}), do: exit_program(exit_software)
defp handle_exit({:reset_failed, _}), do: exit_program(exit_software)
defp handle_exit({:error, _}), do: exit_program(exit_software)
defp handle_exit(true), do: handle_exit(:ok, exit_ok)
defp handle_exit(:ok), do: handle_exit(:ok, exit_ok)
defp handle_exit({:ok, result}), do: handle_exit({:ok, result}, exit_ok)
defp handle_exit(result) when is_list(result), do: handle_exit({:ok, result}, exit_ok)
defp handle_exit(:ok, code), do: exit_program(code)
defp handle_exit({:ok, result}, code) do
case Enumerable.impl_for(result) do
nil -> IO.inspect result;
_ -> result |> Stream.map(&IO.inspect/1) |> Stream.run
end
exit_program(code)
end
# defp handle_exit(true), do: handle_exit(:ok, exit_ok)
# defp handle_exit(:ok), do: handle_exit(:ok, exit_ok)
# defp handle_exit({:ok, result}), do: handle_exit({:ok, result}, exit_ok)
# defp handle_exit(result) when is_list(result), do: handle_exit({:ok, result}, exit_ok)
# defp handle_exit(:ok, code), do: exit_program(code)
# defp handle_exit({:ok, result}, code) do
# case Enumerable.impl_for(result) do
# nil -> IO.inspect result;
# _ -> result |> Stream.map(&IO.inspect/1) |> Stream.run
# end
# exit_program(code)
# end
defp invalid_flags(command, opts) do
Map.keys(opts) -- (command.flags ++ global_flags)
Map.take(opts, Map.keys(opts) -- (command.flags ++ global_flags))
|> Map.to_list
end
defp exit_program(code) do

View File

@ -121,6 +121,7 @@ end
defmodule RabbitMQ.CLI.Ctl.Commands.DuckCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["duck"]
def flags(), do: []
def validate(_,_), do: :ok
@ -133,6 +134,7 @@ end
defmodule RabbitMQ.CLI.Ctl.Commands.GrayGooseCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["gray_goose"]
def flags(), do: []
def validate(_,_), do: :ok
@ -151,6 +153,7 @@ end
defmodule RabbitMQ.CLI.Plugins.Commands.StorkCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["stork"]
def flags(), do: []
def validate(_,_), do: :ok
@ -163,6 +166,7 @@ end
defmodule RabbitMQ.CLI.Plugins.Commands.HeronCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["heron"]
def flags(), do: []
def validate(_,_), do: :ok
@ -177,6 +181,7 @@ end
defmodule RabbitMQ.CLI.Custom.Commands.CrowCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["crow"]
def flags(), do: []
def validate(_,_), do: :ok
@ -190,6 +195,7 @@ end
defmodule RabbitMQ.CLI.Custom.Commands.RavenCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["raven"]
def flags(), do: []
def validate(_,_), do: :ok
@ -202,6 +208,7 @@ end
defmodule RabbitMQ.CLI.Seagull.Commands.SeagullCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput
def usage(), do: ["seagull"]
def flags(), do: []
def validate(_,_), do: :ok