Merge pull request #9692 from thalesmg/sync-e4413-ce-changes-rv44
chore: sync ee changes back into ce repo (re44)
This commit is contained in:
commit
1f49bc9c59
|
@ -1,6 +1,6 @@
|
||||||
{application, emqx_management,
|
{application, emqx_management,
|
||||||
[{description, "EMQ X Management API and CLI"},
|
[{description, "EMQ X Management API and CLI"},
|
||||||
{vsn, "4.4.11"}, % strict semver, bump manually!
|
{vsn, "4.4.12"}, % strict semver, bump manually!
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_management_sup]},
|
{registered, [emqx_management_sup]},
|
||||||
{applications, [kernel,stdlib,emqx_plugin_libs,minirest]},
|
{applications, [kernel,stdlib,emqx_plugin_libs,minirest]},
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
, del_app/1
|
, del_app/1
|
||||||
, list_apps/0
|
, list_apps/0
|
||||||
, init_bootstrap_apps/0
|
, init_bootstrap_apps/0
|
||||||
, need_bootstrap/0
|
|
||||||
, clear_bootstrap_apps/0
|
, clear_bootstrap_apps/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -83,21 +82,8 @@ add_default_app() ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
init_bootstrap_apps() ->
|
init_bootstrap_apps() ->
|
||||||
case need_bootstrap() of
|
Bootstrap = application:get_env(emqx_management, bootstrap_apps_file, undefined),
|
||||||
true ->
|
init_bootstrap_apps(Bootstrap).
|
||||||
Bootstrap = application:get_env(emqx_management, bootstrap_apps_file, undefined),
|
|
||||||
init_bootstrap_apps(Bootstrap);
|
|
||||||
false ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
need_bootstrap() ->
|
|
||||||
{atomic, Res} = mnesia:transaction(
|
|
||||||
fun() ->
|
|
||||||
Spec = [{#mqtt_app{id = '$1', desc = ?BOOTSTRAP_TAG, _ = '_'}, [], ['$1']}],
|
|
||||||
mnesia:select(mqtt_app, Spec, 1, read) =:= '$end_of_table'
|
|
||||||
end),
|
|
||||||
Res.
|
|
||||||
|
|
||||||
clear_bootstrap_apps() ->
|
clear_bootstrap_apps() ->
|
||||||
{atomic, ok} =
|
{atomic, ok} =
|
||||||
|
@ -113,13 +99,7 @@ init_bootstrap_apps(File) ->
|
||||||
case file:open(File, [read, binary]) of
|
case file:open(File, [read, binary]) of
|
||||||
{ok, Dev} ->
|
{ok, Dev} ->
|
||||||
{ok, MP} = re:compile(<<"(\.+):(\.+$)">>, [ungreedy]),
|
{ok, MP} = re:compile(<<"(\.+):(\.+$)">>, [ungreedy]),
|
||||||
case init_bootstrap_apps(File, Dev, MP) of
|
init_bootstrap_apps(File, Dev, MP);
|
||||||
ok -> ok;
|
|
||||||
Error ->
|
|
||||||
%% if failed add bootstrap users, we should clear all bootstrap apps
|
|
||||||
clear_bootstrap_apps(),
|
|
||||||
Error
|
|
||||||
end;
|
|
||||||
{error, Reason} = Error ->
|
{error, Reason} = Error ->
|
||||||
?LOG(error,
|
?LOG(error,
|
||||||
"failed to open the mgmt bootstrap apps file(~s) for ~p",
|
"failed to open the mgmt bootstrap apps file(~s) for ~p",
|
||||||
|
@ -145,8 +125,8 @@ add_bootstrap_app(File, Dev, MP, Line) ->
|
||||||
case re:run(Bin, MP, [global, {capture, all_but_first, binary}]) of
|
case re:run(Bin, MP, [global, {capture, all_but_first, binary}]) of
|
||||||
{match, [[AppId, AppSecret]]} ->
|
{match, [[AppId, AppSecret]]} ->
|
||||||
Name = <<"bootstraped">>,
|
Name = <<"bootstraped">>,
|
||||||
case add_app(AppId, Name, AppSecret, ?BOOTSTRAP_TAG, true, undefined) of
|
case force_add_app(AppId, Name, AppSecret, ?BOOTSTRAP_TAG, true, undefined) of
|
||||||
{ok, _} ->
|
ok ->
|
||||||
add_bootstrap_app(File, Dev, MP, Line + 1);
|
add_bootstrap_app(File, Dev, MP, Line + 1);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
throw(#{file => File, line => Line, content => Bin, reason => Reason})
|
throw(#{file => File, line => Line, content => Bin, reason => Reason})
|
||||||
|
|
|
@ -66,6 +66,70 @@ t_importee430(_) ->
|
||||||
{ok, _} = emqx_mgmt_data_backup:export(),
|
{ok, _} = emqx_mgmt_data_backup:export(),
|
||||||
remove_all_users_and_acl().
|
remove_all_users_and_acl().
|
||||||
|
|
||||||
|
t_import_test(_) ->
|
||||||
|
SimpleAdmin = <<"simpleAdmin">>,
|
||||||
|
SimplePassword = <<"simplepassword">>,
|
||||||
|
SimplePasswordHash = emqx_dashboard_admin:hash(SimplePassword),
|
||||||
|
|
||||||
|
Admins = [<<"Admin1">>, <<"Admin2">>, <<"Admin3">>, <<"Admin4">>, <<"Admin5">>],
|
||||||
|
Passwords = [<<"password1">>, <<"PAssword2">>,<<"3&*)dkdKlkd">>,<<"&*qwl4kd>">>,<<"PASSWORD5D">>],
|
||||||
|
|
||||||
|
%% add some users
|
||||||
|
add_admins(Admins, Passwords),
|
||||||
|
%% Allow force import simple password.
|
||||||
|
ok = emqx_dashboard_admin:force_add_user(SimpleAdmin, SimplePasswordHash, <<"test">>),
|
||||||
|
|
||||||
|
ct:pal("1111~p~n", [ets:info(mqtt_admin)]),
|
||||||
|
ct:pal("~p~n", [ets:tab2list(mqtt_admin)]),
|
||||||
|
check_admins_ok(Admins, Passwords),
|
||||||
|
|
||||||
|
{ok, #{filename := FileName}} = emqx_mgmt_data_backup:export(),
|
||||||
|
|
||||||
|
remove_admins(Admins),
|
||||||
|
ok = emqx_dashboard_admin:remove_user(SimpleAdmin),
|
||||||
|
ct:pal("0000~n"),
|
||||||
|
check_admins_failed(Admins, Passwords),
|
||||||
|
{error, _} = emqx_dashboard_admin:check(SimpleAdmin, SimplePassword),
|
||||||
|
|
||||||
|
ok = emqx_mgmt_data_backup:import(FileName, <<"{}">>),
|
||||||
|
ct:pal("2222~n"),
|
||||||
|
check_admins_ok(Admins, Passwords),
|
||||||
|
ok = emqx_dashboard_admin:check(SimpleAdmin, SimplePassword),
|
||||||
|
|
||||||
|
remove_admins(Admins),
|
||||||
|
ok = emqx_dashboard_admin:remove_user(SimpleAdmin),
|
||||||
|
|
||||||
|
remove_all_users_and_acl(),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
add_admins(Admins, Passwords) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({Admin, Password}) ->
|
||||||
|
ok = emqx_dashboard_admin:add_user(Admin, Password, <<"test">>)
|
||||||
|
end, lists:zip(Admins, Passwords)),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
check_admins_ok(Admins, Passwords) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({Admin, Password}) ->
|
||||||
|
?assertMatch(ok, emqx_dashboard_admin:check(Admin, Password), {Admin, Password})
|
||||||
|
end, lists:zip(Admins, Passwords)),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
check_admins_failed(Admins, Passwords) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({Admin, Password}) ->
|
||||||
|
?assertMatch({error, _}, emqx_dashboard_admin:check(Admin, Password), {Admin, Password})
|
||||||
|
end, lists:zip(Admins, Passwords)),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
remove_admins(Admins) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(Admin) ->
|
||||||
|
ok = emqx_dashboard_admin:remove_user(Admin)
|
||||||
|
end, Admins),
|
||||||
|
ok.
|
||||||
|
|
||||||
remove_all_users_and_acl() ->
|
remove_all_users_and_acl() ->
|
||||||
mnesia:delete_table(emqx_user),
|
mnesia:delete_table(emqx_user),
|
||||||
mnesia:delete_table(emqx_acl).
|
mnesia:delete_table(emqx_acl).
|
||||||
|
|
|
@ -68,10 +68,10 @@ t_load_ok(_) ->
|
||||||
ok = file:write_file(File, Bin1),
|
ok = file:write_file(File, Bin1),
|
||||||
application:set_env(emqx_management, bootstrap_apps_file, File),
|
application:set_env(emqx_management, bootstrap_apps_file, File),
|
||||||
{ok, _} = application:ensure_all_started(emqx_management),
|
{ok, _} = application:ensure_all_started(emqx_management),
|
||||||
?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"secret-1">>)),
|
?assertNot(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"secret-1">>)),
|
||||||
?assert(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"secret-2">>)),
|
?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"secret-2">>)),
|
||||||
?assertNot(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"new-secret-1">>)),
|
?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"new-secret-1">>)),
|
||||||
?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"new-secret-2">>)),
|
?assert(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"new-secret-2">>)),
|
||||||
application:stop(emqx_management).
|
application:stop(emqx_management).
|
||||||
|
|
||||||
t_bootstrap_user_file_not_found(_) ->
|
t_bootstrap_user_file_not_found(_) ->
|
||||||
|
@ -84,13 +84,17 @@ t_load_invalid_username_failed(_) ->
|
||||||
File = "./bootstrap_apps.txt",
|
File = "./bootstrap_apps.txt",
|
||||||
ok = file:write_file(File, Bin),
|
ok = file:write_file(File, Bin),
|
||||||
check_load_failed(File),
|
check_load_failed(File),
|
||||||
|
?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"password-1">>)),
|
||||||
|
?assertNot(emqx_mgmt_auth:is_authorized(<<"test&2">>, <<"password-2">>)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_load_invalid_format_failed(_) ->
|
t_load_invalid_format_failed(_) ->
|
||||||
Bin = <<"test-1:password-1\ntest-2password-2">>,
|
Bin = <<"test-1:password-1\ntest-2 password-2">>,
|
||||||
File = "./bootstrap_apps.txt",
|
File = "./bootstrap_apps.txt",
|
||||||
ok = file:write_file(File, Bin),
|
ok = file:write_file(File, Bin),
|
||||||
check_load_failed(File),
|
check_load_failed(File),
|
||||||
|
?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"password-1">>)),
|
||||||
|
?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"password-2">>)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
check_load_failed(File) ->
|
check_load_failed(File) ->
|
||||||
|
@ -98,5 +102,4 @@ check_load_failed(File) ->
|
||||||
application:stop(emqx_management),
|
application:stop(emqx_management),
|
||||||
application:set_env(emqx_management, bootstrap_apps_file, File),
|
application:set_env(emqx_management, bootstrap_apps_file, File),
|
||||||
?assertMatch({error, _}, application:ensure_all_started(emqx_management)),
|
?assertMatch({error, _}, application:ensure_all_started(emqx_management)),
|
||||||
?assertNot(lists:member(emqx_management, application:which_applications())),
|
?assertNot(lists:member(emqx_management, application:which_applications())).
|
||||||
?assert(emqx_mgmt_auth:need_bootstrap()).
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{application, emqx_rule_engine,
|
{application, emqx_rule_engine,
|
||||||
[{description, "EMQ X Rule Engine"},
|
[{description, "EMQ X Rule Engine"},
|
||||||
{vsn, "4.4.13"}, % strict semver, bump manually!
|
{vsn, "4.4.14"}, % strict semver, bump manually!
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_rule_engine_sup, emqx_rule_registry, emqx_rule_engine_jwt_sup]},
|
{registered, [emqx_rule_engine_sup, emqx_rule_registry, emqx_rule_engine_jwt_sup]},
|
||||||
{applications, [kernel,stdlib,rulesql,getopt,jose]},
|
{applications, [kernel,stdlib,rulesql,getopt,jose]},
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
%% Unless you know what you are doing, DO NOT edit manually!!
|
%% Unless you know what you are doing, DO NOT edit manually!!
|
||||||
{VSN,
|
{VSN,
|
||||||
[{"4.4.12",
|
[{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
|
||||||
|
{"4.4.12",
|
||||||
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
|
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
|
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
|
||||||
{update,emqx_rule_engine_jwt_sup,supervisor},
|
{update,emqx_rule_engine_jwt_sup,supervisor},
|
||||||
|
@ -220,7 +221,8 @@
|
||||||
{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
|
{load_module,emqx_rule_engine,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}]},
|
{load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}]},
|
||||||
{<<".*">>,[]}],
|
{<<".*">>,[]}],
|
||||||
[{"4.4.12",
|
[{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]},
|
||||||
|
{"4.4.12",
|
||||||
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
|
[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
|
{load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]},
|
||||||
{update,emqx_rule_engine_jwt_sup,supervisor},
|
{update,emqx_rule_engine_jwt_sup,supervisor},
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# v4.4.14
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
- Add a password complexity requirement when adding or modifying Dashboard users via the API. Now passwords must contain at least 2 of alphabetic, numeric and special characters, and must be 8 to 64 characters long [#1696](https://github.com/emqx/emqx-enterprise/pull/1696).
|
||||||
|
|
||||||
|
## Bug fixes
|
||||||
|
|
||||||
|
- Fix dashboard password validator is too simple. Now dashboard password must contain at least two different kind of characters from groups of letters, numbers and special characters. [#1696](https://github.com/emqx/emqx-enterprise/pull/1696).
|
||||||
|
- Fix the problem that adding or importing Dashboard users via the API fails to add complex passwords due to incorrect checksum of the passwords [#1696](https://github.com/emqx/emqx-enterprise/pull/1696).
|
||||||
|
|
||||||
|
- Fix load bootstrap_app_file's apps is not sync when reboot. [#1697](https://github.com/emqx/emqx-enterprise/pull/1697).
|
|
@ -0,0 +1,11 @@
|
||||||
|
# v4.4.14
|
||||||
|
|
||||||
|
## 增强
|
||||||
|
|
||||||
|
- 通过 API 添加、修改 Dashboard 用户时,增加对密码复杂度的要求。现在密码必须包含字母、数字以及特殊字符中的至少 2 种,并且长度范围必须是 8~64 个字符 [#1696](https://github.com/emqx/emqx-enterprise/pull/1696)。
|
||||||
|
|
||||||
|
## 修复
|
||||||
|
|
||||||
|
- 修复通过 API 添加或者导入 Dashboard 用户时,对密码进行了错误的校验,导致复杂密码添加失败的问题 [#1696](https://github.com/emqx/emqx-enterprise/pull/1696)。
|
||||||
|
|
||||||
|
- 修复 boostrap_apps_file 文件更新后没有同步更新至数据库导致文件中新加 apps 未生效 [#1697](https://github.com/emqx/emqx-enterprise/pull/1697)。
|
|
@ -57,7 +57,14 @@
|
||||||
<<"4.4.2">>,<<"4.4.3">>,<<"4.4.4">>,<<"4.4.5">>,<<"4.4.6">>,
|
<<"4.4.2">>,<<"4.4.3">>,<<"4.4.4">>,<<"4.4.5">>,<<"4.4.6">>,
|
||||||
<<"4.4.7">>,<<"4.4.8">>,<<"4.4.9">>],
|
<<"4.4.7">>,<<"4.4.8">>,<<"4.4.9">>],
|
||||||
otp => <<"24.3.4.2-1">>}}.
|
otp => <<"24.3.4.2-1">>}}.
|
||||||
|
{<<"4.4.14">>,
|
||||||
|
#{from_versions =>
|
||||||
|
[<<"4.4.0">>,<<"4.4.1">>,<<"4.4.10">>,<<"4.4.11">>,<<"4.4.12">>,
|
||||||
|
<<"4.4.13">>,<<"4.4.2">>,<<"4.4.3">>,<<"4.4.4">>,<<"4.4.5">>,
|
||||||
|
<<"4.4.6">>,<<"4.4.7">>,<<"4.4.8">>,<<"4.4.9">>],
|
||||||
|
otp => <<"24.3.4.2-1">>}}.
|
||||||
{<<"4.5.0">>,
|
{<<"4.5.0">>,
|
||||||
#{from_versions =>
|
#{from_versions =>
|
||||||
[<<"4.4.10">>,<<"4.4.11">>,<<"4.4.13">>,<<"4.4.8">>,<<"4.4.9">>],
|
[<<"4.4.10">>,<<"4.4.11">>,<<"4.4.13">>,<<"4.4.14">>,<<"4.4.8">>,
|
||||||
|
<<"4.4.9">>],
|
||||||
otp => <<"24.3.4.2-1">>}}.
|
otp => <<"24.3.4.2-1">>}}.
|
||||||
|
|
|
@ -13,8 +13,8 @@ type: application
|
||||||
|
|
||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
version: 4.4.13
|
version: 4.4.14
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application.
|
# incremented each time you make changes to the application.
|
||||||
appVersion: 4.4.13
|
appVersion: 4.4.14
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
-ifndef(EMQX_ENTERPRISE).
|
-ifndef(EMQX_ENTERPRISE).
|
||||||
|
|
||||||
-define(EMQX_RELEASE, {opensource, "4.4.13"}).
|
-define(EMQX_RELEASE, {opensource, "4.4.14"}).
|
||||||
|
|
||||||
-else.
|
-else.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{application, emqx_dashboard,
|
{application, emqx_dashboard,
|
||||||
[{description, "EMQX Web Dashboard"},
|
[{description, "EMQX Web Dashboard"},
|
||||||
{vsn, "4.4.12"}, % strict semver, bump manually!
|
{vsn, "4.4.13"}, % strict semver, bump manually!
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, [emqx_dashboard_sup]},
|
{registered, [emqx_dashboard_sup]},
|
||||||
{applications, [kernel,stdlib,mnesia,minirest]},
|
{applications, [kernel,stdlib,mnesia,minirest]},
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
%% the emqx `release' version, which in turn is comprised of several
|
%% the emqx `release' version, which in turn is comprised of several
|
||||||
%% apps, one of which is this. See `emqx_release.hrl' for more
|
%% apps, one of which is this. See `emqx_release.hrl' for more
|
||||||
%% info.
|
%% info.
|
||||||
{vsn, "4.4.13"}, % strict semver, bump manually!
|
{vsn, "4.4.14"}, % strict semver, bump manually!
|
||||||
{modules, []},
|
{modules, []},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications, [ kernel
|
{applications, [ kernel
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
%% Unless you know what you are doing, DO NOT edit manually!!
|
%% Unless you know what you are doing, DO NOT edit manually!!
|
||||||
{VSN,
|
{VSN,
|
||||||
[{"4.4.12",
|
[{"4.4.13",
|
||||||
|
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
||||||
|
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
||||||
|
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
||||||
|
{"4.4.12",
|
||||||
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
||||||
|
@ -393,7 +397,11 @@
|
||||||
{apply,{application,set_env,
|
{apply,{application,set_env,
|
||||||
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
|
[gen_rpc,insecure_auth_fallback_allowed,true]}}]},
|
||||||
{<<".*">>,[]}],
|
{<<".*">>,[]}],
|
||||||
[{"4.4.12",
|
[{"4.4.13",
|
||||||
|
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
||||||
|
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
||||||
|
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
||||||
|
{"4.4.12",
|
||||||
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
[{load_module,emqx_cm,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
{load_module,emqx_relup,brutal_purge,soft_purge,[]},
|
||||||
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
{load_module,emqx_app,brutal_purge,soft_purge,[]}]},
|
||||||
|
|
Loading…
Reference in New Issue