Merge pull request #14321 from rabbitmq/mk-rabbitmq-nodes-helpers
Test (make) / Build and Xref (1.18, 26) (push) Waiting to run Details
Test (make) / Build and Xref (1.18, 27) (push) Waiting to run Details
Test (make) / Build and Xref (1.18, 28) (push) Waiting to run Details
Test (make) / Test (1.18, 28, khepri) (push) Waiting to run Details
Test (make) / Test (1.18, 28, mnesia) (push) Waiting to run Details
Test (make) / Test mixed clusters (1.18, 28, khepri) (push) Waiting to run Details
Test (make) / Test mixed clusters (1.18, 28, mnesia) (push) Waiting to run Details
Test (make) / Type check (1.18, 28) (push) Waiting to run Details
Trigger a 4.2.x alpha release build / trigger_alpha_build (push) Has been cancelled Details
Test Authentication/Authorization backends via mutiple messaging protocols / selenium (chrome, 1.17.3, 27.3) (push) Has been cancelled Details
Test Management UI with Selenium / selenium (chrome, 1.17.3, 27.3) (push) Has been cancelled Details
Test Authentication/Authorization backends via mutiple messaging protocols / summary-selenium (push) Has been cancelled Details

Introduce a few new rabbit_plugins and rabbit_nodes functions
This commit is contained in:
Michael Klishin 2025-08-01 14:54:05 -04:00 committed by GitHub
commit 4c76d6dd8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 87 additions and 1 deletions

View File

@ -23,6 +23,7 @@
filter_running/1, filter_not_running/1, filter_running/1, filter_not_running/1,
is_serving/1, list_serving/0, list_not_serving/0, is_serving/1, list_serving/0, list_not_serving/0,
filter_serving/1, filter_not_serving/1, filter_serving/1, filter_not_serving/1,
list_serving_with_plugin/1, filter_with_plugin/2,
name_type/0, running_count/0, total_count/0, name_type/0, running_count/0, total_count/0,
await_running_count/2, is_single_node_cluster/0, await_running_count/2, is_single_node_cluster/0,
boot/0]). boot/0]).
@ -457,10 +458,63 @@ filter_not_serving(Nodes) ->
Serving = do_filter_serving(Members), Serving = do_filter_serving(Members),
Members -- Serving. Members -- Serving.
%% @doc Combined list_serving/0 and rabbit_plugins:is_enabled_on_node/2
%% to return nodes that are running, not under maintenance mode
%% and have a specific plugin enabled.
%% @see list_serving/0
%% @see rabbit_plugins:is_enabled_on_node/2
-spec list_serving_with_plugin(PluginName :: rabbit_plugins:plugin_name()) -> [node()].
list_serving_with_plugin(PluginName) ->
Members = list_serving(),
filter_with_plugin(PluginName, Members).
%% @doc Filters the given list of nodes to only select those belonging to the
%% cluster and having a specific plugin enabled.
%%
%% The cluster being considered is the one which the node running this
%% function belongs to.
%%
%% @see filter_serving/1.
-spec filter_with_plugin(rabbit_plugins:plugin_name(), [node()]) -> [node()].
filter_with_plugin(PluginName, Nodes) ->
Members = filter_members(Nodes),
do_filter_with_plugin(PluginName, Members).
%% @doc Filters the given list of cluster members to only select those who
%% accept clients.
%%
%% The given list of nodes must have been verified to only contain cluster
%% members.
%%
%% @private
do_filter_with_plugin(PluginName, Members) ->
%% All clustered members having a specific plugin enabled
Rets = erpc:multicall(
Members, rabbit_plugins, is_enabled, [PluginName], ?FILTER_RPC_TIMEOUT),
RetPerMember = lists:zip(Members, Rets),
lists:filtermap(
fun
({Member, {ok, true}}) ->
{true, Member};
({_, {ok, false}}) ->
false;
({_, {error, {erpc, Reason}}})
when Reason =:= noconnection orelse Reason =:= timeout ->
false;
({Member, Error}) ->
?LOG_ERROR(
"~s:~s: Failed to query node ~ts: ~p",
[?MODULE, ?FUNCTION_NAME, Member, Error],
#{domain => ?RMQLOG_DOMAIN_GLOBAL}),
false
end, RetPerMember).
-spec do_filter_serving(Members) -> Members when -spec do_filter_serving(Members) -> Members when
Members :: [node()]. Members :: [node()].
%% @doc Filters the given list of cluster members to only select those who %% @doc Filters the given list of cluster members to only select those who
%% accept clients. %% accept client connections.
%% %%
%% The given list of nodes must have been verified to only contain cluster %% The given list of nodes must have been verified to only contain cluster
%% members. %% members.

View File

@ -13,11 +13,16 @@
-export([validate_plugins/1, format_invalid_plugins/1]). -export([validate_plugins/1, format_invalid_plugins/1]).
-export([is_strictly_plugin/1, strictly_plugins/2, strictly_plugins/1]). -export([is_strictly_plugin/1, strictly_plugins/2, strictly_plugins/1]).
-export([plugins_dir/0, plugin_names/1, plugins_expand_dir/0, enabled_plugins_file/0]). -export([plugins_dir/0, plugin_names/1, plugins_expand_dir/0, enabled_plugins_file/0]).
-export([is_enabled/1, is_enabled_on_node/2]).
% Export for testing purpose. % Export for testing purpose.
-export([is_version_supported/2, validate_plugins/2]). -export([is_version_supported/2, validate_plugins/2]).
%%---------------------------------------------------------------------------- %%----------------------------------------------------------------------------
-export_type([
plugin_name/0
]).
-type plugin_name() :: atom(). -type plugin_name() :: atom().
%%---------------------------------------------------------------------------- %%----------------------------------------------------------------------------
@ -129,6 +134,29 @@ active() ->
[App || {App, _, _} <- rabbit_misc:which_applications(), [App || {App, _, _} <- rabbit_misc:which_applications(),
lists:member(App, InstalledPlugins)]. lists:member(App, InstalledPlugins)].
%% @doc Returns true if the plugin is enabled on the current node.
-spec is_enabled(Name :: plugin_name()) -> boolean().
is_enabled(Name) ->
EnabledPlugins = active(),
lists:member(Name, EnabledPlugins).
%% @doc Returns true if the plugin is enabled on the given node.
-spec is_enabled_on_node(Name :: plugin_name(), Node :: node()) -> boolean().
is_enabled_on_node(Name, Node) ->
try
case erpc:call(Node, ?MODULE, is_enabled, [Name], 5000) of
true -> true;
_ -> false
end
catch
error:{erpc, _} -> false;
_Class:_Reason:_Stacktrace -> false
end.
%% @doc Get the list of plugins which are ready to be enabled. %% @doc Get the list of plugins which are ready to be enabled.
-spec list(string()) -> [#plugin{}]. -spec list(string()) -> [#plugin{}].

View File

@ -61,6 +61,10 @@ listing_plugins_from_multiple_directories(Config) ->
end, end,
Path = FirstDir ++ PathSep ++ SecondDir, Path = FirstDir ++ PathSep ++ SecondDir,
Got = lists:sort([{Name, Vsn} || #plugin{name = Name, version = Vsn} <- rabbit_plugins:list(Path)]), Got = lists:sort([{Name, Vsn} || #plugin{name = Name, version = Vsn} <- rabbit_plugins:list(Path)]),
PluginsMap = maps:from_list(Got),
?assert(maps:is_key(plugin_first_dir, PluginsMap)),
?assert(maps:is_key(plugin_second_dir, PluginsMap)),
?assert(maps:is_key(plugin_both, PluginsMap)),
%% `rabbit` was loaded automatically by `rabbit_plugins:list/1`. %% `rabbit` was loaded automatically by `rabbit_plugins:list/1`.
%% We want to unload it now so it does not interfere with other %% We want to unload it now so it does not interfere with other
%% testcases. %% testcases.