summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <jean-sebastien@rabbitmq.com>2020-01-14 14:16:11 +0100
committerJean-Sébastien Pédron <jean-sebastien@rabbitmq.com>2020-01-16 11:46:59 +0100
commitb07cf2ddbfcfa3543c9cc98ecac07e2cac0fe351 (patch)
tree8ad5237faaae5b1d7ba7ba0dc657ff0282aa394d
parent04700dde4a79ab6501b282d21b9bc3c876e732db (diff)
downloadrabbitmq-server-git-b07cf2ddbfcfa3543c9cc98ecac07e2cac0fe351.tar.gz
rabbit_plugins: Filter non-plugins out
When the module discovers plugins in the plugins directories, it considers all applications there. There are actual RabbitMQ plugins, their dependencies, and possibly other applications which are neither plugins nor dependencies. So far, this was the case of `syslog` which could be used by Lager if the user configures it. To make sure `rabbit_plugins` or rabbitmq-plugins(8) didn't mess with `syslog`, there was a hard-coded filtering function which excluded this specific application. In RabbitMQ Enterprise Edition, we want to add another application of this kind: `inet_tcp_compress_dist`. This application implements an Erlang distribution protocol, so it is effectively unrelated to RabbitMQ. However, to keep packaging simple, it is provided in the plugins directory. We could add it to the hard-coded filtering function, but instead this function is replaced by the following logic to filter plugins: * Applications which depend on `rabbit` are considered actual plugins. * Plugins' dependencies, direct and indirect, are considered plugins as well. Therefore, `rabbit_plugins` will ignore: * Applications which don't depend on `rabbit` and no plugins depend on them (again, directly or indirectly) * Applications which are part of Erlang/OTP. This means the behavior slightly changes: a plugin which didn't declare its dependency to `rabbit` will not be considered a plugin anymore. I consider it is a bug in the plugin in the first place. The code will log the following debug messages to list ignored applications: 2020-01-14 13:18:41.468 [debug] <0.941.0> Plugins discovery: ignoring getopt, not a RabbitMQ plugin 2020-01-14 13:18:41.468 [debug] <0.941.0> Plugins discovery: ignoring inet_tcp_compress_dist, not a RabbitMQ plugin 2020-01-14 13:18:41.468 [debug] <0.941.0> Plugins discovery: ignoring lz4, not a RabbitMQ plugin 2020-01-14 13:18:41.468 [debug] <0.941.0> Plugins discovery: ignoring syslog, not a RabbitMQ plugin 2020-01-14 13:18:41.468 [debug] <0.941.0> Plugins discovery: ignoring zstd, not a RabbitMQ plugin
-rw-r--r--src/rabbit_plugins.erl60
1 files changed, 48 insertions, 12 deletions
diff --git a/src/rabbit_plugins.erl b/src/rabbit_plugins.erl
index 02e3e0d8de..bacb5e8391 100644
--- a/src/rabbit_plugins.erl
+++ b/src/rabbit_plugins.erl
@@ -225,14 +225,6 @@ is_plugin_provided_by_otp(#plugin{name = eldap}) ->
is_plugin_provided_by_otp(_) ->
false.
-is_skipped_plugin(#plugin{name = syslog}) ->
- % syslog is shipped as an .ez file, but it's not an actual plugin and
- % it's not a direct dependency of the rabbit application, so we must
- % skip it here
- true;
-is_skipped_plugin(_) ->
- false.
-
%% Make sure we don't list OTP apps in here, and also that we detect
%% missing dependencies.
ensure_dependencies(Plugins) ->
@@ -659,10 +651,54 @@ list_all_deps([], Deps) ->
Deps.
remove_plugins(Plugins) ->
- Fun = fun(P) ->
- not (is_plugin_provided_by_otp(P) orelse is_skipped_plugin(P))
- end,
- lists:filter(Fun, Plugins).
+ %% We want to filter out all Erlang applications in the plugins
+ %% directories which are not actual RabbitMQ plugin.
+ %%
+ %% A RabbitMQ plugin must depend on `rabbit`. We also want to keep
+ %% all applications they depend on, except Erlang/OTP applications.
+ %% In the end, we will skip:
+ %% * Erlang/OTP applications
+ %% * All applications which do not depend on `rabbit` and which
+ %% are not direct or indirect dependencies of plugins.
+ ActualPlugins = [Plugin
+ || #plugin{dependencies = Deps} = Plugin <- Plugins,
+ lists:member(rabbit, Deps)],
+ %% As said above, we want to keep all non-plugins which are
+ %% dependencies of plugins.
+ PluginDeps = lists:usort(
+ lists:flatten(
+ [resolve_deps(Plugins, Plugin)
+ || Plugin <- ActualPlugins])),
+ lists:filter(
+ fun(#plugin{name = Name} = Plugin) ->
+ IsOTPApp = is_plugin_provided_by_otp(Plugin),
+ IsAPlugin =
+ lists:member(Plugin, ActualPlugins) orelse
+ lists:member(Name, PluginDeps),
+ if
+ IsOTPApp ->
+ rabbit_log:debug(
+ "Plugins discovery: "
+ "ignoring ~s, Erlang/OTP application",
+ [Name]);
+ not IsAPlugin ->
+ rabbit_log:debug(
+ "Plugins discovery: "
+ "ignoring ~s, not a RabbitMQ plugin",
+ [Name]);
+ true ->
+ ok
+ end,
+ not (IsOTPApp orelse not IsAPlugin)
+ end, Plugins).
+
+resolve_deps(Plugins, #plugin{dependencies = Deps}) ->
+ IndirectDeps = [case lists:keyfind(Dep, #plugin.name, Plugins) of
+ false -> [];
+ DepPlugin -> resolve_deps(Plugins, DepPlugin)
+ end
+ || Dep <- Deps],
+ Deps ++ IndirectDeps.
maybe_report_plugin_loading_problems([]) ->
ok;