summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/rabbitmq-env5
-rw-r--r--scripts/rabbitmq-env.bat14
-rwxr-xr-xscripts/rabbitmq-server1
-rw-r--r--scripts/rabbitmq-server.bat1
-rw-r--r--scripts/rabbitmq-service.bat1
-rw-r--r--src/rabbit_plugins.erl190
-rw-r--r--test/plugins_SUITE.erl80
-rw-r--r--test/plugins_SUITE_data/plugins1/mock_rabbitmq_plugins_01-0.1.0.ezbin3280 -> 0 bytes
8 files changed, 80 insertions, 212 deletions
diff --git a/scripts/rabbitmq-env b/scripts/rabbitmq-env
index e9e83f6313..f1624eddf9 100755
--- a/scripts/rabbitmq-env
+++ b/scripts/rabbitmq-env
@@ -220,6 +220,10 @@ rmq_normalize_path_var RABBITMQ_PID_FILE
[ "x" = "x$RABBITMQ_BOOT_MODULE" ] && RABBITMQ_BOOT_MODULE=${BOOT_MODULE}
+[ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${PLUGINS_EXPAND_DIR}
+[ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME}-plugins-expand
+rmq_normalize_path_var RABBITMQ_PLUGINS_EXPAND_DIR
+
[ "x" != "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE_source=environment
[ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE}
rmq_normalize_path_var RABBITMQ_ENABLED_PLUGINS_FILE
@@ -249,6 +253,7 @@ rmq_check_if_shared_with_mnesia \
RABBITMQ_CONFIG_FILE \
RABBITMQ_LOG_BASE \
RABBITMQ_PID_FILE \
+ RABBITMQ_PLUGINS_EXPAND_DIR \
RABBITMQ_ENABLED_PLUGINS_FILE \
RABBITMQ_PLUGINS_DIR \
RABBITMQ_LOGS \
diff --git a/scripts/rabbitmq-env.bat b/scripts/rabbitmq-env.bat
index 9426019003..56b2f69b2d 100644
--- a/scripts/rabbitmq-env.bat
+++ b/scripts/rabbitmq-env.bat
@@ -262,6 +262,20 @@ if "!RABBITMQ_BOOT_MODULE!"=="" (
)
)
+REM [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${PLUGINS_EXPAND_DIR}
+REM [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME}-plugins-expand
+if "!RABBITMQ_PLUGINS_EXPAND_DIR!"=="" (
+ if "!PLUGINS_EXPAND_DIR!"=="" (
+ set RABBITMQ_PLUGINS_EXPAND_DIR=!RABBITMQ_MNESIA_BASE!\!RABBITMQ_NODENAME!-plugins-expand
+ ) else (
+ set RABBITMQ_PLUGINS_EXPAND_DIR=!PLUGINS_EXPAND_DIR!
+ )
+)
+REM FIXME: RabbitMQ removes and recreates RABBITMQ_PLUGINS_EXPAND_DIR
+REM itself. Therefore we can't create it here in advance and escape the
+REM directory name, and RABBITMQ_PLUGINS_EXPAND_DIR must not contain
+REM non-US-ASCII characters.
+
REM [ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE}
if "!RABBITMQ_ENABLED_PLUGINS_FILE!"=="" (
if "!ENABLED_PLUGINS_FILE!"=="" (
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server
index 655fdc3bcb..41d1a81332 100755
--- a/scripts/rabbitmq-server
+++ b/scripts/rabbitmq-server
@@ -221,6 +221,7 @@ start_rabbitmq_server() {
-rabbit lager_handler_upgrade "$RABBITMQ_LAGER_HANDLER_UPGRADE" \
-rabbit enabled_plugins_file "\"$RABBITMQ_ENABLED_PLUGINS_FILE\"" \
-rabbit plugins_dir "\"$RABBITMQ_PLUGINS_DIR\"" \
+ -rabbit plugins_expand_dir "\"$RABBITMQ_PLUGINS_EXPAND_DIR\"" \
-os_mon start_cpu_sup false \
-os_mon start_disksup false \
-os_mon start_memsup false \
diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat
index a51a327fa5..de25f95bdf 100644
--- a/scripts/rabbitmq-server.bat
+++ b/scripts/rabbitmq-server.bat
@@ -180,6 +180,7 @@ if "!ENV_OK!"=="false" (
-rabbit lager_handler !RABBIT_LAGER_HANDLER! ^
-rabbit enabled_plugins_file \""!RABBITMQ_ENABLED_PLUGINS_FILE:\=/!"\" ^
-rabbit plugins_dir \""!RABBITMQ_PLUGINS_DIR:\=/!"\" ^
+-rabbit plugins_expand_dir \""!RABBITMQ_PLUGINS_EXPAND_DIR:\=/!"\" ^
-os_mon start_cpu_sup false ^
-os_mon start_disksup false ^
-os_mon start_memsup false ^
diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat
index 29e7068ab1..624d18d913 100644
--- a/scripts/rabbitmq-service.bat
+++ b/scripts/rabbitmq-service.bat
@@ -257,6 +257,7 @@ set ERLANG_SERVICE_ARGUMENTS= ^
-rabbit lager_handler !RABBIT_LAGER_HANDLER! ^
-rabbit enabled_plugins_file \""!RABBITMQ_ENABLED_PLUGINS_FILE:\=/!"\" ^
-rabbit plugins_dir \""!RABBITMQ_PLUGINS_DIR:\=/!"\" ^
+-rabbit plugins_expand_dir \""!RABBITMQ_PLUGINS_EXPAND_DIR:\=/!"\" ^
-rabbit windows_service_config \""!RABBITMQ_CONFIG_FILE:\=/!"\" ^
-os_mon start_cpu_sup false ^
-os_mon start_disksup false ^
diff --git a/src/rabbit_plugins.erl b/src/rabbit_plugins.erl
index 1b31179c85..994e027eac 100644
--- a/src/rabbit_plugins.erl
+++ b/src/rabbit_plugins.erl
@@ -67,22 +67,15 @@ ensure(FileJustChanged0) ->
{error, {enabled_plugins_mismatch, FileJustChanged, OurFile}}
end.
+%% @doc Prepares the file system and installs all enabled plugins.
setup() ->
- case application:get_env(rabbit, plugins_expand_dir) of
- {ok, ExpandDir} ->
- case filelib:is_dir(ExpandDir) of
- true ->
- rabbit_log:info(
- "\"~s\" is no longer used to expand plugins.~n"
- "RabbitMQ still clears this directory but will "
- "stop doing so in the future.", [ExpandDir]),
-
- _ = delete_recursively(ExpandDir);
- false ->
- ok
- end;
- undefined ->
- ok
+ {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
+
+ %% Eliminate the contents of the destination directory
+ case delete_recursively(ExpandDir) of
+ ok -> ok;
+ {error, E1} -> throw({error, {cannot_delete_plugins_expand_dir,
+ [ExpandDir, E1]}})
end,
{ok, EnabledFile} = application:get_env(rabbit, enabled_plugins_file),
@@ -135,61 +128,10 @@ extract_schema(#plugin{type = dir, location = Location}, SchemaDir) ->
%% @doc Lists the plugins which are currently running.
active() ->
- LoadedPluginNames = maybe_keep_required_deps(false, loaded_plugin_names()),
+ {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
+ InstalledPlugins = plugin_names(list(ExpandDir)),
[App || {App, _, _} <- rabbit_misc:which_applications(),
- lists:member(App, LoadedPluginNames)].
-
-loaded_plugin_names() ->
- {ok, PluginsPath} = application:get_env(rabbit, plugins_dir),
- PluginsDirs = split_path(PluginsPath),
- lists:flatmap(
- fun(PluginsDir) ->
- PluginsDirComponents = filename:split(PluginsDir),
- loaded_plugin_names(code:get_path(), PluginsDirComponents, [])
- end,
- PluginsDirs).
-
-loaded_plugin_names([Path | OtherPaths], PluginsDirComponents, PluginNames) ->
- case lists:sublist(filename:split(Path), length(PluginsDirComponents)) of
- PluginsDirComponents ->
- case build_plugin_name_from_code_path(Path) of
- undefined ->
- loaded_plugin_names(
- OtherPaths, PluginsDirComponents, PluginNames);
- PluginName ->
- loaded_plugin_names(
- OtherPaths, PluginsDirComponents,
- [list_to_atom(PluginName) | PluginNames])
- end;
- _ ->
- loaded_plugin_names(OtherPaths, PluginsDirComponents, PluginNames)
- end;
-loaded_plugin_names([], _, PluginNames) ->
- PluginNames.
-
-build_plugin_name_from_code_path(Path) ->
- AppPath = case filelib:is_dir(Path) of
- true ->
- case filelib:wildcard(filename:join(Path, "*.app")) of
- [AP | _] -> AP;
- [] -> undefined
- end;
- false ->
- EZ = filename:dirname(filename:dirname(Path)),
- case filelib:is_regular(EZ) of
- true ->
- case find_app_path_in_ez(EZ) of
- {ok, AP} -> AP;
- _ -> undefined
- end;
- _ ->
- undefined
- end
- end,
- case AppPath of
- undefined -> undefined;
- _ -> filename:basename(AppPath, ".app")
- end.
+ lists:member(App, InstalledPlugins)].
%% @doc Get the list of plugins which are ready to be enabled.
list(PluginsPath) ->
@@ -279,19 +221,25 @@ running_plugins() ->
%%----------------------------------------------------------------------------
prepare_plugins(Enabled) ->
- AllPlugins = installed_plugins(),
+ {ok, PluginsDistDir} = application:get_env(rabbit, plugins_dir),
+ {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
+
+ AllPlugins = list(PluginsDistDir),
Wanted = dependencies(false, Enabled, AllPlugins),
WantedPlugins = lookup_plugins(Wanted, AllPlugins),
{ValidPlugins, Problems} = validate_plugins(WantedPlugins),
maybe_warn_about_invalid_plugins(Problems),
+ case filelib:ensure_dir(ExpandDir ++ "/") of
+ ok -> ok;
+ {error, E2} -> throw({error, {cannot_create_plugins_expand_dir,
+ [ExpandDir, E2]}})
+ end,
+ [prepare_plugin(Plugin, ExpandDir) || Plugin <- ValidPlugins],
- [prepare_dir_plugin(ValidPlugin) || ValidPlugin <- ValidPlugins],
+ [prepare_dir_plugin(PluginAppDescPath) ||
+ PluginAppDescPath <- filelib:wildcard(ExpandDir ++ "/*/ebin/*.app")],
Wanted.
-installed_plugins() ->
- {ok, PluginsDistDir} = application:get_env(rabbit, plugins_dir),
- list(PluginsDistDir).
-
maybe_warn_about_invalid_plugins([]) ->
ok;
maybe_warn_about_invalid_plugins(InvalidPlugins) ->
@@ -411,60 +359,40 @@ remove_version_preview_part(Version) ->
iolist_to_binary(rabbit_semver:format({Ver, {[], []}})).
clean_plugins(Plugins) ->
- [clean_plugin(Plugin) || Plugin <- Plugins].
+ {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
+ [clean_plugin(Plugin, ExpandDir) || Plugin <- Plugins].
-clean_plugin(Plugin) ->
+clean_plugin(Plugin, ExpandDir) ->
{ok, Mods} = application:get_key(Plugin, modules),
- PluginEbinDir = code:lib_dir(Plugin, ebin),
-
application:unload(Plugin),
[begin
code:soft_purge(Mod),
code:delete(Mod),
false = code:is_loaded(Mod)
end || Mod <- Mods],
-
- code:del_path(PluginEbinDir).
-
-plugin_ebin_dir(#plugin{type = ez, location = Location}) ->
- case find_app_path_in_ez(Location) of
- {ok, AppPath} ->
- filename:join(Location, filename:dirname(AppPath));
- {error, Reason} ->
- {error, Reason}
- end;
-plugin_ebin_dir(#plugin{type = dir, location = Location}) ->
- filename:join(Location, "ebin").
-
-prepare_dir_plugin(#plugin{name = Name} = Plugin) ->
- PluginEbinDir = case plugin_ebin_dir(Plugin) of
- {error, Reason} ->
- throw({plugin_ebin_dir_not_found, Name, Reason});
- Dir ->
- Dir
- end,
- case code:add_patha(PluginEbinDir) of
- true ->
- case filelib:wildcard(PluginEbinDir++ "/*.beam") of
- [] ->
+ delete_recursively(rabbit_misc:format("~s/~s", [ExpandDir, Plugin])).
+
+prepare_dir_plugin(PluginAppDescPath) ->
+ PluginEbinDir = filename:dirname(PluginAppDescPath),
+ Plugin = filename:basename(PluginAppDescPath, ".app"),
+ code:add_patha(PluginEbinDir),
+ case filelib:wildcard(PluginEbinDir++ "/*.beam") of
+ [] ->
+ ok;
+ [BeamPath | _] ->
+ Module = list_to_atom(filename:basename(BeamPath, ".beam")),
+ case code:ensure_loaded(Module) of
+ {module, _} ->
ok;
- [BeamPath | _] ->
- Module = list_to_atom(filename:basename(BeamPath, ".beam")),
- case code:ensure_loaded(Module) of
- {module, _} ->
- ok;
- {error, badfile} ->
- rabbit_log:error("Failed to enable plugin \"~s\": "
- "it may have been built with an "
- "incompatible (more recent?) "
- "version of Erlang~n", [Name]),
- throw({plugin_built_with_incompatible_erlang, Name});
- Error ->
- throw({plugin_module_unloadable, Name, Error})
- end
- end;
- {error, bad_directory} ->
- throw({plugin_ebin_path_incorrect, Name, PluginEbinDir})
+ {error, badfile} ->
+ rabbit_log:error("Failed to enable plugin \"~s\": "
+ "it may have been built with an "
+ "incompatible (more recent?) "
+ "version of Erlang~n", [Plugin]),
+ throw({plugin_built_with_incompatible_erlang, Plugin});
+ Error ->
+ throw({plugin_module_unloadable, Plugin, Error})
+ end
end.
%%----------------------------------------------------------------------------
@@ -475,6 +403,12 @@ delete_recursively(Fn) ->
{error, {Path, E}} -> {error, {cannot_delete, Path, E}}
end.
+prepare_plugin(#plugin{type = ez, location = Location}, ExpandDir) ->
+ zip:unzip(Location, [{cwd, ExpandDir}]);
+prepare_plugin(#plugin{type = dir, name = Name, location = Location},
+ ExpandDir) ->
+ rabbit_file:recursive_copy(Location, filename:join([ExpandDir, Name])).
+
plugin_info({ez, EZ}) ->
case read_app_file(EZ) of
{application, Name, Props} -> mkplugin(Name, Props, ez, EZ);
@@ -501,12 +435,14 @@ mkplugin(Name, Props, Type, Location) ->
broker_version_requirements = BrokerVersions,
dependency_version_requirements = DepsVersions}.
-find_app_path_in_ez(EZ) ->
+read_app_file(EZ) ->
case zip:list_dir(EZ) of
{ok, [_|ZippedFiles]} ->
case find_app_files(ZippedFiles) of
[AppPath|_] ->
- {ok, AppPath};
+ {ok, [{AppPath, AppFile}]} =
+ zip:extract(EZ, [{file_list, [AppPath]}, memory]),
+ parse_binary(AppFile);
[] ->
{error, no_app_file}
end;
@@ -514,16 +450,6 @@ find_app_path_in_ez(EZ) ->
{error, {invalid_ez, Reason}}
end.
-read_app_file(EZ) ->
- case find_app_path_in_ez(EZ) of
- {ok, AppPath} ->
- {ok, [{AppPath, AppFile}]} =
- zip:extract(EZ, [{file_list, [AppPath]}, memory]),
- parse_binary(AppFile);
- {error, Reason} ->
- {error, Reason}
- end.
-
find_app_files(ZippedFiles) ->
{ok, RE} = re:compile("^.*/ebin/.*.app$"),
[Path || {zip_file, Path, _, _, _, _} <- ZippedFiles,
diff --git a/test/plugins_SUITE.erl b/test/plugins_SUITE.erl
deleted file mode 100644
index 8896298df1..0000000000
--- a/test/plugins_SUITE.erl
+++ /dev/null
@@ -1,80 +0,0 @@
-%% The contents of this file are subject to the Mozilla Public License
-%% Version 1.1 (the "License"); you may not use this file except in
-%% compliance with the License. You may obtain a copy of the License at
-%% http://www.mozilla.org/MPL/
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-%% License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Original Code is RabbitMQ.
-%%
-%% The Initial Developer of the Original Code is GoPivotal, Inc.
-%% Copyright (c) 2016 Pivotal Software, Inc. All rights reserved.
-%%
-
--module(plugins_SUITE).
-
--include_lib("common_test/include/ct.hrl").
-
--compile(export_all).
-
-all() ->
- [
- active_with_single_plugin_dir,
- active_with_multiple_plugin_dirs
- ].
-
-%% -------------------------------------------------------------------
-%% Testsuite setup/teardown.
-%% -------------------------------------------------------------------
-
-init_per_suite(Config) ->
- rabbit_ct_helpers:log_environment(),
- application:load(rabbit),
- rabbit_ct_helpers:run_setup_steps(Config).
-
-end_per_suite(Config) ->
- rabbit_ct_helpers:run_teardown_steps(Config).
-
-init_per_group(_, Config) ->
- Config.
-
-end_per_group(_, Config) ->
- Config.
-
-init_per_testcase(Testcase, Config) ->
- rabbit_ct_helpers:testcase_started(Config, Testcase).
-
-end_per_testcase(Testcase, Config) ->
- rabbit_ct_helpers:testcase_finished(Config, Testcase).
-
-%% -------------------------------------------------------------------
-%% Testcases.
-%% -------------------------------------------------------------------
-
-active_with_single_plugin_dir(Config) ->
- DataDir = rabbit_ct_helpers:get_config(Config, data_dir),
- PluginsDir1 = filename:join(DataDir, "plugins1"),
-
- true = code:add_path(filename:join([PluginsDir1,
- "mock_rabbitmq_plugins_01-0.1.0.ez",
- "mock_rabbitmq_plugins_01-0.1.0", "ebin"])),
- {ok, _} = application:ensure_all_started(mock_rabbitmq_plugins_01),
- application:set_env(rabbit, plugins_dir, PluginsDir1),
-
- [mock_rabbitmq_plugins_01] = rabbit_plugins:active().
-
-active_with_multiple_plugin_dirs(Config) ->
- DataDir = rabbit_ct_helpers:get_config(Config, data_dir),
- PluginsDir1 = filename:join(DataDir, "plugins1"),
- PluginsDir2 = filename:join(DataDir, "plugins2"),
-
- true = code:add_path(filename:join([PluginsDir1,
- "mock_rabbitmq_plugins_01-0.1.0.ez",
- "mock_rabbitmq_plugins_01-0.1.0", "ebin"])),
- {ok, _} = application:ensure_all_started(mock_rabbitmq_plugins_01),
- application:set_env(rabbit, plugins_dir, PluginsDir1 ++ ":" ++ PluginsDir2),
-
- [mock_rabbitmq_plugins_01] = rabbit_plugins:active().
diff --git a/test/plugins_SUITE_data/plugins1/mock_rabbitmq_plugins_01-0.1.0.ez b/test/plugins_SUITE_data/plugins1/mock_rabbitmq_plugins_01-0.1.0.ez
deleted file mode 100644
index 40cba9f16b..0000000000
--- a/test/plugins_SUITE_data/plugins1/mock_rabbitmq_plugins_01-0.1.0.ez
+++ /dev/null
Binary files differ