1## This Source Code Form is subject to the terms of the Mozilla Public
2## License, v. 2.0. If a copy of the MPL was not distributed with this
3## file, You can obtain one at https://mozilla.org/MPL/2.0/.
4##
5## Copyright (c) 2007-2021 VMware, Inc. or its affiliates.  All rights reserved.
6
7defmodule RabbitMQ.CLI.Diagnostics.Commands.ListenersCommand do
8  @moduledoc """
9  Displays all listeners on a node.
10
11  Returns a code of 0 unless there were connectivity and authentication
12  errors. This command is not meant to be used in health checks.
13  """
14
15  import RabbitMQ.CLI.Core.Listeners,
16    only: [listeners_on: 2, listener_lines: 1, listener_maps: 1, listener_rows: 1]
17
18  import RabbitMQ.CLI.Core.Platform, only: [line_separator: 0]
19
20  @behaviour RabbitMQ.CLI.CommandBehaviour
21
22  use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout
23  use RabbitMQ.CLI.Core.MergesNoDefaults
24  use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments
25  use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
26
27  def run([], %{node: node_name, timeout: timeout}) do
28    # Example listener list:
29    #
30    # [{listener,rabbit@warp10,clustering,"localhost",
31    #           {0,0,0,0,0,0,0,0},
32    #           25672,[]},
33    # {listener,rabbit@warp10,amqp,"localhost",
34    #           {0,0,0,0,0,0,0,0},
35    #           5672,
36    #           [{backlog,128},
37    #            {nodelay,true},
38    #            {linger,{true,0}},
39    #            {exit_on_close,false}]},
40    # {listener,rabbit@warp10,stomp,"localhost",
41    #           {0,0,0,0,0,0,0,0},
42    #           61613,
43    #           [{backlog,128},{nodelay,true}]}]
44    case :rabbit_misc.rpc_call(node_name, :rabbit_networking, :active_listeners, [], timeout) do
45      {:error, _} = err -> err
46      {:error, _, _} = err -> err
47      xs when is_list(xs) -> listeners_on(xs, node_name)
48      other -> other
49    end
50  end
51
52  def output([], %{formatter: fmt}) when fmt == "csv" or fmt == "erlang" do
53    {:ok, []}
54  end
55
56  def output([], %{node: node_name, formatter: "json"}) do
57    {:ok, %{"result" => "ok", "node" => node_name, "listeners" => []}}
58  end
59
60  def output([], %{node: node_name}) do
61    {:ok, "Node #{node_name} reported no enabled listeners."}
62  end
63
64  def output(listeners, %{formatter: "erlang"}) do
65    {:ok, listener_rows(listeners)}
66  end
67
68  def output(listeners, %{node: node_name, formatter: "json"}) do
69    {:ok, %{"result" => "ok", "node" => node_name, "listeners" => listener_maps(listeners)}}
70  end
71
72  def output(listeners, %{formatter: "csv"}) do
73    {:stream, [listener_rows(listeners)]}
74  end
75
76  def output(listeners, _opts) do
77    lines = listener_lines(listeners)
78
79    {:ok, Enum.join(lines, line_separator())}
80  end
81
82  def help_section(), do: :observability_and_health_checks
83
84  def description(),
85    do: "Lists active connection listeners (bound interface, port, protocol) on the target node"
86
87  def usage, do: "listeners"
88
89  def banner([], %{node: node_name}) do
90    "Asking node #{node_name} to report its protocol listeners ..."
91  end
92end
93