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 DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
TEST_FILE ?= ""
include rabbitmq-components.mk include rabbitmq-components.mk
include erlang.mk include erlang.mk
@ -32,5 +34,11 @@ rel::
tests:: all tests:: all
mix test --trace mix test --trace
test:: all
mix test --trace $(TEST_FILE)
clean:: clean::
mix clean mix clean
repl:
iex -S mix

View File

@ -34,7 +34,7 @@ use Mix.Config
# #
# Or configure a 3rd-party app: # 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 # 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 def get_option(name, opts) do
raw_option = opts[name] || raw_option = opts[name] ||
get_system_option(name) || get_system_option(name) ||
default(name, opts) default(name)
normalize(name, raw_option) normalize(name, raw_option)
end end
@ -28,6 +28,11 @@ defmodule RabbitMQ.CLI.Config do
def normalize(:longnames, _), do: :shortnames def normalize(:longnames, _), do: :shortnames
def normalize(_, value), do: value 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 def get_system_option(name) do
system_env_option = case name do system_env_option = case name do
:longnames -> "RABBITMQ_USE_LONGNAME"; :longnames -> "RABBITMQ_USE_LONGNAME";
@ -40,5 +45,6 @@ defmodule RabbitMQ.CLI.Config do
System.get_env(system_env_option) System.get_env(system_env_option)
end end
def default(_, _), do: nil def default(:script_name), do: :rabbitmqctl
def default(_), do: nil
end end

View File

@ -17,6 +17,7 @@
defmodule AutoComplete do defmodule AutoComplete do
alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers alias RabbitMQ.CLI.Ctl.Helpers, as: Helpers
alias RabbitMQ.CLI.Ctl.Parser, as: Parser alias RabbitMQ.CLI.Ctl.Parser, as: Parser
alias RabbitMQ.CLI.Ctl.CommandModules, as: CommandModules
@spec complete(String.t) :: {:ok, [String.t]} @spec complete(String.t) :: {:ok, [String.t]}
def complete(str) do def complete(str) do
@ -24,7 +25,8 @@ defmodule AutoComplete do
case List.last(tokens) do case List.last(tokens) do
nil -> []; nil -> [];
last_token -> last_token ->
{args, _, _} = Parser.parse(tokens) {args, opts, _} = Parser.parse(tokens)
CommandModules.load(opts)
variants = case args do variants = case args do
[] -> complete_default_opts(last_token); [] -> complete_default_opts(last_token);
[cmd|_] -> complete_command_opts(cmd, 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. ## The Initial Developer of the Original Code is GoPivotal, Inc.
## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. ## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
alias RabbitMQ.CLI.Config, as: Config
defmodule RabbitMQ.CLI.Ctl.CommandModules do defmodule RabbitMQ.CLI.Ctl.CommandModules do
@commands_ns ~r/RabbitMQ.CLI.(.*).Commands/ @commands_ns ~r/RabbitMQ.CLI.(.*).Commands/
def module_map do def module_map do
case Application.get_env(:rabbitmqctl, :commands) do Application.get_env(:rabbitmqctl, :commands) || load(%{})
nil -> load;
val -> val
end
end end
def load do def load(opts) do
scope = script_scope scope = script_scope(opts)
commands = load_commands(scope) commands = load_commands(scope)
Application.put_env(:rabbitmqctl, :commands, commands) Application.put_env(:rabbitmqctl, :commands, commands)
commands commands
end end
def script_scope do def script_scope(opts) do
scopes = Application.get_env(:rabbitmqctl, :scopes, []) scopes = Application.get_env(:rabbitmqctl, :scopes, [])
scopes[script_name] || :none scopes[Config.get_option(:script_name, opts)] || :none
end
def script_name do
Path.basename(:escript.script_name())
|> Path.rootname
|> String.to_atom
end end
def load_commands(scope) do 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, # Output: A 2-tuple of lists: one containing the command,
# one containing flagged options. # one containing flagged options.
def parse(command) do def parse(command) do
switches = build_switches(default_switches())
{options, cmd, invalid} = OptionParser.parse( {options, cmd, invalid} = OptionParser.parse(
command, command,
strict: build_switches(default_switches()), strict: switches,
aliases: build_aliases([p: :vhost, n: :node, q: :quiet, aliases: build_aliases([p: :vhost, n: :node, q: :quiet,
t: :timeout, l: :longnames]) 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 end
def default_switches() do def default_switches() do
@ -37,7 +39,8 @@ defmodule RabbitMQ.CLI.Ctl.Parser do
longnames: :boolean, longnames: :boolean,
formatter: :string, formatter: :string,
printer: :string, printer: :string,
file: :string] file: :string,
script_name: :atom]
end end
defp build_switches(default) do defp build_switches(default) do
@ -78,9 +81,18 @@ defmodule RabbitMQ.CLI.Ctl.Parser do
end) end)
end end
defp options_map(opts) do defp normalize_options(options, switches) do
opts Enum.map(options,
|> Map.new 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
# Discards entire command if first command term is empty. # 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 @behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput 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 def merge_defaults(args, opts) do
{args, Map.merge(%{online: true, offline: false}, opts)} {args, Map.merge(%{online: false, offline: false}, opts)}
end end
def switches(), do: [online: :boolean, def switches(), do: [online: :boolean,

View File

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

View File

@ -22,11 +22,9 @@ defmodule RabbitMQ.CLI.Plugins.Commands.SetCommand do
@behaviour RabbitMQ.CLI.CommandBehaviour @behaviour RabbitMQ.CLI.CommandBehaviour
use RabbitMQ.CLI.DefaultOutput 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 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 end
def switches(), do: [online: :boolean, def switches(), do: [online: :boolean,
@ -66,8 +64,9 @@ defmodule RabbitMQ.CLI.Plugins.Commands.SetCommand do
%{online: online, offline: offline} = opts %{online: online, offline: offline} = opts
mode = case {online, offline} do mode = case {online, offline} do
{true, false} -> :online; {true, false} -> :online;
{false, true} -> :offline {false, true} -> :offline;
{false, false} -> :online
end end
PluginHelpers.set_enabled_plugins(plugins, mode, node_name, opts) 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.Ctl.Commands.HelpCommand, as: HelpCommand
alias RabbitMQ.CLI.Output, as: Output alias RabbitMQ.CLI.Output, as: Output
alias RabbitMQ.CLI.ExitCodes, as: ExitCodes alias RabbitMQ.CLI.ExitCodes, as: ExitCodes
alias RabbitMQ.CLI.Ctl.CommandModules, as: CommandModules
import RabbitMQ.CLI.Ctl.Helpers import RabbitMQ.CLI.Ctl.Helpers
import RabbitMQ.CLI.Ctl.Parser import RabbitMQ.CLI.Ctl.Parser
@ -32,6 +33,8 @@ defmodule RabbitMQCtl do
end end
def main(unparsed_command) do def main(unparsed_command) do
{parsed_cmd, parsed_options, invalid} = parse(unparsed_command) {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 case {is_command?(parsed_cmd), invalid} do
## No such command ## No such command
{false, _} -> {false, _} ->
@ -42,7 +45,6 @@ defmodule RabbitMQCtl do
error = validation_error({:bad_option, invalid}, unparsed_command); error = validation_error({:bad_option, invalid}, unparsed_command);
## Command valid ## Command valid
{true, []} -> {true, []} ->
options = parsed_options |> merge_all_defaults |> normalize_node
Distribution.start(options) Distribution.start(options)
[command_name | arguments] = parsed_cmd [command_name | arguments] = parsed_cmd

View File

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

View File

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