1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
## 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-2022 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()
@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
|