@@ -216,19 +216,19 @@ setup_steps() ->
216216 fun rabbit_ct_helpers :ensure_rabbitmqctl_app /1 ,
217217 fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
218218 fun set_lager_flood_limit /1 ,
219+ fun configure_metadata_store /1 ,
219220 fun start_rabbitmq_nodes /1 ,
220- fun share_dist_and_proxy_ports_map /1 ,
221- fun configure_metadata_store /1
221+ fun share_dist_and_proxy_ports_map /1
222222 ];
223223 _ ->
224224 [
225225 fun rabbit_ct_helpers :ensure_rabbitmqctl_cmd /1 ,
226226 fun rabbit_ct_helpers :load_rabbitmqctl_app /1 ,
227227 fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
228228 fun set_lager_flood_limit /1 ,
229+ fun configure_metadata_store /1 ,
229230 fun start_rabbitmq_nodes /1 ,
230- fun share_dist_and_proxy_ports_map /1 ,
231- fun configure_metadata_store /1
231+ fun share_dist_and_proxy_ports_map /1
232232 ]
233233 end .
234234
@@ -442,8 +442,24 @@ start_rabbitmq_node(Master, Config, NodeConfig, I) ->
442442 {failed_boot_attempts , Attempts + 1 }),
443443 start_rabbitmq_node (Master , Config , NodeConfig5 , I );
444444 NodeConfig4 ->
445- Master ! {self (), I , NodeConfig4 },
446- unlink (Master )
445+ case uses_expected_metadata_store (Config , NodeConfig4 ) of
446+ {MetadataStore , MetadataStore } ->
447+ Master ! {self (), I , NodeConfig4 },
448+ unlink (Master );
449+ {ExpectedMetadataStore , UsedMetadataStore } ->
450+ % % If the active metadata store is not the one expected, we
451+ % % stop the node and skip the test.
452+ _ = stop_rabbitmq_node (Config , NodeConfig4 ),
453+ Nodename = ? config (nodename , NodeConfig4 ),
454+ Error = {skip ,
455+ rabbit_misc :format (
456+ " Node ~s is using the ~s metadata store, "
457+ " ~s was expected" ,
458+ [Nodename , UsedMetadataStore ,
459+ ExpectedMetadataStore ])},
460+ Master ! {self (), Error },
461+ unlink (Master )
462+ end
447463 end .
448464
449465run_node_steps (Config , NodeConfig , I , [Step | Rest ]) ->
@@ -631,29 +647,29 @@ write_config_file(Config, NodeConfig, _I) ->
631647
632648-define (REQUIRED_FEATURE_FLAGS , [
633649 % % Required in 3.11:
634- " virtual_host_metadata,"
635- " quorum_queue,"
636- " implicit_default_bindings,"
637- " maintenance_mode_status,"
638- " user_limits,"
650+ virtual_host_metadata ,
651+ quorum_queue ,
652+ implicit_default_bindings ,
653+ maintenance_mode_status ,
654+ user_limits ,
639655 % % Required in 3.12:
640- " stream_queue,"
641- " classic_queue_type_delivery_support,"
642- " tracking_records_in_ets,"
643- " stream_single_active_consumer,"
644- " listener_records_in_ets,"
645- " feature_flags_v2,"
646- " direct_exchange_routing_v2,"
647- " classic_mirrored_queue_version," % % @todo Missing in FF docs!!
656+ stream_queue ,
657+ classic_queue_type_delivery_support ,
658+ tracking_records_in_ets ,
659+ stream_single_active_consumer ,
660+ listener_records_in_ets ,
661+ feature_flags_v2 ,
662+ direct_exchange_routing_v2 ,
663+ classic_mirrored_queue_version , % % @todo Missing in FF docs!!
648664 % % Required in 3.12 in rabbitmq_management_agent:
649- % " drop_unroutable_metric,"
650- % " empty_basic_get_metric,"
665+ % drop_unroutable_metric,
666+ % empty_basic_get_metric,
651667 % % Required in 4.0:
652- " stream_sac_coordinator_unblock_group,"
653- " restart_streams,"
654- " stream_update_config_command,"
655- " stream_filtering,"
656- " message_containers" % % @todo Update FF docs!! It *is* required.
668+ stream_sac_coordinator_unblock_group ,
669+ restart_streams ,
670+ stream_update_config_command ,
671+ stream_filtering ,
672+ message_containers % % @todo Update FF docs!! It *is* required.
657673]).
658674
659675do_start_rabbitmq_node (Config , NodeConfig , I ) ->
@@ -735,6 +751,17 @@ do_start_rabbitmq_node(Config, NodeConfig, I) ->
735751 false -> ExtraArgs3 ;
736752 _ -> [" NOBUILD=1" | ExtraArgs3 ]
737753 end ,
754+ % % TODO: When we start to do mixed-version testing against 4.1.x as the
755+ % % secondary umbrella, we will need to stop setting
756+ % % `$RABBITMQ_FEATURE_FLAGS'.
757+ MetadataStore = rabbit_ct_helpers :get_config (Config , metadata_store ),
758+ SecFeatureFlags0 = case MetadataStore of
759+ mnesia -> ? REQUIRED_FEATURE_FLAGS ;
760+ khepri -> [khepri_db | ? REQUIRED_FEATURE_FLAGS ]
761+ end ,
762+ SecFeatureFlags = string :join (
763+ [atom_to_list (F ) || F <- SecFeatureFlags0 ],
764+ " ," ),
738765 ExtraArgs = case UseSecondaryUmbrella of
739766 true ->
740767 DepsDir = ? config (erlang_mk_depsdir , Config ),
@@ -764,7 +791,8 @@ do_start_rabbitmq_node(Config, NodeConfig, I) ->
764791 {" RABBITMQ_SCRIPTS_DIR=~ts " , [SecScriptsDir ]},
765792 {" RABBITMQ_SERVER=~ts /rabbitmq-server" , [SecScriptsDir ]},
766793 {" RABBITMQCTL=~ts /rabbitmqctl" , [SecScriptsDir ]},
767- {" RABBITMQ_PLUGINS=~ts /rabbitmq-plugins" , [SecScriptsDir ]}
794+ {" RABBITMQ_PLUGINS=~ts /rabbitmq-plugins" , [SecScriptsDir ]},
795+ {" RABBITMQ_FEATURE_FLAGS=~ts " , [SecFeatureFlags ]}
768796 | ExtraArgs4 ];
769797 false ->
770798 case UseSecondaryDist of
@@ -786,7 +814,7 @@ do_start_rabbitmq_node(Config, NodeConfig, I) ->
786814 {" RABBITMQ_SCRIPTS_DIR=~ts /sbin" , [SecondaryDist ]},
787815 {" RABBITMQ_SERVER=~ts /sbin/rabbitmq-server" , [SecondaryDist ]},
788816 {" RABBITMQ_ENABLED_PLUGINS=~ts " , [SecondaryEnabledPlugins ]},
789- {" RABBITMQ_FEATURE_FLAGS=~ts " , [? REQUIRED_FEATURE_FLAGS ]}
817+ {" RABBITMQ_FEATURE_FLAGS=~ts " , [SecFeatureFlags ]}
790818 | ExtraArgs4 ];
791819 false ->
792820 ExtraArgs4
@@ -884,6 +912,21 @@ query_node(Config, NodeConfig) ->
884912 cover_add_node (Nodename ),
885913 rabbit_ct_helpers :set_config (NodeConfig , Vars ).
886914
915+ uses_expected_metadata_store (Config , NodeConfig ) ->
916+ % % We want to verify if the active metadata store matches the expected one.
917+ Nodename = ? config (nodename , NodeConfig ),
918+ ExpectedMetadataStore = rabbit_ct_helpers :get_config (
919+ Config , metadata_store ),
920+ IsKhepriEnabled = rpc (Config , Nodename , rabbit_khepri , is_enabled , []),
921+ UsedMetadataStore = case IsKhepriEnabled of
922+ true -> khepri ;
923+ false -> mnesia
924+ end ,
925+ ct :pal (
926+ " Metadata store on ~s : expected=~s , used=~s " ,
927+ [Nodename , UsedMetadataStore , ExpectedMetadataStore ]),
928+ {ExpectedMetadataStore , UsedMetadataStore }.
929+
887930maybe_cluster_nodes (Config ) ->
888931 Clustered0 = rabbit_ct_helpers :get_config (Config , rmq_nodes_clustered ),
889932 Clustered = case Clustered0 of
@@ -1000,57 +1043,79 @@ share_dist_and_proxy_ports_map(Config) ->
10001043configured_metadata_store (Config ) ->
10011044 case rabbit_ct_helpers :get_config (Config , metadata_store ) of
10021045 khepri ->
1003- {khepri , []};
1004- {khepri , _FFs0 } = Khepri ->
1005- Khepri ;
1046+ khepri ;
10061047 mnesia ->
10071048 mnesia ;
10081049 _ ->
10091050 case os :getenv (" RABBITMQ_METADATA_STORE" ) of
1010- " khepri" ->
1011- {khepri , []};
1012- _ ->
1013- mnesia
1051+ " khepri" -> khepri ;
1052+ _ -> mnesia
10141053 end
10151054 end .
10161055
10171056configure_metadata_store (Config ) ->
10181057 ct :log (" Configuring metadata store..." ),
1019- case configured_metadata_store (Config ) of
1020- {khepri , FFs0 } ->
1021- case enable_khepri_metadata_store (Config , FFs0 ) of
1022- {skip , _ } = Skip ->
1023- _ = stop_rabbitmq_nodes (Config ),
1024- Skip ;
1025- Config1 ->
1026- Config1
1058+ Value = rabbit_ct_helpers :get_app_env (
1059+ Config , rabbit , forced_feature_flags_on_init , undefined ),
1060+ MetadataStore = configured_metadata_store (Config ),
1061+ Config1 = rabbit_ct_helpers :set_config (
1062+ Config , {metadata_store , MetadataStore }),
1063+ % % To enabled or disable `khepri_db', we use the relative forced feature
1064+ % % flags mechanism. This allows us to select the state of Khepri without
1065+ % % having to worry about other feature flags.
1066+ % %
1067+ % % However, RabbitMQ 4.0.x and older don't support it. See the
1068+ % % `uses_expected_metadata_store/2' check to see how Khepri is enabled in
1069+ % % this case.
1070+ % %
1071+ % % Note that this setting will be ignored by the secondary umbrella because
1072+ % % we set `$RABBITMQ_FEATURE_FLAGS' explisitly. In this case, we handle the
1073+ % % `khepri_db' feature flag when we compute the value of that variable.
1074+ % %
1075+ % % TODO: When we start to do mixed-version testing against 4.1.x as the
1076+ % % secondary umbrella, we will need to stop setting
1077+ % % `$RABBITMQ_FEATURE_FLAGS'.
1078+ case MetadataStore of
1079+ khepri ->
1080+ ct :log (" Enabling Khepri metadata store" ),
1081+ case Value of
1082+ undefined ->
1083+ rabbit_ct_helpers :merge_app_env (
1084+ Config1 ,
1085+ {rabbit ,
1086+ [{forced_feature_flags_on_init ,
1087+ {rel , [khepri_db ], []}}]});
1088+ _ ->
1089+ rabbit_ct_helpers :merge_app_env (
1090+ Config1 ,
1091+ {rabbit ,
1092+ [{forced_feature_flags_on_init ,
1093+ [khepri_db | Value ]}]})
10271094 end ;
10281095 mnesia ->
10291096 ct :log (" Enabling Mnesia metadata store" ),
1030- Config
1097+ case Value of
1098+ undefined ->
1099+ rabbit_ct_helpers :merge_app_env (
1100+ Config1 ,
1101+ {rabbit ,
1102+ [{forced_feature_flags_on_init ,
1103+ {rel , [], [khepri_db ]}}]});
1104+ _ ->
1105+ rabbit_ct_helpers :merge_app_env (
1106+ Config1 ,
1107+ {rabbit ,
1108+ [{forced_feature_flags_on_init ,
1109+ Value -- [khepri_db ]}]})
1110+ end
10311111 end .
10321112
1033- enable_khepri_metadata_store (Config , FFs0 ) ->
1034- ct :log (" Enabling Khepri metadata store" ),
1035- FFs = [khepri_db | FFs0 ],
1036- lists :foldl (fun (_FF , {skip , _Reason } = Skip ) ->
1037- Skip ;
1038- (FF , C ) ->
1039- case enable_feature_flag (C , FF ) of
1040- ok ->
1041- C ;
1042- {skip , _ } = Skip ->
1043- ct :pal (" Enabling metadata store failed: ~p " , [Skip ]),
1044- Skip
1045- end
1046- end , Config , FFs ).
1047-
10481113% % Waits until the metadata store replica on Node is up to date with the leader.
10491114await_metadata_store_consistent (Config , Node ) ->
10501115 case configured_metadata_store (Config ) of
10511116 mnesia ->
10521117 ok ;
1053- { khepri , _ } ->
1118+ khepri ->
10541119 RaClusterName = rabbit_khepri :get_ra_cluster_name (),
10551120 Leader = rpc (Config , Node , ra_leaderboard , lookup_leader , [RaClusterName ]),
10561121 LastAppliedLeader = ra_last_applied (Leader ),
0 commit comments