@@ -409,6 +409,13 @@ should_skip_if_unchanged() ->
409
409
ReachedTargetClusterSize = rabbit_nodes :reached_target_cluster_size (),
410
410
OptedIn andalso ReachedTargetClusterSize .
411
411
412
+ -spec any_orphaned_objects (list (#{atom () => any ()})) -> boolean ().
413
+ any_orphaned_objects (Maps ) ->
414
+ Filtered = lists :filter (fun (M ) ->
415
+ maps :get (<<" vhost" >>, M , undefined ) =:= undefined
416
+ end , Maps ),
417
+ length (Filtered ) > 0 .
418
+
412
419
413
420
-spec apply_defs (Map :: #{atom () => any ()}, ActingUser :: rabbit_types :username ()) -> 'ok' | {error , term ()}.
414
421
@@ -424,6 +431,25 @@ apply_defs(Map, ActingUser, VHost) when is_binary(VHost) ->
424
431
apply_defs (Map , ActingUser , fun () -> ok end , VHost );
425
432
apply_defs (Map , ActingUser , SuccessFun ) when is_function (SuccessFun ) ->
426
433
Version = maps :get (rabbitmq_version , Map , maps :get (rabbit_version , Map , undefined )),
434
+
435
+ % % If any of the queues or exchanges do not have virtual hosts set,
436
+ % % this definition file was a virtual-host specific import. They cannot be applied
437
+ % % as "complete" definition imports, most notably, imported on boot.
438
+ HasQueuesWithoutVirtualHostField = any_orphaned_objects (maps :get (queues , Map , [])),
439
+ HasExchangesWithoutVirtualHostField = any_orphaned_objects (maps :get (exchanges , Map , [])),
440
+ HasBindingsWithoutVirtualHostField = any_orphaned_objects (maps :get (bindings , Map , [])),
441
+
442
+ case (HasQueuesWithoutVirtualHostField and HasExchangesWithoutVirtualHostField and HasBindingsWithoutVirtualHostField ) of
443
+ true ->
444
+ rabbit_log :error (" Definitions import: some queues, exchanges or bindings in the definition file "
445
+ " are missing the virtual host field. Such files are produced when definitions of "
446
+ " a single virtual host are exported. They cannot be used to import definitions at boot time" ,
447
+ []),
448
+ throw ({error , invalid_definitions_file });
449
+ false ->
450
+ ok
451
+ end ,
452
+
427
453
try
428
454
concurrent_for_all (users , ActingUser , Map ,
429
455
fun (User , _Username ) ->
@@ -824,6 +850,7 @@ validate_limits(All) ->
824
850
undefined -> ok ;
825
851
Queues0 ->
826
852
{ok , VHostMap } = filter_out_existing_queues (Queues0 ),
853
+ _ = rabbit_log :debug (" Definition import. Virtual host map for validation: ~p " , [VHostMap ]),
827
854
maps :fold (fun validate_vhost_limit /3 , ok , VHostMap )
828
855
end .
829
856
@@ -855,12 +882,21 @@ build_filtered_map([], AccMap) ->
855
882
{ok , AccMap };
856
883
build_filtered_map ([Queue |Rest ], AccMap0 ) ->
857
884
{Rec , VHost } = build_queue_data (Queue ),
858
- case rabbit_amqqueue :exists (Rec ) of
859
- false ->
860
- AccMap1 = maps :update_with (VHost , fun (V ) -> V + 1 end , 1 , AccMap0 ),
861
- build_filtered_map (Rest , AccMap1 );
862
- true ->
863
- build_filtered_map (Rest , AccMap0 )
885
+ % % If virtual host is not specified in a queue,
886
+ % % this definition file is likely virtual host-specific.
887
+ % %
888
+ % % Skip such queues.
889
+ case VHost of
890
+ undefined ->
891
+ build_filtered_map (Rest , AccMap0 );
892
+ _Other ->
893
+ case rabbit_amqqueue :exists (Rec ) of
894
+ false ->
895
+ AccMap1 = maps :update_with (VHost , fun (V ) -> V + 1 end , 1 , AccMap0 ),
896
+ build_filtered_map (Rest , AccMap1 );
897
+ true ->
898
+ build_filtered_map (Rest , AccMap0 )
899
+ end
864
900
end .
865
901
866
902
validate_vhost_limit (VHost , AddCount , ok ) ->
0 commit comments