summaryrefslogtreecommitdiff
path: root/deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex
diff options
context:
space:
mode:
Diffstat (limited to 'deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex')
-rw-r--r--deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex90
1 files changed, 90 insertions, 0 deletions
diff --git a/deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex b/deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex
new file mode 100644
index 0000000000..10c81c971e
--- /dev/null
+++ b/deps/rabbitmq_cli/lib/rabbitmq/cli/diagnostics/commands/check_protocol_listener_command.ex
@@ -0,0 +1,90 @@
+## 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-2020 VMware, Inc. or its affiliates. All rights reserved.
+
+defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckProtocolListenerCommand do
+ @moduledoc """
+ Exits with a non-zero code if there is no active listener
+ for the given protocol on the target node.
+
+ This command is meant to be used in health checks.
+ """
+
+ import RabbitMQ.CLI.Core.Listeners,
+ only: [listeners_on: 2, listener_maps: 1, normalize_protocol: 1]
+
+ @behaviour RabbitMQ.CLI.CommandBehaviour
+
+ use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout
+ use RabbitMQ.CLI.Core.MergesNoDefaults
+ use RabbitMQ.CLI.Core.AcceptsOnePositionalArgument
+ use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
+
+ def run([proto], %{node: node_name, timeout: timeout}) do
+ proto = normalize_protocol(proto)
+
+ case :rabbit_misc.rpc_call(node_name, :rabbit_networking, :active_listeners, [], timeout) do
+ {:error, _} = err ->
+ err
+
+ {:error, _, _} = err ->
+ err
+
+ xs when is_list(xs) ->
+ locals = listeners_on(xs, node_name) |> listener_maps
+
+ found =
+ Enum.any?(locals, fn %{protocol: p} ->
+ to_string(proto) == to_string(p)
+ end)
+
+ case found do
+ true -> {true, proto}
+ false -> {false, proto, locals}
+ end
+
+ other ->
+ other
+ end
+ end
+
+ def output({true, proto}, %{node: node_name, formatter: "json"}) do
+ {:ok, %{"result" => "ok", "node" => node_name, "protocol" => proto}}
+ end
+
+ def output({true, proto}, %{node: node_name}) do
+ {:ok, "A listener for protocol #{proto} is running on node #{node_name}."}
+ end
+
+ def output({false, proto, listeners}, %{formatter: "json"}) do
+ protocols = Enum.map(listeners, fn %{protocol: p} -> p end)
+
+ {:error,
+ %{
+ "result" => "error",
+ "missing" => proto,
+ "protocols" => protocols,
+ "listeners" => listeners
+ }}
+ end
+
+ def output({false, proto, listeners}, %{node: node_name}) do
+ protocols = Enum.map(listeners, fn %{protocol: p} -> p end) |> Enum.sort() |> Enum.join(", ")
+
+ {:error,
+ "No listener for protocol #{proto} is active on node #{node_name}. " <>
+ "Found listeners for the following protocols: #{protocols}"}
+ end
+
+ def help_section(), do: :observability_and_health_checks
+
+ def description(), do: "Health check that exits with a non-zero code if target node does not have an active listener for given protocol"
+
+ def usage, do: "check_protocol_listener <protocol>"
+
+ def banner([proto], %{node: node_name}) do
+ "Asking node #{node_name} if there's an active listener for protocol #{proto} ..."
+ end
+end