Merge pull request #13871 from rabbitmq/md/health-check-multi-protocol-listener
Allow multiple protocols in protocol listener health check
This commit is contained in:
commit
98ba31a381
|
@ -1202,10 +1202,12 @@ or:
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td class="path">/api/health/checks/protocol-listener/<i>protocol</i></td>
|
<td class="path">/api/health/checks/protocol-listener/<i>protocols</i></td>
|
||||||
<td>
|
<td>
|
||||||
Responds a 200 OK if there is an active listener for the given protocol,
|
Responds a 200 OK if all given protocols have active listeners,
|
||||||
otherwise responds with a 503 Service Unavailable. Valid protocol names are: amqp091, amqp10, mqtt, stomp, web-mqtt, web-stomp.
|
otherwise responds with a 503 Service Unavailable. Multiple protocols
|
||||||
|
may be provided by separating the names with commas. Valid protocol
|
||||||
|
names are: amqp091, amqp10, mqtt, stomp, web-mqtt, web-stomp.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -200,7 +200,7 @@ dispatcher() ->
|
||||||
{"/health/checks/metadata-store/initialized/with-data", rabbit_mgmt_wm_health_check_metadata_store_initialized_with_data, []},
|
{"/health/checks/metadata-store/initialized/with-data", rabbit_mgmt_wm_health_check_metadata_store_initialized_with_data, []},
|
||||||
{"/health/checks/certificate-expiration/:within/:unit", rabbit_mgmt_wm_health_check_certificate_expiration, []},
|
{"/health/checks/certificate-expiration/:within/:unit", rabbit_mgmt_wm_health_check_certificate_expiration, []},
|
||||||
{"/health/checks/port-listener/:port", rabbit_mgmt_wm_health_check_port_listener, []},
|
{"/health/checks/port-listener/:port", rabbit_mgmt_wm_health_check_port_listener, []},
|
||||||
{"/health/checks/protocol-listener/:protocol", rabbit_mgmt_wm_health_check_protocol_listener, []},
|
{"/health/checks/protocol-listener/:protocols", rabbit_mgmt_wm_health_check_protocol_listener, []},
|
||||||
{"/health/checks/virtual-hosts", rabbit_mgmt_wm_health_check_virtual_hosts, []},
|
{"/health/checks/virtual-hosts", rabbit_mgmt_wm_health_check_virtual_hosts, []},
|
||||||
{"/health/checks/quorum-queues-without-elected-leaders/all-vhosts/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders_across_all_vhosts, []},
|
{"/health/checks/quorum-queues-without-elected-leaders/all-vhosts/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders_across_all_vhosts, []},
|
||||||
{"/health/checks/quorum-queues-without-elected-leaders/vhost/:vhost/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders, []},
|
{"/health/checks/quorum-queues-without-elected-leaders/vhost/:vhost/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders, []},
|
||||||
|
|
|
@ -27,32 +27,37 @@ content_types_provided(ReqData, Context) ->
|
||||||
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
|
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
|
||||||
|
|
||||||
resource_exists(ReqData, Context) ->
|
resource_exists(ReqData, Context) ->
|
||||||
{case protocol(ReqData) of
|
{case protocols(ReqData) of
|
||||||
none -> false;
|
none -> false;
|
||||||
_ -> true
|
_ -> true
|
||||||
end, ReqData, Context}.
|
end, ReqData, Context}.
|
||||||
|
|
||||||
to_json(ReqData, Context) ->
|
to_json(ReqData, Context) ->
|
||||||
Protocol = normalize_protocol(protocol(ReqData)),
|
Protocols = string:split(protocols(ReqData), ",", all),
|
||||||
Listeners = rabbit_networking:active_listeners(),
|
RequestedProtocols = sets:from_list(
|
||||||
Local = [L || #listener{node = N} = L <- Listeners, N == node()],
|
[normalize_protocol(P) || P <- Protocols],
|
||||||
ProtoListeners = [L || #listener{protocol = P} = L <- Local, atom_to_list(P) == Protocol],
|
[{version, 2}]),
|
||||||
case ProtoListeners of
|
Listeners = rabbit_networking:node_listeners(node()),
|
||||||
|
ActiveProtocols = sets:from_list(
|
||||||
|
[atom_to_list(P) || #listener{protocol = P} <- Listeners],
|
||||||
|
[{version, 2}]),
|
||||||
|
MissingProtocols = sets:to_list(sets:subtract(RequestedProtocols, ActiveProtocols)),
|
||||||
|
case MissingProtocols of
|
||||||
[] ->
|
[] ->
|
||||||
Msg = <<"No active listener">>,
|
Body = #{status => ok,
|
||||||
failure(Msg, Protocol, [P || #listener{protocol = P} <- Local], ReqData, Context);
|
protocols => [list_to_binary(P) || P <- sets:to_list(ActiveProtocols)]},
|
||||||
|
rabbit_mgmt_util:reply(Body, ReqData, Context);
|
||||||
_ ->
|
_ ->
|
||||||
Body = #{status => ok,
|
Msg = <<"No active listener">>,
|
||||||
protocol => list_to_binary(Protocol)},
|
failure(Msg, MissingProtocols, sets:to_list(ActiveProtocols), ReqData, Context)
|
||||||
rabbit_mgmt_util:reply(Body, ReqData, Context)
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
failure(Message, Missing, Protocols, ReqData, Context) ->
|
failure(Message, Missing, Protocols, ReqData, Context) ->
|
||||||
Body = #{
|
Body = #{
|
||||||
status => failed,
|
status => failed,
|
||||||
reason => Message,
|
reason => Message,
|
||||||
missing => list_to_binary(Missing),
|
missing => [list_to_binary(P) || P <- Missing],
|
||||||
protocols => Protocols
|
protocols => [list_to_binary(P) || P <- Protocols]
|
||||||
},
|
},
|
||||||
{Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData, Context),
|
{Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData, Context),
|
||||||
{stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}.
|
{stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}.
|
||||||
|
@ -60,8 +65,8 @@ failure(Message, Missing, Protocols, ReqData, Context) ->
|
||||||
is_authorized(ReqData, Context) ->
|
is_authorized(ReqData, Context) ->
|
||||||
rabbit_mgmt_util:is_authorized(ReqData, Context).
|
rabbit_mgmt_util:is_authorized(ReqData, Context).
|
||||||
|
|
||||||
protocol(ReqData) ->
|
protocols(ReqData) ->
|
||||||
rabbit_mgmt_util:id(protocol, ReqData).
|
rabbit_mgmt_util:id(protocols, ReqData).
|
||||||
|
|
||||||
normalize_protocol(Protocol) ->
|
normalize_protocol(Protocol) ->
|
||||||
case string:lowercase(binary_to_list(Protocol)) of
|
case string:lowercase(binary_to_list(Protocol)) of
|
||||||
|
|
|
@ -384,7 +384,7 @@ protocol_listener_test(Config) ->
|
||||||
Body0 = http_get_failed(Config, "/health/checks/protocol-listener/mqtt"),
|
Body0 = http_get_failed(Config, "/health/checks/protocol-listener/mqtt"),
|
||||||
?assertEqual(<<"failed">>, maps:get(<<"status">>, Body0)),
|
?assertEqual(<<"failed">>, maps:get(<<"status">>, Body0)),
|
||||||
?assertEqual(true, maps:is_key(<<"reason">>, Body0)),
|
?assertEqual(true, maps:is_key(<<"reason">>, Body0)),
|
||||||
?assertEqual(<<"mqtt">>, maps:get(<<"missing">>, Body0)),
|
?assertEqual([<<"mqtt">>], maps:get(<<"missing">>, Body0)),
|
||||||
?assert(lists:member(<<"http">>, maps:get(<<"protocols">>, Body0))),
|
?assert(lists:member(<<"http">>, maps:get(<<"protocols">>, Body0))),
|
||||||
?assert(lists:member(<<"clustering">>, maps:get(<<"protocols">>, Body0))),
|
?assert(lists:member(<<"clustering">>, maps:get(<<"protocols">>, Body0))),
|
||||||
?assert(lists:member(<<"amqp">>, maps:get(<<"protocols">>, Body0))),
|
?assert(lists:member(<<"amqp">>, maps:get(<<"protocols">>, Body0))),
|
||||||
|
@ -394,6 +394,14 @@ protocol_listener_test(Config) ->
|
||||||
http_get_failed(Config, "/health/checks/protocol-listener/stomp"),
|
http_get_failed(Config, "/health/checks/protocol-listener/stomp"),
|
||||||
http_get_failed(Config, "/health/checks/protocol-listener/stomp1.0"),
|
http_get_failed(Config, "/health/checks/protocol-listener/stomp1.0"),
|
||||||
|
|
||||||
|
%% Multiple protocols may be supplied. The health check only returns OK if
|
||||||
|
%% all requested protocols are available.
|
||||||
|
Body1 = http_get_failed(Config, "/health/checks/protocol-listener/amqp,mqtt"),
|
||||||
|
?assertEqual(<<"failed">>, maps:get(<<"status">>, Body1)),
|
||||||
|
?assertEqual(true, maps:is_key(<<"reason">>, Body1)),
|
||||||
|
?assert(lists:member(<<"mqtt">>, maps:get(<<"missing">>, Body1))),
|
||||||
|
?assert(lists:member(<<"amqp">>, maps:get(<<"protocols">>, Body1))),
|
||||||
|
|
||||||
passed.
|
passed.
|
||||||
|
|
||||||
port_listener_test(Config) ->
|
port_listener_test(Config) ->
|
||||||
|
|
Loading…
Reference in New Issue