fix(plugins): update plugin order on whole cluster
Fixes https://emqx.atlassian.net/browse/EMQX-10879
This commit is contained in:
parent
1cab687153
commit
4dfbc859f9
|
@ -20,6 +20,7 @@
|
||||||
-export([stop/1]).
|
-export([stop/1]).
|
||||||
|
|
||||||
-export([share_load_module/2]).
|
-export([share_load_module/2]).
|
||||||
|
-export([node_name/1]).
|
||||||
|
|
||||||
-define(APPS_CLUSTERING, [gen_rpc, mria, ekka]).
|
-define(APPS_CLUSTERING, [gen_rpc, mria, ekka]).
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
multipart_formdata_request/4,
|
multipart_formdata_request/4,
|
||||||
host/0,
|
host/0,
|
||||||
uri/0,
|
uri/0,
|
||||||
uri/1
|
uri/1,
|
||||||
|
uri/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(HOST, "http://127.0.0.1:18083").
|
-define(HOST, "http://127.0.0.1:18083").
|
||||||
|
@ -96,10 +97,15 @@ request(Username, Method, Url, Body) ->
|
||||||
host() ->
|
host() ->
|
||||||
?HOST.
|
?HOST.
|
||||||
|
|
||||||
uri() -> uri([]).
|
uri() ->
|
||||||
|
uri([]).
|
||||||
|
|
||||||
uri(Parts) when is_list(Parts) ->
|
uri(Parts) when is_list(Parts) ->
|
||||||
|
uri(host(), Parts).
|
||||||
|
|
||||||
|
uri(Host, Parts) when is_list(Host), is_list(Parts) ->
|
||||||
NParts = [E || E <- Parts],
|
NParts = [E || E <- Parts],
|
||||||
host() ++ "/" ++ to_list(filename:join([?BASE_PATH, ?API_VERSION | NParts])).
|
Host ++ "/" ++ to_list(filename:join([?BASE_PATH, ?API_VERSION | NParts])).
|
||||||
|
|
||||||
auth_header(Username) ->
|
auth_header(Username) ->
|
||||||
Password = <<"public">>,
|
Password = <<"public">>,
|
||||||
|
|
|
@ -420,7 +420,7 @@ update_boot_order(post, #{bindings := #{name := Name}, body := Body}) ->
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{400, #{code => 'BAD_POSITION', message => Reason}};
|
{400, #{code => 'BAD_POSITION', message => Reason}};
|
||||||
Position ->
|
Position ->
|
||||||
case emqx_plugins:ensure_enabled(Name, Position) of
|
case emqx_plugins:ensure_enabled(Name, Position, _ConfLocation = global) of
|
||||||
ok ->
|
ok ->
|
||||||
{200};
|
{200};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
|
|
|
@ -19,11 +19,14 @@
|
||||||
-compile(nowarn_export_all).
|
-compile(nowarn_export_all).
|
||||||
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
|
||||||
-define(EMQX_PLUGIN_TEMPLATE_NAME, "emqx_plugin_template").
|
-define(EMQX_PLUGIN_TEMPLATE_NAME, "emqx_plugin_template").
|
||||||
-define(EMQX_PLUGIN_TEMPLATE_VSN, "5.0.0").
|
-define(EMQX_PLUGIN_TEMPLATE_VSN, "5.0.0").
|
||||||
-define(PACKAGE_SUFFIX, ".tar.gz").
|
-define(PACKAGE_SUFFIX, ".tar.gz").
|
||||||
|
|
||||||
|
-define(CLUSTER_API_SERVER(PORT), ("http://127.0.0.1:" ++ (integer_to_list(PORT)))).
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
emqx_common_test_helpers:all(?MODULE).
|
emqx_common_test_helpers:all(?MODULE).
|
||||||
|
|
||||||
|
@ -48,6 +51,25 @@ end_per_suite(Config) ->
|
||||||
emqx_mgmt_api_test_util:end_suite([emqx_plugins, emqx_conf]),
|
emqx_mgmt_api_test_util:end_suite([emqx_plugins, emqx_conf]),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
init_per_testcase(t_cluster_update_order = TestCase, Config0) ->
|
||||||
|
Config = [{api_port, 18085} | Config0],
|
||||||
|
Cluster = [Node1 | _] = cluster(TestCase, Config),
|
||||||
|
{ok, API} = init_api(Node1),
|
||||||
|
[
|
||||||
|
{api, API},
|
||||||
|
{cluster, Cluster}
|
||||||
|
| Config
|
||||||
|
];
|
||||||
|
init_per_testcase(_TestCase, Config) ->
|
||||||
|
Config.
|
||||||
|
|
||||||
|
end_per_testcase(t_cluster_update_order, Config) ->
|
||||||
|
Cluster = ?config(cluster, Config),
|
||||||
|
emqx_cth_cluster:stop(Cluster),
|
||||||
|
ok;
|
||||||
|
end_per_testcase(_TestCase, _Config) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
t_plugins(Config) ->
|
t_plugins(Config) ->
|
||||||
DemoShDir = proplists:get_value(demo_sh_dir, Config),
|
DemoShDir = proplists:get_value(demo_sh_dir, Config),
|
||||||
PackagePath = get_demo_plugin_package(DemoShDir),
|
PackagePath = get_demo_plugin_package(DemoShDir),
|
||||||
|
@ -141,9 +163,83 @@ t_delete_non_existing(_Config) ->
|
||||||
),
|
),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
list_plugins() ->
|
t_cluster_update_order(Config) ->
|
||||||
Path = emqx_mgmt_api_test_util:api_path(["plugins"]),
|
DemoShDir = proplists:get_value(demo_sh_dir, Config),
|
||||||
case emqx_mgmt_api_test_util:request_api(get, Path) of
|
PackagePath1 = get_demo_plugin_package(DemoShDir),
|
||||||
|
NameVsn1 = filename:basename(PackagePath1, ?PACKAGE_SUFFIX),
|
||||||
|
Name2Str = ?EMQX_PLUGIN_TEMPLATE_NAME ++ "_a",
|
||||||
|
NameVsn2 = Name2Str ++ "-" ++ ?EMQX_PLUGIN_TEMPLATE_VSN,
|
||||||
|
PackagePath2 = create_renamed_package(PackagePath1, NameVsn2),
|
||||||
|
Name1 = list_to_binary(?EMQX_PLUGIN_TEMPLATE_NAME),
|
||||||
|
Name2 = list_to_binary(Name2Str),
|
||||||
|
|
||||||
|
ok = install_plugin(Config, PackagePath1),
|
||||||
|
ok = install_plugin(Config, PackagePath2),
|
||||||
|
%% to get them configured...
|
||||||
|
{ok, _} = update_plugin(Config, NameVsn1, "start"),
|
||||||
|
{ok, _} = update_plugin(Config, NameVsn2, "start"),
|
||||||
|
|
||||||
|
?assertMatch(
|
||||||
|
{ok, [
|
||||||
|
#{<<"name">> := Name1},
|
||||||
|
#{<<"name">> := Name2}
|
||||||
|
]},
|
||||||
|
list_plugins(Config)
|
||||||
|
),
|
||||||
|
|
||||||
|
ct:pal("moving to rear"),
|
||||||
|
?assertMatch({ok, _}, update_boot_order(NameVsn1, #{position => rear}, Config)),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, [
|
||||||
|
#{<<"name">> := Name2},
|
||||||
|
#{<<"name">> := Name1}
|
||||||
|
]},
|
||||||
|
list_plugins(Config)
|
||||||
|
),
|
||||||
|
|
||||||
|
ct:pal("moving to front"),
|
||||||
|
?assertMatch({ok, _}, update_boot_order(NameVsn1, #{position => front}, Config)),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, [
|
||||||
|
#{<<"name">> := Name1},
|
||||||
|
#{<<"name">> := Name2}
|
||||||
|
]},
|
||||||
|
list_plugins(Config)
|
||||||
|
),
|
||||||
|
|
||||||
|
ct:pal("moving after"),
|
||||||
|
NameVsn2Bin = list_to_binary(NameVsn2),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, _},
|
||||||
|
update_boot_order(NameVsn1, #{position => <<"after:", NameVsn2Bin/binary>>}, Config)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, [
|
||||||
|
#{<<"name">> := Name2},
|
||||||
|
#{<<"name">> := Name1}
|
||||||
|
]},
|
||||||
|
list_plugins(Config)
|
||||||
|
),
|
||||||
|
|
||||||
|
ct:pal("moving before"),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, _},
|
||||||
|
update_boot_order(NameVsn1, #{position => <<"before:", NameVsn2Bin/binary>>}, Config)
|
||||||
|
),
|
||||||
|
?assertMatch(
|
||||||
|
{ok, [
|
||||||
|
#{<<"name">> := Name1},
|
||||||
|
#{<<"name">> := Name2}
|
||||||
|
]},
|
||||||
|
list_plugins(Config)
|
||||||
|
),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
list_plugins(Config) ->
|
||||||
|
#{host := Host, auth := Auth} = get_host_and_auth(Config),
|
||||||
|
Path = emqx_mgmt_api_test_util:api_path(Host, ["plugins"]),
|
||||||
|
case emqx_mgmt_api_test_util:request_api(get, Path, Auth) of
|
||||||
{ok, Apps} -> {ok, emqx_utils_json:decode(Apps, [return_maps])};
|
{ok, Apps} -> {ok, emqx_utils_json:decode(Apps, [return_maps])};
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
@ -172,16 +268,46 @@ install_plugin(FilePath) ->
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
install_plugin(Config, FilePath) ->
|
||||||
|
#{host := Host, auth := Auth} = get_host_and_auth(Config),
|
||||||
|
Path = emqx_mgmt_api_test_util:api_path(Host, ["plugins", "install"]),
|
||||||
|
case
|
||||||
|
emqx_mgmt_api_test_util:upload_request(
|
||||||
|
Path,
|
||||||
|
FilePath,
|
||||||
|
"plugin",
|
||||||
|
<<"application/gzip">>,
|
||||||
|
[],
|
||||||
|
Auth
|
||||||
|
)
|
||||||
|
of
|
||||||
|
{ok, {{"HTTP/1.1", 200, "OK"}, _Headers, <<>>}} -> ok;
|
||||||
|
Error -> Error
|
||||||
|
end.
|
||||||
|
|
||||||
update_plugin(Name, Action) ->
|
update_plugin(Name, Action) ->
|
||||||
Path = emqx_mgmt_api_test_util:api_path(["plugins", Name, Action]),
|
Path = emqx_mgmt_api_test_util:api_path(["plugins", Name, Action]),
|
||||||
emqx_mgmt_api_test_util:request_api(put, Path).
|
emqx_mgmt_api_test_util:request_api(put, Path).
|
||||||
|
|
||||||
update_boot_order(Name, MoveBody) ->
|
update_plugin(Config, Name, Action) when is_list(Config) ->
|
||||||
Auth = emqx_mgmt_api_test_util:auth_header_(),
|
#{host := Host, auth := Auth} = get_host_and_auth(Config),
|
||||||
Path = emqx_mgmt_api_test_util:api_path(["plugins", Name, "move"]),
|
Path = emqx_mgmt_api_test_util:api_path(Host, ["plugins", Name, Action]),
|
||||||
|
emqx_mgmt_api_test_util:request_api(put, Path, Auth).
|
||||||
|
|
||||||
|
update_boot_order(Name, MoveBody, Config) ->
|
||||||
|
#{host := Host, auth := Auth} = get_host_and_auth(Config),
|
||||||
|
Path = emqx_mgmt_api_test_util:api_path(Host, ["plugins", Name, "move"]),
|
||||||
case emqx_mgmt_api_test_util:request_api(post, Path, "", Auth, MoveBody) of
|
case emqx_mgmt_api_test_util:request_api(post, Path, "", Auth, MoveBody) of
|
||||||
{ok, Res} -> {ok, emqx_utils_json:decode(Res, [return_maps])};
|
{ok, Res} ->
|
||||||
Error -> Error
|
Resp =
|
||||||
|
case emqx_utils_json:safe_decode(Res, [return_maps]) of
|
||||||
|
{ok, Decoded} -> Decoded;
|
||||||
|
{error, _} -> Res
|
||||||
|
end,
|
||||||
|
ct:pal("update_boot_order response:\n ~p", [Resp]),
|
||||||
|
{ok, Resp};
|
||||||
|
Error ->
|
||||||
|
Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
uninstall_plugin(Name) ->
|
uninstall_plugin(Name) ->
|
||||||
|
@ -218,3 +344,51 @@ update_release_json(["release.json"], FileContent, NewName) ->
|
||||||
emqx_utils_json:encode(ContentMap#{<<"name">> => NewName});
|
emqx_utils_json:encode(ContentMap#{<<"name">> => NewName});
|
||||||
update_release_json(_FileName, FileContent, _NewName) ->
|
update_release_json(_FileName, FileContent, _NewName) ->
|
||||||
FileContent.
|
FileContent.
|
||||||
|
|
||||||
|
cluster(TestCase, Config) ->
|
||||||
|
APIPort = ?config(api_port, Config),
|
||||||
|
AppSpecs = app_specs(Config),
|
||||||
|
Node1Apps = AppSpecs ++ [app_spec_dashboard(APIPort)],
|
||||||
|
Node2Apps = AppSpecs,
|
||||||
|
Node1Name = emqx_mgmt_api_plugins_SUITE1,
|
||||||
|
Node1 = emqx_cth_cluster:node_name(Node1Name),
|
||||||
|
emqx_cth_cluster:start(
|
||||||
|
[
|
||||||
|
{Node1Name, #{role => core, apps => Node1Apps, join_to => Node1}},
|
||||||
|
{emqx_mgmt_api_plugins_SUITE2, #{role => core, apps => Node2Apps, join_to => Node1}}
|
||||||
|
],
|
||||||
|
#{work_dir => filename:join(?config(priv_dir, Config), TestCase)}
|
||||||
|
).
|
||||||
|
|
||||||
|
app_specs(_Config) ->
|
||||||
|
[
|
||||||
|
emqx_conf,
|
||||||
|
emqx,
|
||||||
|
emqx_management,
|
||||||
|
emqx_plugins
|
||||||
|
].
|
||||||
|
|
||||||
|
app_spec_dashboard(APIPort) ->
|
||||||
|
{emqx_dashboard, #{
|
||||||
|
config =>
|
||||||
|
#{
|
||||||
|
dashboard =>
|
||||||
|
#{
|
||||||
|
listeners =>
|
||||||
|
#{
|
||||||
|
http =>
|
||||||
|
#{bind => APIPort}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}.
|
||||||
|
|
||||||
|
init_api(Node) ->
|
||||||
|
erpc:call(Node, emqx_common_test_http, create_default_app, []).
|
||||||
|
|
||||||
|
get_host_and_auth(Config) when is_list(Config) ->
|
||||||
|
API = ?config(api, Config),
|
||||||
|
APIPort = ?config(api_port, Config),
|
||||||
|
Host = ?CLUSTER_API_SERVER(APIPort),
|
||||||
|
Auth = emqx_common_test_http:auth_header(API),
|
||||||
|
#{host => Host, auth => Auth}.
|
||||||
|
|
|
@ -61,6 +61,9 @@ request(Method, Url, Body) ->
|
||||||
uri(Parts) ->
|
uri(Parts) ->
|
||||||
emqx_dashboard_api_test_helpers:uri(Parts).
|
emqx_dashboard_api_test_helpers:uri(Parts).
|
||||||
|
|
||||||
|
uri(Host, Parts) ->
|
||||||
|
emqx_dashboard_api_test_helpers:uri(Host, Parts).
|
||||||
|
|
||||||
%% compatible_mode will return as same as 'emqx_dashboard_api_test_helpers:request'
|
%% compatible_mode will return as same as 'emqx_dashboard_api_test_helpers:request'
|
||||||
request_api_with_body(Method, Url, Body) ->
|
request_api_with_body(Method, Url, Body) ->
|
||||||
Opts = #{compatible_mode => true, httpc_req_opts => [{body_format, binary}]},
|
Opts = #{compatible_mode => true, httpc_req_opts => [{body_format, binary}]},
|
||||||
|
@ -144,9 +147,15 @@ build_http_header(X) when is_list(X) ->
|
||||||
build_http_header(X) ->
|
build_http_header(X) ->
|
||||||
[X].
|
[X].
|
||||||
|
|
||||||
|
default_server() ->
|
||||||
|
?SERVER.
|
||||||
|
|
||||||
api_path(Parts) ->
|
api_path(Parts) ->
|
||||||
join_http_path([?SERVER, ?BASE_PATH | Parts]).
|
join_http_path([?SERVER, ?BASE_PATH | Parts]).
|
||||||
|
|
||||||
|
api_path(Host, Parts) ->
|
||||||
|
join_http_path([Host, ?BASE_PATH | Parts]).
|
||||||
|
|
||||||
api_path_without_base_path(Parts) ->
|
api_path_without_base_path(Parts) ->
|
||||||
join_http_path([?SERVER | Parts]).
|
join_http_path([?SERVER | Parts]).
|
||||||
|
|
||||||
|
@ -193,9 +202,13 @@ upload_request(URL, FilePath, Name, MimeType, RequestData, AuthorizationToken) -
|
||||||
ContentLength = integer_to_list(length(binary_to_list(RequestBody))),
|
ContentLength = integer_to_list(length(binary_to_list(RequestBody))),
|
||||||
Headers = [
|
Headers = [
|
||||||
{"Content-Length", ContentLength},
|
{"Content-Length", ContentLength},
|
||||||
case AuthorizationToken =/= undefined of
|
case AuthorizationToken of
|
||||||
true -> {"Authorization", "Bearer " ++ binary_to_list(AuthorizationToken)};
|
_ when is_tuple(AuthorizationToken) ->
|
||||||
false -> {}
|
AuthorizationToken;
|
||||||
|
_ when is_binary(AuthorizationToken) ->
|
||||||
|
{"Authorization", "Bearer " ++ binary_to_list(AuthorizationToken)};
|
||||||
|
_ ->
|
||||||
|
{}
|
||||||
end
|
end
|
||||||
],
|
],
|
||||||
HTTPOptions = [],
|
HTTPOptions = [],
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
{application, emqx_plugins, [
|
{application, emqx_plugins, [
|
||||||
{description, "EMQX Plugin Management"},
|
{description, "EMQX Plugin Management"},
|
||||||
{vsn, "0.1.5"},
|
{vsn, "0.1.6"},
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{mod, {emqx_plugins_app, []}},
|
{mod, {emqx_plugins_app, []}},
|
||||||
{applications, [kernel, stdlib, emqx]},
|
{applications, [kernel, stdlib, emqx]},
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
ensure_uninstalled/1,
|
ensure_uninstalled/1,
|
||||||
ensure_enabled/1,
|
ensure_enabled/1,
|
||||||
ensure_enabled/2,
|
ensure_enabled/2,
|
||||||
|
ensure_enabled/3,
|
||||||
ensure_disabled/1,
|
ensure_disabled/1,
|
||||||
purge/1,
|
purge/1,
|
||||||
delete_package/1
|
delete_package/1
|
||||||
|
@ -240,28 +241,34 @@ ensure_enabled(NameVsn) ->
|
||||||
%% @doc Ensure a plugin is enabled at the given position of the plugin list.
|
%% @doc Ensure a plugin is enabled at the given position of the plugin list.
|
||||||
-spec ensure_enabled(name_vsn(), position()) -> ok | {error, any()}.
|
-spec ensure_enabled(name_vsn(), position()) -> ok | {error, any()}.
|
||||||
ensure_enabled(NameVsn, Position) ->
|
ensure_enabled(NameVsn, Position) ->
|
||||||
ensure_state(NameVsn, Position, true).
|
ensure_state(NameVsn, Position, _Enabled = true, _ConfLocation = local).
|
||||||
|
|
||||||
|
-spec ensure_enabled(name_vsn(), position(), local | global) -> ok | {error, any()}.
|
||||||
|
ensure_enabled(NameVsn, Position, ConfLocation) when
|
||||||
|
ConfLocation =:= local; ConfLocation =:= global
|
||||||
|
->
|
||||||
|
ensure_state(NameVsn, Position, _Enabled = true, ConfLocation).
|
||||||
|
|
||||||
%% @doc Ensure a plugin is disabled.
|
%% @doc Ensure a plugin is disabled.
|
||||||
-spec ensure_disabled(name_vsn()) -> ok | {error, any()}.
|
-spec ensure_disabled(name_vsn()) -> ok | {error, any()}.
|
||||||
ensure_disabled(NameVsn) ->
|
ensure_disabled(NameVsn) ->
|
||||||
ensure_state(NameVsn, no_move, false).
|
ensure_state(NameVsn, no_move, false, _ConfLocation = local).
|
||||||
|
|
||||||
ensure_state(NameVsn, Position, State) when is_binary(NameVsn) ->
|
ensure_state(NameVsn, Position, State, ConfLocation) when is_binary(NameVsn) ->
|
||||||
ensure_state(binary_to_list(NameVsn), Position, State);
|
ensure_state(binary_to_list(NameVsn), Position, State, ConfLocation);
|
||||||
ensure_state(NameVsn, Position, State) ->
|
ensure_state(NameVsn, Position, State, ConfLocation) ->
|
||||||
case read_plugin(NameVsn, #{}) of
|
case read_plugin(NameVsn, #{}) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
Item = #{
|
Item = #{
|
||||||
name_vsn => NameVsn,
|
name_vsn => NameVsn,
|
||||||
enable => State
|
enable => State
|
||||||
},
|
},
|
||||||
tryit("ensure_state", fun() -> ensure_configured(Item, Position) end);
|
tryit("ensure_state", fun() -> ensure_configured(Item, Position, ConfLocation) end);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
ensure_configured(#{name_vsn := NameVsn} = Item, Position) ->
|
ensure_configured(#{name_vsn := NameVsn} = Item, Position, ConfLocation) ->
|
||||||
Configured = configured(),
|
Configured = configured(),
|
||||||
SplitFun = fun(#{name_vsn := Nv}) -> bin(Nv) =/= bin(NameVsn) end,
|
SplitFun = fun(#{name_vsn := Nv}) -> bin(Nv) =/= bin(NameVsn) end,
|
||||||
{Front, Rear} = lists:splitwith(SplitFun, Configured),
|
{Front, Rear} = lists:splitwith(SplitFun, Configured),
|
||||||
|
@ -274,7 +281,7 @@ ensure_configured(#{name_vsn := NameVsn} = Item, Position) ->
|
||||||
[] ->
|
[] ->
|
||||||
add_new_configured(Configured, Position, Item)
|
add_new_configured(Configured, Position, Item)
|
||||||
end,
|
end,
|
||||||
ok = put_configured(NewConfigured).
|
ok = put_configured(NewConfigured, ConfLocation).
|
||||||
|
|
||||||
add_new_configured(Configured, no_move, Item) ->
|
add_new_configured(Configured, no_move, Item) ->
|
||||||
%% default to rear
|
%% default to rear
|
||||||
|
@ -787,14 +794,23 @@ is_needed_by(AppToStop, RunningApp) ->
|
||||||
undefined -> false
|
undefined -> false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
put_config(Key, Value) when is_atom(Key) ->
|
put_config(Key, Value) ->
|
||||||
put_config([Key], Value);
|
put_config(Key, Value, _ConfLocation = local).
|
||||||
put_config(Path, Values) when is_list(Path) ->
|
|
||||||
|
put_config(Key, Value, ConfLocation) when is_atom(Key) ->
|
||||||
|
put_config([Key], Value, ConfLocation);
|
||||||
|
put_config(Path, Values, _ConfLocation = local) when is_list(Path) ->
|
||||||
Opts = #{rawconf_with_defaults => true, override_to => cluster},
|
Opts = #{rawconf_with_defaults => true, override_to => cluster},
|
||||||
%% Already in cluster_rpc, don't use emqx_conf:update, dead calls
|
%% Already in cluster_rpc, don't use emqx_conf:update, dead calls
|
||||||
case emqx:update_config([?CONF_ROOT | Path], bin_key(Values), Opts) of
|
case emqx:update_config([?CONF_ROOT | Path], bin_key(Values), Opts) of
|
||||||
{ok, _} -> ok;
|
{ok, _} -> ok;
|
||||||
Error -> Error
|
Error -> Error
|
||||||
|
end;
|
||||||
|
put_config(Path, Values, _ConfLocation = global) when is_list(Path) ->
|
||||||
|
Opts = #{rawconf_with_defaults => true, override_to => cluster},
|
||||||
|
case emqx_conf:update([?CONF_ROOT | Path], bin_key(Values), Opts) of
|
||||||
|
{ok, _} -> ok;
|
||||||
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
bin_key(Map) when is_map(Map) ->
|
bin_key(Map) when is_map(Map) ->
|
||||||
|
@ -812,7 +828,10 @@ get_config(Path, Default) ->
|
||||||
install_dir() -> get_config(install_dir, "").
|
install_dir() -> get_config(install_dir, "").
|
||||||
|
|
||||||
put_configured(Configured) ->
|
put_configured(Configured) ->
|
||||||
ok = put_config(states, bin_key(Configured)).
|
put_configured(Configured, _ConfLocation = local).
|
||||||
|
|
||||||
|
put_configured(Configured, ConfLocation) ->
|
||||||
|
ok = put_config(states, bin_key(Configured), ConfLocation).
|
||||||
|
|
||||||
configured() ->
|
configured() ->
|
||||||
get_config(states, []).
|
get_config(states, []).
|
||||||
|
|
|
@ -70,7 +70,7 @@ restart(NameVsn, LogFun) ->
|
||||||
?PRINT(emqx_plugins:restart(NameVsn), LogFun).
|
?PRINT(emqx_plugins:restart(NameVsn), LogFun).
|
||||||
|
|
||||||
ensure_enabled(NameVsn, Position, LogFun) ->
|
ensure_enabled(NameVsn, Position, LogFun) ->
|
||||||
?PRINT(emqx_plugins:ensure_enabled(NameVsn, Position), LogFun).
|
?PRINT(emqx_plugins:ensure_enabled(NameVsn, Position, _ConfLocation = global), LogFun).
|
||||||
|
|
||||||
ensure_disabled(NameVsn, LogFun) ->
|
ensure_disabled(NameVsn, LogFun) ->
|
||||||
?PRINT(emqx_plugins:ensure_disabled(NameVsn), LogFun).
|
?PRINT(emqx_plugins:ensure_disabled(NameVsn), LogFun).
|
||||||
|
|
|
@ -216,7 +216,7 @@ t_position(Config) ->
|
||||||
PosApp2 = <<"position-2">>,
|
PosApp2 = <<"position-2">>,
|
||||||
ok = write_info_file(Config, PosApp2, FakeInfo),
|
ok = write_info_file(Config, PosApp2, FakeInfo),
|
||||||
%% fake a disabled plugin in config
|
%% fake a disabled plugin in config
|
||||||
ok = emqx_plugins:ensure_state(PosApp2, {before, NameVsn}, false),
|
ok = ensure_state(PosApp2, {before, NameVsn}, false),
|
||||||
ListFun = fun() ->
|
ListFun = fun() ->
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(
|
fun(
|
||||||
|
@ -255,14 +255,14 @@ t_start_restart_and_stop(Config) ->
|
||||||
Bar2 = <<"bar-2">>,
|
Bar2 = <<"bar-2">>,
|
||||||
ok = write_info_file(Config, Bar2, FakeInfo),
|
ok = write_info_file(Config, Bar2, FakeInfo),
|
||||||
%% fake a disabled plugin in config
|
%% fake a disabled plugin in config
|
||||||
ok = emqx_plugins:ensure_state(Bar2, front, false),
|
ok = ensure_state(Bar2, front, false),
|
||||||
|
|
||||||
assert_app_running(emqx_plugin_template, false),
|
assert_app_running(emqx_plugin_template, false),
|
||||||
ok = emqx_plugins:ensure_started(),
|
ok = emqx_plugins:ensure_started(),
|
||||||
assert_app_running(emqx_plugin_template, true),
|
assert_app_running(emqx_plugin_template, true),
|
||||||
|
|
||||||
%% fake enable bar-2
|
%% fake enable bar-2
|
||||||
ok = emqx_plugins:ensure_state(Bar2, rear, true),
|
ok = ensure_state(Bar2, rear, true),
|
||||||
%% should cause an error
|
%% should cause an error
|
||||||
?assertError(
|
?assertError(
|
||||||
#{function := _, errors := [_ | _]},
|
#{function := _, errors := [_ | _]},
|
||||||
|
@ -274,7 +274,7 @@ t_start_restart_and_stop(Config) ->
|
||||||
%% stop all
|
%% stop all
|
||||||
ok = emqx_plugins:ensure_stopped(),
|
ok = emqx_plugins:ensure_stopped(),
|
||||||
assert_app_running(emqx_plugin_template, false),
|
assert_app_running(emqx_plugin_template, false),
|
||||||
ok = emqx_plugins:ensure_state(Bar2, rear, false),
|
ok = ensure_state(Bar2, rear, false),
|
||||||
|
|
||||||
ok = emqx_plugins:restart(NameVsn),
|
ok = emqx_plugins:restart(NameVsn),
|
||||||
assert_app_running(emqx_plugin_template, true),
|
assert_app_running(emqx_plugin_template, true),
|
||||||
|
@ -826,3 +826,7 @@ make_tar(Cwd, NameWithVsn, TarfileVsn) ->
|
||||||
after
|
after
|
||||||
file:set_cwd(OriginalCwd)
|
file:set_cwd(OriginalCwd)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
ensure_state(NameVsn, Position, Enabled) ->
|
||||||
|
%% NOTE: this is an internal function that is (legacy) exported in test builds only...
|
||||||
|
emqx_plugins:ensure_state(NameVsn, Position, Enabled, _ConfLocation = local).
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed an issue that prevented the plugin order to be updated on the whole cluster.
|
Loading…
Reference in New Issue