221 lines
5.7 KiB
Elixir
221 lines
5.7 KiB
Elixir
## This Source Code Form is subject to the terms of the Mozilla Public
|
|
## License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
##
|
|
## Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
|
|
|
|
defmodule RabbitMQ.CLI.CommandBehaviour do
|
|
alias RabbitMQ.CLI.Core.Helpers
|
|
|
|
@type pair_of_strings :: nonempty_list(String.t())
|
|
|
|
@callback usage() :: String.t() | [String.t()]
|
|
# validates CLI arguments
|
|
@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 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()]}
|
|
|
|
@optional_callbacks formatter: 0,
|
|
printer: 0,
|
|
scopes: 0,
|
|
usage_additional: 0,
|
|
usage_doc_guides: 0,
|
|
description: 0,
|
|
help_section: 0,
|
|
switches: 0,
|
|
aliases: 0,
|
|
# validates execution environment, e.g. file presence,
|
|
# whether RabbitMQ is in an expected state on a node, etc
|
|
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 formatter() :: atom()
|
|
@callback printer() :: atom()
|
|
@callback scopes() :: [atom()] | nil
|
|
@callback description() :: String.t()
|
|
@callback help_section() :: String.t() | atom() | {:plugin, atom()}
|
|
@callback usage_additional() ::
|
|
String.t()
|
|
| [String.t()]
|
|
| nonempty_list(pair_of_strings())
|
|
| [{String.t(), String.t()}]
|
|
@callback usage_doc_guides() :: 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()})}
|
|
|
|
defmacro defcmd(map) do
|
|
usage_q =
|
|
case map[:usage] do
|
|
nil ->
|
|
:ok
|
|
|
|
usage ->
|
|
quote do
|
|
def usage(), do: unquote(usage)
|
|
end
|
|
end
|
|
|
|
scopes_q =
|
|
case map[:scopes] do
|
|
nil ->
|
|
:ok
|
|
|
|
scopes ->
|
|
quote do
|
|
def scopes(), do: unquote(scopes)
|
|
end
|
|
end
|
|
|
|
description_q =
|
|
case map[:description] do
|
|
nil ->
|
|
:ok
|
|
|
|
description ->
|
|
quote do
|
|
def description(), do: unquote(description)
|
|
end
|
|
end
|
|
|
|
help_section_q =
|
|
case map[:help_section] do
|
|
nil ->
|
|
:ok
|
|
|
|
help_section ->
|
|
quote do
|
|
def help_section(), do: unquote(help_section)
|
|
end
|
|
end
|
|
|
|
usage_additional_q =
|
|
case map[:usage_additional] do
|
|
nil ->
|
|
:ok
|
|
|
|
usage_additional ->
|
|
quote do
|
|
def usage_additional(), do: unquote(usage_additional)
|
|
end
|
|
end
|
|
|
|
formatter_q =
|
|
case map[:formatter] do
|
|
nil ->
|
|
:ok
|
|
|
|
formatter ->
|
|
quote do
|
|
def formatter(), do: unquote(formatter)
|
|
end
|
|
end
|
|
|
|
switches_q =
|
|
case map[:switches] do
|
|
nil ->
|
|
:ok
|
|
|
|
switches ->
|
|
quote do
|
|
def switches(), do: unquote(switches)
|
|
end
|
|
end
|
|
|
|
aliases_q =
|
|
case map[:aliases] do
|
|
nil ->
|
|
:ok
|
|
|
|
aliases ->
|
|
quote do
|
|
def aliases(), do: unquote(aliases)
|
|
end
|
|
end
|
|
|
|
quote do
|
|
unquote(usage_q)
|
|
unquote(scopes_q)
|
|
unquote(description_q)
|
|
unquote(help_section_q)
|
|
unquote(usage_additional_q)
|
|
unquote(formatter_q)
|
|
unquote(switches_q)
|
|
unquote(aliases_q)
|
|
end
|
|
end
|
|
|
|
def usage(cmd) do
|
|
cmd.usage()
|
|
end
|
|
|
|
def scopes(cmd) do
|
|
Helpers.apply_if_exported(cmd, :scopes, [], nil)
|
|
end
|
|
|
|
def description(cmd) do
|
|
Helpers.apply_if_exported(cmd, :description, [], "")
|
|
end
|
|
|
|
def help_section(cmd) do
|
|
case Helpers.apply_if_exported(cmd, :help_section, [], :other) do
|
|
:other ->
|
|
case Application.get_application(cmd) do
|
|
:rabbitmqctl -> :other
|
|
plugin -> {:plugin, plugin}
|
|
end
|
|
|
|
section ->
|
|
section
|
|
end
|
|
end
|
|
|
|
def usage_additional(cmd) do
|
|
Helpers.apply_if_exported(cmd, :usage_additional, [], [])
|
|
end
|
|
|
|
def usage_doc_guides(cmd) do
|
|
Helpers.apply_if_exported(cmd, :usage_doc_guides, [], [])
|
|
end
|
|
|
|
def formatter(cmd, default) do
|
|
Helpers.apply_if_exported(cmd, :formatter, [], default)
|
|
end
|
|
|
|
def printer(cmd, default) do
|
|
Helpers.apply_if_exported(cmd, :printer, [], default)
|
|
end
|
|
|
|
def switches(cmd) do
|
|
Helpers.apply_if_exported(cmd, :switches, [], [])
|
|
end
|
|
|
|
def aliases(cmd) do
|
|
Helpers.apply_if_exported(cmd, :aliases, [], [])
|
|
end
|
|
|
|
def validate_execution_environment(cmd, args, options) do
|
|
Helpers.apply_if_exported(cmd, :validate_execution_environment, [args, options], :ok)
|
|
end
|
|
|
|
def distribution(cmd, options) do
|
|
Helpers.apply_if_exported(cmd, :distribution, [options], :cli)
|
|
end
|
|
end
|