Merge pull request #6864 from rabbitmq/rabbitmq-server-6853
diagnostics check_port_connectivity: support --address
This commit is contained in:
commit
9b0d2d3e60
|
@ -14,7 +14,7 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
"""
|
||||
|
||||
import RabbitMQ.CLI.Diagnostics.Helpers,
|
||||
only: [check_listener_connectivity: 3]
|
||||
only: [check_listener_connectivity: 4]
|
||||
|
||||
import RabbitMQ.CLI.Core.Platform, only: [line_separator: 0]
|
||||
import RabbitMQ.CLI.Core.Listeners
|
||||
|
@ -23,7 +23,8 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
|
||||
@default_timeout 30_000
|
||||
|
||||
use RabbitMQ.CLI.Core.AcceptsDefaultSwitchesAndTimeout
|
||||
def switches(), do: [timeout: :integer, address: :string]
|
||||
def aliases(), do: [t: :timeout, a: :address]
|
||||
|
||||
def merge_defaults(args, opts) do
|
||||
timeout =
|
||||
|
@ -33,13 +34,14 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
other -> other
|
||||
end
|
||||
|
||||
{args, Map.merge(opts, %{timeout: timeout})}
|
||||
opts1 = Map.merge(%{address: nil}, opts)
|
||||
{args, Map.merge(opts1, %{timeout: timeout})}
|
||||
end
|
||||
|
||||
use RabbitMQ.CLI.Core.AcceptsNoPositionalArguments
|
||||
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
|
||||
|
||||
def run([], %{node: node_name, timeout: timeout}) do
|
||||
def run([], %{node: node_name, address: target_ip, timeout: timeout}) do
|
||||
case :rabbit_misc.rpc_call(node_name, :rabbit_networking, :active_listeners, [], timeout) do
|
||||
{:error, _} = err ->
|
||||
err
|
||||
|
@ -52,7 +54,7 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
|
||||
case locals do
|
||||
[] -> {true, locals}
|
||||
_ -> check_connectivity_of(locals, node_name, timeout)
|
||||
_ -> check_connectivity_of(locals, node_name, target_ip, timeout)
|
||||
end
|
||||
|
||||
other ->
|
||||
|
@ -64,7 +66,7 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
{:ok, %{"result" => "ok", "node" => node_name, "listeners" => listener_maps(listeners)}}
|
||||
end
|
||||
|
||||
def output({true, listeners}, %{node: node_name}) do
|
||||
def output({true, listeners}, %{node: node_name, address: nil}) do
|
||||
ports =
|
||||
listeners
|
||||
|> listener_maps
|
||||
|
@ -72,7 +74,20 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
|> Enum.sort()
|
||||
|> Enum.join(", ")
|
||||
|
||||
{:ok, "Successfully connected to ports #{ports} on node #{node_name}."}
|
||||
{:ok,
|
||||
"Successfully connected to ports #{ports} on node #{node_name} (using node hostname resolution)"}
|
||||
end
|
||||
|
||||
def output({true, listeners}, %{node: node_name, address: target_ip}) do
|
||||
ports =
|
||||
listeners
|
||||
|> listener_maps
|
||||
|> Enum.map(fn %{port: p} -> p end)
|
||||
|> Enum.sort()
|
||||
|> Enum.join(", ")
|
||||
|
||||
{:ok,
|
||||
"Successfully connected to ports #{ports} on node #{node_name} (using #{target_ip} for target IP address)"}
|
||||
end
|
||||
|
||||
def output({false, failures}, %{formatter: "json", node: node_name}) do
|
||||
|
@ -93,24 +108,28 @@ defmodule RabbitMQ.CLI.Diagnostics.Commands.CheckPortConnectivityCommand do
|
|||
|
||||
def help_section(), do: :observability_and_health_checks
|
||||
|
||||
def usage, do: "check_port_connectivity"
|
||||
def usage, do: "check_port_connectivity [--address <target address>]"
|
||||
|
||||
def banner([], %{node: node_name}) do
|
||||
"Testing TCP connections to all active listeners on node #{node_name} ..."
|
||||
def banner([], %{node: node_name, address: nil}) do
|
||||
"Testing TCP connections to all active listeners on node #{node_name} using hostname resolution ..."
|
||||
end
|
||||
|
||||
def banner([], %{node: node_name, address: target_ip}) do
|
||||
"Testing TCP connections to all active listeners on node #{node_name} using #{target_ip} for node IP address ..."
|
||||
end
|
||||
|
||||
#
|
||||
# Implementation
|
||||
#
|
||||
|
||||
defp check_connectivity_of(listeners, node_name, timeout) do
|
||||
defp check_connectivity_of(listeners, node_name, address, timeout) do
|
||||
# per listener timeout
|
||||
t = Kernel.trunc(timeout / (length(listeners) + 1))
|
||||
|
||||
failures =
|
||||
Enum.reject(
|
||||
listeners,
|
||||
fn l -> check_listener_connectivity(listener_map(l), node_name, t) end
|
||||
fn l -> check_listener_connectivity(listener_map(l), node_name, address, t) end
|
||||
)
|
||||
|
||||
case failures do
|
||||
|
|
|
@ -5,20 +5,33 @@
|
|||
## Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
|
||||
|
||||
defmodule RabbitMQ.CLI.Diagnostics.Helpers do
|
||||
def test_connection(hostname, port, timeout) do
|
||||
case :gen_tcp.connect(hostname, port, [], timeout) do
|
||||
{:error, _} -> :gen_tcp.connect(hostname, port, [:inet6], timeout)
|
||||
def test_connection(hostname_or_ip, port, timeout) do
|
||||
hostname_as_list = :rabbit_data_coercion.to_list(hostname_or_ip)
|
||||
|
||||
case :gen_tcp.connect(hostname_as_list, port, [], timeout) do
|
||||
{:error, _} -> :gen_tcp.connect(hostname_as_list, port, [:inet6], timeout)
|
||||
r -> r
|
||||
end
|
||||
end
|
||||
|
||||
def check_port_connectivity(port, node_name, timeout) do
|
||||
check_port_connectivity(port, node_name, nil, timeout)
|
||||
end
|
||||
|
||||
def check_port_connectivity(port, node_name, nil, timeout) do
|
||||
regex = Regex.recompile!(~r/^(.+)@/)
|
||||
hostname = Regex.replace(regex, to_string(node_name), "") |> to_charlist
|
||||
|
||||
check_port_connectivity(port, node_name, hostname, timeout)
|
||||
end
|
||||
|
||||
def check_port_connectivity(port, node_name, hostname_or_ip, timeout) do
|
||||
try do
|
||||
case test_connection(hostname, port, timeout) do
|
||||
{:error, _} ->
|
||||
IO.puts("Will connect to #{hostname_or_ip}:#{port}")
|
||||
|
||||
case test_connection(hostname_or_ip, port, timeout) do
|
||||
{:error, err} ->
|
||||
IO.puts("Error connecting to #{hostname_or_ip}:#{port}: #{err}")
|
||||
false
|
||||
|
||||
{:ok, port} ->
|
||||
|
@ -33,7 +46,7 @@ defmodule RabbitMQ.CLI.Diagnostics.Helpers do
|
|||
end
|
||||
end
|
||||
|
||||
def check_listener_connectivity(%{port: port}, node_name, timeout) do
|
||||
check_port_connectivity(port, node_name, timeout)
|
||||
def check_listener_connectivity(%{port: port}, node_name, target_ip, timeout) do
|
||||
check_port_connectivity(port, node_name, target_ip, timeout)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,12 +20,13 @@ defmodule CheckPortConnectivityCommandTest do
|
|||
{:ok,
|
||||
opts: %{
|
||||
node: get_rabbit_hostname(),
|
||||
address: nil,
|
||||
timeout: context[:test_timeout] || 30000
|
||||
}}
|
||||
end
|
||||
|
||||
test "merge_defaults: provides a default timeout" do
|
||||
assert @command.merge_defaults([], %{}) == {[], %{timeout: 30000}}
|
||||
assert @command.merge_defaults([], %{}) == {[], %{address: nil, timeout: 30000}}
|
||||
end
|
||||
|
||||
test "validate: treats positional arguments as a failure" do
|
||||
|
@ -40,11 +41,12 @@ defmodule CheckPortConnectivityCommandTest do
|
|||
test "run: targeting an unreachable node throws a badrpc", context do
|
||||
assert match?(
|
||||
{:badrpc, _},
|
||||
@command.run([], Map.merge(context[:opts], %{node: :jake@thedog}))
|
||||
@command.run([], Map.merge(context[:opts], %{node: :jake@thedog, address: nil}))
|
||||
)
|
||||
end
|
||||
|
||||
test "run: tries to connect to every inferred active listener", context do
|
||||
test "run: without --address tries to connect to every inferred active listener using hostname resolution",
|
||||
context do
|
||||
assert match?({true, _}, @command.run([], context[:opts]))
|
||||
end
|
||||
|
||||
|
@ -53,7 +55,7 @@ defmodule CheckPortConnectivityCommandTest do
|
|||
end
|
||||
|
||||
# note: it's run/2 that filters out non-local alarms
|
||||
test "output: when target node has a local alarm in effect, returns a failure", context do
|
||||
test "output: when check failed to connect to a port, returns a failure", context do
|
||||
failure =
|
||||
{:listener, :rabbit@mercurio, :lolz, 'mercurio', {0, 0, 0, 0, 0, 0, 0, 0}, 7_761_613,
|
||||
[backlog: 128, nodelay: true]}
|
||||
|
|
Loading…
Reference in New Issue