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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
## 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 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 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
|