Skip to content

Commit 98ba31a

Browse files
Merge pull request #13871 from rabbitmq/md/health-check-multi-protocol-listener
Allow multiple protocols in protocol listener health check
2 parents d27d5c4 + 5d319be commit 98ba31a

File tree

4 files changed

+35
-20
lines changed

4 files changed

+35
-20
lines changed

deps/rabbitmq_management/priv/www/api/index.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,10 +1202,12 @@ <h2>Reference</h2>
12021202
<td></td>
12031203
<td></td>
12041204
<td></td>
1205-
<td class="path">/api/health/checks/protocol-listener/<i>protocol</i></td>
1205+
<td class="path">/api/health/checks/protocol-listener/<i>protocols</i></td>
12061206
<td>
1207-
Responds a 200 OK if there is an active listener for the given protocol,
1208-
otherwise responds with a 503 Service Unavailable. Valid protocol names are: amqp091, amqp10, mqtt, stomp, web-mqtt, web-stomp.
1207+
Responds a 200 OK if all given protocols have active listeners,
1208+
otherwise responds with a 503 Service Unavailable. Multiple protocols
1209+
may be provided by separating the names with commas. Valid protocol
1210+
names are: amqp091, amqp10, mqtt, stomp, web-mqtt, web-stomp.
12091211
</td>
12101212
</tr>
12111213
<tr>

deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ dispatcher() ->
200200
{"/health/checks/metadata-store/initialized/with-data", rabbit_mgmt_wm_health_check_metadata_store_initialized_with_data, []},
201201
{"/health/checks/certificate-expiration/:within/:unit", rabbit_mgmt_wm_health_check_certificate_expiration, []},
202202
{"/health/checks/port-listener/:port", rabbit_mgmt_wm_health_check_port_listener, []},
203-
{"/health/checks/protocol-listener/:protocol", rabbit_mgmt_wm_health_check_protocol_listener, []},
203+
{"/health/checks/protocol-listener/:protocols", rabbit_mgmt_wm_health_check_protocol_listener, []},
204204
{"/health/checks/virtual-hosts", rabbit_mgmt_wm_health_check_virtual_hosts, []},
205205
{"/health/checks/quorum-queues-without-elected-leaders/all-vhosts/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders_across_all_vhosts, []},
206206
{"/health/checks/quorum-queues-without-elected-leaders/vhost/:vhost/", rabbit_mgmt_wm_health_check_quorum_queues_without_elected_leaders, []},

deps/rabbitmq_management/src/rabbit_mgmt_wm_health_check_protocol_listener.erl

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,41 +27,46 @@ content_types_provided(ReqData, Context) ->
2727
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
2828

2929
resource_exists(ReqData, Context) ->
30-
{case protocol(ReqData) of
30+
{case protocols(ReqData) of
3131
none -> false;
3232
_ -> true
3333
end, ReqData, Context}.
3434

3535
to_json(ReqData, Context) ->
36-
Protocol = normalize_protocol(protocol(ReqData)),
37-
Listeners = rabbit_networking:active_listeners(),
38-
Local = [L || #listener{node = N} = L <- Listeners, N == node()],
39-
ProtoListeners = [L || #listener{protocol = P} = L <- Local, atom_to_list(P) == Protocol],
40-
case ProtoListeners of
36+
Protocols = string:split(protocols(ReqData), ",", all),
37+
RequestedProtocols = sets:from_list(
38+
[normalize_protocol(P) || P <- Protocols],
39+
[{version, 2}]),
40+
Listeners = rabbit_networking:node_listeners(node()),
41+
ActiveProtocols = sets:from_list(
42+
[atom_to_list(P) || #listener{protocol = P} <- Listeners],
43+
[{version, 2}]),
44+
MissingProtocols = sets:to_list(sets:subtract(RequestedProtocols, ActiveProtocols)),
45+
case MissingProtocols of
4146
[] ->
42-
Msg = <<"No active listener">>,
43-
failure(Msg, Protocol, [P || #listener{protocol = P} <- Local], ReqData, Context);
47+
Body = #{status => ok,
48+
protocols => [list_to_binary(P) || P <- sets:to_list(ActiveProtocols)]},
49+
rabbit_mgmt_util:reply(Body, ReqData, Context);
4450
_ ->
45-
Body = #{status => ok,
46-
protocol => list_to_binary(Protocol)},
47-
rabbit_mgmt_util:reply(Body, ReqData, Context)
51+
Msg = <<"No active listener">>,
52+
failure(Msg, MissingProtocols, sets:to_list(ActiveProtocols), ReqData, Context)
4853
end.
4954

5055
failure(Message, Missing, Protocols, ReqData, Context) ->
5156
Body = #{
5257
status => failed,
5358
reason => Message,
54-
missing => list_to_binary(Missing),
55-
protocols => Protocols
59+
missing => [list_to_binary(P) || P <- Missing],
60+
protocols => [list_to_binary(P) || P <- Protocols]
5661
},
5762
{Response, ReqData1, Context1} = rabbit_mgmt_util:reply(Body, ReqData, Context),
5863
{stop, cowboy_req:reply(503, #{}, Response, ReqData1), Context1}.
5964

6065
is_authorized(ReqData, Context) ->
6166
rabbit_mgmt_util:is_authorized(ReqData, Context).
6267

63-
protocol(ReqData) ->
64-
rabbit_mgmt_util:id(protocol, ReqData).
68+
protocols(ReqData) ->
69+
rabbit_mgmt_util:id(protocols, ReqData).
6570

6671
normalize_protocol(Protocol) ->
6772
case string:lowercase(binary_to_list(Protocol)) of

deps/rabbitmq_management/test/rabbit_mgmt_http_health_checks_SUITE.erl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ protocol_listener_test(Config) ->
384384
Body0 = http_get_failed(Config, "/health/checks/protocol-listener/mqtt"),
385385
?assertEqual(<<"failed">>, maps:get(<<"status">>, Body0)),
386386
?assertEqual(true, maps:is_key(<<"reason">>, Body0)),
387-
?assertEqual(<<"mqtt">>, maps:get(<<"missing">>, Body0)),
387+
?assertEqual([<<"mqtt">>], maps:get(<<"missing">>, Body0)),
388388
?assert(lists:member(<<"http">>, maps:get(<<"protocols">>, Body0))),
389389
?assert(lists:member(<<"clustering">>, maps:get(<<"protocols">>, Body0))),
390390
?assert(lists:member(<<"amqp">>, maps:get(<<"protocols">>, Body0))),
@@ -394,6 +394,14 @@ protocol_listener_test(Config) ->
394394
http_get_failed(Config, "/health/checks/protocol-listener/stomp"),
395395
http_get_failed(Config, "/health/checks/protocol-listener/stomp1.0"),
396396

397+
%% Multiple protocols may be supplied. The health check only returns OK if
398+
%% all requested protocols are available.
399+
Body1 = http_get_failed(Config, "/health/checks/protocol-listener/amqp,mqtt"),
400+
?assertEqual(<<"failed">>, maps:get(<<"status">>, Body1)),
401+
?assertEqual(true, maps:is_key(<<"reason">>, Body1)),
402+
?assert(lists:member(<<"mqtt">>, maps:get(<<"missing">>, Body1))),
403+
?assert(lists:member(<<"amqp">>, maps:get(<<"protocols">>, Body1))),
404+
397405
passed.
398406

399407
port_listener_test(Config) ->

0 commit comments

Comments
 (0)