From b515a45a4f7ba70573420491961d994682f2f70c Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 18:24:59 +0200 Subject: [PATCH 01/88] chore(mria): Rename module: ekka_mnesia -> mria --- apps/emqx/rebar.config | 2 +- apps/emqx/src/emqx_alarm.erl | 12 ++--- apps/emqx/src/emqx_banned.erl | 16 +++---- apps/emqx/src/emqx_cm_registry.erl | 6 +-- apps/emqx/src/emqx_router.erl | 6 +-- apps/emqx/src/emqx_router_helper.erl | 6 +-- apps/emqx/src/emqx_shared_sub.erl | 8 ++-- apps/emqx/test/props/prop_emqx_sys.erl | 2 +- .../emqx_enhanced_authn_scram_mnesia.erl | 2 +- .../src/simple_authn/emqx_authn_mnesia.erl | 2 +- apps/emqx_authz/src/emqx_authz_api_mnesia.erl | 46 +++++++++---------- .../test/emqx_authz_mnesia_SUITE.erl | 29 ++++++------ .../src/emqx_dashboard_admin.erl | 10 ++-- .../src/emqx_dashboard_collection.erl | 2 +- .../src/emqx_dashboard_token.erl | 6 +-- .../test/emqx_dashboard_SUITE.erl | 2 +- .../src/emqx_gateway_cm_registry.erl | 6 +-- .../src/mqttsn/emqx_sn_registry.erl | 20 ++++---- apps/emqx_machine/src/emqx_cluster_rpc.erl | 2 +- .../src/emqx_cluster_rpc_handler.erl | 2 +- apps/emqx_modules/src/emqx_delayed.erl | 8 ++-- apps/emqx_modules/src/emqx_telemetry.erl | 4 +- apps/emqx_psk/src/emqx_psk.erl | 2 +- .../src/emqx_retainer_mnesia.erl | 16 +++---- rebar.config | 2 +- 25 files changed, 109 insertions(+), 110 deletions(-) diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index b851700b9..0c8f5e7ba 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -15,7 +15,7 @@ , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.8.3"}}} , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} - , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.10.9"}}} + , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.0"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.19.6"}}} , {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}} diff --git a/apps/emqx/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl index 2df126ea7..412880bad 100644 --- a/apps/emqx/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -201,7 +201,7 @@ handle_call({activate_alarm, Name, Details}, _From, State) -> details = Details, message = normalize_message(Name, Details), activate_at = erlang:system_time(microsecond)}, - ekka_mnesia:dirty_write(?ACTIVATED_ALARM, Alarm), + mria:dirty_write(?ACTIVATED_ALARM, Alarm), do_actions(activate, Alarm, emqx:get_config([alarm, actions])), {reply, ok, State} end; @@ -282,7 +282,7 @@ deactivate_alarm(Details, #activated_alarm{activate_at = ActivateAt, name = Name case mnesia:dirty_first(?DEACTIVATED_ALARM) of '$end_of_table' -> ok; ActivateAt2 -> - ekka_mnesia:dirty_delete(?DEACTIVATED_ALARM, ActivateAt2) + mria:dirty_delete(?DEACTIVATED_ALARM, ActivateAt2) end; false -> ok end, @@ -291,8 +291,8 @@ deactivate_alarm(Details, #activated_alarm{activate_at = ActivateAt, name = Name DeActAlarm = make_deactivated_alarm(ActivateAt, Name, Details, normalize_message(Name, Details), erlang:system_time(microsecond)), - ekka_mnesia:dirty_write(?DEACTIVATED_ALARM, HistoryAlarm), - ekka_mnesia:dirty_delete(?ACTIVATED_ALARM, Name), + mria:dirty_write(?DEACTIVATED_ALARM, HistoryAlarm), + mria:dirty_delete(?ACTIVATED_ALARM, Name), do_actions(deactivate, DeActAlarm, emqx:get_config([alarm, actions])). make_deactivated_alarm(ActivateAt, Name, Details, Message, DeActivateAt) -> @@ -309,7 +309,7 @@ deactivate_all_alarms() -> details = Details, message = Message, activate_at = ActivateAt}) -> - ekka_mnesia:dirty_write(?DEACTIVATED_ALARM, + mria:dirty_write(?DEACTIVATED_ALARM, #deactivated_alarm{ activate_at = ActivateAt, name = Name, @@ -347,7 +347,7 @@ delete_expired_deactivated_alarms('$end_of_table', _Checkpoint) -> delete_expired_deactivated_alarms(ActivatedAt, Checkpoint) -> case ActivatedAt =< Checkpoint of true -> - ekka_mnesia:dirty_delete(?DEACTIVATED_ALARM, ActivatedAt), + mria:dirty_delete(?DEACTIVATED_ALARM, ActivatedAt), NActivatedAt = mnesia:dirty_next(?DEACTIVATED_ALARM, ActivatedAt), delete_expired_deactivated_alarms(NActivatedAt, Checkpoint); false -> diff --git a/apps/emqx/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl index 759c9f955..86f79ede8 100644 --- a/apps/emqx/src/emqx_banned.erl +++ b/apps/emqx/src/emqx_banned.erl @@ -155,13 +155,13 @@ create(#{who := Who, reason := Reason, at := At, until := Until}) -> - ekka_mnesia:dirty_write(?BANNED_TAB, #banned{who = Who, - by = By, - reason = Reason, - at = At, - until = Until}); + mria:dirty_write(?BANNED_TAB, #banned{who = Who, + by = By, + reason = Reason, + at = At, + until = Until}); create(Banned) when is_record(Banned, banned) -> - ekka_mnesia:dirty_write(?BANNED_TAB, Banned). + mria:dirty_write(?BANNED_TAB, Banned). look_up(Who) when is_map(Who) -> look_up(pares_who(Who)); @@ -174,7 +174,7 @@ look_up(Who) -> delete(Who) when is_map(Who)-> delete(pares_who(Who)); delete(Who) -> - ekka_mnesia:dirty_delete(?BANNED_TAB, Who). + mria:dirty_delete(?BANNED_TAB, Who). info(InfoKey) -> mnesia:table_info(?BANNED_TAB, InfoKey). @@ -195,7 +195,7 @@ handle_cast(Msg, State) -> {noreply, State}. handle_info({timeout, TRef, expire}, State = #{expiry_timer := TRef}) -> - ekka_mnesia:transaction(?COMMON_SHARD, fun expire_banned_items/1, [erlang:system_time(second)]), + mria:transaction(?COMMON_SHARD, fun expire_banned_items/1, [erlang:system_time(second)]), {noreply, ensure_expiry_timer(State), hibernate}; handle_info(Info, State) -> diff --git a/apps/emqx/src/emqx_cm_registry.erl b/apps/emqx/src/emqx_cm_registry.erl index ef7ad6131..65b89a884 100644 --- a/apps/emqx/src/emqx_cm_registry.erl +++ b/apps/emqx/src/emqx_cm_registry.erl @@ -71,7 +71,7 @@ register_channel(ClientId) when is_binary(ClientId) -> register_channel({ClientId, ChanPid}) when is_binary(ClientId), is_pid(ChanPid) -> case is_enabled() of - true -> ekka_mnesia:dirty_write(?TAB, record(ClientId, ChanPid)); + true -> mria:dirty_write(?TAB, record(ClientId, ChanPid)); false -> ok end. @@ -83,7 +83,7 @@ unregister_channel(ClientId) when is_binary(ClientId) -> unregister_channel({ClientId, ChanPid}) when is_binary(ClientId), is_pid(ChanPid) -> case is_enabled() of - true -> ekka_mnesia:dirty_delete_object(?TAB, record(ClientId, ChanPid)); + true -> mria:dirty_delete_object(?TAB, record(ClientId, ChanPid)); false -> ok end. @@ -124,7 +124,7 @@ handle_cast(Msg, State) -> handle_info({membership, {mnesia, down, Node}}, State) -> global:trans({?LOCK, self()}, fun() -> - ekka_mnesia:transaction(?CM_SHARD, fun cleanup_channels/1, [Node]) + mria:transaction(?CM_SHARD, fun cleanup_channels/1, [Node]) end), {noreply, State}; diff --git a/apps/emqx/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl index 3e5475c13..4793100ba 100644 --- a/apps/emqx/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -225,7 +225,7 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- insert_direct_route(Route) -> - ekka_mnesia:dirty_write(?ROUTE_TAB, Route). + mria:dirty_write(?ROUTE_TAB, Route). insert_trie_route(Route = #route{topic = Topic}) -> case mnesia:wread({?ROUTE_TAB, Topic}) of @@ -235,7 +235,7 @@ insert_trie_route(Route = #route{topic = Topic}) -> mnesia:write(?ROUTE_TAB, Route, sticky_write). delete_direct_route(Route) -> - ekka_mnesia:dirty_delete_object(?ROUTE_TAB, Route). + mria:dirty_delete_object(?ROUTE_TAB, Route). delete_trie_route(Route = #route{topic = Topic}) -> case mnesia:wread({?ROUTE_TAB, Topic}) of @@ -280,7 +280,7 @@ trans(Fun, Args) -> %% Future changes should keep in mind that this process %% always exit with database write result. fun() -> - Res = case ekka_mnesia:transaction(?ROUTE_SHARD, Fun, Args) of + Res = case mria:transaction(?ROUTE_SHARD, Fun, Args) of {atomic, Ok} -> Ok; {aborted, Reason} -> {error, Reason} end, diff --git a/apps/emqx/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl index a88e82d8d..6542e3983 100644 --- a/apps/emqx/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -87,7 +87,7 @@ monitor(Node) when is_atom(Node) -> case ekka:is_member(Node) orelse ets:member(?ROUTING_NODE, Node) of true -> ok; - false -> ekka_mnesia:dirty_write(?ROUTING_NODE, #routing_node{name = Node}) + false -> mria:dirty_write(?ROUTING_NODE, #routing_node{name = Node}) end. %%-------------------------------------------------------------------- @@ -136,9 +136,9 @@ handle_info({mnesia_table_event, Event}, State) -> handle_info({nodedown, Node}, State = #{nodes := Nodes}) -> global:trans({?LOCK, self()}, fun() -> - ekka_mnesia:transaction(fun cleanup_routes/1, [Node]) + mria:transaction(fun cleanup_routes/1, [Node]) end), - ok = ekka_mnesia:dirty_delete(?ROUTING_NODE, Node), + ok = mria:dirty_delete(?ROUTING_NODE, Node), {noreply, State#{nodes := lists:delete(Node, Nodes)}, hibernate}; handle_info({membership, {mnesia, down, Node}}, State) -> diff --git a/apps/emqx/src/emqx_shared_sub.erl b/apps/emqx/src/emqx_shared_sub.erl index ef8e3d288..299c4df38 100644 --- a/apps/emqx/src/emqx_shared_sub.erl +++ b/apps/emqx/src/emqx_shared_sub.erl @@ -297,7 +297,7 @@ subscribers(Group, Topic) -> init([]) -> {ok, _} = mnesia:subscribe({table, ?TAB, simple}), - {atomic, PMon} = ekka_mnesia:transaction(?SHARED_SUB_SHARD, fun init_monitors/0), + {atomic, PMon} = mria:transaction(?SHARED_SUB_SHARD, fun init_monitors/0), ok = emqx_tables:new(?SHARED_SUBS, [protected, bag]), ok = emqx_tables:new(?ALIVE_SUBS, [protected, set, {read_concurrency, true}]), {ok, update_stats(#state{pmon = PMon})}. @@ -309,7 +309,7 @@ init_monitors() -> end, emqx_pmon:new(), ?TAB). handle_call({subscribe, Group, Topic, SubPid}, _From, State = #state{pmon = PMon}) -> - ekka_mnesia:dirty_write(?TAB, record(Group, Topic, SubPid)), + mria:dirty_write(?TAB, record(Group, Topic, SubPid)), case ets:member(?SHARED_SUBS, {Group, Topic}) of true -> ok; false -> ok = emqx_router:do_add_route(Topic, {Group, node()}) @@ -319,7 +319,7 @@ handle_call({subscribe, Group, Topic, SubPid}, _From, State = #state{pmon = PMon {reply, ok, update_stats(State#state{pmon = emqx_pmon:monitor(SubPid, PMon)})}; handle_call({unsubscribe, Group, Topic, SubPid}, _From, State) -> - ekka_mnesia:dirty_delete_object(?TAB, record(Group, Topic, SubPid)), + mria:dirty_delete_object(?TAB, record(Group, Topic, SubPid)), true = ets:delete_object(?SHARED_SUBS, {{Group, Topic}, SubPid}), delete_route_if_needed({Group, Topic}), {reply, ok, State}; @@ -373,7 +373,7 @@ cleanup_down(SubPid) -> ?IS_LOCAL_PID(SubPid) orelse ets:delete(?ALIVE_SUBS, SubPid), lists:foreach( fun(Record = #emqx_shared_subscription{topic = Topic, group = Group}) -> - ok = ekka_mnesia:dirty_delete_object(?TAB, Record), + ok = mria:dirty_delete_object(?TAB, Record), true = ets:delete_object(?SHARED_SUBS, {{Group, Topic}, SubPid}), delete_route_if_needed({Group, Topic}) end, mnesia:dirty_match_object(#emqx_shared_subscription{_ = '_', subpid = SubPid})). diff --git a/apps/emqx/test/props/prop_emqx_sys.erl b/apps/emqx/test/props/prop_emqx_sys.erl index 3b2b8b94c..b6a0e0e38 100644 --- a/apps/emqx/test/props/prop_emqx_sys.erl +++ b/apps/emqx/test/props/prop_emqx_sys.erl @@ -29,7 +29,7 @@ [ emqx_metrics , emqx_stats , emqx_broker - , ekka_mnesia + , mria_mnesia ]). -define(ALL(Vars, Types, Exprs), diff --git a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl index 3daece601..4f8b38b1e 100644 --- a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl +++ b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl @@ -268,7 +268,7 @@ trans(Fun) -> trans(Fun, []). trans(Fun, Args) -> - case ekka_mnesia:transaction(?AUTH_SHARD, Fun, Args) of + case mria:transaction(?AUTH_SHARD, Fun, Args) of {atomic, Res} -> Res; {aborted, Reason} -> {error, Reason} end. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index c3b6badf7..314c3d578 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -390,7 +390,7 @@ trans(Fun) -> trans(Fun, []). trans(Fun, Args) -> - case ekka_mnesia:transaction(?AUTH_SHARD, Fun, Args) of + case mria:transaction(?AUTH_SHARD, Fun, Args) of {atomic, Res} -> Res; {aborted, Reason} -> {error, Reason} end. diff --git a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl index c29f90f43..78a08f570 100644 --- a/apps/emqx_authz/src/emqx_authz_api_mnesia.erl +++ b/apps/emqx_authz/src/emqx_authz_api_mnesia.erl @@ -528,10 +528,10 @@ users(get, #{query_string := Qs}) -> end; users(post, #{body := Body}) when is_list(Body) -> lists:foreach(fun(#{<<"username">> := Username, <<"rules">> := Rules}) -> - ekka_mnesia:dirty_write(#emqx_acl{ - who = {?ACL_TABLE_USERNAME, Username}, - rules = format_rules(Rules) - }) + mria:dirty_write(#emqx_acl{ + who = {?ACL_TABLE_USERNAME, Username}, + rules = format_rules(Rules) + }) end, Body), {204}. @@ -561,10 +561,10 @@ clients(get, #{query_string := Qs}) -> end; clients(post, #{body := Body}) when is_list(Body) -> lists:foreach(fun(#{<<"clientid">> := Clientid, <<"rules">> := Rules}) -> - ekka_mnesia:dirty_write(#emqx_acl{ - who = {?ACL_TABLE_CLIENTID, Clientid}, - rules = format_rules(Rules) - }) + mria:dirty_write(#emqx_acl{ + who = {?ACL_TABLE_CLIENTID, Clientid}, + rules = format_rules(Rules) + }) end, Body), {204}. @@ -581,13 +581,13 @@ user(get, #{bindings := #{username := Username}}) -> end; user(put, #{bindings := #{username := Username}, body := #{<<"username">> := Username, <<"rules">> := Rules}}) -> - ekka_mnesia:dirty_write(#emqx_acl{ - who = {?ACL_TABLE_USERNAME, Username}, - rules = format_rules(Rules) - }), + mria:dirty_write(#emqx_acl{ + who = {?ACL_TABLE_USERNAME, Username}, + rules = format_rules(Rules) + }), {204}; user(delete, #{bindings := #{username := Username}}) -> - ekka_mnesia:dirty_delete({?ACL_TABLE, {?ACL_TABLE_USERNAME, Username}}), + mria:dirty_delete({?ACL_TABLE, {?ACL_TABLE_USERNAME, Username}}), {204}. client(get, #{bindings := #{clientid := Clientid}}) -> @@ -603,13 +603,13 @@ client(get, #{bindings := #{clientid := Clientid}}) -> end; client(put, #{bindings := #{clientid := Clientid}, body := #{<<"clientid">> := Clientid, <<"rules">> := Rules}}) -> - ekka_mnesia:dirty_write(#emqx_acl{ - who = {?ACL_TABLE_CLIENTID, Clientid}, - rules = format_rules(Rules) - }), + mria:dirty_write(#emqx_acl{ + who = {?ACL_TABLE_CLIENTID, Clientid}, + rules = format_rules(Rules) + }), {204}; client(delete, #{bindings := #{clientid := Clientid}}) -> - ekka_mnesia:dirty_delete({?ACL_TABLE, {?ACL_TABLE_CLIENTID, Clientid}}), + mria:dirty_delete({?ACL_TABLE, {?ACL_TABLE_CLIENTID, Clientid}}), {204}. all(get, _) -> @@ -624,17 +624,17 @@ all(get, _) -> } end; all(put, #{body := #{<<"rules">> := Rules}}) -> - ekka_mnesia:dirty_write(#emqx_acl{ - who = ?ACL_TABLE_ALL, - rules = format_rules(Rules) - }), + mria:dirty_write(#emqx_acl{ + who = ?ACL_TABLE_ALL, + rules = format_rules(Rules) + }), {204}. purge(delete, _) -> case emqx_authz_api_sources:get_raw_source(<<"built-in-database">>) of [#{enable := false}] -> ok = lists:foreach(fun(Key) -> - ok = ekka_mnesia:dirty_delete(?ACL_TABLE, Key) + ok = mria:dirty_delete(?ACL_TABLE, Key) end, mnesia:dirty_all_keys(?ACL_TABLE)), {204}; _ -> diff --git a/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl b/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl index 947f46a82..ed82e9b1d 100644 --- a/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl @@ -54,24 +54,24 @@ end_per_suite(_Config) -> ok. init_per_testcase(t_authz, Config) -> - mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_USERNAME, <<"test_username">>}, - rules = [{allow, publish, <<"test/%u">>}, - {allow, subscribe, <<"eq #">>} - ] - }]), - mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_CLIENTID, <<"test_clientid">>}, - rules = [{allow, publish, <<"test/%c">>}, - {deny, subscribe, <<"eq #">>} - ] - }]), - mnesia:transaction(fun ekka_mnesia:dirty_write/1, [#emqx_acl{who = ?ACL_TABLE_ALL, - rules = [{deny, all, <<"#">>}] + mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_USERNAME, <<"test_username">>}, + rules = [{allow, publish, <<"test/%u">>}, + {allow, subscribe, <<"eq #">>} + ] }]), + mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_CLIENTID, <<"test_clientid">>}, + rules = [{allow, publish, <<"test/%c">>}, + {deny, subscribe, <<"eq #">>} + ] + }]), + mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = ?ACL_TABLE_ALL, + rules = [{deny, all, <<"#">>}] + }]), Config; init_per_testcase(_, Config) -> Config. end_per_testcase(t_authz, Config) -> - [ ekka_mnesia:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)], + [ mria:dirty_delete(?ACL_TABLE, K) || K <- mnesia:dirty_all_keys(?ACL_TABLE)], Config; end_per_testcase(_, Config) -> Config. @@ -96,7 +96,7 @@ t_authz(_) -> listener => {tcp, default} }, - ?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)), + ?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, subscribe, <<"#">>)), ?assertEqual(deny, emqx_access_control:authorize(ClientInfo1, publish, <<"#">>)), ?assertEqual(allow, emqx_access_control:authorize(ClientInfo2, publish, <<"test/test_username">>)), @@ -106,4 +106,3 @@ t_authz(_) -> ?assertEqual(deny, emqx_access_control:authorize(ClientInfo3, subscribe, <<"#">>)), ok. - diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 5af983b4d..72115a80b 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -68,7 +68,7 @@ mnesia(copy) -> -spec(add_user(binary(), binary(), binary()) -> ok | {error, any()}). add_user(Username, Password, Tags) when is_binary(Username), is_binary(Password) -> Admin = #mqtt_admin{username = Username, password = hash(Password), tags = Tags}, - return(ekka_mnesia:transaction(?DASHBOARD_SHARD, fun add_user_/1, [Admin])). + return(mria:transaction(?DASHBOARD_SHARD, fun add_user_/1, [Admin])). force_add_user(Username, Password, Tags) -> AddFun = fun() -> @@ -76,7 +76,7 @@ force_add_user(Username, Password, Tags) -> password = Password, tags = Tags}) end, - case ekka_mnesia:transaction(?DASHBOARD_SHARD, AddFun) of + case mria:transaction(?DASHBOARD_SHARD, AddFun) of {atomic, ok} -> ok; {aborted, Reason} -> {error, Reason} end. @@ -98,11 +98,11 @@ remove_user(Username) when is_binary(Username) -> end, mnesia:delete({mqtt_admin, Username}) end, - return(ekka_mnesia:transaction(?DASHBOARD_SHARD, Trans)). + return(mria:transaction(?DASHBOARD_SHARD, Trans)). -spec(update_user(binary(), binary()) -> ok | {error, term()}). update_user(Username, Tags) when is_binary(Username) -> - return(ekka_mnesia:transaction(?DASHBOARD_SHARD, fun update_user_/2, [Username, Tags])). + return(mria:transaction(?DASHBOARD_SHARD, fun update_user_/2, [Username, Tags])). %% @private update_user_(Username, Tags) -> @@ -135,7 +135,7 @@ update_pwd(Username, Fun) -> end, mnesia:write(Fun(User)) end, - return(ekka_mnesia:transaction(?DASHBOARD_SHARD, Trans)). + return(mria:transaction(?DASHBOARD_SHARD, Trans)). -spec(lookup_user(binary()) -> [mqtt_admin()]). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 0e2adf7c3..7ef5e0972 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -162,7 +162,7 @@ flush({Connection, Route, Subscription}, {Received0, Sent0, Dropped0}) -> diff(Sent, Sent0), diff(Dropped, Dropped0)}, Ts = get_local_time(), - ekka_mnesia:transaction(ekka_mnesia:local_content_shard(), + mria:transaction(ekka_mnesia:local_content_shard(), fun mnesia:write/1, [#mqtt_collect{timestamp = Ts, collect = Collect}]), {Received, Sent, Dropped}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index c1ca15cb3..7d53ee06b 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -104,7 +104,7 @@ do_sign(Username, Password) -> Signed = jose_jwt:sign(JWK, JWS, JWT), {_, Token} = jose_jws:compact(Signed), JWTRec = format(Token, Username, ExpTime), - ekka_mnesia:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [JWTRec]), + mria:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [JWTRec]), {ok, Token}. do_verify(Token)-> @@ -113,7 +113,7 @@ do_verify(Token)-> case ExpTime > erlang:system_time(millisecond) of true -> NewJWT = JWT#mqtt_admin_jwt{exptime = jwt_expiration_time()}, - {atomic, Res} = ekka_mnesia:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [NewJWT]), + {atomic, Res} = mria:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [NewJWT]), Res; _ -> {error, token_timeout} @@ -124,7 +124,7 @@ do_verify(Token)-> do_destroy(Token) -> Fun = fun mnesia:delete/1, - {atomic, ok} = ekka_mnesia:transaction(?DASHBOARD_SHARD, Fun, [{?TAB, Token}]), + {atomic, ok} = mria:transaction(?DASHBOARD_SHARD, Fun, [{?TAB, Token}]), ok. do_destroy_by_username(Username) -> diff --git a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl index 6d245c9bc..cb947b995 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl @@ -102,7 +102,7 @@ t_rest_api(_Config) -> ok. t_cli(_Config) -> - [ekka_mnesia:dirty_delete(mqtt_admin, Admin) || Admin <- mnesia:dirty_all_keys(mqtt_admin)], + [mria:dirty_delete(mqtt_admin, Admin) || Admin <- mnesia:dirty_all_keys(mqtt_admin)], emqx_dashboard_cli:admins(["add", "username", "password"]), [{mqtt_admin, <<"username">>, <>, _}] = emqx_dashboard_admin:lookup_user(<<"username">>), diff --git a/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl b/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl index 1d9daa637..51c4e95c2 100644 --- a/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl +++ b/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl @@ -65,7 +65,7 @@ register_channel(Type, ClientId) when is_binary(ClientId) -> register_channel(Type, {ClientId, self()}); register_channel(Type, {ClientId, ChanPid}) when is_binary(ClientId), is_pid(ChanPid) -> - ekka_mnesia:dirty_write(tabname(Type), record(ClientId, ChanPid)). + mria:dirty_write(tabname(Type), record(ClientId, ChanPid)). %% @doc Unregister a global channel. -spec unregister_channel(atom(), binary() | {binary(), pid()}) -> ok. @@ -73,7 +73,7 @@ unregister_channel(Type, ClientId) when is_binary(ClientId) -> unregister_channel(Type, {ClientId, self()}); unregister_channel(Type, {ClientId, ChanPid}) when is_binary(ClientId), is_pid(ChanPid) -> - ekka_mnesia:dirty_delete_object(tabname(Type), record(ClientId, ChanPid)). + mria:dirty_delete_object(tabname(Type), record(ClientId, ChanPid)). %% @doc Lookup the global channels. -spec lookup_channels(atom(), binary()) -> list(pid()). @@ -115,7 +115,7 @@ handle_info({membership, {mnesia, down, Node}}, State = #{type := Type}) -> global:trans({?LOCK, self()}, fun() -> %% FIXME: The shard name should be fixed later - ekka_mnesia:transaction(?MODULE, fun cleanup_channels/2, [Node, Tab]) + mria:transaction(?MODULE, fun cleanup_channels/2, [Node, Tab]) end), {noreply, State}; diff --git a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl index 2534eee26..863ea2be7 100644 --- a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl +++ b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl @@ -157,14 +157,14 @@ init([InstaId, PredefTopics]) -> MaxPredefId = lists:foldl( fun(#{id := TopicId, topic := TopicName0}, AccId) -> TopicName = iolist_to_binary(TopicName0), - ekka_mnesia:dirty_write(Tab, #emqx_sn_registry{ - key = {predef, TopicId}, - value = TopicName} - ), - ekka_mnesia:dirty_write(Tab, #emqx_sn_registry{ - key = {predef, TopicName}, - value = TopicId} - ), + mria:dirty_write(Tab, #emqx_sn_registry{ + key = {predef, TopicId}, + value = TopicName} + ), + mria:dirty_write(Tab, #emqx_sn_registry{ + key = {predef, TopicName}, + value = TopicId} + ), if TopicId > AccId -> TopicId; true -> AccId end end, 0, PredefTopics), {ok, #state{tabname = Tab, max_predef_topic_id = MaxPredefId}}. @@ -192,7 +192,7 @@ handle_call({register, ClientId, TopicName}, _From, key = {ClientId, TopicId}, value = TopicName}, write) end, - case ekka_mnesia:transaction(?SN_SHARD, Fun) of + case mria:transaction(?SN_SHARD, Fun) of {atomic, ok} -> {reply, TopicId, State}; {aborted, Error} -> @@ -207,7 +207,7 @@ handle_call({unregister, ClientId}, _From, State = #state{tabname = Tab}) -> {emqx_sn_registry, {ClientId, '_'}, '_'} ), lists:foreach(fun(R) -> - ekka_mnesia:dirty_delete_object(Tab, R) + mria:dirty_delete_object(Tab, R) end, Registry), {reply, ok, State}; diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index 66616f3ea..0d963a2de 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -280,7 +280,7 @@ do_catch_up_in_one_trans(LatestId, Node) -> end. transaction(Func, Args) -> - ekka_mnesia:transaction(?EMQX_MACHINE_SHARD, Func, Args). + mria:transaction(?EMQX_MACHINE_SHARD, Func, Args). trans_status() -> mnesia:foldl(fun(Rec, Acc) -> diff --git a/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl b/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl index 6dcbd3d25..2b1242fa7 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl @@ -49,7 +49,7 @@ handle_cast(Msg, State) -> {noreply, State}. handle_info({timeout, TRef, del_stale_mfa}, State = #{timer := TRef, max_history := MaxHistory}) -> - case ekka_mnesia:transaction(?EMQX_MACHINE_SHARD, fun del_stale_mfa/1, [MaxHistory]) of + case mria:transaction(?EMQX_MACHINE_SHARD, fun del_stale_mfa/1, [MaxHistory]) of {atomic, ok} -> ok; Error -> ?LOG(error, "del_stale_cluster_rpc_mfa error:~p", [Error]) end, diff --git a/apps/emqx_modules/src/emqx_delayed.erl b/apps/emqx_modules/src/emqx_delayed.erl index 86ef97dac..f2eef3f39 100644 --- a/apps/emqx_modules/src/emqx_delayed.erl +++ b/apps/emqx_modules/src/emqx_delayed.erl @@ -184,7 +184,7 @@ delete_delayed_message(Id0) -> {error, not_found}; Rows -> Timestamp = hd(Rows), - ekka_mnesia:dirty_delete(?TAB, {Timestamp, Id}) + mria:dirty_delete(?TAB, {Timestamp, Id}) end. update_config(Config) -> {ok, _} = emqx:update_config([delayed], Config). @@ -205,7 +205,7 @@ handle_call({set_max_delayed_messages, Max}, _From, State) -> handle_call({store, DelayedMsg = #delayed_message{key = Key}}, _From, State = #{max_delayed_messages := 0}) -> - ok = ekka_mnesia:dirty_write(?TAB, DelayedMsg), + ok = mria:dirty_write(?TAB, DelayedMsg), emqx_metrics:inc('messages.delayed'), {reply, ok, ensure_publish_timer(Key, State)}; @@ -216,7 +216,7 @@ handle_call({store, DelayedMsg = #delayed_message{key = Key}}, true -> {reply, {error, max_delayed_messages_full}, State}; false -> - ok = ekka_mnesia:dirty_write(?TAB, DelayedMsg), + ok = mria:dirty_write(?TAB, DelayedMsg), emqx_metrics:inc('messages.delayed'), {reply, ok, ensure_publish_timer(Key, State)} end; @@ -240,7 +240,7 @@ handle_cast(Msg, State) -> %% Do Publish... handle_info({timeout, TRef, do_publish}, State = #{timer := TRef}) -> DeletedKeys = do_publish(mnesia:dirty_first(?TAB), os:system_time(seconds)), - lists:foreach(fun(Key) -> ekka_mnesia:dirty_delete(?TAB, Key) end, DeletedKeys), + lists:foreach(fun(Key) -> mria:dirty_delete(?TAB, Key) end, DeletedKeys), {noreply, ensure_publish_timer(State#{timer := undefined, publish_at := 0})}; handle_info(stats, State = #{stats_fun := StatsFun}) -> diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index 65852df93..04586e8fc 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -140,8 +140,8 @@ init(_Opts) -> UUID1 = case mnesia:dirty_read(?TELEMETRY, ?UNIQUE_ID) of [] -> UUID = generate_uuid(), - ekka_mnesia:dirty_write(?TELEMETRY, #telemetry{id = ?UNIQUE_ID, - uuid = UUID}), + mria:dirty_write(?TELEMETRY, #telemetry{id = ?UNIQUE_ID, + uuid = UUID}), UUID; [#telemetry{uuid = UUID} | _] -> UUID diff --git a/apps/emqx_psk/src/emqx_psk.erl b/apps/emqx_psk/src/emqx_psk.erl index 9ea25cdeb..65ce1025b 100644 --- a/apps/emqx_psk/src/emqx_psk.erl +++ b/apps/emqx_psk/src/emqx_psk.erl @@ -237,7 +237,7 @@ trim_crlf(Bin) -> end. trans(Fun, Args) -> - case ekka_mnesia:transaction(?PSK_SHARD, Fun, Args) of + case mria:transaction(?PSK_SHARD, Fun, Args) of {atomic, Res} -> Res; {aborted, Reason} -> {error, Reason} end. diff --git a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl index 0fc0a4615..e3d90fe7d 100644 --- a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl +++ b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl @@ -73,10 +73,10 @@ store_retained(_, Msg =#message{topic = Topic}) -> case is_table_full() of false -> ok = emqx_metrics:inc('messages.retained'), - ekka_mnesia:dirty_write(?TAB, - #retained{topic = topic2tokens(Topic), - msg = Msg, - expiry_time = ExpiryTime}); + mria:dirty_write(?TAB, + #retained{topic = topic2tokens(Topic), + msg = Msg, + expiry_time = ExpiryTime}); _ -> Tokens = topic2tokens(Topic), Fun = fun() -> @@ -94,7 +94,7 @@ store_retained(_, Msg =#message{topic = Topic}) -> ok end end, - {atomic, ok} = ekka_mnesia:transaction(?RETAINER_SHARD, Fun), + {atomic, ok} = mria:transaction(?RETAINER_SHARD, Fun), ok end. @@ -106,7 +106,7 @@ clear_expired(_) -> Keys = mnesia:select(?TAB, Ms, write), lists:foreach(fun(Key) -> mnesia:delete({?TAB, Key}) end, Keys) end, - {atomic, _} = ekka_mnesia:transaction(?RETAINER_SHARD, Fun), + {atomic, _} = mria:transaction(?RETAINER_SHARD, Fun), ok. delete_message(_, Topic) -> @@ -117,7 +117,7 @@ delete_message(_, Topic) -> Fun = fun() -> mnesia:delete({?TAB, Tokens}) end, - case ekka_mnesia:transaction(?RETAINER_SHARD, Fun) of + case mria:transaction(?RETAINER_SHARD, Fun) of {atomic, Result} -> Result; ok -> @@ -214,7 +214,7 @@ match_delete_messages(Filter) -> MsHd = #retained{topic = Cond, msg = '_', expiry_time = '_'}, Ms = [{MsHd, [], ['$_']}], Rs = mnesia:dirty_select(?TAB, Ms), - lists:foreach(fun(R) -> ekka_mnesia:dirty_delete_object(?TAB, R) end, Rs). + lists:foreach(fun(R) -> mria:dirty_delete_object(?TAB, R) end, Rs). %% @private condition(Ws) -> diff --git a/rebar.config b/rebar.config index 89b8e3a9f..91c0196c2 100644 --- a/rebar.config +++ b/rebar.config @@ -50,7 +50,7 @@ , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.8.3"}}} , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} - , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.10.9"}}} + , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.0"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.5"}}} , {ecpool, {git, "https://github.com/emqx/ecpool", {tag, "0.5.1"}}} From ff48322e0c75175b74e79626eab37f4867f15d6c Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 18:30:22 +0200 Subject: [PATCH 02/88] chore(mria): ekka_mnesia:running_nodes -> mria:running_nodes --- apps/emqx/src/emqx_sys.erl | 2 +- apps/emqx_bridge/src/emqx_bridge_api.erl | 4 +- .../src/emqx_dashboard_monitor_api.erl | 10 ++--- apps/emqx_gateway/src/emqx_gateway_http.erl | 4 +- apps/emqx_management/src/emqx_mgmt.erl | 42 +++++++++---------- apps/emqx_management/src/emqx_mgmt_api.erl | 2 +- .../src/emqx_mgmt_api_listeners.erl | 2 +- .../src/emqx_mgmt_api_metrics.erl | 2 +- .../src/emqx_mgmt_api_stats.erl | 2 +- apps/emqx_modules/src/emqx_delayed_api.erl | 2 +- apps/emqx_modules/src/emqx_telemetry.erl | 2 +- apps/emqx_modules/src/emqx_telemetry_api.erl | 2 +- .../src/emqx_rule_engine_api.erl | 2 +- 13 files changed, 38 insertions(+), 40 deletions(-) diff --git a/apps/emqx/src/emqx_sys.erl b/apps/emqx/src/emqx_sys.erl index 692d2bd0a..7882abc19 100644 --- a/apps/emqx/src/emqx_sys.erl +++ b/apps/emqx/src/emqx_sys.erl @@ -150,7 +150,7 @@ handle_info({timeout, TRef, tick}, State = #state{ticker = TRef, version = Version, sysdescr = Descr}) -> publish_any(version, Version), publish_any(sysdescr, Descr), - publish_any(brokers, ekka_mnesia:running_nodes()), + publish_any(brokers, mria_mnesia:running_nodes()), publish_any(stats, emqx_stats:getstats()), publish_any(metrics, emqx_metrics:all()), {noreply, tick(State), hibernate}; diff --git a/apps/emqx_bridge/src/emqx_bridge_api.erl b/apps/emqx_bridge/src/emqx_bridge_api.erl index e4805d7eb..40a101640 100644 --- a/apps/emqx_bridge/src/emqx_bridge_api.erl +++ b/apps/emqx_bridge/src/emqx_bridge_api.erl @@ -153,7 +153,7 @@ param_path_operation()-> }. list_bridges(get, _Params) -> - {200, lists:append([list_local_bridges(Node) || Node <- ekka_mnesia:running_nodes()])}. + {200, lists:append([list_local_bridges(Node) || Node <- mria_mnesia:running_nodes()])}. list_local_bridges(Node) when Node =:= node() -> [format_resp(Data) || Data <- emqx_bridge:list_bridges()]; @@ -161,7 +161,7 @@ list_local_bridges(Node) -> rpc_call(Node, list_local_bridges, [Node]). crud_bridges_cluster(Method, Params) -> - Results = [crud_bridges(Node, Method, Params) || Node <- ekka_mnesia:running_nodes()], + Results = [crud_bridges(Node, Method, Params) || Node <- mria_mnesia:running_nodes()], case lists:filter(fun({200}) -> false; ({200, _}) -> false; (_) -> true end, Results) of [] -> case Results of diff --git a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl index c00310211..ba2fc6dbe 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_monitor_api.erl @@ -158,8 +158,8 @@ counters(get, #{bindings := #{counter := Counter}}) -> lookup([{<<"counter">>, Counter}]). current_counters(get, _Params) -> - Data = [get_collect(Node) || Node <- ekka_mnesia:running_nodes()], - Nodes = length(ekka_mnesia:running_nodes()), + Data = [get_collect(Node) || Node <- mria_mnesia:running_nodes()], + Nodes = length(mria_mnesia:running_nodes()), {Received, Sent, Sub, Conn} = format_current_metrics(Data), Response = #{ nodes => Nodes, @@ -194,16 +194,16 @@ lookup_(#{node := Node, counter := Counter}) -> lookup_(#{node := Node}) -> {200, sampling(Node)}; lookup_(#{counter := Counter}) -> - CounterData = merger_counters([sampling(Node, Counter) || Node <- ekka_mnesia:running_nodes()]), + CounterData = merger_counters([sampling(Node, Counter) || Node <- mria_mnesia:running_nodes()]), Data = hd(maps:values(CounterData)), {200, Data}. list_collect(Aggregate) -> case Aggregate of <<"true">> -> - [maps:put(node, Node, sampling(Node)) || Node <- ekka_mnesia:running_nodes()]; + [maps:put(node, Node, sampling(Node)) || Node <- mria_mnesia:running_nodes()]; _ -> - Counters = [sampling(Node) || Node <- ekka_mnesia:running_nodes()], + Counters = [sampling(Node) || Node <- mria_mnesia:running_nodes()], merger_counters(Counters) end. diff --git a/apps/emqx_gateway/src/emqx_gateway_http.erl b/apps/emqx_gateway/src/emqx_gateway_http.erl index e5c927a1a..6b6e8b636 100644 --- a/apps/emqx_gateway/src/emqx_gateway_http.erl +++ b/apps/emqx_gateway/src/emqx_gateway_http.erl @@ -209,7 +209,7 @@ confexp({error, already_exist}) -> emqx_type:clientid(), {atom(), atom()}) -> list(). lookup_client(GwName, ClientId, FormatFun) -> lists:append([lookup_client(Node, GwName, {clientid, ClientId}, FormatFun) - || Node <- ekka_mnesia:running_nodes()]). + || Node <- mria_mnesia:running_nodes()]). lookup_client(Node, GwName, {clientid, ClientId}, {M,F}) when Node =:= node() -> ChanTab = emqx_gateway_cm:tabname(chan, GwName), @@ -229,7 +229,7 @@ lookup_client(Node, GwName, {clientid, ClientId}, FormatFun) -> | ok. kickout_client(GwName, ClientId) -> Results = [kickout_client(Node, GwName, ClientId) - || Node <- ekka_mnesia:running_nodes()], + || Node <- mria_mnesia:running_nodes()], case lists:any(fun(Item) -> Item =:= ok end, Results) of true -> ok; false -> lists:last(Results) diff --git a/apps/emqx_management/src/emqx_mgmt.erl b/apps/emqx_management/src/emqx_mgmt.erl index 3b1fd5903..eca5b3e56 100644 --- a/apps/emqx_management/src/emqx_mgmt.erl +++ b/apps/emqx_management/src/emqx_mgmt.erl @@ -164,7 +164,7 @@ stopped_node_info(Node) -> %%-------------------------------------------------------------------- list_brokers() -> - [{Node, broker_info(Node)} || Node <- ekka_mnesia:running_nodes()]. + [{Node, broker_info(Node)} || Node <- mria_mnesia:running_nodes()]. lookup_broker(Node) -> broker_info(Node). @@ -181,7 +181,7 @@ broker_info(Node) -> %%-------------------------------------------------------------------- get_metrics() -> - nodes_info_count([get_metrics(Node) || Node <- ekka_mnesia:running_nodes()]). + nodes_info_count([get_metrics(Node) || Node <- mria_mnesia:running_nodes()]). get_metrics(Node) when Node =:= node() -> emqx_metrics:all(); @@ -201,7 +201,7 @@ get_stats() -> begin Stats = get_stats(Node), delete_keys(Stats, GlobalStatsKeys) - end || Node <- ekka_mnesia:running_nodes()]), + end || Node <- mria_mnesia:running_nodes()]), GlobalStats = maps:with(GlobalStatsKeys, maps:from_list(get_stats(node()))), maps:merge(CountStats, GlobalStats). @@ -232,10 +232,10 @@ nodes_info_count(PropList) -> %%-------------------------------------------------------------------- lookup_client({clientid, ClientId}, FormatFun) -> - lists:append([lookup_client(Node, {clientid, ClientId}, FormatFun) || Node <- ekka_mnesia:running_nodes()]); + lists:append([lookup_client(Node, {clientid, ClientId}, FormatFun) || Node <- mria_mnesia:running_nodes()]); lookup_client({username, Username}, FormatFun) -> - lists:append([lookup_client(Node, {username, Username}, FormatFun) || Node <- ekka_mnesia:running_nodes()]). + lists:append([lookup_client(Node, {username, Username}, FormatFun) || Node <- mria_mnesia:running_nodes()]). lookup_client(Node, {clientid, ClientId}, {M,F}) when Node =:= node() -> lists:append(lists:map( @@ -257,7 +257,7 @@ lookup_client(Node, {username, Username}, FormatFun) -> rpc_call(Node, lookup_client, [Node, {username, Username}, FormatFun]). kickout_client(ClientId) -> - Results = [kickout_client(Node, ClientId) || Node <- ekka_mnesia:running_nodes()], + Results = [kickout_client(Node, ClientId) || Node <- mria_mnesia:running_nodes()], case lists:any(fun(Item) -> Item =:= ok end, Results) of true -> ok; false -> lists:last(Results) @@ -273,7 +273,7 @@ list_authz_cache(ClientId) -> call_client(ClientId, list_authz_cache). list_client_subscriptions(ClientId) -> - Results = [client_subscriptions(Node, ClientId) || Node <- ekka_mnesia:running_nodes()], + Results = [client_subscriptions(Node, ClientId) || Node <- mria_mnesia:running_nodes()], Expected = lists:filter(fun({error, _}) -> false; ([]) -> false; (_) -> true @@ -290,7 +290,7 @@ client_subscriptions(Node, ClientId) -> rpc_call(Node, client_subscriptions, [Node, ClientId]). clean_authz_cache(ClientId) -> - Results = [clean_authz_cache(Node, ClientId) || Node <- ekka_mnesia:running_nodes()], + Results = [clean_authz_cache(Node, ClientId) || Node <- mria_mnesia:running_nodes()], case lists:any(fun(Item) -> Item =:= ok end, Results) of true -> ok; false -> lists:last(Results) @@ -308,7 +308,7 @@ clean_authz_cache(Node, ClientId) -> rpc_call(Node, clean_authz_cache, [Node, ClientId]). clean_authz_cache_all() -> - Results = [{Node, clean_authz_cache_all(Node)} || Node <- ekka_mnesia:running_nodes()], + Results = [{Node, clean_authz_cache_all(Node)} || Node <- mria_mnesia:running_nodes()], case lists:filter(fun({_Node, Item}) -> Item =/= ok end, Results) of [] -> ok; BadNodes -> {error, BadNodes} @@ -328,7 +328,7 @@ set_quota_policy(ClientId, Policy) -> %% @private call_client(ClientId, Req) -> - Results = [call_client(Node, ClientId, Req) || Node <- ekka_mnesia:running_nodes()], + Results = [call_client(Node, ClientId, Req) || Node <- mria_mnesia:running_nodes()], Expected = lists:filter(fun({error, _}) -> false; (_) -> true end, Results), @@ -366,7 +366,7 @@ list_subscriptions(Node) -> rpc_call(Node, list_subscriptions, [Node]). list_subscriptions_via_topic(Topic, FormatFun) -> - lists:append([list_subscriptions_via_topic(Node, Topic, FormatFun) || Node <- ekka_mnesia:running_nodes()]). + lists:append([list_subscriptions_via_topic(Node, Topic, FormatFun) || Node <- mria_mnesia:running_nodes()]). list_subscriptions_via_topic(Node, Topic, {M,F}) when Node =:= node() -> MatchSpec = [{{{'_', '$1'}, '_'}, [{'=:=','$1', Topic}], ['$_']}], @@ -376,7 +376,7 @@ list_subscriptions_via_topic(Node, Topic, FormatFun) -> rpc_call(Node, list_subscriptions_via_topic, [Node, Topic, FormatFun]). lookup_subscriptions(ClientId) -> - lists:append([lookup_subscriptions(Node, ClientId) || Node <- ekka_mnesia:running_nodes()]). + lists:append([lookup_subscriptions(Node, ClientId) || Node <- mria_mnesia:running_nodes()]). lookup_subscriptions(Node, ClientId) when Node =:= node() -> case ets:lookup(emqx_subid, ClientId) of @@ -400,7 +400,7 @@ lookup_routes(Topic) -> %%-------------------------------------------------------------------- subscribe(ClientId, TopicTables) -> - subscribe(ekka_mnesia:running_nodes(), ClientId, TopicTables). + subscribe(mria_mnesia:running_nodes(), ClientId, TopicTables). subscribe([Node | Nodes], ClientId, TopicTables) -> case rpc_call(Node, do_subscribe, [ClientId, TopicTables]) of @@ -424,7 +424,7 @@ publish(Msg) -> emqx:publish(Msg). unsubscribe(ClientId, Topic) -> - unsubscribe(ekka_mnesia:running_nodes(), ClientId, Topic). + unsubscribe(mria_mnesia:running_nodes(), ClientId, Topic). unsubscribe([Node | Nodes], ClientId, Topic) -> case rpc_call(Node, do_unsubscribe, [ClientId, Topic]) of @@ -447,7 +447,7 @@ do_unsubscribe(ClientId, Topic) -> %%-------------------------------------------------------------------- list_plugins() -> - [{Node, list_plugins(Node)} || Node <- ekka_mnesia:running_nodes()]. + [{Node, list_plugins(Node)} || Node <- mria_mnesia:running_nodes()]. list_plugins(Node) when Node =:= node() -> emqx_plugins:list(); @@ -474,7 +474,7 @@ reload_plugin(Node, Plugin) -> %%-------------------------------------------------------------------- list_listeners() -> - lists:append([list_listeners(Node) || Node <- ekka_mnesia:running_nodes()]). + lists:append([list_listeners(Node) || Node <- mria_mnesia:running_nodes()]). list_listeners(Node) when Node =:= node() -> [Conf#{node => Node, id => Id} || {Id, Conf} <- emqx_listeners:list()]; @@ -505,7 +505,7 @@ manage_listener(Operation, Param = #{node := Node}) -> rpc_call(Node, manage_listener, [Operation, Param]). update_listener(Id, Config) -> - [update_listener(Node, Id, Config) || Node <- ekka_mnesia:running_nodes()]. + [update_listener(Node, Id, Config) || Node <- mria_mnesia:running_nodes()]. update_listener(Node, Id, Config) when Node =:= node() -> case emqx_listeners:parse_listener_id(Id) of @@ -523,7 +523,7 @@ update_listener(Node, Id, Config) -> rpc_call(Node, update_listener, [Node, Id, Config]). remove_listener(Id) -> - [remove_listener(Node, Id) || Node <- ekka_mnesia:running_nodes()]. + [remove_listener(Node, Id) || Node <- mria_mnesia:running_nodes()]. remove_listener(Node, Id) when Node =:= node() -> {Type, Name} = emqx_listeners:parse_listener_id(Id), @@ -540,7 +540,7 @@ remove_listener(Node, Id) -> %%-------------------------------------------------------------------- get_alarms(Type) -> - [{Node, get_alarms(Node, Type)} || Node <- ekka_mnesia:running_nodes()]. + [{Node, get_alarms(Node, Type)} || Node <- mria_mnesia:running_nodes()]. get_alarms(Node, Type) when Node =:= node() -> add_duration_field(emqx_alarm:get_alarms(Type)); @@ -553,7 +553,7 @@ deactivate(Node, Name) -> rpc_call(Node, deactivate, [Node, Name]). delete_all_deactivated_alarms() -> - [delete_all_deactivated_alarms(Node) || Node <- ekka_mnesia:running_nodes()]. + [delete_all_deactivated_alarms(Node) || Node <- mria_mnesia:running_nodes()]. delete_all_deactivated_alarms(Node) when Node =:= node() -> emqx_alarm:delete_all_deactivated_alarms(); @@ -621,5 +621,3 @@ max_row_limit() -> ?MAX_ROW_LIMIT. table_size(Tab) -> ets:info(Tab, size). - - diff --git a/apps/emqx_management/src/emqx_mgmt_api.erl b/apps/emqx_management/src/emqx_mgmt_api.erl index c7da2e752..783f0b2f6 100644 --- a/apps/emqx_management/src/emqx_mgmt_api.erl +++ b/apps/emqx_management/src/emqx_mgmt_api.erl @@ -167,7 +167,7 @@ cluster_query(Params, Tab, QsSchema, QueryFun) -> {_CodCnt, Qs} = params2qs(Params, QsSchema), Limit = b2i(limit(Params)), Page = b2i(page(Params)), - Nodes = ekka_mnesia:running_nodes(), + Nodes = mria_mnesia:running_nodes(), Meta = #{page => Page, limit => Limit, count => 0}, page_limit_check_query(Meta, {fun do_cluster_query/5, [Nodes, Tab, Qs, QueryFun, Meta]}). diff --git a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl index 9e12cbe3a..52c7a8709 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl @@ -300,7 +300,7 @@ manage_listeners(_, #{bindings := #{id := Id, operation := Oper, node := Node}}) Result; manage_listeners(_, #{bindings := #{id := Id, operation := Oper}}) -> - Results = [do_manage_listeners(Node, Id, Oper) || Node <- ekka_mnesia:running_nodes()], + Results = [do_manage_listeners(Node, Id, Oper) || Node <- mria_mnesia:running_nodes()], case lists:filter(fun({_, {200}}) -> false; (_) -> true end, Results) of [] -> {200}; Errors -> {500, #{code => 'UNKNOW_ERROR', message => manage_listeners_err(Errors)}} diff --git a/apps/emqx_management/src/emqx_mgmt_api_metrics.erl b/apps/emqx_management/src/emqx_mgmt_api_metrics.erl index 2795fe342..8c0b364c0 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_metrics.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_metrics.erl @@ -154,6 +154,6 @@ list(get, #{query_string := Qs}) -> {200, emqx_mgmt:get_metrics()}; _ -> Data = [maps:from_list(emqx_mgmt:get_metrics(Node) ++ [{node, Node}]) || - Node <- ekka_mnesia:running_nodes()], + Node <- mria_mnesia:running_nodes()], {200, Data} end. diff --git a/apps/emqx_management/src/emqx_mgmt_api_stats.erl b/apps/emqx_management/src/emqx_mgmt_api_stats.erl index 470b5fda1..da8e643d8 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_stats.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_stats.erl @@ -96,6 +96,6 @@ list(get, #{query_string := Qs}) -> {200, emqx_mgmt:get_stats()}; _ -> Data = [maps:from_list(emqx_mgmt:get_stats(Node) ++ [{node, Node}]) || - Node <- ekka_mnesia:running_nodes()], + Node <- mria_mnesia:running_nodes()], {200, Data} end. diff --git a/apps/emqx_modules/src/emqx_delayed_api.erl b/apps/emqx_modules/src/emqx_delayed_api.erl index 94a388767..768ef4590 100644 --- a/apps/emqx_modules/src/emqx_delayed_api.erl +++ b/apps/emqx_modules/src/emqx_delayed_api.erl @@ -210,7 +210,7 @@ generate_max_delayed_messages(Config) -> update_config_(Config) -> lists:foreach(fun(Node) -> update_config_(Node, Config) - end, ekka_mnesia:running_nodes()). + end, mria_mnesia:running_nodes()). update_config_(Node, Config) when Node =:= node() -> _ = emqx_delayed:update_config(Config), diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index 04586e8fc..3c3f9bd6a 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -268,7 +268,7 @@ uptime() -> element(1, erlang:statistics(wall_clock)). nodes_uuid() -> - Nodes = lists:delete(node(), ekka_mnesia:running_nodes()), + Nodes = lists:delete(node(), mria_mnesia:running_nodes()), lists:foldl(fun(Node, Acc) -> case rpc:call(Node, ?MODULE, get_uuid, []) of {badrpc, _Reason} -> diff --git a/apps/emqx_modules/src/emqx_telemetry_api.erl b/apps/emqx_modules/src/emqx_telemetry_api.erl index 5d1cffdcd..7dd36654a 100644 --- a/apps/emqx_modules/src/emqx_telemetry_api.erl +++ b/apps/emqx_modules/src/emqx_telemetry_api.erl @@ -152,7 +152,7 @@ data(get, _Request) -> enable_telemetry(Enable) -> lists:foreach(fun(Node) -> enable_telemetry(Node, Enable) - end, ekka_mnesia:running_nodes()). + end, mria_mnesia:running_nodes()). enable_telemetry(Node, Enable) when Node =:= node() -> case Enable of diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl index 5e6b28b61..b9a3b16f7 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_api.erl @@ -338,4 +338,4 @@ do_format_output(BridgeChannelId) when is_binary(BridgeChannelId) -> get_rule_metrics(Id) -> [maps:put(node, Node, rpc:call(Node, emqx_rule_metrics, get_rule_metrics, [Id])) - || Node <- ekka_mnesia:running_nodes()]. + || Node <- mria_mnesia:running_nodes()]. From ae2056da1b60f5e8644cd1d631090bc00c750501 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 19:41:19 +0200 Subject: [PATCH 03/88] chore(mria): Fix clear_table and ro_transaction calls --- apps/emqx/src/emqx_alarm.erl | 4 ++-- apps/emqx/src/emqx_trie.erl | 2 +- apps/emqx_dashboard/src/emqx_dashboard_admin.erl | 2 +- apps/emqx_dashboard/src/emqx_dashboard_token.erl | 6 +++--- apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl | 2 +- apps/emqx_machine/src/emqx_cluster_rpc.erl | 4 ++-- apps/emqx_retainer/src/emqx_retainer_mnesia.erl | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/emqx/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl index 412880bad..39d13cacd 100644 --- a/apps/emqx/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -221,7 +221,7 @@ handle_call(delete_all_deactivated_alarms, _From, State) -> handle_call({get_alarms, all}, _From, State) -> {atomic, Alarms} = - ekka_mnesia:ro_transaction( + mria:ro_transaction( ?COMMON_SHARD, fun() -> [normalize(Alarm) || @@ -321,7 +321,7 @@ deactivate_all_alarms() -> %% Delete all records from the given table, ignore result. clear_table(TableName) -> - case ekka_mnesia:clear_table(TableName) of + case mria:clear_table(TableName) of {aborted, Reason} -> ?SLOG(warning, #{ msg => "fail_to_clear_table", diff --git a/apps/emqx/src/emqx_trie.erl b/apps/emqx/src/emqx_trie.erl index 1e3a0e5a5..327db16c0 100644 --- a/apps/emqx/src/emqx_trie.erl +++ b/apps/emqx/src/emqx_trie.erl @@ -329,6 +329,6 @@ do_compact_test() -> do_compact(words(<<"a/+/+/+/+/b">>))), ok. -clear_tables() -> ekka_mnesia:clear_table(?TRIE). +clear_tables() -> mria:clear_table(?TRIE). -endif. % TEST diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 72115a80b..55cb8ffe5 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -141,7 +141,7 @@ update_pwd(Username, Fun) -> -spec(lookup_user(binary()) -> [mqtt_admin()]). lookup_user(Username) when is_binary(Username) -> Fun = fun() -> mnesia:read(mqtt_admin, Username) end, - {atomic, User} = ekka_mnesia:ro_transaction(?DASHBOARD_SHARD, Fun), + {atomic, User} = mria:ro_transaction(?DASHBOARD_SHARD, Fun), User. -spec(all_users() -> [#mqtt_admin{}]). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index 7d53ee06b..611ef44a2 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -135,7 +135,7 @@ do_destroy_by_username(Username) -> -spec(lookup(Token :: binary()) -> {ok, #mqtt_admin_jwt{}} | {error, not_found}). lookup(Token) -> Fun = fun() -> mnesia:read(?TAB, Token) end, - case ekka_mnesia:ro_transaction(?DASHBOARD_SHARD, Fun) of + case mria:ro_transaction(?DASHBOARD_SHARD, Fun) of {atomic, [JWT]} -> {ok, JWT}; {atomic, []} -> {error, not_found} end. @@ -143,7 +143,7 @@ lookup(Token) -> lookup_by_username(Username) -> Spec = [{{mqtt_admin_jwt, '_', Username, '_'}, [], ['$_']}], Fun = fun() -> mnesia:select(?TAB, Spec) end, - {atomic, List} = ekka_mnesia:ro_transaction(?DASHBOARD_SHARD, Fun), + {atomic, List} = mria:ro_transaction(?DASHBOARD_SHARD, Fun), List. @@ -193,7 +193,7 @@ handle_info(clean_jwt, State) -> timer_clean(self()), Now = erlang:system_time(millisecond), Spec = [{{mqtt_admin_jwt, '_', '_', '$1'}, [{'<', '$1', Now}], ['$_']}], - {atomic, JWTList} = ekka_mnesia:ro_transaction(?DASHBOARD_SHARD, + {atomic, JWTList} = mria:ro_transaction(?DASHBOARD_SHARD, fun() -> mnesia:select(?TAB, Spec) end), destroy(JWTList), {noreply, State}; diff --git a/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl b/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl index e727c6c88..04a3d8024 100644 --- a/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl +++ b/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl @@ -49,7 +49,7 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(_TestCase, Config) -> {Tab, _Pid} = proplists:get_value(reg, Config), - ekka_mnesia:clear_table(Tab), + mria:clear_table(Tab), Config. %%-------------------------------------------------------------------- diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index 0d963a2de..0d93805b7 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -150,8 +150,8 @@ handle_continue(?CATCH_UP, State) -> {noreply, State, catch_up(State)}. handle_call(reset, _From, State) -> - _ = ekka_mnesia:clear_table(?CLUSTER_COMMIT), - _ = ekka_mnesia:clear_table(?CLUSTER_MFA), + _ = mria:clear_table(?CLUSTER_COMMIT), + _ = mria:clear_table(?CLUSTER_MFA), {reply, ok, State, {continue, ?CATCH_UP}}; handle_call({initiate, MFA}, _From, State = #{node := Node}) -> diff --git a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl index e3d90fe7d..456ee6a9a 100644 --- a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl +++ b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl @@ -157,7 +157,7 @@ match_messages(_, Topic, Cursor) -> end. clean(_) -> - ekka_mnesia:clear_table(?TAB), + mria:clear_table(?TAB), ok. %%-------------------------------------------------------------------- %% Internal functions From 9965d6e0285e9261ebef5dee7e4ba5796cb46bc2 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 20:51:36 +0200 Subject: [PATCH 04/88] chore(mria): ekka_mnesia:create_table -> mria:create_table --- apps/emqx/src/emqx_alarm.erl | 13 +++++-------- apps/emqx/src/emqx_banned.erl | 9 +++------ apps/emqx/src/emqx_cm_registry.erl | 5 ++--- apps/emqx/src/emqx_router.erl | 8 +++----- apps/emqx/src/emqx_router_helper.erl | 9 +++------ apps/emqx/src/emqx_shared_sub.erl | 9 +++------ apps/emqx/src/emqx_trie.erl | 9 +++------ .../emqx_enhanced_authn_scram_mnesia.erl | 9 +++------ .../src/simple_authn/emqx_authn_mnesia.erl | 9 +++------ apps/emqx_authz/src/emqx_authz_mnesia.erl | 8 +++----- apps/emqx_dashboard/src/emqx_dashboard_admin.erl | 8 +++----- .../src/emqx_dashboard_collection.erl | 8 +++----- apps/emqx_dashboard/src/emqx_dashboard_token.erl | 8 +++----- apps/emqx_gateway/src/emqx_gateway_cm_registry.erl | 7 +++---- apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl | 14 +++++--------- apps/emqx_machine/src/emqx_cluster_rpc.erl | 13 +++++-------- apps/emqx_modules/src/emqx_delayed.erl | 8 +++----- apps/emqx_modules/src/emqx_telemetry.erl | 8 +++----- apps/emqx_modules/test/emqx_delayed_SUITE.erl | 2 +- apps/emqx_modules/test/emqx_telemetry_SUITE.erl | 2 +- apps/emqx_prometheus/src/emqx_prometheus.erl | 2 +- apps/emqx_psk/src/emqx_psk.erl | 9 +++------ apps/emqx_retainer/src/emqx_retainer_mnesia.erl | 5 ++--- 23 files changed, 67 insertions(+), 115 deletions(-) diff --git a/apps/emqx/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl index 39d13cacd..6c4e348c4 100644 --- a/apps/emqx/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -95,21 +95,18 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?ACTIVATED_ALARM, + ok = mria:create_table(?ACTIVATED_ALARM, [{type, set}, - {disc_copies, [node()]}, + {storage, disc_copies}, {local_content, true}, {record_name, activated_alarm}, {attributes, record_info(fields, activated_alarm)}]), - ok = ekka_mnesia:create_table(?DEACTIVATED_ALARM, + ok = mria:create_table(?DEACTIVATED_ALARM, [{type, ordered_set}, - {disc_copies, [node()]}, + {storage, disc_copies}, {local_content, true}, {record_name, deactivated_alarm}, - {attributes, record_info(fields, deactivated_alarm)}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?ACTIVATED_ALARM, disc_copies), - ok = ekka_mnesia:copy_table(?DEACTIVATED_ALARM, disc_copies). + {attributes, record_info(fields, deactivated_alarm)}]). %%-------------------------------------------------------------------- %% API diff --git a/apps/emqx/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl index 86f79ede8..30f91da6e 100644 --- a/apps/emqx/src/emqx_banned.erl +++ b/apps/emqx/src/emqx_banned.erl @@ -58,16 +58,13 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?BANNED_TAB, [ + ok = mria:create_table(?BANNED_TAB, [ {type, set}, {rlog_shard, ?COMMON_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, banned}, {attributes, record_info(fields, banned)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?BANNED_TAB, disc_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). %% @doc Start the banned server. -spec(start_link() -> startlink_ret()). diff --git a/apps/emqx/src/emqx_cm_registry.erl b/apps/emqx/src/emqx_cm_registry.erl index 65b89a884..c51660353 100644 --- a/apps/emqx/src/emqx_cm_registry.erl +++ b/apps/emqx/src/emqx_cm_registry.erl @@ -100,15 +100,14 @@ record(ClientId, ChanPid) -> %%-------------------------------------------------------------------- init([]) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {type, bag}, {rlog_shard, ?CM_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, channel}, {attributes, record_info(fields, channel)}, {storage_properties, [{ets, [{read_concurrency, true}, {write_concurrency, true}]}]}]), - ok = ekka_mnesia:copy_table(?TAB, ram_copies), ok = ekka_rlog:wait_for_shards([?CM_SHARD], infinity), ok = ekka:monitor(membership), {ok, #{}}. diff --git a/apps/emqx/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl index 4793100ba..0416d6d72 100644 --- a/apps/emqx/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -74,16 +74,14 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?ROUTE_TAB, [ + ok = mria:create_table(?ROUTE_TAB, [ {type, bag}, {rlog_shard, ?ROUTE_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, route}, {attributes, record_info(fields, route)}, {storage_properties, [{ets, [{read_concurrency, true}, - {write_concurrency, true}]}]}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?ROUTE_TAB, ram_copies). + {write_concurrency, true}]}]}]). %%-------------------------------------------------------------------- %% Start a router diff --git a/apps/emqx/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl index 6542e3983..3fc3f42ce 100644 --- a/apps/emqx/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -59,16 +59,13 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?ROUTING_NODE, [ + ok = mria:create_table(?ROUTING_NODE, [ {type, set}, {rlog_shard, ?ROUTE_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, routing_node}, {attributes, record_info(fields, routing_node)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?ROUTING_NODE, ram_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). %%-------------------------------------------------------------------- %% API diff --git a/apps/emqx/src/emqx_shared_sub.erl b/apps/emqx/src/emqx_shared_sub.erl index 299c4df38..9a3c7c74d 100644 --- a/apps/emqx/src/emqx_shared_sub.erl +++ b/apps/emqx/src/emqx_shared_sub.erl @@ -85,15 +85,12 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {type, bag}, {rlog_shard, ?SHARED_SUB_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, emqx_shared_subscription}, - {attributes, record_info(fields, emqx_shared_subscription)}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, ram_copies). + {attributes, record_info(fields, emqx_shared_subscription)}]). %%-------------------------------------------------------------------- %% API diff --git a/apps/emqx/src/emqx_trie.erl b/apps/emqx/src/emqx_trie.erl index 327db16c0..bf2afc910 100644 --- a/apps/emqx/src/emqx_trie.erl +++ b/apps/emqx/src/emqx_trie.erl @@ -61,16 +61,13 @@ mnesia(boot) -> StoreProps = [{ets, [{read_concurrency, true}, {write_concurrency, true} ]}], - ok = ekka_mnesia:create_table(?TRIE, [ + ok = mria:create_table(?TRIE, [ {rlog_shard, ?ROUTE_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, ?TRIE}, {attributes, record_info(fields, ?TRIE)}, {type, ordered_set}, - {storage_properties, StoreProps}]); -mnesia(copy) -> - %% Copy topics table - ok = ekka_mnesia:copy_table(?TRIE, ram_copies). + {storage_properties, StoreProps}]). %%-------------------------------------------------------------------- %% Topics APIs diff --git a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl index 4f8b38b1e..d791d1aed 100644 --- a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl +++ b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl @@ -63,15 +63,12 @@ %% @doc Create or replicate tables. -spec(mnesia(boot | copy) -> ok). mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {rlog_shard, ?AUTH_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, user_info}, {attributes, record_info(fields, user_info)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, disc_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). %%------------------------------------------------------------------------------ %% Hocon Schema diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index 314c3d578..590152aaf 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -70,15 +70,12 @@ %% @doc Create or replicate tables. -spec(mnesia(boot | copy) -> ok). mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {rlog_shard, ?AUTH_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, user_info}, {attributes, record_info(fields, user_info)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, disc_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). %%------------------------------------------------------------------------------ %% Hocon Schema diff --git a/apps/emqx_authz/src/emqx_authz_mnesia.erl b/apps/emqx_authz/src/emqx_authz_mnesia.erl index ab755403e..9c5ca458b 100644 --- a/apps/emqx_authz/src/emqx_authz_mnesia.erl +++ b/apps/emqx_authz/src/emqx_authz_mnesia.erl @@ -36,14 +36,12 @@ -spec(mnesia(boot | copy) -> ok). mnesia(boot) -> - ok = ekka_mnesia:create_table(?ACL_TABLE, [ + ok = mria:create_table(?ACL_TABLE, [ {type, ordered_set}, {rlog_shard, ?ACL_SHARDED}, - {disc_copies, [node()]}, + {storage, disc_copies}, {attributes, record_info(fields, ?ACL_TABLE)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?ACL_TABLE, disc_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). description() -> "AuthZ with Mnesia". diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 55cb8ffe5..f79eb92e5 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -50,16 +50,14 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(mqtt_admin, [ + ok = mria:create_table(mqtt_admin, [ {type, set}, {rlog_shard, ?DASHBOARD_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, mqtt_admin}, {attributes, record_info(fields, mqtt_admin)}, {storage_properties, [{ets, [{read_concurrency, true}, - {write_concurrency, true}]}]}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(mqtt_admin, disc_copies). + {write_concurrency, true}]}]}]). %%-------------------------------------------------------------------- %% API diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 7ef5e0972..03c5bfcb3 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -41,14 +41,12 @@ -define(EXPIRE_INTERVAL, 86400000 * 7). mnesia(boot) -> - ok = ekka_mnesia:create_table(emqx_collect, [ + ok = mria:create_table(emqx_collect, [ {type, set}, {local_content, true}, - {disc_only_copies, [node()]}, + {storage, disc_only_copies}, {record_name, mqtt_collect}, - {attributes, record_info(fields, mqtt_collect)}]); -mnesia(copy) -> - mnesia:add_table_copy(emqx_collect, node(), disc_only_copies). + {attributes, record_info(fields, mqtt_collect)}]). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index 611ef44a2..5b38a163f 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -77,16 +77,14 @@ destroy_by_username(Username) -> do_destroy_by_username(Username). mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {type, set}, {rlog_shard, ?DASHBOARD_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, mqtt_admin_jwt}, {attributes, record_info(fields, mqtt_admin_jwt)}, {storage_properties, [{ets, [{read_concurrency, true}, - {write_concurrency, true}]}]}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, disc_copies). + {write_concurrency, true}]}]}]). %%-------------------------------------------------------------------- %% jwt apply diff --git a/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl b/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl index 51c4e95c2..e82537285 100644 --- a/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl +++ b/apps/emqx_gateway/src/emqx_gateway_cm_registry.erl @@ -89,16 +89,15 @@ record(ClientId, ChanPid) -> init([Type]) -> Tab = tabname(Type), - ok = ekka_mnesia:create_table(Tab, [ + ok = mria:create_table(Tab, [ {type, bag}, {rlog_shard, ?CM_SHARD}, - {ram_copies, [node()]}, + {storage, ram_copies}, {record_name, channel}, {attributes, record_info(fields, channel)}, {storage_properties, [{ets, [{read_concurrency, true}, {write_concurrency, true}]}]}]), - ok = ekka_mnesia:copy_table(Tab, ram_copies), - %%ok = ekka_rlog:wait_for_shards([?CM_SHARD], infinity), + ok = mria:wait_for_tables([Tab]), ok = ekka:monitor(membership), {ok, #{type => Type}}. diff --git a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl index 863ea2be7..48f8e9b5f 100644 --- a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl +++ b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl @@ -65,13 +65,10 @@ %mnesia(boot) -> % %% Optimize storage % StoreProps = [{ets, [{read_concurrency, true}]}], -% ok = ekka_mnesia:create_table(?MODULE, [ +% ok = mria:create_table(?MODULE, [ % {attributes, record_info(fields, emqx_sn_registry)}, % {ram_copies, [node()]}, -% {storage_properties, StoreProps}]); -% -%mnesia(copy) -> -% ok = ekka_mnesia:copy_table(?MODULE, ram_copies). +% {storage_properties, StoreProps}]). -type registry() :: {Tab :: atom(), RegistryPid :: pid()}. @@ -143,15 +140,14 @@ init([InstaId, PredefTopics]) -> %% {ClientId, TopicId} -> TopicName %% {ClientId, TopicName} -> TopicId Tab = name(InstaId), - ok = ekka_mnesia:create_table(Tab, [ - {ram_copies, [node()]}, + ok = mria:create_table(Tab, [ + {storage, ram_copies}, {record_name, emqx_sn_registry}, {attributes, record_info(fields, emqx_sn_registry)}, {storage_properties, [{ets, [{read_concurrency, true}]}]}, {rlog_shard, ?SN_SHARD} ]), - ok = ekka_mnesia:copy_table(Tab, ram_copies), - ok = ekka_rlog:wait_for_shards([?SN_SHARD], infinity), + ok = mria:wait_for_tables([Tab]), % FIXME: %ok = ekka_rlog:wait_for_shards([?CM_SHARD], infinity), MaxPredefId = lists:foldl( diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index 0d93805b7..ebebd19a4 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -45,21 +45,18 @@ %%% API %%%=================================================================== mnesia(boot) -> - ok = ekka_mnesia:create_table(?CLUSTER_MFA, [ + ok = mria:create_table(?CLUSTER_MFA, [ {type, ordered_set}, {rlog_shard, ?EMQX_MACHINE_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, cluster_rpc_mfa}, {attributes, record_info(fields, cluster_rpc_mfa)}]), - ok = ekka_mnesia:create_table(?CLUSTER_COMMIT, [ + ok = mria:create_table(?CLUSTER_COMMIT, [ {type, set}, {rlog_shard, ?EMQX_MACHINE_SHARD}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, cluster_rpc_commit}, - {attributes, record_info(fields, cluster_rpc_commit)}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(cluster_rpc_mfa, disc_copies), - ok = ekka_mnesia:copy_table(cluster_rpc_commit, disc_copies). + {attributes, record_info(fields, cluster_rpc_commit)}]). start_link() -> start_link(node(), ?MODULE, get_retry_ms()). diff --git a/apps/emqx_modules/src/emqx_delayed.erl b/apps/emqx_modules/src/emqx_delayed.erl index f2eef3f39..15cafb614 100644 --- a/apps/emqx_modules/src/emqx_delayed.erl +++ b/apps/emqx_modules/src/emqx_delayed.erl @@ -64,14 +64,12 @@ %% Mnesia bootstrap %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {type, ordered_set}, - {disc_copies, [node()]}, + {storage, disc_copies}, {local_content, true}, {record_name, delayed_message}, - {attributes, record_info(fields, delayed_message)}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, disc_copies). + {attributes, record_info(fields, delayed_message)}]). %%-------------------------------------------------------------------- %% Hooks diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index 3c3f9bd6a..9a4881d9b 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -91,14 +91,12 @@ %%-------------------------------------------------------------------- mnesia(boot) -> - ok = ekka_mnesia:create_table(?TELEMETRY, + ok = mria:create_table(?TELEMETRY, [{type, set}, - {disc_copies, [node()]}, + {storage, disc_copies}, {local_content, true}, {record_name, telemetry}, - {attributes, record_info(fields, telemetry)}]); -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TELEMETRY, disc_copies). + {attributes, record_info(fields, telemetry)}]). %%-------------------------------------------------------------------- %% API diff --git a/apps/emqx_modules/test/emqx_delayed_SUITE.erl b/apps/emqx_modules/test/emqx_delayed_SUITE.erl index 3a070a1e8..81c2c1577 100644 --- a/apps/emqx_modules/test/emqx_delayed_SUITE.erl +++ b/apps/emqx_modules/test/emqx_delayed_SUITE.erl @@ -35,7 +35,7 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), + mria:start(), ok = emqx_delayed:mnesia(boot), emqx_common_test_helpers:start_apps([emqx_modules]), Config. diff --git a/apps/emqx_modules/test/emqx_telemetry_SUITE.erl b/apps/emqx_modules/test/emqx_telemetry_SUITE.erl index cf1ddff93..5380b55a6 100644 --- a/apps/emqx_modules/test/emqx_telemetry_SUITE.erl +++ b/apps/emqx_modules/test/emqx_telemetry_SUITE.erl @@ -28,7 +28,7 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - ok = ekka_mnesia:start(), + ok = mria:start(), ok = emqx_telemetry:mnesia(boot), emqx_common_test_helpers:start_apps([emqx_modules]), Config. diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl index bbdbab6b2..0a7aaa8e4 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus.erl @@ -590,6 +590,6 @@ emqx_cluster() -> ]. emqx_cluster_data() -> - #{running_nodes := Running, stopped_nodes := Stopped} = ekka_mnesia:cluster_info(), + #{running_nodes := Running, stopped_nodes := Stopped} = mria:cluster_info(), [{nodes_running, length(Running)}, {nodes_stopped, length(Stopped)}]. diff --git a/apps/emqx_psk/src/emqx_psk.erl b/apps/emqx_psk/src/emqx_psk.erl index 65ce1025b..871276c24 100644 --- a/apps/emqx_psk/src/emqx_psk.erl +++ b/apps/emqx_psk/src/emqx_psk.erl @@ -64,16 +64,13 @@ %% @doc Create or replicate tables. -spec(mnesia(boot | copy) -> ok). mnesia(boot) -> - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {rlog_shard, ?PSK_SHARD}, {type, ordered_set}, - {disc_copies, [node()]}, + {storage, disc_copies}, {record_name, psk_entry}, {attributes, record_info(fields, psk_entry)}, - {storage_properties, [{ets, [{read_concurrency, true}]}]}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(?TAB, disc_copies). + {storage_properties, [{ets, [{read_concurrency, true}]}]}]). %%------------------------------------------------------------------------------ %% APIs diff --git a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl index 456ee6a9a..478234def 100644 --- a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl +++ b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl @@ -52,14 +52,13 @@ create_resource(#{storage_type := StorageType}) -> {read_concurrency, true}, {write_concurrency, true}]}, {dets, [{auto_save, 1000}]}], - ok = ekka_mnesia:create_table(?TAB, [ + ok = mria:create_table(?TAB, [ {type, set}, {rlog_shard, ?RETAINER_SHARD}, - {Copies, [node()]}, + {storage, Copies}, {record_name, retained}, {attributes, record_info(fields, retained)}, {storage_properties, StoreProps}]), - ok = ekka_mnesia:copy_table(?TAB, Copies), ok = ekka_rlog:wait_for_shards([?RETAINER_SHARD], infinity), case mnesia:table_info(?TAB, storage_type) of Copies -> ok; From e14a62d4d6e76e0651b5637f1adafe185fe571fb Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Fri, 15 Oct 2021 17:47:49 +0200 Subject: [PATCH 05/88] chore(mria): ekka_mnesia:start/stop -> mria:start/stop --- apps/emqx/test/emqx_banned_SUITE.erl | 5 ++--- apps/emqx/test/emqx_flapping_SUITE.erl | 2 +- apps/emqx/test/emqx_trie_SUITE.erl | 5 ++--- apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl | 5 ++--- apps/emqx_dashboard/src/emqx_dashboard_collection.erl | 2 +- apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl | 2 +- apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl | 2 +- apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl | 4 ++-- apps/emqx_management/test/emqx_mgmt_api_test_util.erl | 2 +- 9 files changed, 13 insertions(+), 16 deletions(-) diff --git a/apps/emqx/test/emqx_banned_SUITE.erl b/apps/emqx/test/emqx_banned_SUITE.erl index b215b5055..258030513 100644 --- a/apps/emqx/test/emqx_banned_SUITE.erl +++ b/apps/emqx/test/emqx_banned_SUITE.erl @@ -33,8 +33,8 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ekka:stop(), - ekka_mnesia:ensure_stopped(), - ekka_mnesia:delete_schema(). + mria:ensure_stopped(), + mria_mnesia:delete_schema(). t_add_delete(_) -> Banned = #banned{who = {clientid, <<"TestClient">>}, @@ -92,4 +92,3 @@ t_unused(_) -> ?assertEqual(ok, Banned ! ok), timer:sleep(500), %% expiry timer ok = emqx_banned:stop(). - diff --git a/apps/emqx/test/emqx_flapping_SUITE.erl b/apps/emqx/test/emqx_flapping_SUITE.erl index 88a4d8ee0..b5a5314d7 100644 --- a/apps/emqx/test/emqx_flapping_SUITE.erl +++ b/apps/emqx/test/emqx_flapping_SUITE.erl @@ -35,7 +35,7 @@ init_per_suite(Config) -> end_per_suite(_Config) -> emqx_common_test_helpers:stop_apps([]), - ekka_mnesia:delete_schema(), %% Clean emqx_banned table + mria_mnesia:delete_schema(), %% Clean emqx_banned table ok. t_detect_check(_) -> diff --git a/apps/emqx/test/emqx_trie_SUITE.erl b/apps/emqx/test/emqx_trie_SUITE.erl index e22e643b0..713671766 100644 --- a/apps/emqx/test/emqx_trie_SUITE.erl +++ b/apps/emqx/test/emqx_trie_SUITE.erl @@ -50,8 +50,8 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ekka:stop(), - ekka_mnesia:ensure_stopped(), - ekka_mnesia:delete_schema(). + mria:ensure_stopped(), + mria_mnesia:delete_schema(). init_per_testcase(_TestCase, Config) -> clear_tables(), @@ -194,4 +194,3 @@ trans(Fun) -> mnesia:transaction(Fun). trans(Fun, Args) -> mnesia:transaction(Fun, Args). - diff --git a/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl b/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl index 58f64be90..744267e74 100644 --- a/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl +++ b/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl @@ -41,8 +41,8 @@ all() -> [t_auto_subscribe, t_update]. -init_per_suite(Config) -> - ekka_mnesia:start(), +init_per_suite(Config) -> + mria:start(), application:stop(?APP), meck:new(emqx_schema, [non_strict, passthrough, no_history, no_link]), @@ -159,4 +159,3 @@ check_subs([{{_, Topic}, #{subid := ?CLIENT_ID}} | Subs], List) -> check_subs(Subs, lists:delete(Topic, List)); check_subs([_ | Subs], List) -> check_subs(Subs, List). - diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 03c5bfcb3..9f856c36d 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -160,7 +160,7 @@ flush({Connection, Route, Subscription}, {Received0, Sent0, Dropped0}) -> diff(Sent, Sent0), diff(Dropped, Dropped0)}, Ts = get_local_time(), - mria:transaction(ekka_mnesia:local_content_shard(), + mria:transaction(mria:local_content_shard(), fun mnesia:write/1, [#mqtt_collect{timestamp = Ts, collect = Collect}]), {Received, Sent, Dropped}. diff --git a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl index cb947b995..b9008d128 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl @@ -50,7 +50,7 @@ init_per_suite(Config) -> end_per_suite(_Config) -> emqx_common_test_helpers:stop_apps([emqx_dashboard, emqx_management]), - ekka_mnesia:ensure_stopped(). + mria:ensure_stopped(). set_special_configs(emqx_management) -> emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], diff --git a/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl b/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl index 04a3d8024..d7a8f1d1c 100644 --- a/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl +++ b/apps/emqx_gateway/test/emqx_sn_registry_SUITE.erl @@ -35,7 +35,7 @@ all() -> init_per_suite(Config) -> application:ensure_all_started(ekka), - ekka_mnesia:start(), + mria:start(), Config. end_per_suite(_Config) -> diff --git a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl b/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl index 4e3b2d2c2..8da2dd107 100644 --- a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl +++ b/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl @@ -54,8 +54,8 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ekka:stop(), - ekka_mnesia:ensure_stopped(), - ekka_mnesia:delete_schema(), + mria:stop(), + mria_mnesia:delete_schema(), meck:unload(emqx_alarm), ok. diff --git a/apps/emqx_management/test/emqx_mgmt_api_test_util.erl b/apps/emqx_management/test/emqx_mgmt_api_test_util.erl index c023267a6..cdad91b0c 100644 --- a/apps/emqx_management/test/emqx_mgmt_api_test_util.erl +++ b/apps/emqx_management/test/emqx_mgmt_api_test_util.erl @@ -24,7 +24,7 @@ init_suite() -> init_suite([]). init_suite(Apps) -> - ekka_mnesia:start(), + mria:start(), application:load(emqx_management), emqx_common_test_helpers:start_apps(Apps ++ [emqx_dashboard], fun set_special_configs/1). From 326923850c1a920bf4520b596da49d3ea7cebcde Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 20:54:46 +0200 Subject: [PATCH 06/88] chore(mria): Get rid of copy_mnesia callback --- apps/emqx/src/emqx_alarm.erl | 1 - apps/emqx/src/emqx_banned.erl | 1 - apps/emqx/src/emqx_router.erl | 1 - apps/emqx/src/emqx_router_helper.erl | 1 - apps/emqx/src/emqx_shared_sub.erl | 1 - apps/emqx/src/emqx_trie.erl | 1 - .../src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl | 1 - apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl | 1 - apps/emqx_authz/src/emqx_authz_mnesia.erl | 1 - apps/emqx_dashboard/src/emqx_dashboard_admin.erl | 1 - apps/emqx_dashboard/src/emqx_dashboard_collection.erl | 1 - apps/emqx_dashboard/src/emqx_dashboard_token.erl | 1 - apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl | 1 - apps/emqx_machine/src/emqx_cluster_rpc.erl | 1 - apps/emqx_modules/src/emqx_delayed.erl | 1 - apps/emqx_modules/src/emqx_telemetry.erl | 1 - apps/emqx_psk/src/emqx_psk.erl | 1 - 17 files changed, 17 deletions(-) diff --git a/apps/emqx/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl index 6c4e348c4..83a12472d 100644 --- a/apps/emqx/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -26,7 +26,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([post_config_update/4]). diff --git a/apps/emqx/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl index 30f91da6e..89442a6aa 100644 --- a/apps/emqx/src/emqx_banned.erl +++ b/apps/emqx/src/emqx_banned.erl @@ -27,7 +27,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([start_link/0, stop/0]). diff --git a/apps/emqx/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl index 0416d6d72..915b01dd6 100644 --- a/apps/emqx/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -28,7 +28,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([start_link/2]). diff --git a/apps/emqx/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl index 3fc3f42ce..edec76d06 100644 --- a/apps/emqx/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -27,7 +27,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). %% API -export([ start_link/0 diff --git a/apps/emqx/src/emqx_shared_sub.erl b/apps/emqx/src/emqx_shared_sub.erl index 9a3c7c74d..79a7d5522 100644 --- a/apps/emqx/src/emqx_shared_sub.erl +++ b/apps/emqx/src/emqx_shared_sub.erl @@ -28,7 +28,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). %% APIs -export([start_link/0]). diff --git a/apps/emqx/src/emqx_trie.erl b/apps/emqx/src/emqx_trie.erl index bf2afc910..4354a2bab 100644 --- a/apps/emqx/src/emqx_trie.erl +++ b/apps/emqx/src/emqx_trie.erl @@ -22,7 +22,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). %% Trie APIs -export([ insert/1 diff --git a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl index d791d1aed..92bdf0619 100644 --- a/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl +++ b/apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl @@ -46,7 +46,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -record(user_info, { user_id diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index 590152aaf..095dc6ef8 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -59,7 +59,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -define(TAB, ?MODULE). diff --git a/apps/emqx_authz/src/emqx_authz_mnesia.erl b/apps/emqx_authz/src/emqx_authz_mnesia.erl index 9c5ca458b..3851affed 100644 --- a/apps/emqx_authz/src/emqx_authz_mnesia.erl +++ b/apps/emqx_authz/src/emqx_authz_mnesia.erl @@ -32,7 +32,6 @@ -endif. -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -spec(mnesia(boot | copy) -> ok). mnesia(boot) -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index f79eb92e5..2a7f2410a 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -21,7 +21,6 @@ -include("emqx_dashboard.hrl"). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). %% Mnesia bootstrap -export([mnesia/1]). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 9f856c36d..2108d0919 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -25,7 +25,6 @@ -export([get_local_time/0]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). %% Mnesia bootstrap -export([mnesia/1]). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index 5b38a163f..b1eb32d74 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -28,7 +28,6 @@ ]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([mnesia/1]). diff --git a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl index 48f8e9b5f..7be7a28e2 100644 --- a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl +++ b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl @@ -58,7 +58,6 @@ %-export([mnesia/1]). %-boot_mnesia({mnesia, [boot]}). -%-copy_mnesia({mnesia, [copy]}). %%% @doc Create or replicate tables. %-spec(mnesia(boot | copy) -> ok). diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index ebebd19a4..e64623bdc 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -30,7 +30,6 @@ -endif. -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -include_lib("emqx/include/logger.hrl"). -include("emqx_machine.hrl"). diff --git a/apps/emqx_modules/src/emqx_delayed.erl b/apps/emqx_modules/src/emqx_delayed.erl index 15cafb614..401e2a10c 100644 --- a/apps/emqx_modules/src/emqx_delayed.erl +++ b/apps/emqx_modules/src/emqx_delayed.erl @@ -25,7 +25,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([ start_link/0 , on_message_publish/1 diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index 9a4881d9b..f9903b845 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -30,7 +30,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -export([ start_link/0 , stop/0 diff --git a/apps/emqx_psk/src/emqx_psk.erl b/apps/emqx_psk/src/emqx_psk.erl index 871276c24..7de332cb9 100644 --- a/apps/emqx_psk/src/emqx_psk.erl +++ b/apps/emqx_psk/src/emqx_psk.erl @@ -47,7 +47,6 @@ -export([mnesia/1]). -boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). -define(TAB, ?MODULE). -define(PSK_SHARD, emqx_psk_shard). From d14b8e7da9e86416c2c04e3094f44776d3d20aa3 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 14 Oct 2021 21:49:07 +0200 Subject: [PATCH 07/88] chore(mria): ekka_rlog -> mria_rlog --- apps/emqx/src/emqx_app.erl | 2 +- apps/emqx/src/emqx_cm_registry.erl | 2 +- apps/emqx/src/emqx_router.erl | 2 +- apps/emqx_authn/src/emqx_authn_app.erl | 2 +- apps/emqx_authz/src/emqx_authz_app.erl | 2 +- apps/emqx_dashboard/src/emqx_dashboard_app.erl | 2 +- apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl | 2 +- apps/emqx_machine/src/emqx_cluster_rpc.erl | 2 +- apps/emqx_machine/src/emqx_machine.erl | 2 +- apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl | 2 +- apps/emqx_management/src/emqx_mgmt_app.erl | 2 +- apps/emqx_retainer/src/emqx_retainer_mnesia.erl | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/emqx/src/emqx_app.erl b/apps/emqx/src/emqx_app.erl index cd435b864..662439397 100644 --- a/apps/emqx/src/emqx_app.erl +++ b/apps/emqx/src/emqx_app.erl @@ -57,7 +57,7 @@ stop(_State) -> ok. ensure_ekka_started() -> ekka:start(), - ok = ekka_rlog:wait_for_shards(?BOOT_SHARDS, infinity). + ok = mria_rlog:wait_for_shards(?BOOT_SHARDS, infinity). %% @doc Call this function to make emqx boot without loading config, %% in case we want to delegate the config load to a higher level app diff --git a/apps/emqx/src/emqx_cm_registry.erl b/apps/emqx/src/emqx_cm_registry.erl index c51660353..492c6dacd 100644 --- a/apps/emqx/src/emqx_cm_registry.erl +++ b/apps/emqx/src/emqx_cm_registry.erl @@ -108,7 +108,7 @@ init([]) -> {attributes, record_info(fields, channel)}, {storage_properties, [{ets, [{read_concurrency, true}, {write_concurrency, true}]}]}]), - ok = ekka_rlog:wait_for_shards([?CM_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?CM_SHARD], infinity), ok = ekka:monitor(membership), {ok, #{}}. diff --git a/apps/emqx/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl index 915b01dd6..ad63c6657 100644 --- a/apps/emqx/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -252,7 +252,7 @@ maybe_trans(Fun, Args) -> trans(Fun, Args); global -> %% Assert: - mnesia = ekka_rlog:backend(), %% TODO: do something smarter than just crash + mnesia = mria_rlog:backend(), %% TODO: do something smarter than just crash lock_router(), try mnesia:sync_dirty(Fun, Args) after diff --git a/apps/emqx_authn/src/emqx_authn_app.erl b/apps/emqx_authn/src/emqx_authn_app.erl index d297c9042..b71a3e16b 100644 --- a/apps/emqx_authn/src/emqx_authn_app.erl +++ b/apps/emqx_authn/src/emqx_authn_app.erl @@ -30,7 +30,7 @@ %%------------------------------------------------------------------------------ start(_StartType, _StartArgs) -> - ok = ekka_rlog:wait_for_shards([?AUTH_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?AUTH_SHARD], infinity), {ok, Sup} = emqx_authn_sup:start_link(), ok = ?AUTHN:register_providers(providers()), ok = initialize(), diff --git a/apps/emqx_authz/src/emqx_authz_app.erl b/apps/emqx_authz/src/emqx_authz_app.erl index f868ac342..a5044443b 100644 --- a/apps/emqx_authz/src/emqx_authz_app.erl +++ b/apps/emqx_authz/src/emqx_authz_app.erl @@ -12,7 +12,7 @@ -export([start/2, stop/1]). start(_StartType, _StartArgs) -> - ok = ekka_rlog:wait_for_shards([?ACL_SHARDED], infinity), + ok = mria_rlog:wait_for_shards([?ACL_SHARDED], infinity), {ok, Sup} = emqx_authz_sup:start_link(), ok = emqx_authz:init(), {ok, Sup}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_app.erl b/apps/emqx_dashboard/src/emqx_dashboard_app.erl index 4e1b0caec..16acdb182 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_app.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_app.erl @@ -26,7 +26,7 @@ start(_StartType, _StartArgs) -> {ok, Sup} = emqx_dashboard_sup:start_link(), - ok = ekka_rlog:wait_for_shards([?DASHBOARD_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?DASHBOARD_SHARD], infinity), _ = emqx_dashboard:start_listeners(), emqx_dashboard_cli:load(), ok = emqx_dashboard_admin:add_default_user(), diff --git a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl index 7be7a28e2..b52d9c7dc 100644 --- a/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl +++ b/apps/emqx_gateway/src/mqttsn/emqx_sn_registry.erl @@ -148,7 +148,7 @@ init([InstaId, PredefTopics]) -> ]), ok = mria:wait_for_tables([Tab]), % FIXME: - %ok = ekka_rlog:wait_for_shards([?CM_SHARD], infinity), + %ok = mria_rlog:wait_for_shards([?CM_SHARD], infinity), MaxPredefId = lists:foldl( fun(#{id := TopicId, topic := TopicName0}, AccId) -> TopicName = iolist_to_binary(TopicName0), diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index e64623bdc..7ca6b3571 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -84,7 +84,7 @@ multicall(M, F, A, RequireNum, Timeout) when RequireNum =:= all orelse RequireNu MFA = {initiate, {M, F, A}}, Begin = erlang:monotonic_time(), InitRes = - case ekka_rlog:role() of + case mria_rlog:role() of core -> gen_server:call(?MODULE, MFA, Timeout); replicant -> %% the initiate transaction must happened on core node diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index 0f8208b46..996f40bf7 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -36,7 +36,7 @@ start() -> ok = print_otp_version_warning(), ok = load_config_files(), ekka:start(), - ekka_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), + mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), ok. graceful_shutdown() -> diff --git a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl b/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl index 8da2dd107..cf6c794a7 100644 --- a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl +++ b/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl @@ -43,7 +43,7 @@ init_per_suite(Config) -> application:load(emqx), application:load(emqx_machine), ok = ekka:start(), - ok = ekka_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), application:set_env(emqx_machine, cluster_call_max_history, 100), application:set_env(emqx_machine, cluster_call_clean_interval, 1000), application:set_env(emqx_machine, cluster_call_retry_interval, 900), diff --git a/apps/emqx_management/src/emqx_mgmt_app.erl b/apps/emqx_management/src/emqx_mgmt_app.erl index 8dc1651da..4dae30a97 100644 --- a/apps/emqx_management/src/emqx_mgmt_app.erl +++ b/apps/emqx_management/src/emqx_mgmt_app.erl @@ -28,7 +28,7 @@ start(_Type, _Args) -> {ok, Sup} = emqx_mgmt_sup:start_link(), - ok = ekka_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity), emqx_mgmt_cli:load(), {ok, Sup}. diff --git a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl index 478234def..0d112995f 100644 --- a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl +++ b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl @@ -59,7 +59,7 @@ create_resource(#{storage_type := StorageType}) -> {record_name, retained}, {attributes, record_info(fields, retained)}, {storage_properties, StoreProps}]), - ok = ekka_rlog:wait_for_shards([?RETAINER_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?RETAINER_SHARD], infinity), case mnesia:table_info(?TAB, storage_type) of Copies -> ok; _Other -> From 7086135ec8480753b5e3aec905920b5b50b705f6 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Fri, 15 Oct 2021 17:40:22 +0200 Subject: [PATCH 08/88] chore(mria): Remove the obsolete annotiation --- apps/emqx_machine/src/emqx_cluster_rpc.erl | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index 7ca6b3571..f7b755137 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -34,9 +34,6 @@ -include_lib("emqx/include/logger.hrl"). -include("emqx_machine.hrl"). --rlog_shard({?EMQX_MACHINE_SHARD, ?CLUSTER_MFA}). --rlog_shard({?EMQX_MACHINE_SHARD, ?CLUSTER_COMMIT}). - -define(CATCH_UP, catch_up). -define(TIMEOUT, timer:minutes(1)). From 73a4816d9cd68305aab9619eca2b23272191dc0c Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Fri, 15 Oct 2021 17:41:03 +0200 Subject: [PATCH 09/88] fix(mria): Hook up mria to emqx_machine --- apps/emqx_machine/src/emqx_cluster_rpc.erl | 2 +- apps/emqx_machine/src/emqx_machine.erl | 1 + apps/emqx_machine/src/emqx_machine_schema.erl | 6 +++--- apps/emqx_prometheus/src/emqx_prometheus.erl | 2 +- rebar.config.erl | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index f7b755137..a55d17616 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -87,7 +87,7 @@ multicall(M, F, A, RequireNum, Timeout) when RequireNum =:= all orelse RequireNu %% the initiate transaction must happened on core node %% make sure MFA(in the transaction) and the transaction on the same node %% don't need rpc again inside transaction. - case ekka_rlog_status:upstream_node(?EMQX_MACHINE_SHARD) of + case mria_status:upstream_node(?EMQX_MACHINE_SHARD) of {ok, Node} -> gen_server:call({?MODULE, Node}, MFA, Timeout); disconnected -> {error, disconnected} end diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index 996f40bf7..1df7dba36 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -35,6 +35,7 @@ start() -> ok = set_backtrace_depth(), ok = print_otp_version_warning(), ok = load_config_files(), + mria:start(), ekka:start(), mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), ok. diff --git a/apps/emqx_machine/src/emqx_machine_schema.erl b/apps/emqx_machine/src/emqx_machine_schema.erl index a124166e5..05c7d3ffa 100644 --- a/apps/emqx_machine/src/emqx_machine_schema.erl +++ b/apps/emqx_machine/src/emqx_machine_schema.erl @@ -139,7 +139,7 @@ fields("cluster") -> #{})} , {"db_backend", sc(hoconsc:enum([mnesia, rlog]), - #{ mapping => "ekka.db_backend" + #{ mapping => "mria.db_backend" , default => mnesia })} , {"rlog", @@ -245,12 +245,12 @@ fields(cluster_k8s) -> fields("rlog") -> [ {"role", sc(hoconsc:enum([core, replicant]), - #{ mapping => "ekka.node_role" + #{ mapping => "mria.node_role" , default => core })} , {"core_nodes", sc(emqx_schema:comma_separated_atoms(), - #{ mapping => "ekka.core_nodes" + #{ mapping => "mria.core_nodes" , default => [] })} ]; diff --git a/apps/emqx_prometheus/src/emqx_prometheus.erl b/apps/emqx_prometheus/src/emqx_prometheus.erl index 0a7aaa8e4..4667de24f 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus.erl @@ -590,6 +590,6 @@ emqx_cluster() -> ]. emqx_cluster_data() -> - #{running_nodes := Running, stopped_nodes := Stopped} = mria:cluster_info(), + #{running_nodes := Running, stopped_nodes := Stopped} = mria_mnesia:cluster_info(), [{nodes_running, length(Running)}, {nodes_stopped, length(Stopped)}]. diff --git a/rebar.config.erl b/rebar.config.erl index a3f32d0c4..d5ff6de80 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -60,7 +60,7 @@ community_plugin_overrides() -> %% Temporary workaround for a rebar3 erl_opts duplication %% bug. Ideally, we want to set this define globally snabbkaffe_overrides() -> - Apps = [snabbkaffe, ekka], + Apps = [snabbkaffe, ekka, mria], [{add, App, [{erl_opts, [{d, snk_kind, msg}]}]} || App <- Apps]. config(HasElixir) -> From fcdf10080dcb39f09d546cd3b4d9512d6b895d36 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Fri, 15 Oct 2021 20:00:35 +0200 Subject: [PATCH 10/88] chore(ct): ekka_mnesia -> mria_mnesia --- apps/emqx/test/emqx_common_test_helpers.erl | 4 ++-- apps/emqx/test/props/prop_emqx_sys.erl | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index 119f39ae2..e52aad3f2 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -290,8 +290,8 @@ reload(App, SpecAppConfigHandler) -> application:start(App). ensure_mnesia_stopped() -> - ekka_mnesia:ensure_stopped(), - ekka_mnesia:delete_schema(). + mria:stop(), + mria_mnesia:delete_schema(). %% Help function to wait for Fun to yield 'true'. wait_for(Fn, Ln, F, Timeout) -> diff --git a/apps/emqx/test/props/prop_emqx_sys.erl b/apps/emqx/test/props/prop_emqx_sys.erl index b6a0e0e38..3f0373d39 100644 --- a/apps/emqx/test/props/prop_emqx_sys.erl +++ b/apps/emqx/test/props/prop_emqx_sys.erl @@ -80,8 +80,8 @@ do_mock(emqx_broker) -> fun(Msg) -> {node(), <<"test">>, Msg} end); do_mock(emqx_stats) -> meck:expect(emqx_stats, getstats, fun() -> [0] end); -do_mock(ekka_mnesia) -> - meck:expect(ekka_mnesia, running_nodes, fun() -> [node()] end); +do_mock(mria_mnesia) -> + meck:expect(mria_mnesia, running_nodes, fun() -> [node()] end); do_mock(emqx_metrics) -> meck:expect(emqx_metrics, all, fun() -> [{hello, 3}] end). @@ -129,4 +129,3 @@ postcondition(_State, {call, _Mod, _Fun, _Args}, _Res) -> next_state(State, _Res, {call, _Mod, _Fun, _Args}) -> NewState = State, NewState. - From 07ea6e56894866597b680a416ac5320524558f60 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Mon, 18 Oct 2021 11:42:00 +0200 Subject: [PATCH 11/88] fix(mria): Fix startup sequence --- apps/emqx/src/emqx.app.src | 2 +- apps/emqx/test/emqx_banned_SUITE.erl | 4 +--- apps/emqx/test/emqx_common_test_helpers.erl | 3 ++- apps/emqx/test/emqx_router_SUITE.erl | 5 ----- apps/emqx/test/emqx_trie_SUITE.erl | 5 +---- apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl | 2 +- apps/emqx_machine/src/emqx_machine.erl | 1 - 7 files changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/emqx/src/emqx.app.src b/apps/emqx/src/emqx.app.src index 3f167d093..f3ea37b67 100644 --- a/apps/emqx/src/emqx.app.src +++ b/apps/emqx/src/emqx.app.src @@ -5,7 +5,7 @@ {vsn, "5.0.0"}, % strict semver, bump manually! {modules, []}, {registered, []}, - {applications, [kernel,stdlib,gproc,gen_rpc,esockd,cowboy,sasl,os_mon,jiffy,lc]}, + {applications, [kernel,stdlib,gproc,gen_rpc,mria,esockd,cowboy,sasl,os_mon,jiffy,lc]}, {mod, {emqx_app,[]}}, {env, []}, {licenses, ["Apache-2.0"]}, diff --git a/apps/emqx/test/emqx_banned_SUITE.erl b/apps/emqx/test/emqx_banned_SUITE.erl index 258030513..de117ab00 100644 --- a/apps/emqx/test/emqx_banned_SUITE.erl +++ b/apps/emqx/test/emqx_banned_SUITE.erl @@ -27,13 +27,11 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> application:load(emqx), ok = ekka:start(), - %% for coverage - ok = emqx_banned:mnesia(copy), Config. end_per_suite(_Config) -> ekka:stop(), - mria:ensure_stopped(), + mria:stop(), mria_mnesia:delete_schema(). t_add_delete(_) -> diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index e52aad3f2..bc2fdb7c0 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -216,7 +216,8 @@ generate_config(SchemaFile, ConfigFile) -> -spec(stop_apps(list()) -> ok). stop_apps(Apps) -> - [application:stop(App) || App <- Apps ++ [emqx, mnesia]]. + [application:stop(App) || App <- Apps ++ [emqx, mria, mnesia]], + ok. %% backward compatible deps_path(App, RelativePath) -> app_path(App, RelativePath). diff --git a/apps/emqx/test/emqx_router_SUITE.erl b/apps/emqx/test/emqx_router_SUITE.erl index aeb60fc2c..0d14a7992 100644 --- a/apps/emqx/test/emqx_router_SUITE.erl +++ b/apps/emqx/test/emqx_router_SUITE.erl @@ -41,10 +41,6 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(_TestCase, _Config) -> clear_tables(). -t_mnesia(_) -> - %% for coverage - ok = emqx_router:mnesia(copy). - % t_add_route(_) -> % error('TODO'). @@ -117,4 +113,3 @@ t_unexpected(_) -> clear_tables() -> lists:foreach(fun mnesia:clear_table/1, [emqx_route, emqx_trie, emqx_trie_node]). - diff --git a/apps/emqx/test/emqx_trie_SUITE.erl b/apps/emqx/test/emqx_trie_SUITE.erl index 713671766..9135a45dc 100644 --- a/apps/emqx/test/emqx_trie_SUITE.erl +++ b/apps/emqx/test/emqx_trie_SUITE.erl @@ -50,7 +50,7 @@ init_per_suite(Config) -> end_per_suite(_Config) -> ekka:stop(), - mria:ensure_stopped(), + mria:stop(), mria_mnesia:delete_schema(). init_per_testcase(_TestCase, Config) -> @@ -60,9 +60,6 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(_TestCase, _Config) -> clear_tables(). -t_mnesia(_) -> - ok = ?TRIE:mnesia(copy). - t_insert(_) -> Fun = fun() -> ?TRIE:insert(<<"sensor/1/metric/2">>), diff --git a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl index b9008d128..9f5fb3526 100644 --- a/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_dashboard_SUITE.erl @@ -50,7 +50,7 @@ init_per_suite(Config) -> end_per_suite(_Config) -> emqx_common_test_helpers:stop_apps([emqx_dashboard, emqx_management]), - mria:ensure_stopped(). + mria:stop(). set_special_configs(emqx_management) -> emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index 1df7dba36..996f40bf7 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -35,7 +35,6 @@ start() -> ok = set_backtrace_depth(), ok = print_otp_version_warning(), ok = load_config_files(), - mria:start(), ekka:start(), mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), ok. From 37a1c45af0e7c335ee7e6acd187f2146cb6c97e4 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Mon, 18 Oct 2021 17:13:11 +0200 Subject: [PATCH 12/88] fix(dialyzer): Fix problems found by dialyzer --- apps/emqx/src/emqx_banned.erl | 2 +- apps/emqx/src/emqx_router_helper.erl | 2 +- apps/emqx_dashboard/src/emqx_dashboard_collection.erl | 4 ++-- apps/emqx_dashboard/src/emqx_dashboard_token.erl | 2 +- apps/emqx_machine/src/emqx_machine.erl | 2 +- apps/emqx_retainer/src/emqx_retainer_mnesia.erl | 10 +++------- 6 files changed, 9 insertions(+), 13 deletions(-) diff --git a/apps/emqx/src/emqx_banned.erl b/apps/emqx/src/emqx_banned.erl index 89442a6aa..dfd299d90 100644 --- a/apps/emqx/src/emqx_banned.erl +++ b/apps/emqx/src/emqx_banned.erl @@ -191,7 +191,7 @@ handle_cast(Msg, State) -> {noreply, State}. handle_info({timeout, TRef, expire}, State = #{expiry_timer := TRef}) -> - mria:transaction(?COMMON_SHARD, fun expire_banned_items/1, [erlang:system_time(second)]), + _ = mria:transaction(?COMMON_SHARD, fun expire_banned_items/1, [erlang:system_time(second)]), {noreply, ensure_expiry_timer(State), hibernate}; handle_info(Info, State) -> diff --git a/apps/emqx/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl index edec76d06..aecce70ac 100644 --- a/apps/emqx/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -132,7 +132,7 @@ handle_info({mnesia_table_event, Event}, State) -> handle_info({nodedown, Node}, State = #{nodes := Nodes}) -> global:trans({?LOCK, self()}, fun() -> - mria:transaction(fun cleanup_routes/1, [Node]) + mria:transaction(?ROUTE_SHARD, fun cleanup_routes/1, [Node]) end), ok = mria:dirty_delete(?ROUTING_NODE, Node), {noreply, State#{nodes := lists:delete(Node, Nodes)}, hibernate}; diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 2108d0919..0eb1e033b 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -159,8 +159,8 @@ flush({Connection, Route, Subscription}, {Received0, Sent0, Dropped0}) -> diff(Sent, Sent0), diff(Dropped, Dropped0)}, Ts = get_local_time(), - mria:transaction(mria:local_content_shard(), - fun mnesia:write/1, [#mqtt_collect{timestamp = Ts, collect = Collect}]), + _ = mria:transaction(mria:local_content_shard(), + fun mnesia:write/1, [#mqtt_collect{timestamp = Ts, collect = Collect}]), {Received, Sent, Dropped}. avg(Items) -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index b1eb32d74..5a6771ae5 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -101,7 +101,7 @@ do_sign(Username, Password) -> Signed = jose_jwt:sign(JWK, JWS, JWT), {_, Token} = jose_jws:compact(Signed), JWTRec = format(Token, Username, ExpTime), - mria:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [JWTRec]), + _ = mria:transaction(?DASHBOARD_SHARD, fun mnesia:write/1, [JWTRec]), {ok, Token}. do_verify(Token)-> diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index 996f40bf7..313f45dd3 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -36,7 +36,7 @@ start() -> ok = print_otp_version_warning(), ok = load_config_files(), ekka:start(), - mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), + ok = mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), ok. graceful_shutdown() -> diff --git a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl index 0d112995f..6b5a9ac14 100644 --- a/apps/emqx_retainer/src/emqx_retainer_mnesia.erl +++ b/apps/emqx_retainer/src/emqx_retainer_mnesia.erl @@ -116,12 +116,8 @@ delete_message(_, Topic) -> Fun = fun() -> mnesia:delete({?TAB, Tokens}) end, - case mria:transaction(?RETAINER_SHARD, Fun) of - {atomic, Result} -> - Result; - ok -> - ok - end + _ = mria:transaction(?RETAINER_SHARD, Fun), + ok end, ok. @@ -156,7 +152,7 @@ match_messages(_, Topic, Cursor) -> end. clean(_) -> - mria:clear_table(?TAB), + _ = mria:clear_table(?TAB), ok. %%-------------------------------------------------------------------- %% Internal functions From 0d2d5f6bf98fddfc5b34d6e3cb205462666d4dfc Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Mon, 18 Oct 2021 22:09:48 +0200 Subject: [PATCH 13/88] fix(emqx_alarm): Wait for tables --- apps/emqx/src/emqx_alarm.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/emqx/src/emqx_alarm.erl b/apps/emqx/src/emqx_alarm.erl index 83a12472d..2585494eb 100644 --- a/apps/emqx/src/emqx_alarm.erl +++ b/apps/emqx/src/emqx_alarm.erl @@ -180,6 +180,7 @@ to_rfc3339(Timestamp) -> %%-------------------------------------------------------------------- init([]) -> + _ = mria:wait_for_tables([?ACTIVATED_ALARM, ?DEACTIVATED_ALARM]), deactivate_all_alarms(), ok = emqx_config_handler:add_handler([alarm], ?MODULE), {ok, #state{timer = ensure_timer(undefined, get_validity_period())}}. From b3a87532194f5817f7eb28ba6aae8b6f76b1685e Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Tue, 19 Oct 2021 12:24:35 +0200 Subject: [PATCH 14/88] fix(mria): Replace mnesia calls with mria --- apps/emqx/src/emqx_router.erl | 2 +- apps/emqx/test/emqx_trie_SUITE.erl | 4 +-- .../test/emqx_authz_mnesia_SUITE.erl | 26 +++++++++---------- apps/emqx_modules/src/emqx_telemetry.erl | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/emqx/src/emqx_router.erl b/apps/emqx/src/emqx_router.erl index ad63c6657..3337b57c8 100644 --- a/apps/emqx/src/emqx_router.erl +++ b/apps/emqx/src/emqx_router.erl @@ -273,7 +273,7 @@ trans(Fun, Args) -> {WPid, RefMon} = spawn_monitor( %% NOTE: this is under the assumption that crashes in Fun - %% are caught by mnesia:transaction/2. + %% are caught by mria:transaction/2. %% Future changes should keep in mind that this process %% always exit with database write result. fun() -> diff --git a/apps/emqx/test/emqx_trie_SUITE.erl b/apps/emqx/test/emqx_trie_SUITE.erl index 9135a45dc..00d64877c 100644 --- a/apps/emqx/test/emqx_trie_SUITE.erl +++ b/apps/emqx/test/emqx_trie_SUITE.erl @@ -188,6 +188,6 @@ t_delete3(_) -> clear_tables() -> emqx_trie:clear_tables(). trans(Fun) -> - mnesia:transaction(Fun). + mria:transaction(?ROUTE_SHARD, Fun). trans(Fun, Args) -> - mnesia:transaction(Fun, Args). + mria:transaction(?ROUTE_SHARD, Fun, Args). diff --git a/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl b/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl index ed82e9b1d..f2562becc 100644 --- a/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_mnesia_SUITE.erl @@ -54,19 +54,19 @@ end_per_suite(_Config) -> ok. init_per_testcase(t_authz, Config) -> - mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_USERNAME, <<"test_username">>}, - rules = [{allow, publish, <<"test/%u">>}, - {allow, subscribe, <<"eq #">>} - ] - }]), - mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = {?ACL_TABLE_CLIENTID, <<"test_clientid">>}, - rules = [{allow, publish, <<"test/%c">>}, - {deny, subscribe, <<"eq #">>} - ] - }]), - mnesia:transaction(fun mria:dirty_write/1, [#emqx_acl{who = ?ACL_TABLE_ALL, - rules = [{deny, all, <<"#">>}] - }]), + mria:dirty_write(#emqx_acl{who = {?ACL_TABLE_USERNAME, <<"test_username">>}, + rules = [{allow, publish, <<"test/%u">>}, + {allow, subscribe, <<"eq #">>} + ] + }), + mria:dirty_write(#emqx_acl{who = {?ACL_TABLE_CLIENTID, <<"test_clientid">>}, + rules = [{allow, publish, <<"test/%c">>}, + {deny, subscribe, <<"eq #">>} + ] + }), + mria:dirty_write(#emqx_acl{who = ?ACL_TABLE_ALL, + rules = [{deny, all, <<"#">>}] + }), Config; init_per_testcase(_, Config) -> Config. diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index f9903b845..17f32ee58 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -127,7 +127,7 @@ get_telemetry() -> %% gen_server callbacks %%-------------------------------------------------------------------- -%% This is to suppress dialyzer warnings for mnesia:dirty_write and +%% This is to suppress dialyzer warnings for mria:dirty_write and %% dirty_read race condition. Given that the init function is not evaluated %% concurrently in one node, it should be free of race condition. %% Given the chance of having two nodes bootstraping with the write From d3ddecb14478f802a5533fbcc4939066eb322b2e Mon Sep 17 00:00:00 2001 From: William Yang Date: Tue, 19 Oct 2021 21:20:12 +0200 Subject: [PATCH 15/88] feat(olp): bump to 0.1.2 remove noop logging --- apps/emqx/rebar.config | 2 +- rebar.config | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index b851700b9..59dd8a956 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -9,7 +9,7 @@ %% This rebar.config is necessary because the app may be used as a %% `git_subdir` dependency in other projects. {deps, - [ {lc, {git, "https://github.com/qzhuyan/lc.git", {tag, "0.1.1"}}} + [ {lc, {git, "https://github.com/qzhuyan/lc.git", {tag, "0.1.2"}}} , {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}} , {typerefl, {git, "https://github.com/k32/typerefl", {tag, "0.8.5"}}} , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} diff --git a/rebar.config b/rebar.config index 89b8e3a9f..fde7f1c47 100644 --- a/rebar.config +++ b/rebar.config @@ -42,7 +42,7 @@ {post_hooks,[]}. {deps, - [ {lc, {git, "https://github.com/qzhuyan/lc.git", {tag, "0.1.1"}}} + [ {lc, {git, "https://github.com/qzhuyan/lc.git", {tag, "0.1.2"}}} , {gpb, "4.11.2"} %% gpb only used to build, but not for release, pin it here to avoid fetching a wrong version due to rebar plugins scattered in all the deps , {typerefl, {git, "https://github.com/k32/typerefl", {tag, "0.8.5"}}} , {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.1.9"}}} From 4ae38b7c6a64a9538160b040a79d8fa2ff6a4cbc Mon Sep 17 00:00:00 2001 From: zhouzb Date: Wed, 20 Oct 2021 10:14:47 +0800 Subject: [PATCH 16/88] fix(authn): fix placeholders are not replaced correctly --- apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index b4c6dac08..cd658e6f1 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -144,7 +144,7 @@ destroy(#{'_unique' := Unique}) -> parse_query(Query) -> case re:run(Query, ?RE_PLACEHOLDER, [global, {capture, all, binary}]) of {match, Captured} -> - PlaceHolders = [PlaceHolder || PlaceHolder <- Captured], + PlaceHolders = [PlaceHolder || [PlaceHolder] <- Captured], NQuery = re:replace(Query, "'\\$\\{[a-z0-9\\_]+\\}'", "?", [global, {return, binary}]), {NQuery, PlaceHolders}; nomatch -> From 1b9c0825639998a75897c1ddfe26ed8376b6d1d2 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 19 Oct 2021 23:32:16 +0200 Subject: [PATCH 17/88] refactor(authn): check authenticator config with provider module mainly two changes: 1. the schema is simplified at root level, per-authenticator checks are done after the type can be identified 2. the config handling part is split out from emqx_authentication module to emqx_authentication_config module --- apps/emqx/src/emqx_authentication.erl | 371 +++--------------- apps/emqx/src/emqx_authentication_config.erl | 323 +++++++++++++++ apps/emqx/src/emqx_broker_sup.erl | 2 +- apps/emqx/src/emqx_config_handler.erl | 9 +- apps/emqx_authn/src/emqx_authn.erl | 47 +++ apps/emqx_authn/src/emqx_authn_api.erl | 21 +- apps/emqx_authn/src/emqx_authn_app.erl | 19 +- apps/emqx_authn/src/emqx_authn_schema.erl | 2 +- .../src/simple_authn/emqx_authn_http.erl | 17 +- 9 files changed, 467 insertions(+), 344 deletions(-) create mode 100644 apps/emqx/src/emqx_authentication_config.erl diff --git a/apps/emqx/src/emqx_authentication.erl b/apps/emqx/src/emqx_authentication.erl index 5f9d72ca7..c96db115f 100644 --- a/apps/emqx/src/emqx_authentication.erl +++ b/apps/emqx/src/emqx_authentication.erl @@ -14,33 +14,30 @@ %% limitations under the License. %%-------------------------------------------------------------------- +%% @doc Authenticator management API module. +%% Authentication is a core functionality of MQTT, +%% the 'emqx' APP provides APIs for other APPs to implement +%% the authentication callbacks. -module(emqx_authentication). -behaviour(gen_server). --behaviour(hocon_schema). --behaviour(emqx_config_handler). -include("emqx.hrl"). -include("logger.hrl"). --export([ roots/0 - , fields/1 - ]). - --export([ pre_config_update/2 - , post_config_update/4 - ]). - +%% The authentication entrypoint. -export([ authenticate/2 ]). --export([ initialize_authentication/2 ]). - +%% Authenticator manager process start/stop -export([ start_link/0 , stop/0 + , get_providers/0 ]). --export([ register_provider/2 +%% Authenticator management APIs +-export([ initialize_authentication/2 + , register_provider/2 , register_providers/1 , deregister_provider/1 , deregister_providers/1 @@ -56,6 +53,7 @@ , move_authenticator/3 ]). +%% APIs for observer built-in-database -export([ import_users/3 , add_user/3 , delete_user/3 @@ -64,8 +62,6 @@ , list_users/2 ]). --export([ generate_id/1 ]). - %% gen_server callbacks -export([ init/1 , handle_call/3 @@ -75,6 +71,20 @@ , code_change/3 ]). +%% utility functions +-export([ authenticator_id/1 + ]). + +%% proxy callback +-export([ pre_config_update/2 + , post_config_update/4 + ]). + +-export_type([ authenticator_id/0 + , position/0 + , chain_name/0 + ]). + -ifdef(TEST). -compile(export_all). -compile(nowarn_export_all). @@ -88,10 +98,6 @@ -type chain_name() :: atom(). -type authenticator_id() :: binary(). -type position() :: top | bottom | {before, authenticator_id()}. --type update_request() :: {create_authenticator, chain_name(), map()} - | {delete_authenticator, chain_name(), authenticator_id()} - | {update_authenticator, chain_name(), authenticator_id(), map()} - | {move_authenticator, chain_name(), authenticator_id(), position()}. -type authn_type() :: atom() | {atom(), atom()}. -type provider() :: module(). @@ -103,8 +109,7 @@ enable := boolean(), state := map()}. - --type config() :: #{atom() => term()}. +-type config() :: emqx_authentication_config:config(). -type state() :: #{atom() => term()}. -type extra() :: #{is_superuser := boolean(), atom() => term()}. @@ -173,117 +178,6 @@ , list_users/1 ]). -%%------------------------------------------------------------------------------ -%% Hocon Schema -%%------------------------------------------------------------------------------ - -roots() -> [{authentication, fun authentication/1}]. - -fields(_) -> []. - -authentication(type) -> - {ok, Refs} = get_refs(), - hoconsc:union([hoconsc:array(hoconsc:union(Refs)) | Refs]); -authentication(default) -> []; -authentication(_) -> undefined. - -%%------------------------------------------------------------------------------ -%% Callbacks of config handler -%%------------------------------------------------------------------------------ - --spec pre_config_update(update_request(), emqx_config:raw_config()) - -> {ok, map() | list()} | {error, term()}. -pre_config_update(UpdateReq, OldConfig) -> - case do_pre_config_update(UpdateReq, to_list(OldConfig)) of - {error, Reason} -> {error, Reason}; - {ok, NewConfig} -> {ok, may_to_map(NewConfig)} - end. - -do_pre_config_update({create_authenticator, ChainName, Config}, OldConfig) -> - try - CertsDir = certs_dir([to_bin(ChainName), generate_id(Config)]), - NConfig = convert_certs(CertsDir, Config), - {ok, OldConfig ++ [NConfig]} - catch - error:{save_cert_to_file, _} = Reason -> - {error, Reason}; - error:{missing_parameter, _} = Reason -> - {error, Reason} - end; -do_pre_config_update({delete_authenticator, _ChainName, AuthenticatorID}, OldConfig) -> - NewConfig = lists:filter(fun(OldConfig0) -> - AuthenticatorID =/= generate_id(OldConfig0) - end, OldConfig), - {ok, NewConfig}; -do_pre_config_update({update_authenticator, ChainName, AuthenticatorID, Config}, OldConfig) -> - try - CertsDir = certs_dir([to_bin(ChainName), AuthenticatorID]), - NewConfig = lists:map( - fun(OldConfig0) -> - case AuthenticatorID =:= generate_id(OldConfig0) of - true -> convert_certs(CertsDir, Config, OldConfig0); - false -> OldConfig0 - end - end, OldConfig), - {ok, NewConfig} - catch - error:{save_cert_to_file, _} = Reason -> - {error, Reason}; - error:{missing_parameter, _} = Reason -> - {error, Reason} - end; -do_pre_config_update({move_authenticator, _ChainName, AuthenticatorID, Position}, OldConfig) -> - case split_by_id(AuthenticatorID, OldConfig) of - {error, Reason} -> {error, Reason}; - {ok, Part1, [Found | Part2]} -> - case Position of - top -> - {ok, [Found | Part1] ++ Part2}; - bottom -> - {ok, Part1 ++ Part2 ++ [Found]}; - {before, Before} -> - case split_by_id(Before, Part1 ++ Part2) of - {error, Reason} -> - {error, Reason}; - {ok, NPart1, [NFound | NPart2]} -> - {ok, NPart1 ++ [Found, NFound | NPart2]} - end - end - end. - --spec post_config_update(update_request(), map() | list(), emqx_config:raw_config(), emqx_config:app_envs()) - -> ok | {ok, map()} | {error, term()}. -post_config_update(UpdateReq, NewConfig, OldConfig, AppEnvs) -> - do_post_config_update(UpdateReq, check_config(to_list(NewConfig)), OldConfig, AppEnvs). - -do_post_config_update({create_authenticator, ChainName, Config}, _NewConfig, _OldConfig, _AppEnvs) -> - NConfig = check_config(Config), - _ = create_chain(ChainName), - create_authenticator(ChainName, NConfig); - -do_post_config_update({delete_authenticator, ChainName, AuthenticatorID}, _NewConfig, OldConfig, _AppEnvs) -> - case delete_authenticator(ChainName, AuthenticatorID) of - ok -> - [Config] = [Config0 || Config0 <- to_list(OldConfig), AuthenticatorID == generate_id(Config0)], - CertsDir = certs_dir([to_bin(ChainName), AuthenticatorID]), - clear_certs(CertsDir, Config), - ok; - {error, Reason} -> - {error, Reason} - end; - -do_post_config_update({update_authenticator, ChainName, AuthenticatorID, Config}, _NewConfig, _OldConfig, _AppEnvs) -> - NConfig = check_config(Config), - update_authenticator(ChainName, AuthenticatorID, NConfig); - -do_post_config_update({move_authenticator, ChainName, AuthenticatorID, Position}, _NewConfig, _OldConfig, _AppEnvs) -> - move_authenticator(ChainName, AuthenticatorID, Position). - -check_config(Config) -> - #{authentication := CheckedConfig} = - hocon_schema:check_plain(?MODULE, #{<<"authentication">> => Config}, #{atom_key => true}), - CheckedConfig. - %%------------------------------------------------------------------------------ %% Authenticate %%------------------------------------------------------------------------------ @@ -338,12 +232,30 @@ get_enabled(Authenticators) -> %% APIs %%------------------------------------------------------------------------------ --spec initialize_authentication(chain_name(), [#{binary() => term()}]) -> ok. -initialize_authentication(_, []) -> - ok; +pre_config_update(UpdateReq, OldConfig) -> + emqx_authentication_config:pre_config_update(UpdateReq, OldConfig). + +post_config_update(UpdateReq, NewConfig, OldConfig, AppEnvs) -> + emqx_authentication_config:post_config_update(UpdateReq, NewConfig, OldConfig, AppEnvs). + +%% @doc Get all registered authentication providers. +get_providers() -> + call(get_providers). + +%% @doc Get authenticator identifier from its config. +%% The authenticator config must contain a 'mechanism' key +%% and maybe a 'backend' key. +%% This function works with both parsed (atom keys) and raw (binary keys) +%% configurations. +authenticator_id(Config) -> + emqx_authentication_config:authenticator_id(Config). + +%% @doc Call this API to initialize authenticators implemented in another APP. +-spec initialize_authentication(chain_name(), config()) -> ok. +initialize_authentication(_, []) -> ok; initialize_authentication(ChainName, AuthenticatorsConfig) -> _ = create_chain(ChainName), - CheckedConfig = check_config(to_list(AuthenticatorsConfig)), + CheckedConfig = to_list(AuthenticatorsConfig), lists:foreach(fun(AuthenticatorConfig) -> case create_authenticator(ChainName, AuthenticatorConfig) of {ok, _} -> @@ -351,7 +263,7 @@ initialize_authentication(ChainName, AuthenticatorsConfig) -> {error, Reason} -> ?SLOG(error, #{ msg => "failed_to_create_authenticator", - authenticator => generate_id(AuthenticatorConfig), + authenticator => authenticator_id(AuthenticatorConfig), reason => Reason }) end @@ -365,10 +277,6 @@ start_link() -> stop() -> gen_server:stop(?MODULE). --spec get_refs() -> {ok, Refs} when Refs :: [{authn_type(), module()}]. -get_refs() -> - call(get_refs). - %% @doc Register authentication providers. %% A provider is a tuple of `AuthNType' the module which implements %% the authenticator callbacks. @@ -472,20 +380,6 @@ lookup_user(ChainName, AuthenticatorID, UserID) -> list_users(ChainName, AuthenticatorID) -> call({list_users, ChainName, AuthenticatorID}). --spec generate_id(config()) -> authenticator_id(). -generate_id(#{mechanism := Mechanism0, backend := Backend0}) -> - Mechanism = to_bin(Mechanism0), - Backend = to_bin(Backend0), - <>; -generate_id(#{mechanism := Mechanism}) -> - to_bin(Mechanism); -generate_id(#{<<"mechanism">> := Mechanism, <<"backend">> := Backend}) -> - <>; -generate_id(#{<<"mechanism">> := Mechanism}) -> - Mechanism; -generate_id(_) -> - error({missing_parameter, mechanism}). - %%-------------------------------------------------------------------- %% gen_server callbacks %%-------------------------------------------------------------------- @@ -498,6 +392,8 @@ init(_Opts) -> ok = emqx_config_handler:add_handler([listeners, '?', '?', authentication], ?MODULE), {ok, #{hooked => false, providers => #{}}}. +handle_call(get_providers, _From, #{providers := Providers} = State) -> + reply(Providers, State); handle_call({register_providers, Providers}, _From, #{providers := Reg0} = State) -> case lists:filter(fun({T, _}) -> maps:is_key(T, Reg0) end, Providers) of @@ -513,12 +409,6 @@ handle_call({register_providers, Providers}, _From, handle_call({deregister_providers, AuthNTypes}, _From, #{providers := Providers} = State) -> reply(ok, State#{providers := maps:without(AuthNTypes, Providers)}); -handle_call(get_refs, _From, #{providers := Providers} = State) -> - Refs = lists:foldl(fun({_, Provider}, Acc) -> - Acc ++ Provider:refs() - end, [], maps:to_list(Providers)), - reply({ok, Refs}, State); - handle_call({create_chain, Name}, _From, State) -> case ets:member(?CHAINS_TAB, Name) of true -> @@ -549,9 +439,9 @@ handle_call({lookup_chain, Name}, _From, State) -> end; handle_call({create_authenticator, ChainName, Config}, _From, #{providers := Providers} = State) -> - UpdateFun = + UpdateFun = fun(#chain{authenticators = Authenticators} = Chain) -> - AuthenticatorID = generate_id(Config), + AuthenticatorID = authenticator_id(Config), case lists:keymember(AuthenticatorID, #authenticator.id, Authenticators) of true -> {error, {already_exists, {authenticator, AuthenticatorID}}}; @@ -570,7 +460,7 @@ handle_call({create_authenticator, ChainName, Config}, _From, #{providers := Pro reply(Reply, maybe_hook(State)); handle_call({delete_authenticator, ChainName, AuthenticatorID}, _From, State) -> - UpdateFun = + UpdateFun = fun(#chain{authenticators = Authenticators} = Chain) -> case lists:keytake(AuthenticatorID, #authenticator.id, Authenticators) of false -> @@ -592,7 +482,7 @@ handle_call({update_authenticator, ChainName, AuthenticatorID, Config}, _From, S {error, {not_found, {authenticator, AuthenticatorID}}}; #authenticator{provider = Provider, state = #{version := Version} = ST} = Authenticator -> - case AuthenticatorID =:= generate_id(Config) of + case AuthenticatorID =:= authenticator_id(Config) of true -> Unique = unique(ChainName, AuthenticatorID, Version), case Provider:update(Config#{'_unique' => Unique}, ST) of @@ -614,7 +504,7 @@ handle_call({update_authenticator, ChainName, AuthenticatorID, Config}, _From, S reply(Reply, State); handle_call({move_authenticator, ChainName, AuthenticatorID, Position}, _From, State) -> - UpdateFun = + UpdateFun = fun(#chain{authenticators = Authenticators} = Chain) -> case do_move_authenticator(AuthenticatorID, Authenticators, Position) of {ok, NAuthenticators} -> @@ -663,9 +553,9 @@ handle_info(Info, State) -> ?SLOG(error, #{msg => "unexpected_info", info => Info}), {noreply, State}. -terminate(_Reason, _State) -> - emqx_config_handler:remove_handler([authentication]), - emqx_config_handler:remove_handler([listeners, '?', '?', authentication]), +terminate(Reason, _State) -> + ?SLOG(error, #{msg => "emqx_authentication_terminating", + reason => Reason}), ok. code_change(_OldVsn, State, _Extra) -> @@ -674,128 +564,6 @@ code_change(_OldVsn, State, _Extra) -> reply(Reply, State) -> {reply, Reply, State}. -%%------------------------------------------------------------------------------ -%% Internal functions -%%------------------------------------------------------------------------------ - -certs_dir(Dirs) when is_list(Dirs) -> - to_bin(filename:join([emqx:get_config([node, data_dir]), "certs/authn"] ++ Dirs)). - -convert_certs(CertsDir, Config) -> - case maps:get(<<"ssl">>, Config, undefined) of - undefined -> - Config; - SSLOpts -> - NSSLOPts = lists:foldl(fun(K, Acc) -> - case maps:get(K, Acc, undefined) of - undefined -> Acc; - PemBin -> - CertFile = generate_filename(CertsDir, K), - ok = save_cert_to_file(CertFile, PemBin), - Acc#{K => CertFile} - end - end, SSLOpts, [<<"certfile">>, <<"keyfile">>, <<"cacertfile">>]), - Config#{<<"ssl">> => NSSLOPts} - end. - -convert_certs(CertsDir, NewConfig, OldConfig) -> - case maps:get(<<"ssl">>, NewConfig, undefined) of - undefined -> - NewConfig; - NewSSLOpts -> - OldSSLOpts = maps:get(<<"ssl">>, OldConfig, #{}), - Diff = diff_certs(NewSSLOpts, OldSSLOpts), - NSSLOpts = lists:foldl(fun({identical, K}, Acc) -> - Acc#{K => maps:get(K, OldSSLOpts)}; - ({_, K}, Acc) -> - CertFile = generate_filename(CertsDir, K), - ok = save_cert_to_file(CertFile, maps:get(K, NewSSLOpts)), - Acc#{K => CertFile} - end, NewSSLOpts, Diff), - NewConfig#{<<"ssl">> => NSSLOpts} - end. - -clear_certs(CertsDir, Config) -> - case maps:get(<<"ssl">>, Config, undefined) of - undefined -> - ok; - SSLOpts -> - lists:foreach( - fun({_, Filename}) -> - _ = file:delete(filename:join([CertsDir, Filename])) - end, - maps:to_list(maps:with([<<"certfile">>, <<"keyfile">>, <<"cacertfile">>], SSLOpts))) - end. - -save_cert_to_file(Filename, PemBin) -> - case public_key:pem_decode(PemBin) =/= [] of - true -> - case filelib:ensure_dir(Filename) of - ok -> - case file:write_file(Filename, PemBin) of - ok -> ok; - {error, Reason} -> error({save_cert_to_file, {write_file, Reason}}) - end; - {error, Reason} -> - error({save_cert_to_file, {ensure_dir, Reason}}) - end; - false -> - error({save_cert_to_file, invalid_certificate}) - end. - -generate_filename(CertsDir, Key) -> - Prefix = case Key of - <<"keyfile">> -> "key-"; - <<"certfile">> -> "cert-"; - <<"cacertfile">> -> "cacert-" - end, - to_bin(filename:join([CertsDir, Prefix ++ emqx_misc:gen_id() ++ ".pem"])). - -diff_certs(NewSSLOpts, OldSSLOpts) -> - Keys = [<<"cacertfile">>, <<"certfile">>, <<"keyfile">>], - CertPems = maps:with(Keys, NewSSLOpts), - CertFiles = maps:with(Keys, OldSSLOpts), - Diff = lists:foldl(fun({K, CertFile}, Acc) -> - case maps:find(K, CertPems) of - error -> Acc; - {ok, PemBin1} -> - {ok, PemBin2} = file:read_file(CertFile), - case diff_cert(PemBin1, PemBin2) of - true -> - [{changed, K} | Acc]; - false -> - [{identical, K} | Acc] - end - end - end, - [], maps:to_list(CertFiles)), - Added = [{added, K} || K <- maps:keys(maps:without(maps:keys(CertFiles), CertPems))], - Diff ++ Added. - -diff_cert(Pem1, Pem2) -> - cal_md5_for_cert(Pem1) =/= cal_md5_for_cert(Pem2). - -cal_md5_for_cert(Pem) -> - crypto:hash(md5, term_to_binary(public_key:pem_decode(Pem))). - -split_by_id(ID, AuthenticatorsConfig) -> - case lists:foldl( - fun(C, {P1, P2, F0}) -> - F = case ID =:= generate_id(C) of - true -> true; - false -> F0 - end, - case F of - false -> {[C | P1], P2, F}; - true -> {P1, [C | P2], F} - end - end, {[], [], false}, AuthenticatorsConfig) of - {_, _, false} -> - {error, {not_found, {authenticator, ID}}}; - {Part1, Part2, true} -> - {ok, lists:reverse(Part1), lists:reverse(Part2)} - end. - global_chain(mqtt) -> 'mqtt:global'; global_chain('mqtt-sn') -> @@ -942,22 +710,9 @@ authn_type(#{mechanism := Mechanism, backend := Backend}) -> authn_type(#{mechanism := Mechanism}) -> Mechanism. -may_to_map([L]) -> - L; -may_to_map(L) -> - L. - -to_list(undefined) -> - []; -to_list(M) when M =:= #{} -> - []; -to_list(M) when is_map(M) -> - [M]; -to_list(L) when is_list(L) -> - L. - -to_bin(B) when is_binary(B) -> B; -to_bin(L) when is_list(L) -> list_to_binary(L); -to_bin(A) when is_atom(A) -> atom_to_binary(A). +to_list(undefined) -> []; +to_list(M) when M =:= #{} -> []; +to_list(M) when is_map(M) -> [M]; +to_list(L) when is_list(L) -> L. call(Call) -> gen_server:call(?MODULE, Call, infinity). diff --git a/apps/emqx/src/emqx_authentication_config.erl b/apps/emqx/src/emqx_authentication_config.erl new file mode 100644 index 000000000..526d9d6ff --- /dev/null +++ b/apps/emqx/src/emqx_authentication_config.erl @@ -0,0 +1,323 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +%% @doc Authenticator configuration management module. +-module(emqx_authentication_config). + +-behaviour(emqx_config_handler). + +-export([ pre_config_update/2 + , post_config_update/4 + ]). + +-export([ authenticator_id/1 + , authn_type/1 + ]). + +-export_type([config/0]). + +-include("logger.hrl"). + +-type parsed_config() :: #{mechanism := atom(), + backend => atom(), + atom() => term()}. +-type raw_config() :: #{binary() => term()}. +-type config() :: parsed_config() | raw_config(). + +-type authenticator_id() :: emqx_authentication:authenticator_id(). +-type position() :: emqx_authentication:position(). +-type chain_name() :: emqx_authentication:chain_name(). +-type update_request() :: {create_authenticator, chain_name(), map()} + | {delete_authenticator, chain_name(), authenticator_id()} + | {update_authenticator, chain_name(), authenticator_id(), map()} + | {move_authenticator, chain_name(), authenticator_id(), position()}. + +%%------------------------------------------------------------------------------ +%% Callbacks of config handler +%%------------------------------------------------------------------------------ + +-spec pre_config_update(update_request(), emqx_config:raw_config()) + -> {ok, map() | list()} | {error, term()}. +pre_config_update(UpdateReq, OldConfig) -> + case do_pre_config_update(UpdateReq, to_list(OldConfig)) of + {error, Reason} -> {error, Reason}; + {ok, NewConfig} -> {ok, return_map(NewConfig)} + end. + +do_pre_config_update({create_authenticator, ChainName, Config}, OldConfig) -> + try + CertsDir = certs_dir([to_bin(ChainName), authenticator_id(Config)]), + NConfig = convert_certs(CertsDir, Config), + {ok, OldConfig ++ [NConfig]} + catch + error:{save_cert_to_file, _} = Reason -> + {error, Reason}; + error:{missing_parameter, _} = Reason -> + {error, Reason} + end; +do_pre_config_update({delete_authenticator, _ChainName, AuthenticatorID}, OldConfig) -> + NewConfig = lists:filter(fun(OldConfig0) -> + AuthenticatorID =/= authenticator_id(OldConfig0) + end, OldConfig), + {ok, NewConfig}; +do_pre_config_update({update_authenticator, ChainName, AuthenticatorID, Config}, OldConfig) -> + try + CertsDir = certs_dir([to_bin(ChainName), AuthenticatorID]), + NewConfig = lists:map( + fun(OldConfig0) -> + case AuthenticatorID =:= authenticator_id(OldConfig0) of + true -> convert_certs(CertsDir, Config, OldConfig0); + false -> OldConfig0 + end + end, OldConfig), + {ok, NewConfig} + catch + error:{save_cert_to_file, _} = Reason -> + {error, Reason}; + error:{missing_parameter, _} = Reason -> + {error, Reason} + end; +do_pre_config_update({move_authenticator, _ChainName, AuthenticatorID, Position}, OldConfig) -> + case split_by_id(AuthenticatorID, OldConfig) of + {error, Reason} -> {error, Reason}; + {ok, Part1, [Found | Part2]} -> + case Position of + top -> + {ok, [Found | Part1] ++ Part2}; + bottom -> + {ok, Part1 ++ Part2 ++ [Found]}; + {before, Before} -> + case split_by_id(Before, Part1 ++ Part2) of + {error, Reason} -> + {error, Reason}; + {ok, NPart1, [NFound | NPart2]} -> + {ok, NPart1 ++ [Found, NFound | NPart2]} + end + end + end. + +-spec post_config_update(update_request(), map() | list(), emqx_config:raw_config(), emqx_config:app_envs()) + -> ok | {ok, map()} | {error, term()}. +post_config_update(UpdateReq, NewConfig, OldConfig, AppEnvs) -> + do_post_config_update(UpdateReq, check_configs(to_list(NewConfig)), OldConfig, AppEnvs). + +do_post_config_update({create_authenticator, ChainName, Config}, _NewConfig, _OldConfig, _AppEnvs) -> + NConfig = check_config(Config), + _ = emqx_authentication:create_chain(ChainName), + emqx_authentication:create_authenticator(ChainName, NConfig); +do_post_config_update({delete_authenticator, ChainName, AuthenticatorID}, _NewConfig, OldConfig, _AppEnvs) -> + case emqx_authentication:delete_authenticator(ChainName, AuthenticatorID) of + ok -> + [Config] = [Config0 || Config0 <- to_list(OldConfig), AuthenticatorID == authenticator_id(Config0)], + CertsDir = certs_dir([to_bin(ChainName), AuthenticatorID]), + clear_certs(CertsDir, Config), + ok; + {error, Reason} -> + {error, Reason} + end; +do_post_config_update({update_authenticator, ChainName, AuthenticatorID, Config}, _NewConfig, _OldConfig, _AppEnvs) -> + NConfig = check_config(Config), + emqx_authentication:update_authenticator(ChainName, AuthenticatorID, NConfig); +do_post_config_update({move_authenticator, ChainName, AuthenticatorID, Position}, _NewConfig, _OldConfig, _AppEnvs) -> + emqx_authentication:move_authenticator(ChainName, AuthenticatorID, Position). + +check_config(Config) -> + [Checked] = check_configs([Config]), + Checked. + +check_configs(Configs) -> + Providers = emqx_authentication:get_providers(), + lists:map(fun(C) -> do_check_conifg(C, Providers) end, Configs). + +do_check_conifg(Config, Providers) -> + Type = authn_type(Config), + case maps:get(Type, Providers, false) of + false -> + ?SLOG(warning, #{msg => "unknown_authn_type", + type => Type, + providers => Providers}), + throw(unknown_authn_type); + Module -> + %% TODO: check if Module:check_config/1 is exported + %% so we do not force all providers to implement hocon schema + try hocon_schema:check_plain(Module, #{<<"config">> => Config}, + #{atom_key => true}) of + #{config := Result} -> + Result + catch + C : E : S -> + ?SLOG(warning, #{msg => "failed_to_check_config", config => Config}), + erlang:raise(C, E, S) + end + end. + +return_map([L]) -> L; +return_map(L) -> L. + +to_list(undefined) -> []; +to_list(M) when M =:= #{} -> []; +to_list(M) when is_map(M) -> [M]; +to_list(L) when is_list(L) -> L. + +certs_dir(Dirs) when is_list(Dirs) -> + to_bin(filename:join([emqx:get_config([node, data_dir]), "certs", "authn"] ++ Dirs)). + +convert_certs(CertsDir, Config) -> + case maps:get(<<"ssl">>, Config, undefined) of + undefined -> + Config; + SSLOpts -> + NSSLOPts = lists:foldl(fun(K, Acc) -> + case maps:get(K, Acc, undefined) of + undefined -> Acc; + PemBin -> + CertFile = generate_filename(CertsDir, K), + ok = save_cert_to_file(CertFile, PemBin), + Acc#{K => CertFile} + end + end, SSLOpts, [<<"certfile">>, <<"keyfile">>, <<"cacertfile">>]), + Config#{<<"ssl">> => NSSLOPts} + end. + +convert_certs(CertsDir, NewConfig, OldConfig) -> + case maps:get(<<"ssl">>, NewConfig, undefined) of + undefined -> + NewConfig; + NewSSLOpts -> + OldSSLOpts = maps:get(<<"ssl">>, OldConfig, #{}), + Diff = diff_certs(NewSSLOpts, OldSSLOpts), + NSSLOpts = lists:foldl(fun({identical, K}, Acc) -> + Acc#{K => maps:get(K, OldSSLOpts)}; + ({_, K}, Acc) -> + CertFile = generate_filename(CertsDir, K), + ok = save_cert_to_file(CertFile, maps:get(K, NewSSLOpts)), + Acc#{K => CertFile} + end, NewSSLOpts, Diff), + NewConfig#{<<"ssl">> => NSSLOpts} + end. + +clear_certs(CertsDir, Config) -> + case maps:get(<<"ssl">>, Config, undefined) of + undefined -> + ok; + SSLOpts -> + lists:foreach( + fun({_, Filename}) -> + _ = file:delete(filename:join([CertsDir, Filename])) + end, + maps:to_list(maps:with([<<"certfile">>, <<"keyfile">>, <<"cacertfile">>], SSLOpts))) + end. + +save_cert_to_file(Filename, PemBin) -> + case public_key:pem_decode(PemBin) =/= [] of + true -> + case filelib:ensure_dir(Filename) of + ok -> + case file:write_file(Filename, PemBin) of + ok -> ok; + {error, Reason} -> error({save_cert_to_file, {write_file, Reason}}) + end; + {error, Reason} -> + error({save_cert_to_file, {ensure_dir, Reason}}) + end; + false -> + error({save_cert_to_file, invalid_certificate}) + end. + +generate_filename(CertsDir, Key) -> + Prefix = case Key of + <<"keyfile">> -> "key-"; + <<"certfile">> -> "cert-"; + <<"cacertfile">> -> "cacert-" + end, + to_bin(filename:join([CertsDir, Prefix ++ emqx_misc:gen_id() ++ ".pem"])). + +diff_certs(NewSSLOpts, OldSSLOpts) -> + Keys = [<<"cacertfile">>, <<"certfile">>, <<"keyfile">>], + CertPems = maps:with(Keys, NewSSLOpts), + CertFiles = maps:with(Keys, OldSSLOpts), + Diff = lists:foldl(fun({K, CertFile}, Acc) -> + case maps:find(K, CertPems) of + error -> Acc; + {ok, PemBin1} -> + {ok, PemBin2} = file:read_file(CertFile), + case diff_cert(PemBin1, PemBin2) of + true -> + [{changed, K} | Acc]; + false -> + [{identical, K} | Acc] + end + end + end, + [], maps:to_list(CertFiles)), + Added = [{added, K} || K <- maps:keys(maps:without(maps:keys(CertFiles), CertPems))], + Diff ++ Added. + +diff_cert(Pem1, Pem2) -> + cal_md5_for_cert(Pem1) =/= cal_md5_for_cert(Pem2). + +cal_md5_for_cert(Pem) -> + crypto:hash(md5, term_to_binary(public_key:pem_decode(Pem))). + +split_by_id(ID, AuthenticatorsConfig) -> + case lists:foldl( + fun(C, {P1, P2, F0}) -> + F = case ID =:= authenticator_id(C) of + true -> true; + false -> F0 + end, + case F of + false -> {[C | P1], P2, F}; + true -> {P1, [C | P2], F} + end + end, {[], [], false}, AuthenticatorsConfig) of + {_, _, false} -> + {error, {not_found, {authenticator, ID}}}; + {Part1, Part2, true} -> + {ok, lists:reverse(Part1), lists:reverse(Part2)} + end. + +to_bin(B) when is_binary(B) -> B; +to_bin(L) when is_list(L) -> list_to_binary(L); +to_bin(A) when is_atom(A) -> atom_to_binary(A). + +%% @doc Make an authenticator ID from authenticator's config. +%% The authenticator config must contain a 'mechanism' key +%% and maybe a 'backend' key. +%% This function works with both parsed (atom keys) and raw (binary keys) +%% configurations. +-spec authenticator_id(config()) -> authenticator_id(). +authenticator_id(#{mechanism := Mechanism0, backend := Backend0}) -> + Mechanism = to_bin(Mechanism0), + Backend = to_bin(Backend0), + <>; +authenticator_id(#{mechanism := Mechanism}) -> + to_bin(Mechanism); +authenticator_id(#{<<"mechanism">> := Mechanism, <<"backend">> := Backend}) -> + <>; +authenticator_id(#{<<"mechanism">> := Mechanism}) -> + Mechanism; +authenticator_id(C) -> + error({missing_parameter, mechanism, C}). + +%% @doc Make the authentication type. +authn_type(#{mechanism := M, backend := B}) -> {atom(M), atom(B)}; +authn_type(#{mechanism := M}) -> atom(M); +authn_type(#{<<"mechanism">> := M, <<"backend">> := B}) -> {atom(M), atom(B)}; +authn_type(#{<<"mechanism">> := M}) -> atom(M). + +atom(Bin) -> + binary_to_existing_atom(Bin, utf8). diff --git a/apps/emqx/src/emqx_broker_sup.erl b/apps/emqx/src/emqx_broker_sup.erl index 761537e57..ae917110e 100644 --- a/apps/emqx/src/emqx_broker_sup.erl +++ b/apps/emqx/src/emqx_broker_sup.erl @@ -50,7 +50,7 @@ init([]) -> shutdown => infinity, type => supervisor, modules => [emqx_authentication_sup]}, - + %% Broker helper Helper = #{id => helper, start => {emqx_broker_helper, start_link, []}, diff --git a/apps/emqx/src/emqx_config_handler.erl b/apps/emqx/src/emqx_config_handler.erl index f53b71901..297f1147d 100644 --- a/apps/emqx/src/emqx_config_handler.erl +++ b/apps/emqx/src/emqx_config_handler.erl @@ -71,15 +71,15 @@ stop() -> update_config(SchemaModule, ConfKeyPath, UpdateArgs) -> %% force covert the path to a list of atoms, as there maybe some wildcard names/ids in the path AtomKeyPath = [atom(Key) || Key <- ConfKeyPath], - gen_server:call(?MODULE, {change_config, SchemaModule, AtomKeyPath, UpdateArgs}). + gen_server:call(?MODULE, {change_config, SchemaModule, AtomKeyPath, UpdateArgs}, infinity). -spec add_handler(emqx_config:config_key_path(), handler_name()) -> ok. add_handler(ConfKeyPath, HandlerName) -> - gen_server:call(?MODULE, {add_handler, ConfKeyPath, HandlerName}). + gen_server:call(?MODULE, {add_handler, ConfKeyPath, HandlerName}, infinity). -spec remove_handler(emqx_config:config_key_path()) -> ok. remove_handler(ConfKeyPath) -> - gen_server:call(?MODULE, {remove_handler, ConfKeyPath}). + gen_server:call(?MODULE, {remove_handler, ConfKeyPath}, infinity). %%============================================================================ @@ -247,7 +247,8 @@ call_post_config_update(Handlers, OldConf, NewConf, AppEnvs, UpdateReq, Result) true -> case HandlerName:post_config_update(UpdateReq, NewConf, OldConf, AppEnvs) of ok -> {ok, Result}; - {ok, Result1} -> {ok, Result#{HandlerName => Result1}}; + {ok, Result1} -> + {ok, Result#{HandlerName => Result1}}; {error, Reason} -> {error, {post_config_update, HandlerName, Reason}} end; false -> {ok, Result} diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index 3ab05e6b0..1b0d12fd2 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -15,3 +15,50 @@ %%-------------------------------------------------------------------- -module(emqx_authn). + +-export([ providers/0 + , check_config/1 + , check_config/2 + , check_configs/1 + ]). + +providers() -> + [ {{'password-based', 'built-in-database'}, emqx_authn_mnesia} + , {{'password-based', mysql}, emqx_authn_mysql} + , {{'password-based', postgresql}, emqx_authn_pgsql} + , {{'password-based', mongodb}, emqx_authn_mongodb} + , {{'password-based', redis}, emqx_authn_redis} + , {{'password-based', 'http-server'}, emqx_authn_http} + , {{'password-based', 'http'}, emqx_authn_http} %% TODO: resolve one + , {jwt, emqx_authn_jwt} + , {{scram, 'built-in-database'}, emqx_enhanced_authn_scram_mnesia} + ]. + +check_configs([]) -> []; +check_configs([Config | Configs]) -> + [check_config(Config) | check_configs(Configs)]. + +check_config(Config) -> + check_config(Config, #{}). + +check_config(Config, Opts) -> + case do_check_config(Config, Opts) of + #{config := Checked} -> Checked; + #{<<"config">> := WithDefaults} -> WithDefaults + end. + +do_check_config(#{<<"mechanism">> := Mec} = Config, Opts) -> + Key = case maps:get(<<"backend">>, Config, false) of + false -> atom(Mec); + Backend -> {atom(Mec), atom(Backend)} + end, + case lists:keyfind(Key, 1, providers()) of + false -> + throw({unknown_handler, Key}); + {_, Provider} -> + hocon_schema:check_plain(Provider, #{<<"config">> => Config}, + Opts#{atom_key => true}) + end. + +atom(Bin) -> + binary_to_existing_atom(Bin, utf8). diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 0f89c68d8..93df83829 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -313,7 +313,7 @@ create_authenticator_api_spec() -> }, <<"400">> => ?ERR_RESPONSE(<<"Bad Request">>), <<"409">> => ?ERR_RESPONSE(<<"Conflict">>) - } + } }. create_authenticator_api_spec2() -> @@ -1852,7 +1852,7 @@ create_authenticator(ConfKeyPath, ChainName, Config) -> list_authenticators(ConfKeyPath) -> AuthenticatorsConfig = get_raw_config_with_defaults(ConfKeyPath), - NAuthenticators = [maps:put(id, ?AUTHN:generate_id(AuthenticatorConfig), convert_certs(AuthenticatorConfig)) + NAuthenticators = [maps:put(id, ?AUTHN:authenticator_id(AuthenticatorConfig), convert_certs(AuthenticatorConfig)) || AuthenticatorConfig <- AuthenticatorsConfig], {200, NAuthenticators}. @@ -1961,19 +1961,18 @@ update_config(Path, ConfigRequest) -> get_raw_config_with_defaults(ConfKeyPath) -> NConfKeyPath = [atom_to_binary(Key, utf8) || Key <- ConfKeyPath], RawConfig = emqx_map_lib:deep_get(NConfKeyPath, emqx_config:get_raw([]), []), - to_list(fill_defaults(RawConfig)). + ensure_list(fill_defaults(RawConfig)). find_config(AuthenticatorID, AuthenticatorsConfig) -> - case [AC || AC <- to_list(AuthenticatorsConfig), AuthenticatorID =:= ?AUTHN:generate_id(AC)] of + case [AC || AC <- ensure_list(AuthenticatorsConfig), AuthenticatorID =:= ?AUTHN:authenticator_id(AC)] of [] -> {error, {not_found, {authenticator, AuthenticatorID}}}; [AuthenticatorConfig] -> {ok, AuthenticatorConfig} end. +fill_defaults(Configs) when is_list(Configs) -> + lists:map(fun fill_defaults/1, Configs); fill_defaults(Config) -> - #{<<"authentication">> := CheckedConfig} = - hocon_schema:check_plain(?AUTHN, #{<<"authentication">> => Config}, - #{only_fill_defaults => true}), - CheckedConfig. + emqx_authn:check_config(Config, #{only_fill_defaults => true}). convert_certs(#{<<"ssl">> := SSLOpts} = Config) -> NSSLOpts = lists:foldl(fun(K, Acc) -> @@ -2063,10 +2062,8 @@ parse_position(<<"before:", Before/binary>>) -> parse_position(_) -> {error, {invalid_parameter, position}}. -to_list(M) when is_map(M) -> - [M]; -to_list(L) when is_list(L) -> - L. +ensure_list(M) when is_map(M) -> [M]; +ensure_list(L) when is_list(L) -> L. to_atom(B) when is_binary(B) -> binary_to_atom(B); diff --git a/apps/emqx_authn/src/emqx_authn_app.erl b/apps/emqx_authn/src/emqx_authn_app.erl index d297c9042..9284493bf 100644 --- a/apps/emqx_authn/src/emqx_authn_app.erl +++ b/apps/emqx_authn/src/emqx_authn_app.erl @@ -32,7 +32,7 @@ start(_StartType, _StartArgs) -> ok = ekka_rlog:wait_for_shards([?AUTH_SHARD], infinity), {ok, Sup} = emqx_authn_sup:start_link(), - ok = ?AUTHN:register_providers(providers()), + ok = ?AUTHN:register_providers(emqx_authn:providers()), ok = initialize(), {ok, Sup}. @@ -45,21 +45,12 @@ stop(_State) -> %%------------------------------------------------------------------------------ initialize() -> - ?AUTHN:initialize_authentication(?GLOBAL, emqx:get_raw_config([authentication], [])), + RawConfigs = emqx:get_raw_config([authentication], []), + Config = emqx_authn:check_configs(RawConfigs), + ?AUTHN:initialize_authentication(?GLOBAL, Config), lists:foreach(fun({ListenerID, ListenerConfig}) -> ?AUTHN:initialize_authentication(ListenerID, maps:get(authentication, ListenerConfig, [])) end, emqx_listeners:list()). provider_types() -> - lists:map(fun({Type, _Module}) -> Type end, providers()). - -providers() -> - [ {{'password-based', 'built-in-database'}, emqx_authn_mnesia} - , {{'password-based', mysql}, emqx_authn_mysql} - , {{'password-based', postgresql}, emqx_authn_pgsql} - , {{'password-based', mongodb}, emqx_authn_mongodb} - , {{'password-based', redis}, emqx_authn_redis} - , {{'password-based', 'http-server'}, emqx_authn_http} - , {jwt, emqx_authn_jwt} - , {{scram, 'built-in-database'}, emqx_enhanced_authn_scram_mnesia} - ]. + lists:map(fun({Type, _Module}) -> Type end, emqx_authn:providers()). diff --git a/apps/emqx_authn/src/emqx_authn_schema.erl b/apps/emqx_authn/src/emqx_authn_schema.erl index 23e412088..ca5fe3cc7 100644 --- a/apps/emqx_authn/src/emqx_authn_schema.erl +++ b/apps/emqx_authn/src/emqx_authn_schema.erl @@ -22,7 +22,7 @@ ]). common_fields() -> - [ {enable, fun enable/1} + [ {enable, fun enable/1} ]. enable(type) -> boolean(); diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index 0c5d3f7f7..5ee7a8db8 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -62,7 +62,7 @@ fields(post) -> common_fields() -> [ {mechanism, {enum, ['password-based']}} - , {backend, {enum, ['http-server']}} + , {backend, {enum, ['http-server', 'http']}} %% TODO: delete http , {url, fun url/1} , {body, fun body/1} , {request_timeout, fun request_timeout/1} @@ -78,6 +78,7 @@ validations() -> url(type) -> binary(); url(validator) -> [fun check_url/1]; +url(nullable) -> false; url(_) -> undefined. headers(type) -> map(); @@ -214,11 +215,19 @@ transform_header_name(Headers) -> end, #{}, Headers). check_ssl_opts(Conf) -> - emqx_connector_http:check_ssl_opts("url", Conf). + case parse_url(hocon_schema:get_value("config.url", Conf)) of + #{scheme := https} -> + case hocon_schema:get_value("config.ssl.enable", Conf) of + true -> ok; + false -> false + end; + #{scheme := http} -> + ok + end. check_headers(Conf) -> - Method = hocon_schema:get_value("method", Conf), - Headers = hocon_schema:get_value("headers", Conf), + Method = hocon_schema:get_value("config.method", Conf), + Headers = hocon_schema:get_value("config.headers", Conf), case Method =:= get andalso maps:get(<<"content-type">>, Headers, undefined) =/= undefined of true -> false; false -> true From 72c26931d734afdea940907cbb52ed789806055e Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 11:01:06 +0200 Subject: [PATCH 18/88] fix: fill string fields' default value with binary --- apps/emqx/src/emqx_authentication.erl | 2 +- apps/emqx/src/emqx_schema.erl | 16 +-- apps/emqx_authn/src/emqx_authn_app.erl | 2 + apps/emqx_authn/src/emqx_authn_schema.erl | 7 ++ .../src/simple_authn/emqx_authn_http.erl | 2 +- apps/emqx_authn/test/emqx_authn_api_SUITE.erl | 100 ++++++++++++++++++ apps/emqx_authn/test/emqx_authn_test_lib.erl | 38 +++++++ .../src/emqx_connector_http.erl | 4 +- 8 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 apps/emqx_authn/test/emqx_authn_api_SUITE.erl create mode 100644 apps/emqx_authn/test/emqx_authn_test_lib.erl diff --git a/apps/emqx/src/emqx_authentication.erl b/apps/emqx/src/emqx_authentication.erl index c96db115f..5ee8b2815 100644 --- a/apps/emqx/src/emqx_authentication.erl +++ b/apps/emqx/src/emqx_authentication.erl @@ -251,7 +251,7 @@ authenticator_id(Config) -> emqx_authentication_config:authenticator_id(Config). %% @doc Call this API to initialize authenticators implemented in another APP. --spec initialize_authentication(chain_name(), config()) -> ok. +-spec initialize_authentication(chain_name(), [config()]) -> ok. initialize_authentication(_, []) -> ok; initialize_authentication(ChainName, AuthenticatorsConfig) -> _ = create_chain(ChainName), diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index f9b429e16..245d7d5fc 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -1042,7 +1042,7 @@ In case PSK cipher suites are intended, make sure to configured , {"ciphers", ciphers_schema(D("ciphers"))} , {user_lookup_fun, sc(typerefl:alias("string", any()), - #{ default => "emqx_tls_psk:lookup" + #{ default => <<"emqx_tls_psk:lookup">> , converter => fun ?MODULE:parse_user_lookup_fun/1 }) } @@ -1191,17 +1191,21 @@ RSA-PSK-DES-CBC3-SHA,RSA-PSK-RC4-SHA\"
_ -> "" end}). -default_ciphers(undefined) -> - default_ciphers(tls_all_available); -default_ciphers(quic) -> [ +default_ciphers(Which) -> + lists:map(fun erlang:iolist_to_binary/1, + do_default_ciphers(Which)). + +do_default_ciphers(undefined) -> + do_default_ciphers(tls_all_available); +do_default_ciphers(quic) -> [ "TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256" ]; -default_ciphers(dtls_all_available) -> +do_default_ciphers(dtls_all_available) -> %% as of now, dtls does not support tlsv1.3 ciphers emqx_tls_lib:selected_ciphers(['dtlsv1.2', 'dtlsv1']); -default_ciphers(tls_all_available) -> +do_default_ciphers(tls_all_available) -> emqx_tls_lib:default_ciphers(). %% @private return a list of keys in a parent field diff --git a/apps/emqx_authn/src/emqx_authn_app.erl b/apps/emqx_authn/src/emqx_authn_app.erl index 9284493bf..a59c85e9c 100644 --- a/apps/emqx_authn/src/emqx_authn_app.erl +++ b/apps/emqx_authn/src/emqx_authn_app.erl @@ -25,6 +25,8 @@ , stop/1 ]). +-dialyzer({nowarn_function, [start/2]}). + %%------------------------------------------------------------------------------ %% APIs %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/src/emqx_authn_schema.erl b/apps/emqx_authn/src/emqx_authn_schema.erl index ca5fe3cc7..c0f16b3f3 100644 --- a/apps/emqx_authn/src/emqx_authn_schema.erl +++ b/apps/emqx_authn/src/emqx_authn_schema.erl @@ -19,8 +19,15 @@ -include_lib("typerefl/include/types.hrl"). -export([ common_fields/0 + , roots/0 + , fields/1 ]). +%% just a stub, never used at root level +roots() -> []. + +fields(_) -> []. + common_fields() -> [ {enable, fun enable/1} ]. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index 5ee7a8db8..bbfdaf319 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -102,7 +102,7 @@ body(validator) -> [fun check_body/1]; body(_) -> undefined. request_timeout(type) -> emqx_schema:duration_ms(); -request_timeout(default) -> "5s"; +request_timeout(default) -> <<"5s">>; request_timeout(_) -> undefined. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_authn/test/emqx_authn_api_SUITE.erl b/apps/emqx_authn/test/emqx_authn_api_SUITE.erl new file mode 100644 index 000000000..54c689747 --- /dev/null +++ b/apps/emqx_authn/test/emqx_authn_api_SUITE.erl @@ -0,0 +1,100 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_authn_api_SUITE). + +-compile(nowarn_export_all). +-compile(export_all). + +-include("emqx_authz.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). + + +-define(HOST, "http://127.0.0.1:18083/"). +-define(API_VERSION, "v5"). +-define(BASE_PATH, "api"). + +all() -> + emqx_common_test_helpers:all(?MODULE). + +groups() -> + []. + +init_per_suite(Config) -> + ok = emqx_common_test_helpers:start_apps([emqx_authn, emqx_dashboard], fun set_special_configs/1), + Config. + +end_per_suite(_Config) -> + emqx_common_test_helpers:stop_apps([emqx_authn, emqx_dashboard]), + ok. + +set_special_configs(emqx_dashboard) -> + Config = #{ + default_username => <<"admin">>, + default_password => <<"public">>, + listeners => [#{ + protocol => http, + port => 18083 + }] + }, + emqx_config:put([emqx_dashboard], Config), + emqx_config:put([node, data_dir], "data"), + ok; +set_special_configs(_App) -> + ok. + +t_create_http_authn(_) -> + {ok, 200, _} = request(post, uri(["authentication"]), + emqx_authn_test_lib:http_example()), + {ok, 200, _} = request(get, uri(["authentication"])). + +request(Method, Url) -> + request(Method, Url, []). + +request(Method, Url, Body) -> + Request = + case Body of + [] -> + {Url, [auth_header()]}; + _ -> + {Url, [auth_header()], "application/json", to_json(Body)} + end, + ct:pal("Method: ~p, Request: ~p", [Method, Request]), + case httpc:request(Method, Request, [], [{body_format, binary}]) of + {error, socket_closed_remotely} -> + {error, socket_closed_remotely}; + {ok, {{"HTTP/1.1", Code, _}, _Headers, Return} } -> + {ok, Code, Return}; + {ok, {Reason, _, _}} -> + {error, Reason} + end. + +uri() -> uri([]). +uri(Parts) when is_list(Parts) -> + NParts = [E || E <- Parts], + ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION | NParts]). + +get_sources(Result) -> jsx:decode(Result). + +auth_header() -> + Username = <<"admin">>, + Password = <<"public">>, + {ok, Token} = emqx_dashboard_admin:sign_token(Username, Password), + {"Authorization", "Bearer " ++ binary_to_list(Token)}. + +to_json(Hocon) -> + {ok, Map} =hocon:binary(Hocon), + jiffy:encode(Map). diff --git a/apps/emqx_authn/test/emqx_authn_test_lib.erl b/apps/emqx_authn/test/emqx_authn_test_lib.erl new file mode 100644 index 000000000..e30854318 --- /dev/null +++ b/apps/emqx_authn/test/emqx_authn_test_lib.erl @@ -0,0 +1,38 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_authn_test_lib). + +-compile(nowarn_export_all). +-compile(export_all). + +http_example() -> +""" +{ + mechanism = \"password-based\" + backend = http + method = post + url = \"http://127.0.0.2:8080\" + headers = {\"content-type\" = \"application/json\"} + body = {username = \"${username}\", + password = \"${password}\"} + pool_size = 8 + connect_timeout = 5000 + request_timeout = 5000 + enable_pipelining = true + ssl = {enable = false} +} +""". diff --git a/apps/emqx_connector/src/emqx_connector_http.erl b/apps/emqx_connector/src/emqx_connector_http.erl index 7c71e09b3..c724ddb7a 100644 --- a/apps/emqx_connector/src/emqx_connector_http.erl +++ b/apps/emqx_connector/src/emqx_connector_http.erl @@ -93,7 +93,7 @@ base_url(validator) -> fun(#{query := _Query}) -> base_url(_) -> undefined. connect_timeout(type) -> emqx_schema:duration_ms(); -connect_timeout(default) -> "5s"; +connect_timeout(default) -> <<"5s">>; connect_timeout(_) -> undefined. max_retries(type) -> non_neg_integer(); @@ -101,7 +101,7 @@ max_retries(default) -> 5; max_retries(_) -> undefined. retry_interval(type) -> emqx_schema:duration(); -retry_interval(default) -> "1s"; +retry_interval(default) -> <<"1s">>; retry_interval(_) -> undefined. pool_type(type) -> pool_type(); From 79b5ddb0a7ad203eadb04ce0b277ad12ed716c5c Mon Sep 17 00:00:00 2001 From: zhouzb Date: Wed, 20 Oct 2021 18:07:07 +0800 Subject: [PATCH 19/88] chore(deps): update version of hocon --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 89b8e3a9f..a21341d56 100644 --- a/rebar.config +++ b/rebar.config @@ -61,7 +61,7 @@ , {observer_cli, "1.7.1"} % NOTE: depends on recon 2.5.x , {getopt, "1.0.2"} , {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.14.1"}}} - , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.19.6"}}} + , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.20.3"}}} , {emqx_http_lib, {git, "https://github.com/emqx/emqx_http_lib.git", {tag, "0.4.1"}}} , {esasl, {git, "https://github.com/emqx/esasl", {tag, "0.2.0"}}} , {jose, {git, "https://github.com/potatosalad/erlang-jose", {tag, "1.11.1"}}} From d334b27e56c6dfa438d5d10e03b941cdfa878fc1 Mon Sep 17 00:00:00 2001 From: zhanghongtong Date: Thu, 14 Oct 2021 11:01:06 +0800 Subject: [PATCH 20/88] chore(CI): better build docker image --- .github/workflows/build_packages.yaml | 53 +++++++-------------------- deploy/docker/Dockerfile | 12 ------ 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index 130c3a582..de2f18a58 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -356,62 +356,37 @@ jobs: path: . - name: unzip source code run: unzip -q source-${{ matrix.otp }}.zip - - name: get version - id: version - working-directory: source - run: echo "::set-output name=version::$(./pkg-vsn.sh)" - uses: docker/setup-buildx-action@v1 - uses: docker/setup-qemu-action@v1 with: image: tonistiigi/binfmt:latest platforms: all - - uses: docker/build-push-action@v2 - if: github.event_name != 'release' + - uses: docker/metadata-action@v3 + id: meta with: - push: false - pull: true - no-cache: true - platforms: linux/amd64,linux/arm64 - tags: emqx/${{ matrix.profile }}:${{ steps.version.outputs.version }} - build-args: | - PKG_VSN=${{ steps.version.outputs.version }} - BUILD_FROM=ghcr.io/emqx/emqx-builder-helper/5.0:${{ matrix.otp }}-alpine3.14 - RUN_FROM=alpine:3.14 - EMQX_NAME=${{ matrix.profile }} - file: source/deploy/docker/Dockerfile - context: source + images: ${{ github.repository_owner }}/${{ matrix.profile }} + flavor: | + latest=${{ !github.event.release.prerelease }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=ref,event=tag + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} - uses: docker/login-action@v1 if: github.event_name == 'release' with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - uses: docker/build-push-action@v2 - if: github.event_name == 'release' && github.event.release.prerelease with: - push: true + push: ${{ github.event_name == 'release' }} pull: true no-cache: true platforms: linux/amd64,linux/arm64 - tags: emqx/${{ matrix.profile }}:${{ steps.version.outputs.version }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} build-args: | - PKG_VSN=${{ steps.version.outputs.version }} - BUILD_FROM=ghcr.io/emqx/emqx-builder-helper/5.0:${{ matrix.otp }}-alpine3.14 - RUN_FROM=alpine:3.14 - EMQX_NAME=${{ matrix.profile }} - file: source/deploy/docker/Dockerfile - context: source - - uses: docker/build-push-action@v2 - if: github.event_name == 'release' && !github.event.release.prerelease - with: - push: true - pull: true - no-cache: true - platforms: linux/amd64,linux/arm64 - tags: | - emqx/${{ matrix.profile }}:latest - emqx/${{ matrix.profile }}:${{ steps.version.outputs.version }} - build-args: | - PKG_VSN=${{ steps.version.outputs.version }} BUILD_FROM=ghcr.io/emqx/emqx-builder-helper/5.0:${{ matrix.otp }}-alpine3.14 RUN_FROM=alpine:3.14 EMQX_NAME=${{ matrix.profile }} diff --git a/deploy/docker/Dockerfile b/deploy/docker/Dockerfile index 5aa1d8864..0c9aee451 100644 --- a/deploy/docker/Dockerfile +++ b/deploy/docker/Dockerfile @@ -20,7 +20,6 @@ RUN apk add --no-cache \ COPY . /emqx -ARG PKG_VSN ARG EMQX_NAME=emqx RUN cd /emqx \ @@ -29,17 +28,6 @@ RUN cd /emqx \ FROM $RUN_FROM -# Basic build-time metadata as defined at http://label-schema.org -LABEL org.label-schema.docker.dockerfile="Dockerfile" \ - org.label-schema.license="GNU" \ - org.label-schema.name="emqx" \ - org.label-schema.version=${PKG_VSN} \ - org.label-schema.description="EMQ (Erlang MQTT Broker) is a distributed, massively scalable, highly extensible MQTT messaging broker written in Erlang/OTP." \ - org.label-schema.url="https://emqx.io" \ - org.label-schema.vcs-type="Git" \ - org.label-schema.vcs-url="https://github.com/emqx/emqx" \ - maintainer="Raymond M Mouthaan , Huang Rui , EMQ X Team " - ARG EMQX_NAME=emqx COPY deploy/docker/docker-entrypoint.sh /usr/bin/ From 88d891a59a1aafcb3b7ae50fcad31ad42e1f0fa3 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 13:04:55 +0200 Subject: [PATCH 21/88] feat: support check_config callback for authenticator provider --- apps/emqx/src/emqx_authentication.erl | 5 ++- apps/emqx/src/emqx_authentication_config.erl | 43 ++++++++++++++----- apps/emqx/test/emqx_authentication_SUITE.erl | 44 ++++++++++++++------ 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/apps/emqx/src/emqx_authentication.erl b/apps/emqx/src/emqx_authentication.erl index 5ee8b2815..c3bfe7912 100644 --- a/apps/emqx/src/emqx_authentication.erl +++ b/apps/emqx/src/emqx_authentication.erl @@ -116,7 +116,9 @@ -type user_info() :: #{user_id := binary(), atom() => term()}. --callback refs() -> [{ref, Module, Name}] when Module::module(), Name::atom(). +%% @doc check_config takes raw config from config file, +%% parse and validate it, and reutrn parsed result. +-callback check_config(config()) -> config(). -callback create(Config) -> {ok, State} @@ -176,6 +178,7 @@ , update_user/3 , lookup_user/3 , list_users/1 + , check_config/1 ]). %%------------------------------------------------------------------------------ diff --git a/apps/emqx/src/emqx_authentication_config.erl b/apps/emqx/src/emqx_authentication_config.erl index 526d9d6ff..86182143a 100644 --- a/apps/emqx/src/emqx_authentication_config.erl +++ b/apps/emqx/src/emqx_authentication_config.erl @@ -27,6 +27,11 @@ , authn_type/1 ]). +%% TODO: certs handling should be moved out of emqx app +-ifdef(TEST). +-export([convert_certs/2, convert_certs/3, diff_cert/2, clear_certs/2]). +-endif. + -export_type([config/0]). -include("logger.hrl"). @@ -151,17 +156,33 @@ do_check_conifg(Config, Providers) -> providers => Providers}), throw(unknown_authn_type); Module -> - %% TODO: check if Module:check_config/1 is exported - %% so we do not force all providers to implement hocon schema - try hocon_schema:check_plain(Module, #{<<"config">> => Config}, - #{atom_key => true}) of - #{config := Result} -> - Result - catch - C : E : S -> - ?SLOG(warning, #{msg => "failed_to_check_config", config => Config}), - erlang:raise(C, E, S) - end + do_check_conifg(Type, Config, Module) + end. + +do_check_conifg(Type, Config, Module) -> + F = case erlang:function_exported(Module, check_config, 1) of + true -> + fun Module:check_config/1; + false -> + fun(C) -> + #{config := R} = + hocon_schema:check_plain(Module, #{<<"config">> => C}, + #{atom_key => true}), + R + end + end, + try + F(Config) + catch + C : E : S -> + ?SLOG(warning, #{msg => "failed_to_check_config", + config => Config, + type => Type, + exception => C, + reason => E, + stacktrace => S + }), + throw(bad_authenticator_config) end. return_map([L]) -> L; diff --git a/apps/emqx/test/emqx_authentication_SUITE.erl b/apps/emqx/test/emqx_authentication_SUITE.erl index c4ed85125..cf1514918 100644 --- a/apps/emqx/test/emqx_authentication_SUITE.erl +++ b/apps/emqx/test/emqx_authentication_SUITE.erl @@ -26,13 +26,13 @@ -include_lib("eunit/include/eunit.hrl"). -include_lib("typerefl/include/types.hrl"). --export([ fields/1 ]). +-export([ roots/0, fields/1 ]). --export([ refs/0 - , create/1 +-export([ create/1 , update/2 , authenticate/2 , destroy/1 + , check_config/1 ]). -define(AUTHN, emqx_authentication). @@ -42,6 +42,8 @@ %% Hocon Schema %%------------------------------------------------------------------------------ +roots() -> [{config, #{type => hoconsc:union([hoconsc:ref(type1), hoconsc:ref(type2)])}}]. + fields(type1) -> [ {mechanism, {enum, ['password-based']}} , {backend, {enum, ['built-in-database']}} @@ -62,10 +64,11 @@ enable(_) -> undefined. %% Callbacks %%------------------------------------------------------------------------------ -refs() -> - [ hoconsc:ref(?MODULE, type1) - , hoconsc:ref(?MODULE, type2) - ]. +check_config(C) -> + #{config := R} = + hocon_schema:check_plain(?MODULE, #{<<"config">> => C}, + #{atom_key => true}), + R. create(_Config) -> {ok, #{mark => 1}}. @@ -268,14 +271,14 @@ t_convert_certs(Config) when is_list(Config) -> , {<<"cacertfile">>, "cacert.pem"} ]), - CertsDir = ?AUTHN:certs_dir([Global, <<"password-based:built-in-database">>]), - #{<<"ssl">> := NCerts} = ?AUTHN:convert_certs(CertsDir, #{<<"ssl">> => Certs}), + CertsDir = certs_dir(Config, [Global, <<"password-based:built-in-database">>]), + #{<<"ssl">> := NCerts} = convert_certs(CertsDir, #{<<"ssl">> => Certs}), ?assertEqual(false, diff_cert(maps:get(<<"keyfile">>, NCerts), maps:get(<<"keyfile">>, Certs))), Certs2 = certs([ {<<"keyfile">>, "key.pem"} , {<<"certfile">>, "cert.pem"} ]), - #{<<"ssl">> := NCerts2} = ?AUTHN:convert_certs(CertsDir, #{<<"ssl">> => Certs2}, #{<<"ssl">> => NCerts}), + #{<<"ssl">> := NCerts2} = convert_certs(CertsDir, #{<<"ssl">> => Certs2}, #{<<"ssl">> => NCerts}), ?assertEqual(false, diff_cert(maps:get(<<"keyfile">>, NCerts2), maps:get(<<"keyfile">>, Certs2))), ?assertEqual(maps:get(<<"keyfile">>, NCerts), maps:get(<<"keyfile">>, NCerts2)), ?assertEqual(maps:get(<<"certfile">>, NCerts), maps:get(<<"certfile">>, NCerts2)), @@ -284,13 +287,13 @@ t_convert_certs(Config) when is_list(Config) -> , {<<"certfile">>, "client-cert.pem"} , {<<"cacertfile">>, "cacert.pem"} ]), - #{<<"ssl">> := NCerts3} = ?AUTHN:convert_certs(CertsDir, #{<<"ssl">> => Certs3}, #{<<"ssl">> => NCerts2}), + #{<<"ssl">> := NCerts3} = convert_certs(CertsDir, #{<<"ssl">> => Certs3}, #{<<"ssl">> => NCerts2}), ?assertEqual(false, diff_cert(maps:get(<<"keyfile">>, NCerts3), maps:get(<<"keyfile">>, Certs3))), ?assertNotEqual(maps:get(<<"keyfile">>, NCerts2), maps:get(<<"keyfile">>, NCerts3)), ?assertNotEqual(maps:get(<<"certfile">>, NCerts2), maps:get(<<"certfile">>, NCerts3)), ?assertEqual(true, filelib:is_regular(maps:get(<<"keyfile">>, NCerts3))), - ?AUTHN:clear_certs(CertsDir, #{<<"ssl">> => NCerts3}), + clear_certs(CertsDir, #{<<"ssl">> => NCerts3}), ?assertEqual(false, filelib:is_regular(maps:get(<<"keyfile">>, NCerts3))). update_config(Path, ConfigRequest) -> @@ -305,7 +308,22 @@ certs(Certs) -> diff_cert(CertFile, CertPem2) -> {ok, CertPem1} = file:read_file(CertFile), - ?AUTHN:diff_cert(CertPem1, CertPem2). + emqx_authentication_config:diff_cert(CertPem1, CertPem2). register_provider(Type, Module) -> ok = ?AUTHN:register_providers([{Type, Module}]). + +certs_dir(CtConfig, Path) -> + DataDir = proplists:get_value(data_dir, CtConfig), + Dir = filename:join([DataDir | Path]), + filelib:ensure_dir(Dir), + Dir. + +convert_certs(CertsDir, SslConfig) -> + emqx_authentication_config:convert_certs(CertsDir, SslConfig). + +convert_certs(CertsDir, New, Old) -> + emqx_authentication_config:convert_certs(CertsDir, New, Old). + +clear_certs(CertsDir, SslConfig) -> + emqx_authentication_config:clear_certs(CertsDir, SslConfig). From 019b9d17f6499d6023812a15188a19e5161d9842 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 13:13:03 +0200 Subject: [PATCH 22/88] refactor(emqx_config_handler): async remove --- apps/emqx/src/emqx_authentication.erl | 10 ++++++++-- apps/emqx/src/emqx_authentication_config.erl | 12 ++++++------ apps/emqx/src/emqx_config_handler.erl | 11 +++++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/emqx/src/emqx_authentication.erl b/apps/emqx/src/emqx_authentication.erl index c3bfe7912..793a96cf2 100644 --- a/apps/emqx/src/emqx_authentication.erl +++ b/apps/emqx/src/emqx_authentication.erl @@ -557,8 +557,14 @@ handle_info(Info, State) -> {noreply, State}. terminate(Reason, _State) -> - ?SLOG(error, #{msg => "emqx_authentication_terminating", - reason => Reason}), + case Reason of + normal -> ok; + {shutdown, _} -> ok; + Other -> ?SLOG(error, #{msg => "emqx_authentication_terminating", + reason => Other}) + end, + emqx_config_handler:remove_handler([authentication]), + emqx_config_handler:remove_handler([listeners, '?', '?', authentication]), ok. code_change(_OldVsn, State, _Extra) -> diff --git a/apps/emqx/src/emqx_authentication_config.erl b/apps/emqx/src/emqx_authentication_config.erl index 86182143a..2bea0cbe9 100644 --- a/apps/emqx/src/emqx_authentication_config.erl +++ b/apps/emqx/src/emqx_authentication_config.erl @@ -221,12 +221,12 @@ convert_certs(CertsDir, NewConfig, OldConfig) -> OldSSLOpts = maps:get(<<"ssl">>, OldConfig, #{}), Diff = diff_certs(NewSSLOpts, OldSSLOpts), NSSLOpts = lists:foldl(fun({identical, K}, Acc) -> - Acc#{K => maps:get(K, OldSSLOpts)}; - ({_, K}, Acc) -> - CertFile = generate_filename(CertsDir, K), - ok = save_cert_to_file(CertFile, maps:get(K, NewSSLOpts)), - Acc#{K => CertFile} - end, NewSSLOpts, Diff), + Acc#{K => maps:get(K, OldSSLOpts)}; + ({_, K}, Acc) -> + CertFile = generate_filename(CertsDir, K), + ok = save_cert_to_file(CertFile, maps:get(K, NewSSLOpts)), + Acc#{K => CertFile} + end, NewSSLOpts, Diff), NewConfig#{<<"ssl">> => NSSLOpts} end. diff --git a/apps/emqx/src/emqx_config_handler.erl b/apps/emqx/src/emqx_config_handler.erl index 297f1147d..c44a0cb96 100644 --- a/apps/emqx/src/emqx_config_handler.erl +++ b/apps/emqx/src/emqx_config_handler.erl @@ -77,9 +77,10 @@ update_config(SchemaModule, ConfKeyPath, UpdateArgs) -> add_handler(ConfKeyPath, HandlerName) -> gen_server:call(?MODULE, {add_handler, ConfKeyPath, HandlerName}, infinity). +%% @doc Remove handler asynchronously -spec remove_handler(emqx_config:config_key_path()) -> ok. remove_handler(ConfKeyPath) -> - gen_server:call(?MODULE, {remove_handler, ConfKeyPath}, infinity). + gen_server:cast(?MODULE, {remove_handler, ConfKeyPath}). %%============================================================================ @@ -95,11 +96,6 @@ handle_call({add_handler, ConfKeyPath, HandlerName}, _From, State = #{handlers : {reply, Error, State} end; -handle_call({remove_handler, ConfKeyPath}, _From, - State = #{handlers := Handlers}) -> - {reply, ok, State#{handlers => - emqx_map_lib:deep_remove(ConfKeyPath ++ [?MOD], Handlers)}}; - handle_call({change_config, SchemaModule, ConfKeyPath, UpdateArgs}, _From, #{handlers := Handlers} = State) -> Reply = try @@ -125,6 +121,9 @@ handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. +handle_cast({remove_handler, ConfKeyPath}, + State = #{handlers := Handlers}) -> + {noreply, State#{handlers => emqx_map_lib:deep_remove(ConfKeyPath ++ [?MOD], Handlers)}}; handle_cast(_Msg, State) -> {noreply, State}. From d468c21e61c5d399b174d7c51d964f97318d5d0c Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 14:36:37 +0200 Subject: [PATCH 23/88] fix(authn): rename config key http-server to http --- apps/emqx_authn/src/emqx_authn.erl | 3 +-- apps/emqx_authn/src/emqx_authn_api.erl | 8 ++++---- apps/emqx_authn/src/simple_authn/emqx_authn_http.erl | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index 1b0d12fd2..a49aacff4 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -28,8 +28,7 @@ providers() -> , {{'password-based', postgresql}, emqx_authn_pgsql} , {{'password-based', mongodb}, emqx_authn_mongodb} , {{'password-based', redis}, emqx_authn_redis} - , {{'password-based', 'http-server'}, emqx_authn_http} - , {{'password-based', 'http'}, emqx_authn_http} %% TODO: resolve one + , {{'password-based', 'http'}, emqx_authn_http} , {jwt, emqx_authn_jwt} , {{scram, 'built-in-database'}, emqx_enhanced_authn_scram_mnesia} ]. diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 93df83829..f8e8bf5de 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -43,7 +43,7 @@ }}). -define(EXAMPLE_2, #{mechanism => <<"password-based">>, - backend => <<"http-server">>, + backend => <<"http">>, method => <<"post">>, url => <<"http://localhost:80/login">>, headers => #{ @@ -90,7 +90,7 @@ -define(INSTANCE_EXAMPLE_1, maps:merge(?EXAMPLE_1, #{id => <<"password-based:built-in-database">>, enable => true})). --define(INSTANCE_EXAMPLE_2, maps:merge(?EXAMPLE_2, #{id => <<"password-based:http-server">>, +-define(INSTANCE_EXAMPLE_2, maps:merge(?EXAMPLE_2, #{id => <<"password-based:http">>, connect_timeout => "5s", enable_pipelining => true, headers => #{ @@ -1506,8 +1506,8 @@ definitions() -> }, backend => #{ type => string, - enum => [<<"http-server">>], - example => <<"http-server">> + enum => [<<"http">>], + example => <<"http">> }, method => #{ type => string, diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index bbfdaf319..c99806341 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -61,8 +61,8 @@ fields(post) -> ] ++ common_fields(). common_fields() -> - [ {mechanism, {enum, ['password-based']}} - , {backend, {enum, ['http-server', 'http']}} %% TODO: delete http + [ {mechanism, 'password-based'} + , {backend, 'http'} , {url, fun url/1} , {body, fun body/1} , {request_timeout, fun request_timeout/1} From fa91e5f583b7acb7656c1e5864948fdccd6f4f71 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 15:06:08 +0200 Subject: [PATCH 24/88] fix(authn): allow single authenticator instance from config --- apps/emqx/src/emqx_schema.erl | 19 +++++++++++++------ apps/emqx_authn/src/emqx_authn.erl | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 245d7d5fc..4b1f0c55f 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -103,12 +103,10 @@ The configs here work as default values which can be overriden in zone configs""" })} , {"authentication", - sc(hoconsc:lazy(hoconsc:array(map())), - #{ desc => + authentication( """Default authentication configs for all MQTT listeners.
For per-listener overrides see authentication -in listener configs""" - })} +in listener configs""")} , {"authorization", sc(ref("authorization"), #{})} @@ -903,8 +901,7 @@ mqtt_listener() -> #{}) } , {"authentication", - sc(hoconsc:lazy(hoconsc:array(map())), - #{}) + authentication("Per-listener authentication override") } ]. @@ -1356,3 +1353,13 @@ str(B) when is_binary(B) -> binary_to_list(B); str(S) when is_list(S) -> S. + +authentication(Desc) -> + #{ type => hoconsc:union([typerefl:map(), hoconsc:array(typerefl:map())]) + , desc => [Desc, "
", """ +Authentication can be one single authenticator instance or a chain of authenticators as an array. +The when authenticating a login (username, client ID, etc.) the authenticators are checked +in the configured order. +""" + ] + }. diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index a49aacff4..fbd31c5d2 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -33,6 +33,8 @@ providers() -> , {{scram, 'built-in-database'}, emqx_enhanced_authn_scram_mnesia} ]. +check_configs(C) when is_map(C) -> + check_configs([C]); check_configs([]) -> []; check_configs([Config | Configs]) -> [check_config(Config) | check_configs(Configs)]. From ce5b45687252a892daf80cfc19173c9e5e8c8e26 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Wed, 20 Oct 2021 17:15:16 +0200 Subject: [PATCH 25/88] refactor(authn): make schema doc generation work --- apps/emqx/src/emqx_schema.erl | 11 ++++++----- apps/emqx_authn/src/emqx_authn_schema.erl | 9 +++++++-- apps/emqx_authn/src/simple_authn/emqx_authn_http.erl | 11 +++++------ apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl | 7 +++---- .../emqx_authn/src/simple_authn/emqx_authn_mnesia.erl | 2 +- .../src/simple_authn/emqx_authn_mongodb.erl | 8 +++----- apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl | 2 +- apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl | 2 +- apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl | 8 +++----- apps/emqx_machine/src/emqx_machine_schema.erl | 1 + 10 files changed, 31 insertions(+), 30 deletions(-) diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 4b1f0c55f..5958167cd 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -1355,11 +1355,12 @@ str(S) when is_list(S) -> S. authentication(Desc) -> - #{ type => hoconsc:union([typerefl:map(), hoconsc:array(typerefl:map())]) - , desc => [Desc, "
", """ + #{ type => hoconsc:lazy(hoconsc:union([typerefl:map(), hoconsc:array(typerefl:map())])) + , desc => iolist_to_binary([Desc, "
", """ Authentication can be one single authenticator instance or a chain of authenticators as an array. The when authenticating a login (username, client ID, etc.) the authenticators are checked -in the configured order. -""" - ] +in the configured order.
+EMQ X comes with a set of pre-built autenticators, for more details, see +authenticator_config. +"""]) }. diff --git a/apps/emqx_authn/src/emqx_authn_schema.erl b/apps/emqx_authn/src/emqx_authn_schema.erl index c0f16b3f3..b36e88ebf 100644 --- a/apps/emqx_authn/src/emqx_authn_schema.erl +++ b/apps/emqx_authn/src/emqx_authn_schema.erl @@ -23,8 +23,10 @@ , fields/1 ]). -%% just a stub, never used at root level -roots() -> []. +%% only for doc generation +roots() -> [{authenticator_config, + #{type => hoconsc:union(config_refs([Module || {_AuthnType, Module} <- emqx_authn:providers()])) + }}]. fields(_) -> []. @@ -35,3 +37,6 @@ common_fields() -> enable(type) -> boolean(); enable(default) -> true; enable(_) -> undefined. + +config_refs(Modules) -> + lists:append([Module:refs() || Module <- Modules]). diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl index c99806341..ceb4b30a8 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_http.erl @@ -40,12 +40,11 @@ %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-http_server". +namespace() -> "authn-http". roots() -> - [ {config, {union, [ hoconsc:ref(?MODULE, get) - , hoconsc:ref(?MODULE, post) - ]}} + [ {config, hoconsc:mk(hoconsc:union(refs()), + #{})} ]. fields(get) -> @@ -61,8 +60,8 @@ fields(post) -> ] ++ common_fields(). common_fields() -> - [ {mechanism, 'password-based'} - , {backend, 'http'} + [ {mechanism, hoconsc:enum(['password-based'])} + , {backend, hoconsc:enum(['http'])} , {url, fun url/1} , {body, fun body/1} , {request_timeout, fun request_timeout/1} diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl index 1b7c5b87d..c4e04eac3 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl @@ -40,10 +40,9 @@ namespace() -> "authn-jwt". roots() -> - [ {config, {union, [ hoconsc:mk('hmac-based') - , hoconsc:mk('public-key') - , hoconsc:mk('jwks') - ]}} + [ {config, hoconsc:mk(hoconsc:union(refs()), + #{} + )} ]. fields('hmac-based') -> diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index c3b6badf7..2df09c043 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -84,7 +84,7 @@ mnesia(copy) -> %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-builtin_db". +namespace() -> "authn-builtin_db". roots() -> [config]. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl index 7b986e6f9..ce5d3d8ee 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl @@ -39,13 +39,11 @@ %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-mongodb". +namespace() -> "authn-mongodb". roots() -> - [ {config, {union, [ hoconsc:mk(standalone) - , hoconsc:mk('replica-set') - , hoconsc:mk('sharded-cluster') - ]}} + [ {config, hoconsc:mk(hoconsc:union(refs()), + #{})} ]. fields(standalone) -> diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index b4c6dac08..fb090aca2 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -39,7 +39,7 @@ %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-mysql". +namespace() -> "authn-mysql". roots() -> [config]. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl index 5f1005e9f..4086f4b22 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl @@ -40,7 +40,7 @@ %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-postgresql". +namespace() -> "authn-postgresql". roots() -> [config]. diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl index cb04b0274..3ae333d12 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl @@ -39,13 +39,11 @@ %% Hocon Schema %%------------------------------------------------------------------------------ -namespace() -> "authn-password_based-redis". +namespace() -> "authn-redis". roots() -> - [ {config, {union, [ hoconsc:mk(standalone) - , hoconsc:mk(cluster) - , hoconsc:mk(sentinel) - ]}} + [ {config, hoconsc:mk(hoconsc:union(refs()), + #{})} ]. fields(standalone) -> diff --git a/apps/emqx_machine/src/emqx_machine_schema.erl b/apps/emqx_machine/src/emqx_machine_schema.erl index 995de1f62..ce6fc74db 100644 --- a/apps/emqx_machine/src/emqx_machine_schema.erl +++ b/apps/emqx_machine/src/emqx_machine_schema.erl @@ -45,6 +45,7 @@ [ emqx_bridge_schema , emqx_retainer_schema , emqx_statsd_schema + , emqx_authn_schema , emqx_authz_schema , emqx_auto_subscribe_schema , emqx_modules_schema From ef731c74ebdba7d55a1e8eb0bb67d18d55dd292b Mon Sep 17 00:00:00 2001 From: zhouzb Date: Thu, 21 Oct 2021 09:35:00 +0800 Subject: [PATCH 26/88] chore(deps): unify version of hocon --- apps/emqx/rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index b851700b9..7e4f22345 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -17,7 +17,7 @@ , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.10.9"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} - , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.19.6"}}} + , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.20.3"}}} , {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}} , {recon, {git, "https://github.com/ferd/recon", {tag, "2.5.1"}}} , {snabbkaffe, {git, "https://github.com/kafka4beam/snabbkaffe.git", {tag, "0.14.1"}}} From 9fdd5e6a7e636f7807e59e725c2f7809dae1c1a3 Mon Sep 17 00:00:00 2001 From: k32 <10274441+k32@users.noreply.github.com> Date: Thu, 21 Oct 2021 08:49:21 +0200 Subject: [PATCH 27/88] fix(emqx_machine): Fix start/stop callbacks (#5969) * fix(emqx_machine): Fix start/stop callbacks * chore(ekka): Bump version to 0.11.1 * fix(router): Wait for the tables * fix(emqx_cluster_rpc): Stop cluster RPC when joining a cluster * fix(emqx_app): Fix a deadlock when joining the cluster * fix(emqx_telemetry): Wait for mnesia tables * test(ct_helper): Start ekka before emqx --- apps/emqx/rebar.config | 2 +- apps/emqx/src/emqx_app.erl | 5 ++- apps/emqx/src/emqx_router_helper.erl | 1 + apps/emqx/test/emqx_common_test_helpers.erl | 3 +- apps/emqx_machine/src/emqx_cluster_rpc.erl | 1 + apps/emqx_machine/src/emqx_machine_boot.erl | 18 +++++++---- apps/emqx_machine/src/emqx_machine_sup.erl | 32 +++++++++++++++++++ .../src/emqx_machine_terminator.erl | 2 +- apps/emqx_machine/test/emqx_machine_SUITE.erl | 4 +-- apps/emqx_modules/src/emqx_telemetry.erl | 1 + rebar.config | 2 +- 11 files changed, 55 insertions(+), 16 deletions(-) diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index 714693d88..4ea0b06be 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -15,7 +15,7 @@ , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.8.3"}}} , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} - , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.0"}}} + , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.1"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} , {hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.20.3"}}} , {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}} diff --git a/apps/emqx/src/emqx_app.erl b/apps/emqx/src/emqx_app.erl index 662439397..504b245f3 100644 --- a/apps/emqx/src/emqx_app.erl +++ b/apps/emqx/src/emqx_app.erl @@ -41,7 +41,7 @@ start(_Type, _Args) -> ok = maybe_load_config(), ok = maybe_start_quicer(), - ensure_ekka_started(), + wait_boot_shards(), {ok, Sup} = emqx_sup:start_link(), ok = maybe_start_listeners(), ok = emqx_alarm_handler:load(), @@ -55,8 +55,7 @@ prep_stop(_State) -> stop(_State) -> ok. -ensure_ekka_started() -> - ekka:start(), +wait_boot_shards() -> ok = mria_rlog:wait_for_shards(?BOOT_SHARDS, infinity). %% @doc Call this function to make emqx boot without loading config, diff --git a/apps/emqx/src/emqx_router_helper.erl b/apps/emqx/src/emqx_router_helper.erl index aecce70ac..cc5fc8708 100644 --- a/apps/emqx/src/emqx_router_helper.erl +++ b/apps/emqx/src/emqx_router_helper.erl @@ -92,6 +92,7 @@ monitor(Node) when is_atom(Node) -> init([]) -> ok = ekka:monitor(membership), + _ = mria:wait_for_tables([?ROUTING_NODE]), {ok, _} = mnesia:subscribe({table, ?ROUTING_NODE, simple}), Nodes = lists:foldl( fun(Node, Acc) -> diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index a470370e6..f9cc2d0b0 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -133,6 +133,7 @@ start_apps(Apps, Handler) when is_function(Handler) -> %% Load all application code to beam vm first %% Because, minirest, ekka etc.. application will scan these modules lists:foreach(fun load/1, [emqx | Apps]), + ekka:start(), lists:foreach(fun(App) -> start_app(App, Handler) end, [emqx | Apps]). load(App) -> @@ -195,7 +196,7 @@ generate_config(SchemaModule, ConfigFile) when is_atom(SchemaModule) -> -spec(stop_apps(list()) -> ok). stop_apps(Apps) -> - [application:stop(App) || App <- Apps ++ [emqx, mria, mnesia]], + [application:stop(App) || App <- Apps ++ [emqx, ekka, mria, mnesia]], ok. %% backward compatible diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_machine/src/emqx_cluster_rpc.erl index a55d17616..479561206 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_machine/src/emqx_cluster_rpc.erl @@ -135,6 +135,7 @@ skip_failed_commit(Node) -> %% @private init([Node, RetryMs]) -> + _ = mria:wait_for_tables([?CLUSTER_MFA]), {ok, _} = mnesia:subscribe({table, ?CLUSTER_MFA, simple}), {ok, #{node => Node, retry_interval => RetryMs}, {continue, ?CATCH_UP}}. diff --git a/apps/emqx_machine/src/emqx_machine_boot.erl b/apps/emqx_machine/src/emqx_machine_boot.erl index 83c47331e..ed3b21a9d 100644 --- a/apps/emqx_machine/src/emqx_machine_boot.erl +++ b/apps/emqx_machine/src/emqx_machine_boot.erl @@ -18,7 +18,7 @@ -include_lib("emqx/include/logger.hrl"). -export([post_boot/0]). --export([stop_apps/1, ensure_apps_started/0]). +-export([stop_apps/0, ensure_apps_started/0]). -export([sorted_reboot_apps/0]). -export([start_autocluster/0]). @@ -42,15 +42,16 @@ print_vsn() -> start_autocluster() -> - ekka:callback(prepare, fun ?MODULE:stop_apps/1), - ekka:callback(reboot, fun ?MODULE:ensure_apps_started/0), + ekka:callback(stop, fun emqx_machine_boot:stop_apps/0), + ekka:callback(start, fun emqx_machine_boot:ensure_apps_started/0), _ = ekka:autocluster(emqx), %% returns 'ok' or a pid or 'any()' as in spec ok. -stop_apps(Reason) -> - ?SLOG(info, #{msg => "stopping_apps", reason => Reason}), +stop_apps() -> + ?SLOG(notice, #{msg => "stopping_emqx_apps"}), _ = emqx_alarm_handler:unload(), - lists:foreach(fun stop_one_app/1, lists:reverse(sorted_reboot_apps())). + lists:foreach(fun stop_one_app/1, lists:reverse(sorted_reboot_apps())), + emqx_machine_sup:stop_cluster_rpc(). stop_one_app(App) -> ?SLOG(debug, #{msg => "stopping_app", app => App}), @@ -64,8 +65,11 @@ stop_one_app(App) -> reason => E}) end. - ensure_apps_started() -> + ?SLOG(notice, #{msg => "(re)starting_emqx_apps"}), + %% FIXME: Hack spawning the cluster RPC asynchronously to avoid a + %% deadlock somewhere in EMQ X startup + spawn_link(fun() -> emqx_machine_sup:start_cluster_rpc() end), lists:foreach(fun start_one_app/1, sorted_reboot_apps()). start_one_app(App) -> diff --git a/apps/emqx_machine/src/emqx_machine_sup.erl b/apps/emqx_machine/src/emqx_machine_sup.erl index 406e1d483..bf5403d43 100644 --- a/apps/emqx_machine/src/emqx_machine_sup.erl +++ b/apps/emqx_machine/src/emqx_machine_sup.erl @@ -21,6 +21,8 @@ -behaviour(supervisor). -export([ start_link/0 + , stop_cluster_rpc/0 + , start_cluster_rpc/0 ]). -export([init/1]). @@ -28,6 +30,26 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). +stop_cluster_rpc() -> + case whereis(?MODULE) of + undefined -> + ok; + _ -> + _ = supervisor:terminate_child(?MODULE, emqx_cluster_rpc_handler), + _ = supervisor:terminate_child(?MODULE, emqx_cluster_rpc), + ok + end. + +start_cluster_rpc() -> + case whereis(?MODULE) of + undefined -> + ok; + _ -> + ensure_running(emqx_cluster_rpc), + ensure_running(emqx_cluster_rpc_handler), + ok + end. + init([]) -> GlobalGC = child_worker(emqx_global_gc, [], permanent), Terminator = child_worker(emqx_machine_terminator, [], transient), @@ -52,3 +74,13 @@ child_worker(M, Func, Args, Restart) -> type => worker, modules => [M] }. + +ensure_running(Id) -> + %% Assuming Id == locally registered name + case whereis(Id) of + undefined -> + _ = supervisor:restart_child(?MODULE, Id), + ok; + _ -> + ok + end. diff --git a/apps/emqx_machine/src/emqx_machine_terminator.erl b/apps/emqx_machine/src/emqx_machine_terminator.erl index 733c1a5dc..3f6c29407 100644 --- a/apps/emqx_machine/src/emqx_machine_terminator.erl +++ b/apps/emqx_machine/src/emqx_machine_terminator.erl @@ -80,7 +80,7 @@ handle_cast(_Cast, State) -> handle_call(?DO_IT, _From, State) -> try - emqx_machine_boot:stop_apps(normal) + emqx_machine_boot:stop_apps() catch C : E : St -> Apps = [element(1, A) || A <- application:which_applications()], diff --git a/apps/emqx_machine/test/emqx_machine_SUITE.erl b/apps/emqx_machine/test/emqx_machine_SUITE.erl index 95ce23e11..cce0778e2 100644 --- a/apps/emqx_machine/test/emqx_machine_SUITE.erl +++ b/apps/emqx_machine/test/emqx_machine_SUITE.erl @@ -33,9 +33,9 @@ end_per_suite(_Config) -> emqx_common_test_helpers:stop_apps([]). t_shutdown_reboot(_Config) -> - emqx_machine_boot:stop_apps(normal), + emqx_machine_boot:stop_apps(), false = emqx:is_running(node()), emqx_machine_boot:ensure_apps_started(), true = emqx:is_running(node()), - ok = emqx_machine_boot:stop_apps(for_test), + ok = emqx_machine_boot:stop_apps(), false = emqx:is_running(node()). diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index 17f32ee58..e81d1257d 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -102,6 +102,7 @@ mnesia(boot) -> %%-------------------------------------------------------------------- start_link() -> + _ = mria:wait_for_tables([?TELEMETRY]), Opts = emqx:get_config([telemetry], #{}), gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []). diff --git a/rebar.config b/rebar.config index 030056bac..650b8ca9f 100644 --- a/rebar.config +++ b/rebar.config @@ -50,7 +50,7 @@ , {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}} , {cowboy, {git, "https://github.com/emqx/cowboy", {tag, "2.8.3"}}} , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} - , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.0"}}} + , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.1"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.5"}}} , {ecpool, {git, "https://github.com/emqx/ecpool", {tag, "0.5.1"}}} From 3a834a822f220a93581789db93590b54ac50ecc2 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Thu, 21 Oct 2021 17:07:24 +0800 Subject: [PATCH 28/88] fix(authn): fix sql parse for mysql --- apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index 9df50cf8f..065e951c5 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -145,7 +145,7 @@ parse_query(Query) -> case re:run(Query, ?RE_PLACEHOLDER, [global, {capture, all, binary}]) of {match, Captured} -> PlaceHolders = [PlaceHolder || [PlaceHolder] <- Captured], - NQuery = re:replace(Query, "'\\$\\{[a-z0-9\\_]+\\}'", "?", [global, {return, binary}]), + NQuery = re:replace(Query, "'\\$\\{[a-z0-9\\-]+\\}'", "?", [global, {return, binary}]), {NQuery, PlaceHolders}; nomatch -> {Query, []} From e071a10fee5aa032f54986bbd4163d50b92cdd25 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Thu, 21 Oct 2021 17:14:08 +0800 Subject: [PATCH 29/88] fix(authn): no longer use single quotes to wrap placeholders --- apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl | 2 +- apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl index 065e951c5..98d515310 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl @@ -145,7 +145,7 @@ parse_query(Query) -> case re:run(Query, ?RE_PLACEHOLDER, [global, {capture, all, binary}]) of {match, Captured} -> PlaceHolders = [PlaceHolder || [PlaceHolder] <- Captured], - NQuery = re:replace(Query, "'\\$\\{[a-z0-9\\-]+\\}'", "?", [global, {return, binary}]), + NQuery = re:replace(Query, ?RE_PLACEHOLDER, "?", [global, {return, binary}]), {NQuery, PlaceHolders}; nomatch -> {Query, []} diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl index 4086f4b22..2b8c9b391 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl @@ -137,7 +137,7 @@ parse_query(Query) -> PlaceHolders = [PlaceHolder || [PlaceHolder] <- Captured], Replacements = ["$" ++ integer_to_list(I) || I <- lists:seq(1, length(Captured))], NQuery = lists:foldl(fun({PlaceHolder, Replacement}, Query0) -> - re:replace(Query0, <<"'\\", PlaceHolder/binary, "'">>, Replacement, [{return, binary}]) + re:replace(Query0, PlaceHolder, Replacement, [{return, binary}]) end, Query, lists:zip(PlaceHolders, Replacements)), {NQuery, PlaceHolders}; nomatch -> From 7fdcca587a83db4c6c5e9a9719ad4120bb9e43b0 Mon Sep 17 00:00:00 2001 From: zhouzb Date: Thu, 21 Oct 2021 17:41:16 +0800 Subject: [PATCH 30/88] fix(authn): fix handling of pgsql response --- apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl index 2b8c9b391..d1390697a 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl @@ -108,7 +108,8 @@ authenticate(#{password := Password} = Credential, {ok, _Columns, []} -> ignore; {ok, Columns, Rows} -> NColumns = [Name || #column{name = Name} <- Columns], - Selected = maps:from_list(lists:zip(NColumns, Rows)), + NRows = [erlang:element(1, Row) || Row <- Rows], + Selected = maps:from_list(lists:zip(NColumns, NRows)), case emqx_authn_utils:check_password(Password, Selected, State) of ok -> {ok, emqx_authn_utils:is_superuser(Selected)}; From d784e63b9f219099293669799c4993fc24c88ceb Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Thu, 21 Oct 2021 18:08:51 +0800 Subject: [PATCH 31/88] emqx_conf (#5939) * feat(emqx_conf): move conf manager for emqx_machine to emqx_conf * chore(emqx_conf): change emqx:get_config/2 to emqx_conf:get/2 * fix: common test failed * fix: badmatch by typo wrong key * fix(emqx_conf): get the wrong core nodes * fix(emqx_conf): get core node's tnx_id not latest tnx_id * fix: add ro_transation when copy conf file * fix: delete debug info * fix: change ekka_rlog to mria_rlog * fix: remove cluster_rpc from emqx_machine. * fix: don't call ekka:start/0 explicitly * fix: ekka should be start in emqx_machine --- Makefile | 2 +- apps/emqx/src/emqx_app.erl | 22 ++-- apps/emqx/src/emqx_config.erl | 74 ++++++----- apps/emqx/src/emqx_config_handler.erl | 44 +++++-- apps/emqx/src/emqx_map_lib.erl | 2 +- apps/emqx/src/emqx_schema.erl | 2 +- apps/emqx/test/emqx_channel_SUITE.erl | 13 +- apps/emqx/test/emqx_common_test_helpers.erl | 19 ++- apps/emqx_authz/include/emqx_authz.hrl | 2 + apps/emqx_authz/src/emqx_authz.erl | 5 +- apps/emqx_authz/src/emqx_authz_app.erl | 1 + apps/emqx_authz/test/emqx_authz_SUITE.erl | 4 +- .../src/emqx_auto_subscribe.erl | 2 +- .../emqx_auto_subscribe_handler.erl | 2 +- .../test/emqx_auto_subscribe_SUITE.erl | 4 +- apps/emqx_bridge/src/emqx_bridge.erl | 6 +- apps/emqx_bridge/src/emqx_bridge_app.erl | 6 +- .../etc/emqx_conf.conf} | 20 +-- apps/emqx_conf/include/emqx_conf.hrl | 22 ++++ apps/emqx_conf/rebar.config | 7 + .../src/emqx_cluster_rpc.erl | 39 ++++-- .../src/emqx_cluster_rpc_handler.erl | 8 +- apps/emqx_conf/src/emqx_conf.app.src | 10 ++ apps/emqx_conf/src/emqx_conf.erl | 122 ++++++++++++++++++ apps/emqx_conf/src/emqx_conf_app.erl | 97 ++++++++++++++ .../src/emqx_conf_schema.erl} | 47 ++++--- apps/emqx_conf/src/emqx_conf_sup.erl | 48 +++++++ .../test/emqx_cluster_rpc_SUITE.erl | 17 +-- .../test/emqx_global_gc_SUITE.erl | 0 apps/emqx_dashboard/src/emqx_dashboard.erl | 2 +- .../src/emqx_dashboard_admin.erl | 2 +- .../src/emqx_dashboard_collection.erl | 4 +- .../src/emqx_dashboard_token.erl | 2 +- .../test/emqx_swagger_response_SUITE.erl | 2 +- apps/emqx_exhook/src/emqx_exhook_sup.erl | 2 +- .../src/coap/emqx_coap_channel.erl | 2 +- .../src/coap/emqx_coap_session.erl | 2 +- .../coap/handler/emqx_coap_pubsub_handler.erl | 4 +- apps/emqx_gateway/src/emqx_gateway_app.erl | 2 +- apps/emqx_gateway/src/emqx_gateway_conf.erl | 4 +- apps/emqx_machine/include/emqx_machine.hrl | 37 ------ .../src/emqx_global_gc.erl | 12 +- apps/emqx_machine/src/emqx_machine.erl | 15 +-- apps/emqx_machine/src/emqx_machine_boot.erl | 7 +- apps/emqx_machine/src/emqx_machine_sup.erl | 38 +----- .../src/emqx_mgmt_api_configs.erl | 10 +- .../src/emqx_mgmt_api_listeners.erl | 4 +- apps/emqx_modules/src/emqx_delayed.erl | 2 +- apps/emqx_modules/src/emqx_delayed_api.erl | 2 +- apps/emqx_modules/src/emqx_event_message.erl | 2 +- apps/emqx_modules/src/emqx_modules_app.erl | 12 +- apps/emqx_modules/src/emqx_rewrite.erl | 2 +- apps/emqx_modules/src/emqx_telemetry.erl | 2 +- apps/emqx_modules/src/emqx_topic_metrics.erl | 2 +- .../src/emqx_prometheus_app.erl | 4 +- apps/emqx_psk/src/emqx_psk.erl | 8 +- apps/emqx_retainer/src/emqx_retainer.erl | 6 +- .../emqx_rule_engine/src/emqx_rule_engine.erl | 2 +- .../src/emqx_rule_engine_app.erl | 4 +- .../test/emqx_rule_engine_SUITE.erl | 8 +- .../test/emqx_rule_engine_api_SUITE.erl | 7 +- .../test/emqx_rule_metrics_SUITE.erl | 4 +- apps/emqx_statsd/src/emqx_statsd_app.erl | 4 +- bin/emqx | 10 +- bin/emqx.cmd | 4 +- build | 4 +- rebar.config.erl | 3 +- scripts/merge-config.escript | 8 +- 68 files changed, 586 insertions(+), 312 deletions(-) rename apps/{emqx_machine/etc/emqx_machine.conf => emqx_conf/etc/emqx_conf.conf} (97%) create mode 100644 apps/emqx_conf/include/emqx_conf.hrl create mode 100644 apps/emqx_conf/rebar.config rename apps/{emqx_machine => emqx_conf}/src/emqx_cluster_rpc.erl (92%) rename apps/{emqx_machine => emqx_conf}/src/emqx_cluster_rpc_handler.erl (91%) create mode 100644 apps/emqx_conf/src/emqx_conf.app.src create mode 100644 apps/emqx_conf/src/emqx_conf.erl create mode 100644 apps/emqx_conf/src/emqx_conf_app.erl rename apps/{emqx_machine/src/emqx_machine_schema.erl => emqx_conf/src/emqx_conf_schema.erl} (95%) create mode 100644 apps/emqx_conf/src/emqx_conf_sup.erl rename apps/{emqx_machine => emqx_conf}/test/emqx_cluster_rpc_SUITE.erl (94%) rename apps/{emqx_machine => emqx_conf}/test/emqx_global_gc_SUITE.erl (100%) delete mode 100644 apps/emqx_machine/include/emqx_machine.hrl rename apps/{emqx => emqx_machine}/src/emqx_global_gc.erl (91%) diff --git a/Makefile b/Makefile index 83fa2f15b..50cdcb99d 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ proper: $(REBAR) @ENABLE_COVER_COMPILE=1 $(REBAR) proper -d test/props -c .PHONY: ct -ct: $(REBAR) +ct: $(REBAR) conf-segs @ENABLE_COVER_COMPILE=1 $(REBAR) ct --name 'test@127.0.0.1' -c -v APPS=$(shell $(CURDIR)/scripts/find-apps.sh) diff --git a/apps/emqx/src/emqx_app.erl b/apps/emqx/src/emqx_app.erl index 504b245f3..9091304fc 100644 --- a/apps/emqx/src/emqx_app.erl +++ b/apps/emqx/src/emqx_app.erl @@ -25,7 +25,8 @@ , get_release/0 , set_init_config_load_done/0 , get_init_config_load_done/0 - , set_override_conf_file/1 + , set_init_tnx_id/1 + , get_init_tnx_id/0 ]). -include("emqx.hrl"). @@ -67,21 +68,16 @@ set_init_config_load_done() -> get_init_config_load_done() -> application:get_env(emqx, init_config_load_done, false). -%% @doc This API is mostly for testing. -%% The override config file is typically located in the 'data' dir when -%% it is a emqx release, but emqx app should not have to know where the -%% 'data' dir is located. -set_override_conf_file(File) -> - application:set_env(emqx, override_conf_file, File). +set_init_tnx_id(TnxId) -> + application:set_env(emqx, cluster_rpc_init_tnx_id, TnxId). + +get_init_tnx_id() -> + application:get_env(emqx, cluster_rpc_init_tnx_id, -1). maybe_load_config() -> case get_init_config_load_done() of - true -> - ok; - false -> - %% the app env 'config_files' should be set before emqx get started. - ConfFiles = application:get_env(emqx, config_files, []), - emqx_config:init_load(emqx_schema, ConfFiles) + true -> ok; + false -> emqx_config:init_load(emqx_schema) end. maybe_start_listeners() -> diff --git a/apps/emqx/src/emqx_config.erl b/apps/emqx/src/emqx_config.erl index 05dd3d122..8202d5a6a 100644 --- a/apps/emqx/src/emqx_config.erl +++ b/apps/emqx/src/emqx_config.erl @@ -15,17 +15,18 @@ %%-------------------------------------------------------------------- -module(emqx_config). --compile({no_auto_import, [get/0, get/1, put/2]}). +-compile({no_auto_import, [get/0, get/1, put/2, erase/1]}). --export([ init_load/2 - , read_override_conf/0 +-export([ init_load/1 + , init_load/2 + , read_override_conf/1 , check_config/2 , fill_defaults/1 , fill_defaults/2 - , save_configs/4 + , save_configs/5 , save_to_app_env/1 , save_to_config_map/2 - , save_to_override_conf/1 + , save_to_override_conf/2 ]). -export([ get_root/1 @@ -41,6 +42,7 @@ , find_raw/1 , put/1 , put/2 + , erase/1 ]). -export([ get_raw/1 @@ -96,7 +98,8 @@ %% persistent: %% save the updated config to the emqx_override.conf file %% defaults to `true` - persistent => boolean() + persistent => boolean(), + override_to => local | cluster }. -type update_args() :: {update_cmd(), Opts :: update_opts()}. -type update_stage() :: pre_config_update | post_config_update. @@ -199,6 +202,10 @@ put(Config) -> ?MODULE:put([RootName], RootValue) end, ok, Config). +erase(RootName) -> + persistent_term:erase(?PERSIS_KEY(?CONF, bin(RootName))), + persistent_term:erase(?PERSIS_KEY(?RAW_CONF, bin(RootName))). + -spec put(emqx_map_lib:config_key_path(), term()) -> ok. put(KeyPath, Config) -> do_put(?CONF, KeyPath, Config). @@ -237,13 +244,17 @@ put_raw(KeyPath, Config) -> do_put(?RAW_CONF, KeyPath, Config). %%============================================================================ %% Load/Update configs From/To files %%============================================================================ +init_load(SchemaMod) -> + ConfFiles = application:get_env(emqx, config_files, []), + init_load(SchemaMod, ConfFiles). %% @doc Initial load of the given config files. %% NOTE: The order of the files is significant, configs from files orderd %% in the rear of the list overrides prior values. -spec init_load(module(), [string()] | binary() | hocon:config()) -> ok. init_load(SchemaMod, Conf) when is_list(Conf) orelse is_binary(Conf) -> - ParseOptions = #{format => map}, + IncDir = include_dirs(), + ParseOptions = #{format => map, include_dirs => IncDir}, Parser = case is_binary(Conf) of true -> fun hocon:binary/2; false -> fun hocon:files/2 @@ -253,21 +264,20 @@ init_load(SchemaMod, Conf) when is_list(Conf) orelse is_binary(Conf) -> init_load(SchemaMod, RawRichConf); {error, Reason} -> ?SLOG(error, #{msg => failed_to_load_hocon_conf, - reason => Reason + reason => Reason, + include_dirs => IncDir }), error(failed_to_load_hocon_conf) end; init_load(SchemaMod, RawConf0) when is_map(RawConf0) -> ok = save_schema_mod_and_names(SchemaMod), - %% override part of the input conf using emqx_override.conf - RawConf = merge_with_override_conf(RawConf0), %% check and save configs - {_AppEnvs, CheckedConf} = check_config(SchemaMod, RawConf), + {_AppEnvs, CheckedConf} = check_config(SchemaMod, RawConf0), ok = save_to_config_map(maps:with(get_atom_root_names(), CheckedConf), - maps:with(get_root_names(), RawConf)). + maps:with(get_root_names(), RawConf0)). -merge_with_override_conf(RawConf) -> - maps:merge(RawConf, maps:with(maps:keys(RawConf), read_override_conf())). +include_dirs() -> + [filename:join(application:get_env(emqx, data_dir, "data/"), "configs") ++ "/"]. -spec check_config(module(), raw_config()) -> {AppEnvs, CheckedConf} when AppEnvs :: app_envs(), CheckedConf :: config(). @@ -299,9 +309,18 @@ fill_defaults(SchemaMod, RawConf) -> #{nullable => true, only_fill_defaults => true}, root_names_from_conf(RawConf)). --spec read_override_conf() -> raw_config(). -read_override_conf() -> - load_hocon_file(emqx_override_conf_name(), map). +-spec read_override_conf(map()) -> raw_config(). +read_override_conf(#{} = Opts) -> + File = override_conf_file(Opts), + load_hocon_file(File, map). + +override_conf_file(Opts) -> + Key = + case maps:get(override_to, Opts, local) of + local -> local_override_conf_file; + cluster -> cluster_override_conf_file + end, + application:get_env(emqx, Key, undefined). -spec save_schema_mod_and_names(module()) -> ok. save_schema_mod_and_names(SchemaMod) -> @@ -330,14 +349,13 @@ get_root_names() -> get_atom_root_names() -> [atom(N) || N <- get_root_names()]. --spec save_configs(app_envs(), config(), raw_config(), raw_config()) -> ok | {error, term()}. -save_configs(_AppEnvs, Conf, RawConf, OverrideConf) -> +-spec save_configs(app_envs(), config(), raw_config(), raw_config(), update_opts()) -> ok | {error, term()}. +save_configs(_AppEnvs, Conf, RawConf, OverrideConf, Opts) -> %% We may need also support hot config update for the apps that use application envs. %% If that is the case uncomment the following line to update the configs to app env %save_to_app_env(AppEnvs), save_to_config_map(Conf, RawConf), - %% TODO: merge RawConf to OverrideConf can be done here - save_to_override_conf(OverrideConf). + save_to_override_conf(OverrideConf, Opts). -spec save_to_app_env([tuple()]) -> ok. save_to_app_env(AppEnvs) -> @@ -350,11 +368,11 @@ save_to_config_map(Conf, RawConf) -> ?MODULE:put(Conf), ?MODULE:put_raw(RawConf). --spec save_to_override_conf(raw_config()) -> ok | {error, term()}. -save_to_override_conf(undefined) -> +-spec save_to_override_conf(raw_config(), update_opts()) -> ok | {error, term()}. +save_to_override_conf(undefined, _) -> ok; -save_to_override_conf(RawConf) -> - case emqx_override_conf_name() of +save_to_override_conf(RawConf, Opts) -> + case override_conf_file(Opts) of undefined -> ok; FileName -> ok = filelib:ensure_dir(FileName), @@ -371,14 +389,12 @@ save_to_override_conf(RawConf) -> load_hocon_file(FileName, LoadType) -> case filelib:is_regular(FileName) of true -> - {ok, Raw0} = hocon:load(FileName, #{format => LoadType}), + Opts = #{include_dirs => include_dirs(), format => LoadType}, + {ok, Raw0} = hocon:load(FileName, Opts), Raw0; false -> #{} end. -emqx_override_conf_name() -> - application:get_env(emqx, override_conf_file, undefined). - do_get(Type, KeyPath) -> Ref = make_ref(), Res = do_get(Type, KeyPath, Ref), diff --git a/apps/emqx/src/emqx_config_handler.erl b/apps/emqx/src/emqx_config_handler.erl index c44a0cb96..c75f0ee4d 100644 --- a/apps/emqx/src/emqx_config_handler.erl +++ b/apps/emqx/src/emqx_config_handler.erl @@ -27,6 +27,7 @@ , add_handler/2 , remove_handler/1 , update_config/3 + , get_raw_cluster_override_conf/0 , merge_to_old_config/2 ]). @@ -82,6 +83,9 @@ add_handler(ConfKeyPath, HandlerName) -> remove_handler(ConfKeyPath) -> gen_server:cast(?MODULE, {remove_handler, ConfKeyPath}). +get_raw_cluster_override_conf() -> + gen_server:call(?MODULE, get_raw_cluster_override_conf). + %%============================================================================ -spec init(term()) -> {ok, state()}. @@ -100,9 +104,9 @@ handle_call({change_config, SchemaModule, ConfKeyPath, UpdateArgs}, _From, #{handlers := Handlers} = State) -> Reply = try case process_update_request(ConfKeyPath, Handlers, UpdateArgs) of - {ok, NewRawConf, OverrideConf} -> + {ok, NewRawConf, OverrideConf, Opts} -> check_and_save_configs(SchemaModule, ConfKeyPath, Handlers, NewRawConf, - OverrideConf, UpdateArgs); + OverrideConf, UpdateArgs, Opts); {error, Result} -> {error, Result} end @@ -116,7 +120,9 @@ handle_call({change_config, SchemaModule, ConfKeyPath, UpdateArgs}, _From, {error, Reason} end, {reply, Reply, State}; - +handle_call(get_raw_cluster_override_conf, _From, State) -> + Reply = emqx_config:read_override_conf(#{override_to => cluster}), + {reply, Reply, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. @@ -163,14 +169,15 @@ process_update_request(ConfKeyPath, _Handlers, {remove, Opts}) -> OldRawConf = emqx_config:get_root_raw(ConfKeyPath), BinKeyPath = bin_path(ConfKeyPath), NewRawConf = emqx_map_lib:deep_remove(BinKeyPath, OldRawConf), + _ = remove_from_local_if_cluster_change(BinKeyPath, Opts), OverrideConf = remove_from_override_config(BinKeyPath, Opts), - {ok, NewRawConf, OverrideConf}; + {ok, NewRawConf, OverrideConf, Opts}; process_update_request(ConfKeyPath, Handlers, {{update, UpdateReq}, Opts}) -> OldRawConf = emqx_config:get_root_raw(ConfKeyPath), case do_update_config(ConfKeyPath, Handlers, OldRawConf, UpdateReq) of {ok, NewRawConf} -> OverrideConf = update_override_config(NewRawConf, Opts), - {ok, NewRawConf, OverrideConf}; + {ok, NewRawConf, OverrideConf, Opts}; Error -> Error end. @@ -187,15 +194,16 @@ do_update_config([ConfKey | ConfKeyPath], Handlers, OldRawConf, UpdateReq) -> end. check_and_save_configs(SchemaModule, ConfKeyPath, Handlers, NewRawConf, OverrideConf, - UpdateArgs) -> + UpdateArgs, Opts) -> OldConf = emqx_config:get_root(ConfKeyPath), FullRawConf = with_full_raw_confs(NewRawConf), {AppEnvs, CheckedConf} = emqx_config:check_config(SchemaModule, FullRawConf), NewConf = maps:with(maps:keys(OldConf), CheckedConf), + _ = remove_from_local_if_cluster_change(ConfKeyPath, Opts), case do_post_config_update(ConfKeyPath, Handlers, OldConf, NewConf, AppEnvs, UpdateArgs, #{}) of {ok, Result0} -> case save_configs(ConfKeyPath, AppEnvs, NewConf, NewRawConf, OverrideConf, - UpdateArgs) of + UpdateArgs, Opts) of {ok, Result1} -> {ok, Result1#{post_config_update => Result0}}; Error -> Error @@ -253,8 +261,8 @@ call_post_config_update(Handlers, OldConf, NewConf, AppEnvs, UpdateReq, Result) false -> {ok, Result} end. -save_configs(ConfKeyPath, AppEnvs, CheckedConf, NewRawConf, OverrideConf, UpdateArgs) -> - case emqx_config:save_configs(AppEnvs, CheckedConf, NewRawConf, OverrideConf) of +save_configs(ConfKeyPath, AppEnvs, CheckedConf, NewRawConf, OverrideConf, UpdateArgs, Opts) -> + case emqx_config:save_configs(AppEnvs, CheckedConf, NewRawConf, OverrideConf, Opts) of ok -> {ok, return_change_result(ConfKeyPath, UpdateArgs)}; {error, Reason} -> {error, {save_configs, Reason}} end. @@ -269,16 +277,26 @@ merge_to_old_config(UpdateReq, RawConf) when is_map(UpdateReq), is_map(RawConf) merge_to_old_config(UpdateReq, _RawConf) -> {ok, UpdateReq}. +%% local-override.conf priority is higher than cluster-override.conf +%% If we want cluster to take effect, we must remove the local. +remove_from_local_if_cluster_change(BinKeyPath, Opts) -> + case maps:get(override, Opts, local) of + local -> ok; + cluster -> + Local = remove_from_override_config(BinKeyPath, Opts#{override_to => local}), + emqx_config:save_to_override_conf(Local, Opts) + end. + remove_from_override_config(_BinKeyPath, #{persistent := false}) -> undefined; -remove_from_override_config(BinKeyPath, _Opts) -> - OldConf = emqx_config:read_override_conf(), +remove_from_override_config(BinKeyPath, Opts) -> + OldConf = emqx_config:read_override_conf(Opts), emqx_map_lib:deep_remove(BinKeyPath, OldConf). update_override_config(_RawConf, #{persistent := false}) -> undefined; -update_override_config(RawConf, _Opts) -> - OldConf = emqx_config:read_override_conf(), +update_override_config(RawConf, Opts) -> + OldConf = emqx_config:read_override_conf(Opts), maps:merge(OldConf, RawConf). up_req({remove, _Opts}) -> '$remove'; diff --git a/apps/emqx/src/emqx_map_lib.erl b/apps/emqx/src/emqx_map_lib.erl index 6aa6606c0..729c5f13d 100644 --- a/apps/emqx/src/emqx_map_lib.erl +++ b/apps/emqx/src/emqx_map_lib.erl @@ -31,7 +31,7 @@ ]). -export_type([config_key/0, config_key_path/0]). --type config_key() :: atom() | binary(). +-type config_key() :: atom() | binary() | string(). -type config_key_path() :: [config_key()]. -type convert_fun() :: fun((...) -> {K1::any(), V1::any()} | drop). diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 5958167cd..118cea5df 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -135,7 +135,7 @@ roots(low) -> , {"quota", sc(ref("quota"), #{})} - , {"plugins", %% TODO: move to emqx_machine_schema + , {"plugins", %% TODO: move to emqx_conf_schema sc(ref("plugins"), #{})} , {"stats", diff --git a/apps/emqx/test/emqx_channel_SUITE.erl b/apps/emqx/test/emqx_channel_SUITE.erl index 2b9051de0..10e7db9cf 100644 --- a/apps/emqx/test/emqx_channel_SUITE.erl +++ b/apps/emqx/test/emqx_channel_SUITE.erl @@ -22,6 +22,7 @@ -include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). +-include_lib("common_test/include/ct.hrl"). all() -> @@ -132,7 +133,9 @@ basic_conf() -> }. set_test_listenser_confs() -> - emqx_config:put(basic_conf()). + Conf = emqx_config:get([]), + emqx_config:put(basic_conf()), + Conf. %%-------------------------------------------------------------------- %% CT Callbacks @@ -174,10 +177,11 @@ end_per_suite(_Config) -> ]). init_per_testcase(_TestCase, Config) -> - set_test_listenser_confs(), - Config. + NewConf = set_test_listenser_confs(), + [{config, NewConf}|Config]. end_per_testcase(_TestCase, Config) -> + emqx_config:put(?config(config, Config)), Config. %%-------------------------------------------------------------------- @@ -283,7 +287,7 @@ t_handle_in_re_auth(_) -> ?AUTH_PACKET(?RC_RE_AUTHENTICATE,Properties), channel(#{conninfo => #{proto_ver => ?MQTT_PROTO_V5, conn_props => undefined}}) ), - + Channel1 = channel(), ConnInfo = emqx_channel:info(conninfo, Channel1), Channel2 = emqx_channel:set_field(conninfo, ConnInfo#{conn_props => Properties}, Channel1), @@ -953,4 +957,3 @@ session(InitFields) when is_map(InitFields) -> quota() -> emqx_limiter:init(zone, [{conn_messages_routing, {5, 1}}, {overall_messages_routing, {10, 1}}]). - diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index f9cc2d0b0..127a0892c 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -146,9 +146,13 @@ load(App) -> start_app(App, Handler) -> start_app(App, app_schema(App), - app_path(App, filename:join(["etc", atom_to_list(App) ++ ".conf"])), + app_path(App, filename:join(["etc", app_conf_file(App)])), Handler). +app_conf_file(emqx_conf) -> "emqx.conf.all"; +app_conf_file(App) -> atom_to_list(App) ++ ".conf". + +%% TODO: get rid of cuttlefish app_schema(App) -> Mod = list_to_atom(atom_to_list(App) ++ "_schema"), true = is_list(Mod:roots()), @@ -166,6 +170,7 @@ start_app(App, Schema, ConfigFile, SpecAppConfig) -> RenderedConfigFile = render_config_file(ConfigFile, Vars), read_schema_configs(Schema, RenderedConfigFile), force_set_config_file_paths(App, [RenderedConfigFile]), + copy_certs(App, RenderedConfigFile), SpecAppConfig(App), case application:ensure_all_started(App) of {ok, _} -> ok; @@ -288,7 +293,7 @@ change_emqx_opts(SslType, MoreOpts) -> lists:map(fun(Listener) -> maybe_inject_listener_ssl_options(SslType, MoreOpts, Listener) end, Listeners), - application:set_env(emqx, listeners, NewListeners). + emqx_conf:update([listeners], NewListeners, #{}). maybe_inject_listener_ssl_options(SslType, MoreOpts, {sll, Port, Opts}) -> %% this clause is kept to be backward compatible @@ -409,8 +414,16 @@ catch_call(F) -> C : E : S -> {crashed, {C, E, S}} end. - +force_set_config_file_paths(emqx_conf, Paths) -> + application:set_env(emqx, config_files, Paths); force_set_config_file_paths(emqx, Paths) -> application:set_env(emqx, config_files, Paths); force_set_config_file_paths(_, _) -> ok. + +copy_certs(emqx_conf, Dest0) -> + Dest = filename:dirname(Dest0), + From = string:replace(Dest, "emqx_conf", "emqx"), + os:cmd( ["cp -rf ", From, "/certs ", Dest, "/"]), + ok; +copy_certs(_, _) -> ok. diff --git a/apps/emqx_authz/include/emqx_authz.hrl b/apps/emqx_authz/include/emqx_authz.hrl index fe4514614..c22b93c48 100644 --- a/apps/emqx_authz/include/emqx_authz.hrl +++ b/apps/emqx_authz/include/emqx_authz.hrl @@ -65,3 +65,5 @@ -define(AUTHZ_METRICS, ?METRICS(authz_metrics)). -define(AUTHZ_METRICS(K), ?METRICS(authz_metrics, K)). + +-define(CONF_KEY_PATH, [authorization, sources]). diff --git a/apps/emqx_authz/src/emqx_authz.erl b/apps/emqx_authz/src/emqx_authz.erl index ab49eb894..49570b8fe 100644 --- a/apps/emqx_authz/src/emqx_authz.erl +++ b/apps/emqx_authz/src/emqx_authz.erl @@ -38,7 +38,6 @@ -export([post_config_update/4, pre_config_update/2]). --define(CONF_KEY_PATH, [authorization, sources]). -spec(register_metrics() -> ok). register_metrics() -> @@ -46,8 +45,8 @@ register_metrics() -> init() -> ok = register_metrics(), - emqx_config_handler:add_handler(?CONF_KEY_PATH, ?MODULE), - Sources = emqx:get_config(?CONF_KEY_PATH, []), + emqx_conf:add_handler(?CONF_KEY_PATH, ?MODULE), + Sources = emqx_conf:get(?CONF_KEY_PATH, []), ok = check_dup_types(Sources), NSources = init_sources(Sources), ok = emqx_hooks:add('client.authorize', {?MODULE, authorize, [NSources]}, -1). diff --git a/apps/emqx_authz/src/emqx_authz_app.erl b/apps/emqx_authz/src/emqx_authz_app.erl index a5044443b..5874d5733 100644 --- a/apps/emqx_authz/src/emqx_authz_app.erl +++ b/apps/emqx_authz/src/emqx_authz_app.erl @@ -18,6 +18,7 @@ start(_StartType, _StartArgs) -> {ok, Sup}. stop(_State) -> + emqx_conf:remove_handler(?CONF_KEY_PATH), ok. %% internal functions diff --git a/apps/emqx_authz/test/emqx_authz_SUITE.erl b/apps/emqx_authz/test/emqx_authz_SUITE.erl index fd22bbc7a..d7df8eaa0 100644 --- a/apps/emqx_authz/test/emqx_authz_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_SUITE.erl @@ -133,7 +133,7 @@ t_update_source(_) -> , #{type := postgresql, enable := true} , #{type := redis, enable := true} , #{type := file, enable := true} - ], emqx:get_config([authorization, sources], [])), + ], emqx_conf:get([authorization, sources], [])), {ok, _} = emqx_authz:update({?CMD_REPLACE, http}, ?SOURCE1#{<<"enable">> := false}), {ok, _} = emqx_authz:update({?CMD_REPLACE, mongodb}, ?SOURCE2#{<<"enable">> := false}), @@ -148,7 +148,7 @@ t_update_source(_) -> , #{type := postgresql, enable := false} , #{type := redis, enable := false} , #{type := file, enable := false} - ], emqx:get_config([authorization, sources], [])), + ], emqx_conf:get([authorization, sources], [])), {ok, _} = emqx_authz:update(?CMD_REPLACE, []). diff --git a/apps/emqx_auto_subscribe/src/emqx_auto_subscribe.erl b/apps/emqx_auto_subscribe/src/emqx_auto_subscribe.erl index 56bbf3a1c..558e5005c 100644 --- a/apps/emqx_auto_subscribe/src/emqx_auto_subscribe.erl +++ b/apps/emqx_auto_subscribe/src/emqx_auto_subscribe.erl @@ -38,7 +38,7 @@ max_limit() -> ?MAX_AUTO_SUBSCRIBE. list() -> - format(emqx:get_config([auto_subscribe, topics], [])). + format(emqx_conf:get([auto_subscribe, topics], [])). update(Topics) -> update_(Topics). diff --git a/apps/emqx_auto_subscribe/src/topics_handler/emqx_auto_subscribe_handler.erl b/apps/emqx_auto_subscribe/src/topics_handler/emqx_auto_subscribe_handler.erl index 8e541eaec..b2b5f4473 100644 --- a/apps/emqx_auto_subscribe/src/topics_handler/emqx_auto_subscribe_handler.erl +++ b/apps/emqx_auto_subscribe/src/topics_handler/emqx_auto_subscribe_handler.erl @@ -19,7 +19,7 @@ -spec(init() -> {Module :: atom(), Config :: term()}). init() -> - do_init(emqx:get_config([auto_subscribe], #{})). + do_init(emqx_conf:get([auto_subscribe], #{})). do_init(Config = #{topics := _Topics}) -> Options = emqx_auto_subscribe_internal:init(Config), diff --git a/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl b/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl index 744267e74..0e5022533 100644 --- a/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl +++ b/apps/emqx_auto_subscribe/test/emqx_auto_subscribe_SUITE.erl @@ -44,7 +44,6 @@ all() -> init_per_suite(Config) -> mria:start(), application:stop(?APP), - meck:new(emqx_schema, [non_strict, passthrough, no_history, no_link]), meck:expect(emqx_schema, fields, fun("auto_subscribe") -> meck:passthrough(["auto_subscribe"]) ++ @@ -86,8 +85,7 @@ init_per_suite(Config) -> } ] }">>), - emqx_common_test_helpers:start_apps([emqx_dashboard], fun set_special_configs/1), - emqx_common_test_helpers:start_apps([?APP]), + emqx_common_test_helpers:start_apps([emqx_dashboard, ?APP], fun set_special_configs/1), Config. set_special_configs(emqx_dashboard) -> diff --git a/apps/emqx_bridge/src/emqx_bridge.erl b/apps/emqx_bridge/src/emqx_bridge.erl index 351e6aeca..c07a5b842 100644 --- a/apps/emqx_bridge/src/emqx_bridge.erl +++ b/apps/emqx_bridge/src/emqx_bridge.erl @@ -51,7 +51,7 @@ reload_hook() -> unload_hook(), - Bridges = emqx:get_config([bridges], #{}), + Bridges = emqx_conf:get([bridges], #{}), lists:foreach(fun({_Type, Bridge}) -> lists:foreach(fun({_Name, BridgeConf}) -> load_hook(BridgeConf) @@ -124,7 +124,7 @@ perform_bridge_changes([{Action, MapConfs} | Tasks], Result0) -> perform_bridge_changes(Tasks, Result). load_bridges() -> - Bridges = emqx:get_config([bridges], #{}), + Bridges = emqx_conf:get([bridges], #{}), emqx_bridge_monitor:ensure_all_started(Bridges). resource_id(BridgeId) when is_binary(BridgeId) -> @@ -244,7 +244,7 @@ has_subscribe_local_topic(Channels) -> end, maps:to_list(Channels)). get_matched_channels(Topic) -> - Bridges = emqx:get_config([bridges], #{}), + Bridges = emqx_conf:get([bridges], #{}), maps:fold(fun %% TODO: also trigger 'message.publish' for mqtt bridges. (mqtt, _Conf, Acc0) -> Acc0; diff --git a/apps/emqx_bridge/src/emqx_bridge_app.erl b/apps/emqx_bridge/src/emqx_bridge_app.erl index 2f3601646..3fa8f12dd 100644 --- a/apps/emqx_bridge/src/emqx_bridge_app.erl +++ b/apps/emqx_bridge/src/emqx_bridge_app.erl @@ -23,12 +23,12 @@ start(_StartType, _StartArgs) -> {ok, Sup} = emqx_bridge_sup:start_link(), ok = emqx_bridge:load_bridges(), ok = emqx_bridge:reload_hook(), - emqx_config_handler:add_handler(emqx_bridge:config_key_path(), emqx_bridge), + emqx_conf:add_handler(emqx_bridge:config_key_path(), emqx_bridge), {ok, Sup}. stop(_State) -> - emqx_config_handler:remove_handler(emqx_bridge:config_key_path()), + emqx_conf:remove_handler(emqx_bridge:config_key_path()), ok = emqx_bridge:unload_hook(), ok. -%% internal functions \ No newline at end of file +%% internal functions diff --git a/apps/emqx_machine/etc/emqx_machine.conf b/apps/emqx_conf/etc/emqx_conf.conf similarity index 97% rename from apps/emqx_machine/etc/emqx_machine.conf rename to apps/emqx_conf/etc/emqx_conf.conf index eeab91154..fcb7a2947 100644 --- a/apps/emqx_machine/etc/emqx_machine.conf +++ b/apps/emqx_conf/etc/emqx_conf.conf @@ -93,28 +93,10 @@ node { backtrace_depth = 23 cluster_call { - ## Time interval to retry after a failed call - ## - ## @doc node.cluster_call.retry_interval - ## ValueType: Duration - ## Default: 1s retry_interval = 1s - ## Retain the maximum number of completed transactions (for queries) - ## - ## @doc node.cluster_call.max_history - ## ValueType: Integer - ## Range: [1, 500] - ## Default: 100 max_history = 100 - ## Time interval to clear completed but stale transactions. - ## Ensure that the number of completed transactions is less than the max_history - ## - ## @doc node.cluster_call.cleanup_interval - ## ValueType: Duration - ## Default: 5m cleanup_interval = 5m - } - + } } ##================================================================== diff --git a/apps/emqx_conf/include/emqx_conf.hrl b/apps/emqx_conf/include/emqx_conf.hrl new file mode 100644 index 000000000..82ad8264d --- /dev/null +++ b/apps/emqx_conf/include/emqx_conf.hrl @@ -0,0 +1,22 @@ + +-ifndef(EMQ_X_CONF_HRL). +-define(EMQ_X_CONF_HRL, true). + +-define(CLUSTER_RPC_SHARD, emqx_cluster_rpc_shard). + +-define(CLUSTER_MFA, cluster_rpc_mfa). +-define(CLUSTER_COMMIT, cluster_rpc_commit). + +-record(cluster_rpc_mfa, { + tnx_id :: pos_integer(), + mfa :: mfa(), + created_at :: calendar:datetime(), + initiator :: node() +}). + +-record(cluster_rpc_commit, { + node :: node(), + tnx_id :: pos_integer() | '$1' +}). + +-endif. diff --git a/apps/emqx_conf/rebar.config b/apps/emqx_conf/rebar.config new file mode 100644 index 000000000..e0456112b --- /dev/null +++ b/apps/emqx_conf/rebar.config @@ -0,0 +1,7 @@ +{erl_opts, [debug_info]}. +{deps, []}. + +{shell, [ + % {config, "config/sys.config"}, + {apps, [emqx_conf]} +]}. diff --git a/apps/emqx_machine/src/emqx_cluster_rpc.erl b/apps/emqx_conf/src/emqx_cluster_rpc.erl similarity index 92% rename from apps/emqx_machine/src/emqx_cluster_rpc.erl rename to apps/emqx_conf/src/emqx_cluster_rpc.erl index 479561206..4187b35aa 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc.erl +++ b/apps/emqx_conf/src/emqx_cluster_rpc.erl @@ -19,6 +19,7 @@ %% API -export([start_link/0, mnesia/1]). -export([multicall/3, multicall/5, query/1, reset/0, status/0, skip_failed_commit/1]). +-export([get_node_tnx_id/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, handle_continue/2, code_change/3]). @@ -26,13 +27,12 @@ -ifdef(TEST). -compile(export_all). -compile(nowarn_export_all). --export([start_link/3]). -endif. -boot_mnesia({mnesia, [boot]}). -include_lib("emqx/include/logger.hrl"). --include("emqx_machine.hrl"). +-include("emqx_conf.hrl"). -define(CATCH_UP, catch_up). -define(TIMEOUT, timer:minutes(1)). @@ -43,13 +43,13 @@ mnesia(boot) -> ok = mria:create_table(?CLUSTER_MFA, [ {type, ordered_set}, - {rlog_shard, ?EMQX_MACHINE_SHARD}, + {rlog_shard, ?CLUSTER_RPC_SHARD}, {storage, disc_copies}, {record_name, cluster_rpc_mfa}, {attributes, record_info(fields, cluster_rpc_mfa)}]), ok = mria:create_table(?CLUSTER_COMMIT, [ {type, set}, - {rlog_shard, ?EMQX_MACHINE_SHARD}, + {rlog_shard, ?CLUSTER_RPC_SHARD}, {storage, disc_copies}, {record_name, cluster_rpc_commit}, {attributes, record_info(fields, cluster_rpc_commit)}]). @@ -87,7 +87,7 @@ multicall(M, F, A, RequireNum, Timeout) when RequireNum =:= all orelse RequireNu %% the initiate transaction must happened on core node %% make sure MFA(in the transaction) and the transaction on the same node %% don't need rpc again inside transaction. - case mria_status:upstream_node(?EMQX_MACHINE_SHARD) of + case mria_status:upstream_node(?CLUSTER_RPC_SHARD) of {ok, Node} -> gen_server:call({?MODULE, Node}, MFA, Timeout); disconnected -> {error, disconnected} end @@ -122,6 +122,13 @@ reset() -> gen_server:call(?MODULE, reset). status() -> transaction(fun trans_status/0, []). +-spec get_node_tnx_id(node()) -> integer(). +get_node_tnx_id(Node) -> + case mnesia:wread({?CLUSTER_COMMIT, Node}) of + [] -> -1; + [#cluster_rpc_commit{tnx_id = TnxId}] -> TnxId + end. + %% Regardless of what MFA is returned, consider it a success), %% then move to the next tnxId. %% if the next TnxId failed, need call the function again to skip. @@ -135,9 +142,12 @@ skip_failed_commit(Node) -> %% @private init([Node, RetryMs]) -> - _ = mria:wait_for_tables([?CLUSTER_MFA]), + _ = mria:wait_for_tables([?CLUSTER_MFA, ?CLUSTER_COMMIT]), {ok, _} = mnesia:subscribe({table, ?CLUSTER_MFA, simple}), - {ok, #{node => Node, retry_interval => RetryMs}, {continue, ?CATCH_UP}}. + State = #{node => Node, retry_interval => RetryMs}, + TnxId = emqx_app:get_init_tnx_id(), + ok = maybe_init_tnx_id(Node, TnxId), + {ok, State, {continue, ?CATCH_UP}}. %% @private handle_continue(?CATCH_UP, State) -> @@ -274,7 +284,7 @@ do_catch_up_in_one_trans(LatestId, Node) -> end. transaction(Func, Args) -> - mria:transaction(?EMQX_MACHINE_SHARD, Func, Args). + mria:transaction(?CLUSTER_RPC_SHARD, Func, Args). trans_status() -> mnesia:foldl(fun(Rec, Acc) -> @@ -363,4 +373,15 @@ commit_status_trans(Operator, TnxId) -> mnesia:select(?CLUSTER_COMMIT, [{MatchHead, [Guard], [Result]}]). get_retry_ms() -> - application:get_env(emqx_machine, cluster_call_retry_interval, 1000). + emqx_conf:get(["node", "cluster_call", "retry_interval"], 1000). + +maybe_init_tnx_id(_Node, TnxId)when TnxId < 0 -> ok; +maybe_init_tnx_id(Node, TnxId) -> + {atomic, _} = transaction(fun init_node_tnx_id/2, [Node, TnxId]), + ok. + +init_node_tnx_id(Node, TnxId) -> + case mnesia:read(?CLUSTER_COMMIT, Node) of + [] -> commit(Node, TnxId); + _ -> ok + end. diff --git a/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl b/apps/emqx_conf/src/emqx_cluster_rpc_handler.erl similarity index 91% rename from apps/emqx_machine/src/emqx_cluster_rpc_handler.erl rename to apps/emqx_conf/src/emqx_cluster_rpc_handler.erl index 2b1242fa7..ab2b24d27 100644 --- a/apps/emqx_machine/src/emqx_cluster_rpc_handler.erl +++ b/apps/emqx_conf/src/emqx_cluster_rpc_handler.erl @@ -18,15 +18,15 @@ -behaviour(gen_server). -include_lib("emqx/include/logger.hrl"). --include("emqx_machine.hrl"). +-include("emqx_conf.hrl"). -export([start_link/0, start_link/2]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link() -> - MaxHistory = application:get_env(emqx_machine, cluster_call_max_history, 100), - CleanupMs = application:get_env(emqx_machine, cluster_call_cleanup_interval, 5*60*1000), + MaxHistory = emqx_conf:get(["node", "cluster_call", "max_history"], 100), + CleanupMs = emqx_conf:get(["node", "cluster_call", "cleanup_interval"], 5*60*1000), start_link(MaxHistory, CleanupMs). start_link(MaxHistory, CleanupMs) -> @@ -49,7 +49,7 @@ handle_cast(Msg, State) -> {noreply, State}. handle_info({timeout, TRef, del_stale_mfa}, State = #{timer := TRef, max_history := MaxHistory}) -> - case mria:transaction(?EMQX_MACHINE_SHARD, fun del_stale_mfa/1, [MaxHistory]) of + case mria:transaction(?CLUSTER_RPC_SHARD, fun del_stale_mfa/1, [MaxHistory]) of {atomic, ok} -> ok; Error -> ?LOG(error, "del_stale_cluster_rpc_mfa error:~p", [Error]) end, diff --git a/apps/emqx_conf/src/emqx_conf.app.src b/apps/emqx_conf/src/emqx_conf.app.src new file mode 100644 index 000000000..563c9dc1d --- /dev/null +++ b/apps/emqx_conf/src/emqx_conf.app.src @@ -0,0 +1,10 @@ +{application, emqx_conf, + [{description, "EMQX configuration management"}, + {vsn, "0.1.0"}, + {registered, []}, + {mod, {emqx_conf_app, []}}, + {included_applications, [hocon]}, + {applications, [kernel, stdlib]}, + {env, []}, + {modules, []} + ]}. diff --git a/apps/emqx_conf/src/emqx_conf.erl b/apps/emqx_conf/src/emqx_conf.erl new file mode 100644 index 000000000..3ce3aa52b --- /dev/null +++ b/apps/emqx_conf/src/emqx_conf.erl @@ -0,0 +1,122 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- +-module(emqx_conf). + +-compile({no_auto_import, [get/1, get/2]}). + +-export([add_handler/2, remove_handler/1]). +-export([get/1, get/2, get_all/1]). +-export([get_by_node/2, get_by_node/3]). +-export([update/3, update/4]). +-export([remove/2, remove/3]). +-export([reset/2, reset/3]). + +%% for rpc +-export([get_node_and_config/1]). + +%% API +%% @doc Adds a new config handler to emqx_config_handler. +-spec add_handler(emqx_config:config_key_path(), module()) -> ok. +add_handler(ConfKeyPath, HandlerName) -> + emqx_config_handler:add_handler(ConfKeyPath, HandlerName). + +%% @doc remove config handler from emqx_config_handler. +-spec remove_handler(emqx_config:config_key_path()) -> ok. +remove_handler(ConfKeyPath) -> + emqx_config_handler:remove_handler(ConfKeyPath). + +-spec get(emqx_map_lib:config_key_path()) -> term(). +get(KeyPath) -> + emqx:get_config(KeyPath). + +-spec get(emqx_map_lib:config_key_path(), term()) -> term(). +get(KeyPath, Default) -> + emqx:get_config(KeyPath, Default). + +%% @doc Returns all values in the cluster. +-spec get_all(emqx_map_lib:config_key_path()) -> #{node() => term()}. +get_all(KeyPath) -> + {ResL, []} = rpc:multicall(?MODULE, get_node_and_config, [KeyPath], 5000), + maps:from_list(ResL). + +%% @doc Returns the specified node's KeyPath, or exception if not found +-spec get_by_node(node(), emqx_map_lib:config_key_path()) -> term(). +get_by_node(Node, KeyPath)when Node =:= node() -> + emqx:get_config(KeyPath); +get_by_node(Node, KeyPath) -> + rpc:call(Node, ?MODULE, get_by_node, [Node, KeyPath]). + +%% @doc Returns the specified node's KeyPath, or the default value if not found +-spec get_by_node(node(), emqx_map_lib:config_key_path(), term()) -> term(). +get_by_node(Node, KeyPath, Default)when Node =:= node() -> + emqx:get_config(KeyPath, Default); +get_by_node(Node, KeyPath, Default) -> + rpc:call(Node, ?MODULE, get_by_node, [Node, KeyPath, Default]). + +%% @doc Returns the specified node's KeyPath, or config_not_found if key path not found +-spec get_node_and_config(emqx_map_lib:config_key_path()) -> term(). +get_node_and_config(KeyPath) -> + {node(), emqx:get_config(KeyPath, config_not_found)}. + +%% @doc Update all value of key path in cluster-override.conf or local-override.conf. +-spec update(emqx_map_lib:config_key_path(), emqx_config:update_args(), + emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +update(KeyPath, UpdateReq, Opts0) -> + Args = [KeyPath, UpdateReq, Opts0], + {ok, _TnxId, Res} = emqx_cluster_rpc:multicall(emqx, update_config, Args), + Res. + +%% @doc Update the specified node's key path in local-override.conf. +-spec update(node(), emqx_map_lib:config_key_path(), emqx_config:update_args(), + emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +update(Node, KeyPath, UpdateReq, Opts0)when Node =:= node() -> + emqx:update_config(KeyPath, UpdateReq, Opts0#{override_to => local}); +update(Node, KeyPath, UpdateReq, Opts0) -> + rpc:call(Node, ?MODULE, update, [Node, KeyPath, UpdateReq, Opts0], 5000). + +%% @doc remove all value of key path in cluster-override.conf or local-override.conf. +-spec remove(emqx_map_lib:config_key_path(), emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +remove(KeyPath, Opts0) -> + Args = [KeyPath, Opts0], + {ok, _TnxId, Res} = emqx_cluster_rpc:multicall(emqx, remove_config, Args), + Res. + +%% @doc remove the specified node's key path in local-override.conf. +-spec remove(node(), emqx_map_lib:config_key_path(), emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +remove(Node, KeyPath, Opts) when Node =:= node() -> + emqx:remove_config(KeyPath, Opts#{override_to => local}); +remove(Node, KeyPath, Opts) -> + rpc:call(Node, ?MODULE, remove, [KeyPath, Opts]). + +%% @doc reset all value of key path in cluster-override.conf or local-override.conf. +-spec reset(emqx_map_lib:config_key_path(), emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +reset(KeyPath, Opts0) -> + Args = [KeyPath, Opts0], + {ok, _TnxId, Res} = emqx_cluster_rpc:multicall(emqx, reset_config, Args), + Res. + +%% @doc reset the specified node's key path in local-override.conf. +-spec reset(node(), emqx_map_lib:config_key_path(), emqx_config:update_opts()) -> + {ok, emqx_config:update_result()} | {error, emqx_config:update_error()}. +reset(Node, KeyPath, Opts) when Node =:= node() -> + emqx:reset_config(KeyPath, Opts#{override_to => local}); +reset(Node, KeyPath, Opts) -> + rpc:call(Node, ?MODULE, reset, [KeyPath, Opts]). diff --git a/apps/emqx_conf/src/emqx_conf_app.erl b/apps/emqx_conf/src/emqx_conf_app.erl new file mode 100644 index 000000000..0a33605fe --- /dev/null +++ b/apps/emqx_conf/src/emqx_conf_app.erl @@ -0,0 +1,97 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_conf_app). + +-behaviour(application). + +-export([start/2, stop/1]). +-export([get_override_config_file/0]). + +-include_lib("emqx/include/logger.hrl"). +-include("emqx_conf.hrl"). + +start(_StartType, _StartArgs) -> + init_conf(), + emqx_conf_sup:start_link(). + +stop(_State) -> + ok. + +%% internal functions +init_conf() -> + {ok, TnxId} = copy_override_conf_from_core_node(), + emqx_app:set_init_tnx_id(TnxId), + emqx_config:init_load(emqx_conf_schema), + emqx_app:set_init_config_load_done(). + +copy_override_conf_from_core_node() -> + case nodes() of + [] -> %% The first core nodes is self. + ?SLOG(debug, #{msg => "skip_copy_overide_conf_from_core_node"}), + {ok, -1}; + Nodes -> + {Results, Failed} = rpc:multicall(Nodes, ?MODULE, get_override_config_file, [], 20000), + {Ready, NotReady0} = lists:partition(fun(Res) -> element(1, Res) =:= ok end, Results), + NotReady = lists:filter(fun(Res) -> element(1, Res) =:= error end, NotReady0), + case (Failed =/= [] orelse NotReady =/= []) andalso Ready =/= [] of + true -> + Warning = #{nodes => Nodes, failed => Failed, not_ready => NotReady, + msg => "ignored_bad_nodes_when_copy_init_config"}, + ?SLOG(warning, Warning); + false -> ok + end, + case Ready of + [] -> + %% Other core nodes running but no one replicated it successfully. + ?SLOG(error, #{msg => "copy_overide_conf_from_core_node_failed", + nodes => Nodes, failed => Failed, not_ready => NotReady}), + {error, "core node not ready"}; + _ -> + SortFun = fun({ok, #{wall_clock := W1}}, {ok, #{wall_clock := W2}}) -> W1 > W2 end, + [{ok, Info} | _] = lists:sort(SortFun, Ready), + #{node := Node, conf := RawOverrideConf, tnx_id := TnxId} = Info, + ?SLOG(debug, #{msg => "copy_overide_conf_from_core_node_success", node => Node}), + ok = emqx_config:save_to_override_conf(RawOverrideConf, #{override_to => cluster}), + {ok, TnxId} + end + end. + +get_override_config_file() -> + Node = node(), + case emqx_app:get_init_config_load_done() of + false -> {error, #{node => Node, msg => "init_conf_load_not_done"}}; + true -> + case mria_rlog:role() of + core -> + case erlang:whereis(emqx_config_handler) of + undefined -> {error, #{node => Node, msg => "emqx_config_handler_not_ready"}}; + _ -> + Fun = fun() -> + TnxId = emqx_cluster_rpc:get_node_tnx_id(Node), + WallClock = erlang:statistics(wall_clock), + Conf = emqx_config_handler:get_raw_cluster_override_conf(), + #{wall_clock => WallClock, conf => Conf, tnx_id => TnxId, node => Node} + end, + case mria:ro_transaction(?CLUSTER_RPC_SHARD, Fun) of + {atomic, Res} -> {ok, Res}; + {aborted, Reason} -> {error, #{node => Node, msg => Reason}} + end + end; + replicant -> + {ignore, #{node => Node}} + end + end. diff --git a/apps/emqx_machine/src/emqx_machine_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl similarity index 95% rename from apps/emqx_machine/src/emqx_machine_schema.erl rename to apps/emqx_conf/src/emqx_conf_schema.erl index a67b0ceeb..a187bc58c 100644 --- a/apps/emqx_machine/src/emqx_machine_schema.erl +++ b/apps/emqx_conf/src/emqx_conf_schema.erl @@ -14,7 +14,7 @@ %% limitations under the License. %%-------------------------------------------------------------------- --module(emqx_machine_schema). +-module(emqx_conf_schema). -dialyzer(no_return). -dialyzer(no_match). @@ -279,7 +279,8 @@ fields("node") -> })} , {"data_dir", sc(string(), - #{ nullable => false + #{ nullable => false, + mapping => "emqx.data_dir" })} , {"config_files", sc(list(string()), @@ -288,8 +289,9 @@ fields("node") -> })} , {"global_gc_interval", sc(emqx_schema:duration(), - #{ default => "15m" - })} + #{ mapping => "emqx_machine.global_gc_interval" + , default => "15m" + })} , {"crash_dump_dir", sc(file(), #{ mapping => "vm_args.-env ERL_CRASH_DUMP" @@ -314,32 +316,34 @@ fields("node") -> #{ mapping => "emqx_machine.backtrace_depth" , default => 23 })} - , {"cluster_call", - sc(ref("cluster_call"), - #{} - )} , {"etc_dir", sc(string(), #{ desc => "`etc` dir for the node" } )} + , {"cluster_call", + sc(ref("cluster_call"), + #{ + } + )} ]; fields("cluster_call") -> [ {"retry_interval", sc(emqx_schema:duration(), - #{ mapping => "emqx_machine.retry_interval" - , default => "1s" - })} + #{ desc => "Time interval to retry after a failed call." + , default => "1s" + })} , {"max_history", sc(range(1, 500), - #{mapping => "emqx_machine.max_history", - default => 100 + #{ desc => "Retain the maximum number of completed transactions (for queries)." + , default => 100 })} , {"cleanup_interval", sc(emqx_schema:duration(), - #{mapping => "emqx_machine.cleanup_interval", - default => "5m" + #{ desc => "Time interval to clear completed but stale transactions. + Ensure that the number of completed transactions is less than the max_history." + , default => "5m" })} ]; @@ -507,7 +511,8 @@ translation("kernel") -> , {"logger", fun tr_logger/1}]; translation("emqx") -> [ {"config_files", fun tr_config_files/1} - , {"override_conf_file", fun tr_override_conf_fie/1} + , {"cluster_override_conf_file", fun tr_cluster_override_conf_file/1} + , {"local_override_conf_file", fun tr_local_override_conf_file/1} ]. tr_config_files(Conf) -> @@ -523,11 +528,17 @@ tr_config_files(Conf) -> end end. -tr_override_conf_fie(Conf) -> +tr_cluster_override_conf_file(Conf) -> + tr_override_conf_file(Conf, "cluster-override.conf"). + +tr_local_override_conf_file(Conf) -> + tr_override_conf_file(Conf, "local-override.conf"). + +tr_override_conf_file(Conf, Filename) -> DataDir = conf_get("node.data_dir", Conf), %% assert, this config is not nullable [_ | _] = DataDir, - filename:join([DataDir, "emqx_override.conf"]). + filename:join([DataDir, "configs", Filename]). tr_cluster__discovery(Conf) -> Strategy = conf_get("cluster.discovery_strategy", Conf), diff --git a/apps/emqx_conf/src/emqx_conf_sup.erl b/apps/emqx_conf/src/emqx_conf_sup.erl new file mode 100644 index 000000000..bcecb9798 --- /dev/null +++ b/apps/emqx_conf/src/emqx_conf_sup.erl @@ -0,0 +1,48 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%%-------------------------------------------------------------------- + +-module(emqx_conf_sup). + +-behaviour(supervisor). + +-export([start_link/0]). + +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +init([]) -> + SupFlags = #{strategy => one_for_all, + intensity => 10, + period => 100}, + ChildSpecs = + [ child_spec(emqx_cluster_rpc, []) + , child_spec(emqx_cluster_rpc_handler, []) + ], + {ok, {SupFlags, ChildSpecs}}. + +child_spec(Mod, Args) -> + #{ + id => Mod, + start => {Mod, start_link, Args}, + restart => permanent, + shutdown => 5000, + type => worker, + modules => [Mod] + }. diff --git a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl b/apps/emqx_conf/test/emqx_cluster_rpc_SUITE.erl similarity index 94% rename from apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl rename to apps/emqx_conf/test/emqx_cluster_rpc_SUITE.erl index cf6c794a7..cb79151ce 100644 --- a/apps/emqx_machine/test/emqx_cluster_rpc_SUITE.erl +++ b/apps/emqx_conf/test/emqx_cluster_rpc_SUITE.erl @@ -19,8 +19,7 @@ -compile(export_all). -compile(nowarn_export_all). --include_lib("emqx/include/emqx.hrl"). --include("emqx_machine.hrl"). +-include("emqx_conf.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -define(NODE1, emqx_cluster_rpc). @@ -40,13 +39,9 @@ suite() -> [{timetrap, {minutes, 3}}]. groups() -> []. init_per_suite(Config) -> - application:load(emqx), - application:load(emqx_machine), + application:load(emqx_conf), ok = ekka:start(), - ok = mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), - application:set_env(emqx_machine, cluster_call_max_history, 100), - application:set_env(emqx_machine, cluster_call_clean_interval, 1000), - application:set_env(emqx_machine, cluster_call_retry_interval, 900), + ok = mria_rlog:wait_for_shards([?CLUSTER_RPC_SHARD], infinity), meck:new(emqx_alarm, [non_strict, passthrough, no_link]), meck:expect(emqx_alarm, activate, 2, ok), meck:expect(emqx_alarm, deactivate, 2, ok), @@ -68,6 +63,7 @@ end_per_testcase(_Config) -> ok. t_base_test(_Config) -> + emqx_cluster_rpc:reset(), ?assertEqual(emqx_cluster_rpc:status(), {atomic, []}), Pid = self(), MFA = {M, F, A} = {?MODULE, echo, [Pid, test]}, @@ -181,6 +177,7 @@ t_skip_failed_commit(_Config) -> emqx_cluster_rpc:reset(), {atomic, []} = emqx_cluster_rpc:status(), {ok, 1, ok} = emqx_cluster_rpc:multicall(io, format, ["test~n"], all, 1000), + sleep(180), {atomic, List1} = emqx_cluster_rpc:status(), Node = node(), ?assertEqual([{Node, 1}, {{Node, ?NODE2}, 1}, {{Node, ?NODE3}, 1}], @@ -254,7 +251,7 @@ failed_on_other_recover_after_5_second(Pid, CreatedAt) -> end end. -sleep(Second) -> +sleep(Ms) -> receive _ -> ok - after Second -> timeout + after Ms -> timeout end. diff --git a/apps/emqx_machine/test/emqx_global_gc_SUITE.erl b/apps/emqx_conf/test/emqx_global_gc_SUITE.erl similarity index 100% rename from apps/emqx_machine/test/emqx_global_gc_SUITE.erl rename to apps/emqx_conf/test/emqx_global_gc_SUITE.erl diff --git a/apps/emqx_dashboard/src/emqx_dashboard.erl b/apps/emqx_dashboard/src/emqx_dashboard.erl index d4d5621e7..2a5066d50 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard.erl @@ -88,7 +88,7 @@ listeners() -> Name = listener_name(Protocol, Port), RanchOptions = ranch_opts(maps:without([protocol], ListenerOptions)), {Name, Protocol, Port, RanchOptions} - end || ListenerOptions <- emqx_config:get([emqx_dashboard, listeners], [])]. + end || ListenerOptions <- emqx_conf:get([emqx_dashboard, listeners], [])]. ranch_opts(RanchOptions) -> Keys = [ {ack_timeout, handshake_timeout} diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 2a7f2410a..e2ab0ad8f 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -205,7 +205,7 @@ add_default_user() -> add_default_user(binenv(default_username), binenv(default_password)). binenv(Key) -> - iolist_to_binary(emqx:get_config([emqx_dashboard, Key], "")). + iolist_to_binary(emqx_conf:get([emqx_dashboard, Key], "")). add_default_user(Username, Password) when ?EMPTY_KEY(Username) orelse ?EMPTY_KEY(Password) -> igonre; diff --git a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl index 0eb1e033b..ab5767229 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_collection.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_collection.erl @@ -55,7 +55,7 @@ get_collect() -> gen_server:call(whereis(?MODULE), get_collect). init([]) -> timer(next_interval(), collect), timer(get_today_remaining_seconds(), clear_expire_data), - ExpireInterval = emqx:get_config([emqx_dashboard, monitor, interval], ?EXPIRE_INTERVAL), + ExpireInterval = emqx_conf:get([emqx_dashboard, monitor, interval], ?EXPIRE_INTERVAL), State = #{ count => count(), expire_interval => ExpireInterval, @@ -75,7 +75,7 @@ next_interval() -> (1000 * interval()) - (erlang:system_time(millisecond) rem (1000 * interval())) - 1. interval() -> - emqx:get_config([?APP, sample_interval], ?DEFAULT_INTERVAL). + emqx_conf:get([?APP, sample_interval], ?DEFAULT_INTERVAL). count() -> 60 div interval(). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index 5a6771ae5..e0fa9c415 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -152,7 +152,7 @@ jwk(Username, Password, Salt) -> }. jwt_expiration_time() -> - ExpTime = emqx:get_config([emqx_dashboard, token_expired_time], ?EXPTIME), + ExpTime = emqx_conf:get([emqx_dashboard, token_expired_time], ?EXPTIME), erlang:system_time(millisecond) + ExpTime. salt() -> diff --git a/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl index a9969ba4b..92f411da7 100644 --- a/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_swagger_response_SUITE.erl @@ -339,7 +339,7 @@ schema("/ref/complicated_type") -> {maps, hoconsc:mk(map(), #{})}, {comma_separated_list, hoconsc:mk(emqx_schema:comma_separated_list(), #{})}, {comma_separated_atoms, hoconsc:mk(emqx_schema:comma_separated_atoms(), #{})}, - {log_level, hoconsc:mk(emqx_machine_schema:log_level(), #{})}, + {log_level, hoconsc:mk(emqx_conf_schema:log_level(), #{})}, {fix_integer, hoconsc:mk(typerefl:integer(100), #{})} ] }} diff --git a/apps/emqx_exhook/src/emqx_exhook_sup.erl b/apps/emqx_exhook/src/emqx_exhook_sup.erl index 60a6a2915..ea03a54f9 100644 --- a/apps/emqx_exhook/src/emqx_exhook_sup.erl +++ b/apps/emqx_exhook/src/emqx_exhook_sup.erl @@ -58,7 +58,7 @@ request_options() -> }. env(Key, Def) -> - emqx:get_config([exhook, Key], Def). + emqx_conf:get([exhook, Key], Def). %%-------------------------------------------------------------------- %% APIs diff --git a/apps/emqx_gateway/src/coap/emqx_coap_channel.erl b/apps/emqx_gateway/src/coap/emqx_coap_channel.erl index 839567d1e..acce25807 100644 --- a/apps/emqx_gateway/src/coap/emqx_coap_channel.erl +++ b/apps/emqx_gateway/src/coap/emqx_coap_channel.erl @@ -279,7 +279,7 @@ try_takeover(idle, DesireId, Msg, Channel) -> %% udp connection baseon the clientid call_session(handle_request, Msg, Channel); _ -> - case emqx:get_config([gateway, coap, authentication], undefined) of + case emqx_conf:get([gateway, coap, authentication], undefined) of undefined -> call_session(handle_request, Msg, Channel); _ -> diff --git a/apps/emqx_gateway/src/coap/emqx_coap_session.erl b/apps/emqx_gateway/src/coap/emqx_coap_session.erl index 0fbc47cf8..13f1be240 100644 --- a/apps/emqx_gateway/src/coap/emqx_coap_session.erl +++ b/apps/emqx_gateway/src/coap/emqx_coap_session.erl @@ -216,7 +216,7 @@ mqtt_to_coap(MQTT, Token, SeqId) -> options = #{observe => SeqId}}. get_notify_type(#message{qos = Qos}) -> - case emqx:get_config([gateway, coap, notify_qos], non) of + case emqx_conf:get([gateway, coap, notify_qos], non) of qos -> case Qos of ?QOS_0 -> diff --git a/apps/emqx_gateway/src/coap/handler/emqx_coap_pubsub_handler.erl b/apps/emqx_gateway/src/coap/handler/emqx_coap_pubsub_handler.erl index 85cf32c6d..d1d73e9b9 100644 --- a/apps/emqx_gateway/src/coap/handler/emqx_coap_pubsub_handler.erl +++ b/apps/emqx_gateway/src/coap/handler/emqx_coap_pubsub_handler.erl @@ -86,7 +86,7 @@ get_sub_opts(#coap_message{options = Opts} = Msg) -> #{qos := _} -> maps:merge(SubOpts, ?SUBOPTS); _ -> - CfgType = emqx:get_config([gateway, coap, subscribe_qos], ?QOS_0), + CfgType = emqx_conf:get([gateway, coap, subscribe_qos], ?QOS_0), maps:merge(SubOpts, ?SUBOPTS#{qos => type_to_qos(CfgType, Msg)}) end. @@ -115,7 +115,7 @@ get_publish_qos(Msg) -> #{<<"qos">> := QOS} -> erlang:binary_to_integer(QOS); _ -> - CfgType = emqx:get_config([gateway, coap, publish_qos], ?QOS_0), + CfgType = emqx_conf:get([gateway, coap, publish_qos], ?QOS_0), type_to_qos(CfgType, Msg) end. diff --git a/apps/emqx_gateway/src/emqx_gateway_app.erl b/apps/emqx_gateway/src/emqx_gateway_app.erl index 8b09f18a0..9d1c878e3 100644 --- a/apps/emqx_gateway/src/emqx_gateway_app.erl +++ b/apps/emqx_gateway/src/emqx_gateway_app.erl @@ -88,4 +88,4 @@ load_gateway_by_default([{Type, Confs}|More]) -> load_gateway_by_default(More). confs() -> - maps:to_list(emqx:get_config([gateway], #{})). + maps:to_list(emqx_conf:get([gateway], #{})). diff --git a/apps/emqx_gateway/src/emqx_gateway_conf.erl b/apps/emqx_gateway/src/emqx_gateway_conf.erl index 1d3500b09..557e46693 100644 --- a/apps/emqx_gateway/src/emqx_gateway_conf.erl +++ b/apps/emqx_gateway/src/emqx_gateway_conf.erl @@ -65,11 +65,11 @@ -spec load() -> ok. load() -> - emqx_config_handler:add_handler([gateway], ?MODULE). + emqx_conf:add_handler([gateway], ?MODULE). -spec unload() -> ok. unload() -> - emqx_config_handler:remove_handler([gateway]). + emqx_conf:remove_handler([gateway]). %%-------------------------------------------------------------------- %% APIs diff --git a/apps/emqx_machine/include/emqx_machine.hrl b/apps/emqx_machine/include/emqx_machine.hrl deleted file mode 100644 index cea62c5c3..000000000 --- a/apps/emqx_machine/include/emqx_machine.hrl +++ /dev/null @@ -1,37 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 2017-2021 EMQ Technologies Co., Ltd. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%%-------------------------------------------------------------------- - --ifndef(EMQ_X_CLUSTER_RPC_HRL). --define(EMQ_X_CLUSTER_RPC_HRL, true). - --define(CLUSTER_MFA, cluster_rpc_mfa). --define(CLUSTER_COMMIT, cluster_rpc_commit). - --define(EMQX_MACHINE_SHARD, emqx_machine_shard). - --record(cluster_rpc_mfa, { - tnx_id :: pos_integer(), - mfa :: mfa(), - created_at :: calendar:datetime(), - initiator :: node() -}). - --record(cluster_rpc_commit, { - node :: node(), - tnx_id :: pos_integer() | '$1' -}). - --endif. diff --git a/apps/emqx/src/emqx_global_gc.erl b/apps/emqx_machine/src/emqx_global_gc.erl similarity index 91% rename from apps/emqx/src/emqx_global_gc.erl rename to apps/emqx_machine/src/emqx_global_gc.erl index 5192508e5..87a2f9b5b 100644 --- a/apps/emqx/src/emqx_global_gc.erl +++ b/apps/emqx_machine/src/emqx_global_gc.erl @@ -18,8 +18,6 @@ -behaviour(gen_server). --include("types.hrl"). - -export([start_link/0, stop/0]). -export([run/0]). @@ -40,7 +38,7 @@ %% APIs %%-------------------------------------------------------------------- --spec(start_link() -> startlink_ret()). +-spec(start_link() -> {ok, pid()} | ignore | {error, term()}). start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). @@ -85,10 +83,11 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- ensure_timer(State) -> - case emqx:get_config([node, global_gc_interval]) of + case application:get_env(emqx_machine, global_gc_interval) of undefined -> State; - Interval -> TRef = emqx_misc:start_timer(Interval, run), - State#{timer := TRef} + {ok, Interval} -> + TRef = emqx_misc:start_timer(Interval, run), + State#{timer := TRef} end. run_gc() -> lists:foreach(fun do_gc/1, processes()). @@ -99,4 +98,3 @@ do_gc(Pid) -> -compile({inline, [is_waiting/1]}). is_waiting(Pid) -> {status, waiting} == process_info(Pid, status). - diff --git a/apps/emqx_machine/src/emqx_machine.erl b/apps/emqx_machine/src/emqx_machine.erl index 313f45dd3..fae21eece 100644 --- a/apps/emqx_machine/src/emqx_machine.erl +++ b/apps/emqx_machine/src/emqx_machine.erl @@ -22,7 +22,6 @@ ]). -include_lib("emqx/include/logger.hrl"). --include("emqx_machine.hrl"). %% @doc EMQ X boot entrypoint. start() -> @@ -33,11 +32,8 @@ start() -> os:set_signal(sigterm, handle) %% default is handle end, ok = set_backtrace_depth(), - ok = print_otp_version_warning(), - ok = load_config_files(), ekka:start(), - ok = mria_rlog:wait_for_shards([?EMQX_MACHINE_SHARD], infinity), - ok. + ok = print_otp_version_warning(). graceful_shutdown() -> emqx_machine_terminator:graceful_wait(). @@ -58,12 +54,3 @@ print_otp_version_warning() -> ?ULOG("WARNING: Running on Erlang/OTP version ~p. Recommended: 23~n", [?OTP_RELEASE]). -endif. % OTP_RELEASE > 22 - -load_config_files() -> - %% the app env 'config_files' for 'emqx` app should be set - %% in app.time.config by boot script before starting Erlang VM - ConfFiles = application:get_env(emqx, config_files, []), - %% emqx_machine_schema is a superset of emqx_schema - ok = emqx_config:init_load(emqx_machine_schema, ConfFiles), - %% to avoid config being loaded again when emqx app starts. - ok = emqx_app:set_init_config_load_done(). diff --git a/apps/emqx_machine/src/emqx_machine_boot.erl b/apps/emqx_machine/src/emqx_machine_boot.erl index ed3b21a9d..9fab5854e 100644 --- a/apps/emqx_machine/src/emqx_machine_boot.erl +++ b/apps/emqx_machine/src/emqx_machine_boot.erl @@ -50,8 +50,7 @@ start_autocluster() -> stop_apps() -> ?SLOG(notice, #{msg => "stopping_emqx_apps"}), _ = emqx_alarm_handler:unload(), - lists:foreach(fun stop_one_app/1, lists:reverse(sorted_reboot_apps())), - emqx_machine_sup:stop_cluster_rpc(). + lists:foreach(fun stop_one_app/1, lists:reverse(sorted_reboot_apps())). stop_one_app(App) -> ?SLOG(debug, #{msg => "stopping_app", app => App}), @@ -67,9 +66,6 @@ stop_one_app(App) -> ensure_apps_started() -> ?SLOG(notice, #{msg => "(re)starting_emqx_apps"}), - %% FIXME: Hack spawning the cluster RPC asynchronously to avoid a - %% deadlock somewhere in EMQ X startup - spawn_link(fun() -> emqx_machine_sup:start_cluster_rpc() end), lists:foreach(fun start_one_app/1, sorted_reboot_apps()). start_one_app(App) -> @@ -90,6 +86,7 @@ reboot_apps() -> , esockd , ranch , cowboy + , emqx_conf , emqx , emqx_prometheus , emqx_modules diff --git a/apps/emqx_machine/src/emqx_machine_sup.erl b/apps/emqx_machine/src/emqx_machine_sup.erl index bf5403d43..844cc171b 100644 --- a/apps/emqx_machine/src/emqx_machine_sup.erl +++ b/apps/emqx_machine/src/emqx_machine_sup.erl @@ -21,8 +21,6 @@ -behaviour(supervisor). -export([ start_link/0 - , stop_cluster_rpc/0 - , start_cluster_rpc/0 ]). -export([init/1]). @@ -30,33 +28,11 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). -stop_cluster_rpc() -> - case whereis(?MODULE) of - undefined -> - ok; - _ -> - _ = supervisor:terminate_child(?MODULE, emqx_cluster_rpc_handler), - _ = supervisor:terminate_child(?MODULE, emqx_cluster_rpc), - ok - end. - -start_cluster_rpc() -> - case whereis(?MODULE) of - undefined -> - ok; - _ -> - ensure_running(emqx_cluster_rpc), - ensure_running(emqx_cluster_rpc_handler), - ok - end. - init([]) -> - GlobalGC = child_worker(emqx_global_gc, [], permanent), Terminator = child_worker(emqx_machine_terminator, [], transient), - ClusterRpc = child_worker(emqx_cluster_rpc, [], permanent), - ClusterHandler = child_worker(emqx_cluster_rpc_handler, [], permanent), BootApps = child_worker(emqx_machine_boot, post_boot, [], temporary), - Children = [GlobalGC, Terminator, ClusterRpc, ClusterHandler, BootApps], + GlobalGC = child_worker(emqx_global_gc, [], permanent), + Children = [Terminator, BootApps, GlobalGC], SupFlags = #{strategy => one_for_one, intensity => 100, period => 10 @@ -74,13 +50,3 @@ child_worker(M, Func, Args, Restart) -> type => worker, modules => [M] }. - -ensure_running(Id) -> - %% Assuming Id == locally registered name - case whereis(Id) of - undefined -> - _ = supervisor:restart_child(?MODULE, Id), - ok; - _ -> - ok - end. diff --git a/apps/emqx_management/src/emqx_mgmt_api_configs.erl b/apps/emqx_management/src/emqx_mgmt_api_configs.erl index de2774cae..abf9d7cff 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_configs.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_configs.erl @@ -109,10 +109,10 @@ find_schema(Path) -> {Root, element(2, lists:keyfind(RootAtom, 1, Configs))} end. -%% we load all configs from emqx_machine_schema, some of them are defined as local ref -%% we need redirect to emqx_machine_schema. -%% such as hoconsc:ref("node") to hoconsc:ref(emqx_machine_schema, "node") -fields(Field) -> emqx_machine_schema:fields(Field). +%% we load all configs from emqx_conf_schema, some of them are defined as local ref +%% we need redirect to emqx_conf_schema. +%% such as hoconsc:ref("node") to hoconsc:ref(emqx_conf_schema, "node") +fields(Field) -> emqx_conf_schema:fields(Field). %%%============================================================================================== %% HTTP API Callbacks @@ -165,7 +165,7 @@ conf_path_from_querystr(Req) -> end. config_list(Exclude) -> - Roots = emqx_machine_schema:roots(), + Roots = emqx_conf_schema:roots(), lists:foldl(fun(Key, Acc) -> lists:delete(Key, Acc) end, Roots, Exclude). to_list(L) when is_list(L) -> L; diff --git a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl index 52c7a8709..4568bcd9a 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_listeners.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_listeners.erl @@ -238,7 +238,7 @@ crud_listeners_by_id(put, #{bindings := #{id := Id}, body := Conf}) -> case lists:filter(fun filter_errors/1, Results) of [{error, {invalid_listener_id, Id}} | _] -> {400, #{code => 'BAD_REQUEST', message => ?INVALID_LISTENER_PROTOCOL}}; - [{error, {emqx_machine_schema, _}} | _] -> + [{error, {emqx_conf_schema, _}} | _] -> {400, #{code => 'BAD_REQUEST', message => ?CONFIG_SCHEMA_ERROR}}; [{error, {eaddrinuse, _}} | _] -> {400, #{code => 'BAD_REQUEST', message => ?ADDR_PORT_INUSE}}; @@ -280,7 +280,7 @@ crud_listener_by_id_on_node(put, #{bindings := #{id := Id, node := Node}, body : {404, #{code => 'RESOURCE_NOT_FOUND', message => ?NODE_NOT_FOUND_OR_DOWN}}; {error, {invalid_listener_id, _}} -> {400, #{code => 'BAD_REQUEST', message => ?INVALID_LISTENER_PROTOCOL}}; - {error, {emqx_machine_schema, _}} -> + {error, {emqx_conf_schema, _}} -> {400, #{code => 'BAD_REQUEST', message => ?CONFIG_SCHEMA_ERROR}}; {error, {eaddrinuse, _}} -> {400, #{code => 'BAD_REQUEST', message => ?ADDR_PORT_INUSE}}; diff --git a/apps/emqx_modules/src/emqx_delayed.erl b/apps/emqx_modules/src/emqx_delayed.erl index 401e2a10c..fd831c040 100644 --- a/apps/emqx_modules/src/emqx_delayed.erl +++ b/apps/emqx_modules/src/emqx_delayed.erl @@ -107,7 +107,7 @@ on_message_publish(Msg) -> -spec(start_link() -> emqx_types:startlink_ret()). start_link() -> - Opts = emqx:get_config([delayed], #{}), + Opts = emqx_conf:get([delayed], #{}), gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], []). -spec(store(#delayed_message{}) -> ok | {error, atom()}). diff --git a/apps/emqx_modules/src/emqx_delayed_api.erl b/apps/emqx_modules/src/emqx_delayed_api.erl index 768ef4590..3cc2c7c21 100644 --- a/apps/emqx_modules/src/emqx_delayed_api.erl +++ b/apps/emqx_modules/src/emqx_delayed_api.erl @@ -177,7 +177,7 @@ delayed_message(delete, #{bindings := #{msgid := Id}}) -> %% internal function %%-------------------------------------------------------------------- get_status() -> - emqx:get_config([delayed], #{}). + emqx_conf:get([delayed], #{}). update_config(Config) -> case generate_config(Config) of diff --git a/apps/emqx_modules/src/emqx_event_message.erl b/apps/emqx_modules/src/emqx_event_message.erl index 842ddae04..ccdb75ccb 100644 --- a/apps/emqx_modules/src/emqx_event_message.erl +++ b/apps/emqx_modules/src/emqx_event_message.erl @@ -40,7 +40,7 @@ -endif. list() -> - emqx:get_config([event_message], #{}). + emqx_conf:get([event_message], #{}). update(Params) -> disable(), diff --git a/apps/emqx_modules/src/emqx_modules_app.erl b/apps/emqx_modules/src/emqx_modules_app.erl index 123431605..8804bbc4a 100644 --- a/apps/emqx_modules/src/emqx_modules_app.erl +++ b/apps/emqx_modules/src/emqx_modules_app.erl @@ -32,17 +32,17 @@ stop(_State) -> ok. maybe_enable_modules() -> - emqx:get_config([delayed, enable], true) andalso emqx_delayed:enable(), - emqx:get_config([telemetry, enable], true) andalso emqx_telemetry:enable(), - emqx:get_config([observer_cli, enable], true) andalso emqx_observer_cli:enable(), + emqx_conf:get([delayed, enable], true) andalso emqx_delayed:enable(), + emqx_conf:get([telemetry, enable], true) andalso emqx_telemetry:enable(), + emqx_conf:get([observer_cli, enable], true) andalso emqx_observer_cli:enable(), emqx_event_message:enable(), emqx_rewrite:enable(), emqx_topic_metrics:enable(). maybe_disable_modules() -> - emqx:get_config([delayed, enable], true) andalso emqx_delayed:disable(), - emqx:get_config([telemetry, enable], true) andalso emqx_telemetry:disable(), - emqx:get_config([observer_cli, enable], true) andalso emqx_observer_cli:disable(), + emqx_conf:get([delayed, enable], true) andalso emqx_delayed:disable(), + emqx_conf:get([telemetry, enable], true) andalso emqx_telemetry:disable(), + emqx_conf:get([observer_cli, enable], true) andalso emqx_observer_cli:disable(), emqx_event_message:disable(), emqx_rewrite:disable(), emqx_topic_metrics:disable(). diff --git a/apps/emqx_modules/src/emqx_rewrite.erl b/apps/emqx_modules/src/emqx_rewrite.erl index 1b057ca51..16009d46b 100644 --- a/apps/emqx_modules/src/emqx_rewrite.erl +++ b/apps/emqx_modules/src/emqx_rewrite.erl @@ -43,7 +43,7 @@ %%-------------------------------------------------------------------- enable() -> - Rules = emqx:get_config([rewrite], []), + Rules = emqx_conf:get([rewrite], []), register_hook(Rules). disable() -> diff --git a/apps/emqx_modules/src/emqx_telemetry.erl b/apps/emqx_modules/src/emqx_telemetry.erl index e81d1257d..61f00745e 100644 --- a/apps/emqx_modules/src/emqx_telemetry.erl +++ b/apps/emqx_modules/src/emqx_telemetry.erl @@ -116,7 +116,7 @@ disable() -> gen_server:call(?MODULE, disable). get_status() -> - emqx:get_config([telemetry, enable], true). + emqx_conf:get([telemetry, enable], true). get_uuid() -> gen_server:call(?MODULE, get_uuid). diff --git a/apps/emqx_modules/src/emqx_topic_metrics.erl b/apps/emqx_modules/src/emqx_topic_metrics.erl index 05c45f469..7ca14b921 100644 --- a/apps/emqx_modules/src/emqx_topic_metrics.erl +++ b/apps/emqx_modules/src/emqx_topic_metrics.erl @@ -146,7 +146,7 @@ on_message_dropped(#message{topic = Topic}, _, _) -> end. start_link() -> - Opts = emqx:get_config([topic_metrics], []), + Opts = emqx_conf:get([topic_metrics], []), gen_server:start_link({local, ?MODULE}, ?MODULE, [Opts], []). stop() -> diff --git a/apps/emqx_prometheus/src/emqx_prometheus_app.erl b/apps/emqx_prometheus/src/emqx_prometheus_app.erl index 4f954a792..380f8d8f6 100644 --- a/apps/emqx_prometheus/src/emqx_prometheus_app.erl +++ b/apps/emqx_prometheus/src/emqx_prometheus_app.erl @@ -34,9 +34,9 @@ stop(_State) -> ok. maybe_enable_prometheus() -> - case emqx:get_config([prometheus, enable], false) of + case emqx_conf:get([prometheus, enable], false) of true -> - emqx_prometheus_sup:start_child(?APP, emqx:get_config([prometheus], #{})); + emqx_prometheus_sup:start_child(?APP, emqx_conf:get([prometheus], #{})); false -> ok end. diff --git a/apps/emqx_psk/src/emqx_psk.erl b/apps/emqx_psk/src/emqx_psk.erl index 7de332cb9..ff89041ce 100644 --- a/apps/emqx_psk/src/emqx_psk.erl +++ b/apps/emqx_psk/src/emqx_psk.erl @@ -142,13 +142,13 @@ code_change(_OldVsn, State, _Extra) -> %%------------------------------------------------------------------------------ get_config(enable) -> - emqx_config:get([psk, enable]); + emqx_conf:get([psk, enable]); get_config(init_file) -> - emqx_config:get([psk, init_file], undefined); + emqx_conf:get([psk, init_file], undefined); get_config(separator) -> - emqx_config:get([psk, separator], ?DEFAULT_DELIMITER); + emqx_conf:get([psk, separator], ?DEFAULT_DELIMITER); get_config(chunk_size) -> - emqx_config:get([psk, chunk_size]). + emqx_conf:get([psk, chunk_size]). import_psks(SrcFile) -> case file:open(SrcFile, [read, raw, binary, read_ahead]) of diff --git a/apps/emqx_retainer/src/emqx_retainer.erl b/apps/emqx_retainer/src/emqx_retainer.erl index 2bb62e645..5d248e638 100644 --- a/apps/emqx_retainer/src/emqx_retainer.erl +++ b/apps/emqx_retainer/src/emqx_retainer.erl @@ -151,7 +151,7 @@ get_expiry_time(#message{headers = #{properties := #{'Message-Expiry-Interval' : timestamp = Ts}) -> Ts + Interval * 1000; get_expiry_time(#message{timestamp = Ts}) -> - Interval = emqx:get_config([?APP, msg_expiry_interval], ?DEF_EXPIRY_INTERVAL), + Interval = emqx_conf:get([?APP, msg_expiry_interval], ?DEF_EXPIRY_INTERVAL), case Interval of 0 -> 0; _ -> Ts + Interval @@ -219,7 +219,7 @@ handle_cast(Msg, State) -> handle_info(clear_expired, #{context := Context} = State) -> Mod = get_backend_module(), Mod:clear_expired(Context), - Interval = emqx:get_config([?APP, msg_clear_interval], ?DEF_EXPIRY_INTERVAL), + Interval = emqx_conf:get([?APP, msg_clear_interval], ?DEF_EXPIRY_INTERVAL), {noreply, State#{clear_timer := add_timer(Interval, clear_expired)}, hibernate}; handle_info(release_deliver_quota, #{context := Context, wait_quotas := Waits} = State) -> @@ -268,7 +268,7 @@ new_context(Id) -> #{context_id => Id}. is_too_big(Size) -> - Limit = emqx:get_config([?APP, max_payload_size], ?DEF_MAX_PAYLOAD_SIZE), + Limit = emqx_conf:get([?APP, max_payload_size], ?DEF_MAX_PAYLOAD_SIZE), Limit > 0 andalso (Size > Limit). %% @private diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.erl b/apps/emqx_rule_engine/src/emqx_rule_engine.erl index 8a6d78ff6..42f652d59 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.erl @@ -103,7 +103,7 @@ post_config_update(_Req, NewRules, OldRules, _AppEnvs) -> load_rules() -> maps_foreach(fun({Id, Rule}) -> {ok, _} = create_rule(Rule#{id => bin(Id)}) - end, emqx:get_config([rule_engine, rules], #{})). + end, emqx_conf:get([rule_engine, rules], #{})). -spec create_rule(map()) -> {ok, rule()} | {error, term()}. create_rule(Params = #{id := RuleId}) when is_binary(RuleId) -> diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine_app.erl b/apps/emqx_rule_engine/src/emqx_rule_engine_app.erl index e9ca443ec..610244350 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine_app.erl +++ b/apps/emqx_rule_engine/src/emqx_rule_engine_app.erl @@ -29,9 +29,9 @@ start(_Type, _Args) -> ok = emqx_rule_events:reload(), SupRet = emqx_rule_engine_sup:start_link(), ok = emqx_rule_engine:load_rules(), - emqx_config_handler:add_handler(emqx_rule_engine:config_key_path(), emqx_rule_engine), + emqx_conf:add_handler(emqx_rule_engine:config_key_path(), emqx_rule_engine), SupRet. stop(_State) -> - emqx_config_handler:remove_handler(emqx_rule_engine:config_key_path()), + emqx_conf:remove_handler(emqx_rule_engine:config_key_path()), ok = emqx_rule_events:unload(). diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl index 56af13acc..a920b18ad 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_SUITE.erl @@ -103,12 +103,12 @@ groups() -> %%------------------------------------------------------------------------------ init_per_suite(Config) -> - application:load(emqx_machine), - ok = emqx_common_test_helpers:start_apps([emqx_rule_engine]), + application:load(emqx_conf), + ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_rule_engine]), Config. end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([emqx_rule_engine]), + emqx_common_test_helpers:stop_apps([emqx_conf, emqx_rule_engine]), ok. on_resource_create(_id, _) -> #{}. @@ -136,7 +136,6 @@ end_per_group(_Groupname, _Config) -> init_per_testcase(t_events, Config) -> init_events_counters(), - {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), SQL = "SELECT * FROM \"$events/client_connected\", " "\"$events/client_disconnected\", " "\"$events/session_subscribed\", " @@ -157,7 +156,6 @@ init_per_testcase(t_events, Config) -> ?assertMatch(#{id := <<"rule:t_events">>}, Rule), [{hook_points_rules, Rule} | Config]; init_per_testcase(_TestCase, Config) -> - emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), Config. end_per_testcase(t_events, Config) -> diff --git a/apps/emqx_rule_engine/test/emqx_rule_engine_api_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_engine_api_SUITE.erl index 4b0f027f7..10ea55a69 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_engine_api_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_engine_api_SUITE.erl @@ -12,17 +12,16 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> - application:load(emqx_machine), + application:load(emqx_conf), ok = emqx_config:init_load(emqx_rule_engine_schema, ?CONF_DEFAULT), - ok = emqx_common_test_helpers:start_apps([emqx_rule_engine]), + ok = emqx_common_test_helpers:start_apps([emqx_conf, emqx_rule_engine]), Config. end_per_suite(_Config) -> - emqx_common_test_helpers:stop_apps([emqx_rule_engine]), + emqx_common_test_helpers:stop_apps([emqx_conf, emqx_rule_engine]), ok. init_per_testcase(_, Config) -> - {ok, _} = emqx_cluster_rpc:start_link(node(), emqx_cluster_rpc, 1000), Config. end_per_testcase(_, _Config) -> diff --git a/apps/emqx_rule_engine/test/emqx_rule_metrics_SUITE.erl b/apps/emqx_rule_engine/test/emqx_rule_metrics_SUITE.erl index e30966ab8..418e8dd0f 100644 --- a/apps/emqx_rule_engine/test/emqx_rule_metrics_SUITE.erl +++ b/apps/emqx_rule_engine/test/emqx_rule_metrics_SUITE.erl @@ -40,13 +40,13 @@ groups() -> ]. init_per_suite(Config) -> - emqx_common_test_helpers:start_apps([emqx]), + emqx_common_test_helpers:start_apps([emqx_conf]), {ok, _} = emqx_rule_metrics:start_link(), Config. end_per_suite(_Config) -> catch emqx_rule_metrics:stop(), - emqx_common_test_helpers:stop_apps([emqx]), + emqx_common_test_helpers:stop_apps([emqx_conf]), ok. init_per_testcase(_, Config) -> diff --git a/apps/emqx_statsd/src/emqx_statsd_app.erl b/apps/emqx_statsd/src/emqx_statsd_app.erl index 4a5ff0496..820a86c04 100644 --- a/apps/emqx_statsd/src/emqx_statsd_app.erl +++ b/apps/emqx_statsd/src/emqx_statsd_app.erl @@ -32,9 +32,9 @@ stop(_) -> ok. maybe_enable_statsd() -> - case emqx:get_config([statsd, enable], false) of + case emqx_conf:get([statsd, enable], false) of true -> - emqx_statsd_sup:start_child(?APP, emqx:get_config([statsd], #{})); + emqx_statsd_sup:start_child(?APP, emqx_conf:get([statsd], #{})); false -> ok end. diff --git a/bin/emqx b/bin/emqx index 1be7996d1..23b991337 100755 --- a/bin/emqx +++ b/bin/emqx @@ -22,7 +22,7 @@ export REL_VSN RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME" CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}" REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN" -SCHEMA_MOD=emqx_machine_schema +SCHEMA_MOD=emqx_conf_schema WHOAMI=$(whoami) @@ -244,7 +244,7 @@ generate_config() { ## ths command populates two files: app.