Skip to content

Commit 282d9e2

Browse files
committed
rabbitmq_ct_helpers: Change how Mnesia/Khepri is selected
[Why] Once `khepr_db` is enabled by default, we need another way to disable it to select Mnesia instead. [How] We use the new relative forced feature flags mechanism to indicate if we want to explicitly enable or disable `khepri_db`. This way, we don't touch other stable feature flags and only mess with Khepri. However, this mechanism is not supported by RabbitMQ 4.0.x and older. They will ignore the setting. Therefore, to make this work in mixed-version testing, after a node has been started, we try to enable `khepri_db` if we detect that it doesn't support this mechanism. At the end, we compare the effective metadata store to the expected one. If they don't match, we skip the test. While here, change `rjms_topic_selector_SUITE` to only choose Khepri without specifying any feature flags.
1 parent 6e8b566 commit 282d9e2

File tree

6 files changed

+135
-44
lines changed

6 files changed

+135
-44
lines changed

deps/rabbit/test/bindings_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ end_per_suite(Config) ->
7272
% init_per_group_common(Group, Config, 1);
7373
init_per_group(khepri_migration = Group, Config) ->
7474
case rabbit_ct_broker_helpers:configured_metadata_store(Config) of
75-
{khepri, _} ->
75+
khepri ->
7676
{skip, "skip khepri migration test when khepri already configured"};
7777
mnesia ->
7878
init_per_group_common(Group, Config, 1)

deps/rabbit/test/clustering_management_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ init_per_group(khepri_store, Config) ->
138138
end;
139139
init_per_group(mnesia_store, Config) ->
140140
case rabbit_ct_broker_helpers:configured_metadata_store(Config) of
141-
{khepri, _} ->
141+
khepri ->
142142
{skip, "These tests target mnesia"};
143143
_ ->
144144
Config

deps/rabbit/test/clustering_recovery_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ init_per_group(khepri_store, Config) ->
8080
end;
8181
init_per_group(mnesia_store, Config) ->
8282
case rabbit_ct_broker_helpers:configured_metadata_store(Config) of
83-
{khepri, _} ->
83+
khepri ->
8484
{skip, "These tests target mnesia"};
8585
_ ->
8686
Config

deps/rabbitmq_ct_helpers/src/rabbit_ct_broker_helpers.erl

Lines changed: 129 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -215,19 +215,19 @@ setup_steps() ->
215215
fun rabbit_ct_helpers:ensure_rabbitmqctl_app/1,
216216
fun rabbit_ct_helpers:ensure_rabbitmq_plugins_cmd/1,
217217
fun set_lager_flood_limit/1,
218+
fun configure_metadata_store/1,
218219
fun start_rabbitmq_nodes/1,
219-
fun share_dist_and_proxy_ports_map/1,
220-
fun configure_metadata_store/1
220+
fun share_dist_and_proxy_ports_map/1
221221
];
222222
_ ->
223223
[
224224
fun rabbit_ct_helpers:ensure_rabbitmqctl_cmd/1,
225225
fun rabbit_ct_helpers:load_rabbitmqctl_app/1,
226226
fun rabbit_ct_helpers:ensure_rabbitmq_plugins_cmd/1,
227227
fun set_lager_flood_limit/1,
228+
fun configure_metadata_store/1,
228229
fun start_rabbitmq_nodes/1,
229-
fun share_dist_and_proxy_ports_map/1,
230-
fun configure_metadata_store/1
230+
fun share_dist_and_proxy_ports_map/1
231231
]
232232
end.
233233

@@ -441,8 +441,24 @@ start_rabbitmq_node(Master, Config, NodeConfig, I) ->
441441
{failed_boot_attempts, Attempts + 1}),
442442
start_rabbitmq_node(Master, Config, NodeConfig5, I);
443443
NodeConfig4 ->
444-
Master ! {self(), I, NodeConfig4},
445-
unlink(Master)
444+
case uses_expected_metadata_store(Config, NodeConfig4) of
445+
{MetadataStore, MetadataStore} ->
446+
Master ! {self(), I, NodeConfig4},
447+
unlink(Master);
448+
{ExpectedMetadataStore, UsedMetadataStore} ->
449+
%% If the active metadata store is not the one expected, we
450+
%% stop the node and skip the test.
451+
_ = stop_rabbitmq_node(Config, NodeConfig4),
452+
Nodename = ?config(nodename, NodeConfig4),
453+
Error = {skip,
454+
rabbit_misc:format(
455+
"Node ~s is using the ~s metadata store, "
456+
"~s was expected",
457+
[Nodename, UsedMetadataStore,
458+
ExpectedMetadataStore])},
459+
Master ! {self(), Error},
460+
unlink(Master)
461+
end
446462
end.
447463

448464
run_node_steps(Config, NodeConfig, I, [Step | Rest]) ->
@@ -883,6 +899,67 @@ query_node(Config, NodeConfig) ->
883899
cover_add_node(Nodename),
884900
rabbit_ct_helpers:set_config(NodeConfig, Vars).
885901

902+
uses_expected_metadata_store(Config, NodeConfig) ->
903+
%% We want to verify if the active metadata store matches the expected one.
904+
%%
905+
%% Before that, we may need to enable `khepri_db' on the node because if it
906+
%% doesn't support the relative forced feature flags mechanism, it will
907+
%% ignore the setting from `configure_metadata_store/1'. In this case, we
908+
%% have to enable it at runtime.
909+
Nodename = ?config(nodename, NodeConfig),
910+
ExpectedMetadataStore = rabbit_ct_helpers:get_config(
911+
Config, metadata_store),
912+
case ExpectedMetadataStore of
913+
mnesia -> ok;
914+
khepri -> maybe_enable_khepri_as_expected(Config, Nodename)
915+
end,
916+
IsKhepriEnabled = rpc(Config, Nodename, rabbit_khepri, is_enabled, []),
917+
UsedMetadataStore = case IsKhepriEnabled of
918+
true -> khepri;
919+
false -> mnesia
920+
end,
921+
ct:pal(
922+
"Metadata store on ~s: expected=~s, used=~s",
923+
[Nodename, UsedMetadataStore, ExpectedMetadataStore]),
924+
{ExpectedMetadataStore, UsedMetadataStore}.
925+
926+
maybe_enable_khepri_as_expected(Config, Nodename) ->
927+
%% We detect if the remote node supports the relative forced feature flags
928+
%% mechanism by checking if `rabbit_feature_flags:get_require_level/1' is
929+
%% exported. This is unrelated to the mechanism but it was committed around
930+
%% the same time and was not backported either.
931+
RelativeForcedFeatureFlagsUnsupported = (
932+
rpc(Config, Nodename,
933+
erlang, function_exported,
934+
[rabbit_feature_flags, get_require_level, 1])
935+
),
936+
case RelativeForcedFeatureFlagsUnsupported of
937+
true ->
938+
ok;
939+
false ->
940+
ct:pal(
941+
"Relative forced feature flags unsupported on ~s, "
942+
"enable Khepri now to enable expected metadata store",
943+
[Nodename]),
944+
Ret = enable_feature_flag(Config, [Nodename], khepri_db),
945+
case Ret of
946+
ok ->
947+
ok;
948+
{error, missing_clustered_nodes} ->
949+
ct:pal(
950+
"Tried to enable Khepri on ~s as expected, but node "
951+
"not ready; retrying in 1 second",
952+
[Nodename]),
953+
timer:sleep(1000),
954+
maybe_enable_khepri_as_expected(Config, Nodename);
955+
_ ->
956+
ct:pal(
957+
"Tried to enable Khepri on ~s as expected: ~0p",
958+
[Nodename, Ret]),
959+
ok
960+
end
961+
end.
962+
886963
maybe_cluster_nodes(Config) ->
887964
Clustered0 = rabbit_ct_helpers:get_config(Config, rmq_nodes_clustered),
888965
Clustered = case Clustered0 of
@@ -999,57 +1076,71 @@ share_dist_and_proxy_ports_map(Config) ->
9991076
configured_metadata_store(Config) ->
10001077
case rabbit_ct_helpers:get_config(Config, metadata_store) of
10011078
khepri ->
1002-
{khepri, []};
1003-
{khepri, _FFs0} = Khepri ->
1004-
Khepri;
1079+
khepri;
10051080
mnesia ->
10061081
mnesia;
10071082
_ ->
10081083
case os:getenv("RABBITMQ_METADATA_STORE") of
1009-
"khepri" ->
1010-
{khepri, []};
1011-
_ ->
1012-
mnesia
1084+
"khepri" -> khepri;
1085+
_ -> mnesia
10131086
end
10141087
end.
10151088

10161089
configure_metadata_store(Config) ->
10171090
ct:log("Configuring metadata store..."),
1018-
case configured_metadata_store(Config) of
1019-
{khepri, FFs0} ->
1020-
case enable_khepri_metadata_store(Config, FFs0) of
1021-
{skip, _} = Skip ->
1022-
_ = stop_rabbitmq_nodes(Config),
1023-
Skip;
1024-
Config1 ->
1025-
Config1
1091+
Value = rabbit_ct_helpers:get_app_env(
1092+
Config, rabbit, forced_feature_flags_on_init, undefined),
1093+
MetadataStore = configured_metadata_store(Config),
1094+
Config1 = rabbit_ct_helpers:set_config(
1095+
Config, {metadata_store, MetadataStore}),
1096+
%% To enabled or disable `khepri_db', we use the relative forced feature
1097+
%% flags mechanism. This allows us to select the state of Khepri without
1098+
%% having to worry about other feature flags.
1099+
%%
1100+
%% However, RabbitMQ 4.0.x and older don't support it. See the
1101+
%% `uses_expected_metadata_store/2' check to see how Khepri is enabled in
1102+
%% this case.
1103+
case MetadataStore of
1104+
khepri ->
1105+
ct:log("Enabling Khepri metadata store"),
1106+
case Value of
1107+
undefined ->
1108+
rabbit_ct_helpers:merge_app_env(
1109+
Config1,
1110+
{rabbit,
1111+
[{forced_feature_flags_on_init,
1112+
{rel, [khepri_db], []}}]});
1113+
_ ->
1114+
rabbit_ct_helpers:merge_app_env(
1115+
Config1,
1116+
{rabbit,
1117+
[{forced_feature_flags_on_init,
1118+
[khepri_db | Value]}]})
10261119
end;
10271120
mnesia ->
10281121
ct:log("Enabling Mnesia metadata store"),
1029-
Config
1122+
case Value of
1123+
undefined ->
1124+
rabbit_ct_helpers:merge_app_env(
1125+
Config1,
1126+
{rabbit,
1127+
[{forced_feature_flags_on_init,
1128+
{rel, [], [khepri_db]}}]});
1129+
_ ->
1130+
rabbit_ct_helpers:merge_app_env(
1131+
Config1,
1132+
{rabbit,
1133+
[{forced_feature_flags_on_init,
1134+
Value -- [khepri_db]}]})
1135+
end
10301136
end.
10311137

1032-
enable_khepri_metadata_store(Config, FFs0) ->
1033-
ct:log("Enabling Khepri metadata store"),
1034-
FFs = [khepri_db | FFs0],
1035-
lists:foldl(fun(_FF, {skip, _Reason} = Skip) ->
1036-
Skip;
1037-
(FF, C) ->
1038-
case enable_feature_flag(C, FF) of
1039-
ok ->
1040-
C;
1041-
{skip, _} = Skip ->
1042-
ct:pal("Enabling metadata store failed: ~p", [Skip]),
1043-
Skip
1044-
end
1045-
end, Config, FFs).
1046-
10471138
%% Waits until the metadata store replica on Node is up to date with the leader.
10481139
await_metadata_store_consistent(Config, Node) ->
10491140
case configured_metadata_store(Config) of
10501141
mnesia ->
10511142
ok;
1052-
{khepri, _} ->
1143+
khepri ->
10531144
RaClusterName = rabbit_khepri:get_ra_cluster_name(),
10541145
Leader = rpc(Config, Node, ra_leaderboard, lookup_leader, [RaClusterName]),
10551146
LastAppliedLeader = ra_last_applied(Leader),

deps/rabbitmq_jms_topic_exchange/test/rjms_topic_selector_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ init_per_group(mnesia_store = Group, Config0) ->
5656
init_per_group(khepri_store = Group, Config0) ->
5757
Config = rabbit_ct_helpers:set_config(
5858
Config0,
59-
[{metadata_store, {khepri, [khepri_db]}}]),
59+
[{metadata_store, khepri}]),
6060
init_per_group_common(Group, Config);
6161
init_per_group(khepri_migration = Group, Config0) ->
6262
Config = rabbit_ct_helpers:set_config(Config0, [{metadata_store, mnesia}]),

deps/rabbitmq_recent_history_exchange/test/system_SUITE.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ end_per_suite(Config) ->
5959

6060
init_per_group(mnesia_store, Config) ->
6161
case rabbit_ct_broker_helpers:configured_metadata_store(Config) of
62-
{khepri, _} -> {skip, "These tests target Mnesia"};
63-
_ -> Config
62+
khepri -> {skip, "These tests target Mnesia"};
63+
_ -> Config
6464
end;
6565
init_per_group(khepri_store, Config) ->
6666
case rabbit_ct_broker_helpers:configured_metadata_store(Config) of

0 commit comments

Comments
 (0)