@@ -37,7 +37,10 @@ groups() ->
3737 local_alarms_test ,
3838 metadata_store_initialized_test ,
3939 metadata_store_initialized_with_data_test ,
40- is_quorum_critical_single_node_test ]}
40+ is_quorum_critical_single_node_test ,
41+ quorum_queues_without_elected_leader_single_node_test ,
42+ quorum_queues_without_elected_leader_across_all_virtual_hosts_single_node_test
43+ ]}
4144 ].
4245
4346all_tests () -> [
@@ -165,7 +168,8 @@ local_alarms_test(Config) ->
165168
166169
167170is_quorum_critical_single_node_test (Config ) ->
168- Check0 = http_get (Config , " /health/checks/node-is-quorum-critical" , ? OK ),
171+ EndpointPath = " /health/checks/node-is-quorum-critical" ,
172+ Check0 = http_get (Config , EndpointPath , ? OK ),
169173 ? assertEqual (<<" single node cluster" >>, maps :get (reason , Check0 )),
170174 ? assertEqual (<<" ok" >>, maps :get (status , Check0 )),
171175
@@ -178,13 +182,14 @@ is_quorum_critical_single_node_test(Config) ->
178182 durable = true ,
179183 auto_delete = false ,
180184 arguments = Args })),
181- Check1 = http_get (Config , " /health/checks/node-is-quorum-critical " , ? OK ),
185+ Check1 = http_get (Config , EndpointPath , ? OK ),
182186 ? assertEqual (<<" single node cluster" >>, maps :get (reason , Check1 )),
183187
184188 passed .
185189
186190is_quorum_critical_test (Config ) ->
187- Check0 = http_get (Config , " /health/checks/node-is-quorum-critical" , ? OK ),
191+ EndpointPath = " /health/checks/node-is-quorum-critical" ,
192+ Check0 = http_get (Config , EndpointPath , ? OK ),
188193 ? assertEqual (false , maps :is_key (reason , Check0 )),
189194 ? assertEqual (<<" ok" >>, maps :get (status , Check0 )),
190195
@@ -198,7 +203,7 @@ is_quorum_critical_test(Config) ->
198203 durable = true ,
199204 auto_delete = false ,
200205 arguments = Args })),
201- Check1 = http_get (Config , " /health/checks/node-is-quorum-critical " , ? OK ),
206+ Check1 = http_get (Config , EndpointPath , ? OK ),
202207 ? assertEqual (false , maps :is_key (reason , Check1 )),
203208
204209 RaName = binary_to_atom (<<" %2F_" , QName /binary >>, utf8 ),
@@ -207,7 +212,104 @@ is_quorum_critical_test(Config) ->
207212 ok = rabbit_ct_broker_helpers :stop_node (Config , Server2 ),
208213 ok = rabbit_ct_broker_helpers :stop_node (Config , Server3 ),
209214
210- Body = http_get_failed (Config , " /health/checks/node-is-quorum-critical" ),
215+ Body = http_get_failed (Config , EndpointPath ),
216+ ? assertEqual (<<" failed" >>, maps :get (<<" status" >>, Body )),
217+ ? assertEqual (true , maps :is_key (<<" reason" >>, Body )),
218+ Queues = maps :get (<<" queues" >>, Body ),
219+ ? assert (lists :any (
220+ fun (Item ) ->
221+ QName =:= maps :get (<<" name" >>, Item )
222+ end , Queues )),
223+
224+ passed .
225+
226+ quorum_queues_without_elected_leader_single_node_test (Config ) ->
227+ EndpointPath = " /health/checks/quorum-queues-without-elected-leaders/all-vhosts/" ,
228+ Check0 = http_get (Config , EndpointPath , ? OK ),
229+ ? assertEqual (false , maps :is_key (reason , Check0 )),
230+ ? assertEqual (<<" ok" >>, maps :get (status , Check0 )),
231+
232+ [Server | _ ] = rabbit_ct_broker_helpers :get_node_configs (Config , nodename ),
233+ Ch = rabbit_ct_client_helpers :open_channel (Config , Server ),
234+ Args = [{<<" x-queue-type" >>, longstr , <<" quorum" >>},
235+ {<<" x-quorum-initial-group-size" >>, long , 3 }],
236+ QName = <<" quorum_queues_without_elected_leader" >>,
237+ ? assertEqual ({'queue.declare_ok' , QName , 0 , 0 },
238+ amqp_channel :call (Ch , # 'queue.declare' {
239+ queue = QName ,
240+ durable = true ,
241+ auto_delete = false ,
242+ arguments = Args
243+ })),
244+
245+ Check1 = http_get (Config , EndpointPath , ? OK ),
246+ ? assertEqual (false , maps :is_key (reason , Check1 )),
247+
248+ RaSystem = quorum_queues ,
249+ QResource = rabbit_misc :r (<<" /" >>, queue , QName ),
250+ {ok , Q1 } = rabbit_ct_broker_helpers :rpc (Config , 0 , rabbit_db_queue , get , [QResource ]),
251+
252+ _ = rabbit_ct_broker_helpers :rpc (Config , 0 , ra , stop_server , [RaSystem , amqqueue :get_pid (Q1 )]),
253+
254+ Body = http_get_failed (Config , EndpointPath ),
255+ ? assertEqual (<<" failed" >>, maps :get (<<" status" >>, Body )),
256+ ? assertEqual (true , maps :is_key (<<" reason" >>, Body )),
257+ Queues = maps :get (<<" queues" >>, Body ),
258+ ? assert (lists :any (
259+ fun (Item ) ->
260+ QName =:= maps :get (<<" name" >>, Item )
261+ end , Queues )),
262+
263+ _ = rabbit_ct_broker_helpers :rpc (Config , 0 , ra , restart_server , [RaSystem , amqqueue :get_pid (Q1 )]),
264+ rabbit_ct_helpers :await_condition (
265+ fun () ->
266+ try
267+ Check2 = http_get (Config , EndpointPath , ? OK ),
268+ false =:= maps :is_key (reason , Check2 )
269+ catch _ :_ ->
270+ false
271+ end
272+ end ),
273+
274+ passed .
275+
276+ quorum_queues_without_elected_leader_across_all_virtual_hosts_single_node_test (Config ) ->
277+ VH2 = <<" vh-2" >>,
278+ rabbit_ct_broker_helpers :add_vhost (Config , VH2 ),
279+
280+ EndpointPath1 = " /health/checks/quorum-queues-without-elected-leaders/vhost/%2f/" ,
281+ EndpointPath2 = " /health/checks/quorum-queues-without-elected-leaders/vhost/vh-2/" ,
282+ % % ^other
283+ EndpointPath3 = " /health/checks/quorum-queues-without-elected-leaders/vhost/vh-2/pattern/%5Eother" ,
284+
285+ Check0 = http_get (Config , EndpointPath1 , ? OK ),
286+ Check0 = http_get (Config , EndpointPath2 , ? OK ),
287+ ? assertEqual (false , maps :is_key (reason , Check0 )),
288+ ? assertEqual (<<" ok" >>, maps :get (status , Check0 )),
289+
290+ [Server | _ ] = rabbit_ct_broker_helpers :get_node_configs (Config , nodename ),
291+ Ch = rabbit_ct_client_helpers :open_channel (Config , Server ),
292+ Args = [{<<" x-queue-type" >>, longstr , <<" quorum" >>},
293+ {<<" x-quorum-initial-group-size" >>, long , 3 }],
294+ QName = <<" quorum_queues_without_elected_leader_across_all_virtual_hosts_single_node_test" >>,
295+ ? assertEqual ({'queue.declare_ok' , QName , 0 , 0 },
296+ amqp_channel :call (Ch , # 'queue.declare' {
297+ queue = QName ,
298+ durable = true ,
299+ auto_delete = false ,
300+ arguments = Args
301+ })),
302+
303+ Check1 = http_get (Config , EndpointPath1 , ? OK ),
304+ ? assertEqual (false , maps :is_key (reason , Check1 )),
305+
306+ RaSystem = quorum_queues ,
307+ QResource = rabbit_misc :r (<<" /" >>, queue , QName ),
308+ {ok , Q1 } = rabbit_ct_broker_helpers :rpc (Config , 0 , rabbit_db_queue , get , [QResource ]),
309+
310+ _ = rabbit_ct_broker_helpers :rpc (Config , 0 , ra , stop_server , [RaSystem , amqqueue :get_pid (Q1 )]),
311+
312+ Body = http_get_failed (Config , EndpointPath1 ),
211313 ? assertEqual (<<" failed" >>, maps :get (<<" status" >>, Body )),
212314 ? assertEqual (true , maps :is_key (<<" reason" >>, Body )),
213315 Queues = maps :get (<<" queues" >>, Body ),
@@ -216,8 +318,30 @@ is_quorum_critical_test(Config) ->
216318 QName =:= maps :get (<<" name" >>, Item )
217319 end , Queues )),
218320
321+ % % virtual host vh-2 is still fine
322+ Check2 = http_get (Config , EndpointPath2 , ? OK ),
323+ ? assertEqual (false , maps :is_key (reason , Check2 )),
324+
325+ % % a different queue name pattern succeeds
326+ Check3 = http_get (Config , EndpointPath3 , ? OK ),
327+ ? assertEqual (false , maps :is_key (reason , Check3 )),
328+
329+ _ = rabbit_ct_broker_helpers :rpc (Config , 0 , ra , restart_server , [RaSystem , amqqueue :get_pid (Q1 )]),
330+ rabbit_ct_helpers :await_condition (
331+ fun () ->
332+ try
333+ Check4 = http_get (Config , EndpointPath1 , ? OK ),
334+ false =:= maps :is_key (reason , Check4 )
335+ catch _ :_ ->
336+ false
337+ end
338+ end ),
339+
340+ rabbit_ct_broker_helpers :delete_vhost (Config , VH2 ),
341+
219342 passed .
220343
344+
221345virtual_hosts_test (Config ) ->
222346 VHost1 = <<" vhost1" >>,
223347 VHost2 = <<" vhost2" >>,
0 commit comments