Merge pull request #11229 from thalesmg/fix-plugin-load-conf-master

fix(plugins): start/stop plugins when loading config from CLI
This commit is contained in:
Thales Macedo Garitezi 2023-07-07 16:36:48 -03:00 committed by GitHub
commit 0d1abf7d8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 3 deletions

View File

@ -1,7 +1,7 @@
%% -*- mode: erlang -*-
{application, emqx_plugins, [
{description, "EMQX Plugin Management"},
{vsn, "0.1.4"},
{vsn, "0.1.5"},
{modules, []},
{mod, {emqx_plugins_app, []}},
{applications, [kernel, stdlib, emqx]},

View File

@ -51,6 +51,11 @@
get_tar/1
]).
%% `emqx_config_handler' API
-export([
post_config_update/5
]).
%% internal
-export([do_ensure_started/1]).
-export([
@ -857,3 +862,27 @@ running_apps() ->
end,
application:which_applications(infinity)
).
%%--------------------------------------------------------------------
%% `emqx_config_handler' API
%%--------------------------------------------------------------------
post_config_update([?CONF_ROOT], _Req, #{states := NewStates}, #{states := OldStates}, _Envs) ->
NewStatesIndex = maps:from_list([{NV, S} || S = #{name_vsn := NV} <- NewStates]),
OldStatesIndex = maps:from_list([{NV, S} || S = #{name_vsn := NV} <- OldStates]),
#{changed := Changed} = emqx_utils_maps:diff_maps(NewStatesIndex, OldStatesIndex),
maps:foreach(fun enable_disable_plugin/2, Changed),
ok;
post_config_update(_Path, _Req, _NewConf, _OldConf, _Envs) ->
ok.
enable_disable_plugin(NameVsn, {#{enable := true}, #{enable := false}}) ->
%% errors are already logged in this fn
_ = ensure_stopped(NameVsn),
ok;
enable_disable_plugin(NameVsn, {#{enable := false}, #{enable := true}}) ->
%% errors are already logged in this fn
_ = ensure_started(NameVsn),
ok;
enable_disable_plugin(_NameVsn, _Diff) ->
ok.

View File

@ -18,6 +18,8 @@
-behaviour(application).
-include("emqx_plugins.hrl").
-export([
start/2,
stop/1
@ -27,7 +29,9 @@ start(_Type, _Args) ->
%% load all pre-configured
ok = emqx_plugins:ensure_started(),
{ok, Sup} = emqx_plugins_sup:start_link(),
ok = emqx_config_handler:add_handler([?CONF_ROOT], emqx_plugins),
{ok, Sup}.
stop(_State) ->
ok = emqx_config_handler:remove_handler([?CONF_ROOT]),
ok.

View File

@ -65,7 +65,7 @@ init_per_suite(Config) ->
WorkDir = proplists:get_value(data_dir, Config),
filelib:ensure_path(WorkDir),
OrigInstallDir = emqx_plugins:get_config(install_dir, undefined),
emqx_common_test_helpers:start_apps([emqx_conf]),
emqx_common_test_helpers:start_apps([emqx_conf, emqx_plugins]),
emqx_plugins:put_config(install_dir, WorkDir),
[{orig_install_dir, OrigInstallDir} | Config].
@ -77,7 +77,7 @@ end_per_suite(Config) ->
undefined -> ok;
OrigInstallDir -> emqx_plugins:put_config(install_dir, OrigInstallDir)
end,
emqx_common_test_helpers:stop_apps([emqx_conf]),
emqx_common_test_helpers:stop_apps([emqx_plugins, emqx_conf]),
ok.
init_per_testcase(TestCase, Config) ->
@ -505,6 +505,65 @@ t_elixir_plugin(Config) ->
?assertEqual([], emqx_plugins:list()),
ok.
t_load_config_from_cli({init, Config}) ->
#{package := Package} = get_demo_plugin_package(),
NameVsn = filename:basename(Package, ?PACKAGE_SUFFIX),
[{name_vsn, NameVsn} | Config];
t_load_config_from_cli({'end', Config}) ->
NameVsn = ?config(name_vsn, Config),
ok = emqx_plugins:ensure_stopped(NameVsn),
ok = emqx_plugins:ensure_uninstalled(NameVsn),
ok;
t_load_config_from_cli(Config) when is_list(Config) ->
NameVsn = ?config(name_vsn, Config),
ok = emqx_plugins:ensure_installed(NameVsn),
?assertEqual([], emqx_plugins:configured()),
ok = emqx_plugins:ensure_enabled(NameVsn),
ok = emqx_plugins:ensure_started(NameVsn),
Params0 = unused,
?assertMatch(
{200, [#{running_status := [#{status := running}]}]},
emqx_mgmt_api_plugins:list_plugins(get, Params0)
),
%% Now we disable it via CLI loading
Conf0 = emqx_config:get([plugins]),
?assertMatch(
#{states := [#{enable := true}]},
Conf0
),
#{states := [Plugin0]} = Conf0,
Conf1 = Conf0#{states := [Plugin0#{enable := false}]},
Filename = filename:join(["/tmp", [?FUNCTION_NAME, ".hocon"]]),
ok = file:write_file(Filename, hocon_pp:do(#{plugins => Conf1}, #{})),
ok = emqx_conf_cli:conf(["load", Filename]),
Conf2 = emqx_config:get([plugins]),
?assertMatch(
#{states := [#{enable := false}]},
Conf2
),
?assertMatch(
{200, [#{running_status := [#{status := stopped}]}]},
emqx_mgmt_api_plugins:list_plugins(get, Params0)
),
%% Re-enable it via CLI loading
ok = file:write_file(Filename, hocon_pp:do(#{plugins => Conf0}, #{})),
ok = emqx_conf_cli:conf(["load", Filename]),
Conf3 = emqx_config:get([plugins]),
?assertMatch(
#{states := [#{enable := true}]},
Conf3
),
?assertMatch(
{200, [#{running_status := [#{status := running}]}]},
emqx_mgmt_api_plugins:list_plugins(get, Params0)
),
ok.
group_t_copy_plugin_to_a_new_node({init, Config}) ->
WorkDir = proplists:get_value(data_dir, Config),
FromInstallDir = filename:join(WorkDir, atom_to_list(plugins_copy_from)),

View File

@ -0,0 +1 @@
Fixed an issue preventing plugins from starting/stopping after changing configuration via `emqx ctl conf load`.