script name is overridable via argument

This commit is contained in:
Daniil Fedotov 2016-10-31 11:21:10 +00:00
parent 60fdcecdb4
commit ad90e60121
12 changed files with 64 additions and 48 deletions

View File

@ -8,6 +8,8 @@ dep_json = hex 1.0.0
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
TEST_FILE ?= ""
include rabbitmq-components.mk
include erlang.mk
@ -32,5 +34,11 @@ rel::
tests:: all
mix test --trace
test:: all
mix test --trace $(TEST_FILE)
clean::
mix clean
mix clean
repl:
iex -S mix

View File

@ -34,7 +34,7 @@ use Mix.Config
#
# Or configure a 3rd-party app:
#
# config :logger, level: :info
config :logger, level: :warn
#
# It is also possible to import configuration files, relative to this

View File

@ -18,7 +18,7 @@ defmodule RabbitMQ.CLI.Config do
def get_option(name, opts) do
raw_option = opts[name] ||
get_system_option(name) ||
default(name, opts)
default(name)
normalize(name, raw_option)
end
@ -28,6 +28,11 @@ defmodule RabbitMQ.CLI.Config do
def normalize(:longnames, _), do: :shortnames
def normalize(_, value), do: value
def get_system_option(:script_name) do
Path.basename(:escript.script_name())
|> Path.rootname
|> String.to_atom
end
def get_system_option(name) do
system_env_option = case name do
:longnames -> "RABBITMQ_USE_LONGNAME";
@ -40,5 +45,6 @@ defmodule RabbitMQ.CLI.Config do
System.get_env(system_env_option)
end
def default(_, _), do: nil
def default(:script_name), do: :rabbitmqctl
def default(_), do: nil
end

View File

@ -17,6 +17,7 @@
defmodule AutoComplete do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
alias RabbitMQ.CLI.Ctl.Parser, as: Parser
alias RabbitMQ.CLI.Ctl.CommandModules, as: CommandModules
@spec complete(String.t) :: {:ok, [String.t]}
def complete(str) do
@ -24,7 +25,8 @@ defmodule AutoComplete do
case List.last(tokens) do
nil -> [];
last_token ->
{args, _, _} = Parser.parse(tokens)
{args, opts, _} = Parser.parse(tokens)
CommandModules.load(opts)
variants = case args do
[] -> complete_default_opts(last_token);
[cmd|_] -> complete_command_opts(cmd, last_token)

View File

@ -13,33 +13,25 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
alias RabbitMQ.CLI.Config, as: Config
defmodule RabbitMQ.CLI.Ctl.CommandModules do
@commands_ns ~r/RabbitMQ.CLI.(.*).Commands/
def module_map do
case Application.get_env(:rabbitmqctl, :commands) do
nil -> load;
val -> val
end
Application.get_env(:rabbitmqctl, :commands) || load(%{})
end
def load do
scope = script_scope
def load(opts) do
scope = script_scope(opts)
commands = load_commands(scope)
Application.put_env(:rabbitmqctl, :commands, commands)
commands
end
def script_scope do
def script_scope(opts) do
scopes = Application.get_env(:rabbitmqctl, :scopes, [])
scopes[script_name] || :none
end
def script_name do
Path.basename(:escript.script_name())
|> Path.rootname
|> String.to_atom
scopes[Config.get_option(:script_name, opts)] || :none
end
def load_commands(scope) do

View File

@ -20,13 +20,15 @@ defmodule RabbitMQ.CLI.Ctl.Parser do
# Output: A 2-tuple of lists: one containing the command,
# one containing flagged options.
def parse(command) do
switches = build_switches(default_switches())
{options, cmd, invalid} = OptionParser.parse(
command,
strict: build_switches(default_switches()),
strict: switches,
aliases: build_aliases([p: :vhost, n: :node, q: :quiet,
t: :timeout, l: :longnames])
)
{clear_on_empty_command(cmd), options_map(options), invalid}
norm_options = normalize_options(options, switches)
{clear_on_empty_command(cmd), Map.new(norm_options), invalid}
end
def default_switches() do
@ -37,7 +39,8 @@ defmodule RabbitMQ.CLI.Ctl.Parser do
longnames: :boolean,
formatter: :string,
printer: :string,
file: :string]
file: :string,
script_name: :atom]
end
defp build_switches(default) do
@ -78,9 +81,18 @@ defmodule RabbitMQ.CLI.Ctl.Parser do
end)
end
defp options_map(opts) do
opts
|> Map.new
defp normalize_options(options, switches) do
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
# Discards entire command if first command term is empty.

View File

@ -22,11 +22,8 @@ defmodule RabbitMQ.CLI.Plugins.Commands.DisableCommand do
@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)}
end
def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}
{args, Map.merge(%{online: false, offline: false}, opts)}
end
def switches(), do: [online: :boolean,

View File

@ -22,11 +22,8 @@ defmodule RabbitMQ.CLI.Plugins.Commands.EnableCommand do
@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)}
end
def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}
{args, Map.merge(%{online: false, offline: false}, opts)}
end
def switches(), do: [online: :boolean,

View File

@ -22,11 +22,9 @@ defmodule RabbitMQ.CLI.Plugins.Commands.SetCommand do
@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)}
end
def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)}
IO.inspect opts
{args, Map.merge(%{online: false, offline: false}, opts)}
end
def switches(), do: [online: :boolean,
@ -66,8 +64,9 @@ defmodule RabbitMQ.CLI.Plugins.Commands.SetCommand do
%{online: online, offline: offline} = opts
mode = case {online, offline} do
{true, false} -> :online;
{false, true} -> :offline
{true, false} -> :online;
{false, true} -> :offline;
{false, false} -> :online
end
PluginHelpers.set_enabled_plugins(plugins, mode, node_name, opts)

View File

@ -20,6 +20,7 @@ defmodule RabbitMQCtl do
alias RabbitMQ.CLI.Ctl.Commands.HelpCommand, as: HelpCommand
alias RabbitMQ.CLI.Output, as: Output
alias RabbitMQ.CLI.ExitCodes, as: ExitCodes
alias RabbitMQ.CLI.Ctl.CommandModules, as: CommandModules
import RabbitMQ.CLI.Ctl.Helpers
import RabbitMQ.CLI.Ctl.Parser
@ -32,6 +33,8 @@ defmodule RabbitMQCtl do
end
def main(unparsed_command) do
{parsed_cmd, parsed_options, invalid} = parse(unparsed_command)
options = parsed_options |> merge_all_defaults |> normalize_node
CommandModules.load(options)
case {is_command?(parsed_cmd), invalid} do
## No such command
{false, _} ->
@ -42,7 +45,6 @@ defmodule RabbitMQCtl do
error = validation_error({:bad_option, invalid}, unparsed_command);
## Command valid
{true, []} ->
options = parsed_options |> merge_all_defaults |> normalize_node
Distribution.start(options)
[command_name | arguments] = parsed_cmd

View File

@ -13,6 +13,7 @@
## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
alias RabbitMQ.CLI.Config, as: Config
defmodule CommandModulesTest do
use ExUnit.Case, async: false
@ -54,7 +55,7 @@ defmodule CommandModulesTest do
test "load commands for current scope" do
set_scope(:ctl)
commands = @subject.load
commands = @subject.load(%{})
assert commands == @subject.load_commands(:ctl)
assert commands["duck"] == RabbitMQ.CLI.Ctl.Commands.DuckCommand
@ -67,7 +68,7 @@ defmodule CommandModulesTest do
assert commands["raven"] == nil
set_scope(:plugins)
commands = @subject.load
commands = @subject.load(%{})
assert commands == @subject.load_commands(:plugins)
assert commands["duck"] == nil
assert commands["gray_goose"] == nil
@ -111,7 +112,7 @@ defmodule CommandModulesTest do
end
def set_scope(scope) do
script_name = @subject.script_name
script_name = Config.get_option(:script_name, %{})
scopes = Keyword.put(Application.get_env(:rabbitmqctl, :scopes), script_name, scope)
Application.put_env(:rabbitmqctl, :scopes, scopes)
end

View File

@ -47,26 +47,26 @@ defmodule ParserTest do
test "one arity 0 command, one single-dash node option" do
assert @subject.parse(["sandwich", "-n", "rabbitmq@localhost"]) ==
{["sandwich"], %{node: "rabbitmq@localhost"}, []}
{["sandwich"], %{node: :"rabbitmq@localhost"}, []}
end
test "one arity 1 command, one single-dash node option" do
assert @subject.parse(["sandwich", "pastrami", "-n", "rabbitmq@localhost"]) ==
{["sandwich", "pastrami"], %{node: "rabbitmq@localhost"}, []}
{["sandwich", "pastrami"], %{node: :"rabbitmq@localhost"}, []}
end
test "one arity 1 command, one single-dash node option and one quiet flag" do
assert @subject.parse(["sandwich", "pastrami", "-n", "rabbitmq@localhost", "--quiet"]) ==
{["sandwich", "pastrami"], %{node: "rabbitmq@localhost", quiet: true}, []}
{["sandwich", "pastrami"], %{node: :"rabbitmq@localhost", quiet: true}, []}
end
test "single-dash node option before command" do
assert @subject.parse(["-n", "rabbitmq@localhost", "sandwich", "pastrami"]) ==
{["sandwich", "pastrami"], %{node: "rabbitmq@localhost"}, []}
{["sandwich", "pastrami"], %{node: :"rabbitmq@localhost"}, []}
end
test "no commands, one double-dash node option" do
assert @subject.parse(["--node=rabbitmq@localhost"]) == {[], %{node: "rabbitmq@localhost"}, []}
assert @subject.parse(["--node=rabbitmq@localhost"]) == {[], %{node: :"rabbitmq@localhost"}, []}
end
test "no commands, one integer --timeout value" do