diff --git a/apps/emqx/src/emqx_config_handler.erl b/apps/emqx/src/emqx_config_handler.erl index e634112d7..a189fc9e5 100644 --- a/apps/emqx/src/emqx_config_handler.erl +++ b/apps/emqx/src/emqx_config_handler.erl @@ -61,7 +61,7 @@ -callback pre_config_update([atom()], emqx_config:update_request(), emqx_config:raw_config()) -> ok | {ok, emqx_config:update_request()} | {error, term()}. -callback propagated_pre_config_update( - [atom()], emqx_config:update_request(), emqx_config:raw_config() + [binary()], emqx_config:update_request(), emqx_config:raw_config() ) -> ok | {ok, emqx_config:update_request()} | {error, term()}. @@ -264,7 +264,8 @@ do_update_config([], Handlers, OldRawConf, UpdateReq, ConfKeyPath) -> old_raw_conf => OldRawConf, update_req => UpdateReq, conf_key_path => ConfKeyPath, - callback => pre_config_update + callback => pre_config_update, + is_propagated => false }); do_update_config( [ConfKey | SubConfKeyPath], @@ -391,6 +392,12 @@ get_sub_handlers(ConfKey, Handlers) when is_atom(ConfKey) -> case maps:find(ConfKey, Handlers) of error -> maps:get(?WKEY, Handlers, #{}); {ok, SubHandlers} -> SubHandlers + end; +get_sub_handlers(ConfKey, Handlers) when is_binary(ConfKey) -> + ConcreteHandlerKeys = maps:keys(Handlers) -- [?MOD, ?WKEY], + case lists:search(fun(K) -> bin(K) =:= ConfKey end, ConcreteHandlerKeys) of + {value, Key} -> maps:get(Key, Handlers); + false -> maps:get(?WKEY, Handlers, #{}) end. get_sub_config(ConfKey, Conf) when is_map(Conf) -> @@ -487,15 +494,19 @@ propagate_pre_config_updates_to_subconf_key( handlers := Handlers, old_raw_conf := OldRawConf, update_req := UpdateReq, - conf_key_path := ConfKeyPath + conf_key_path := ConfKeyPath, + is_propagated := IsPropagated } = Ctx ) -> - AtomKey = atom(Key), - SubHandlers = get_sub_handlers(AtomKey, Handlers), BinKey = bin(Key), + SubHandlers = get_sub_handlers(BinKey, Handlers), SubUpdateReq = get_sub_config(BinKey, UpdateReq), SubOldConf = get_sub_config(BinKey, OldRawConf), - SubConfKeyPath = ConfKeyPath ++ [AtomKey], + SubConfKeyPath = + case IsPropagated of + true -> ConfKeyPath ++ [BinKey]; + false -> bin_path(ConfKeyPath) ++ [BinKey] + end, case {SubOldConf, SubUpdateReq} of %% we have handler, but no relevant keys in both configs (new and old), %% so we don't need to go further @@ -508,6 +519,7 @@ propagate_pre_config_updates_to_subconf_key( old_raw_conf := SubOldConf, update_req := SubUpdateReq, conf_key_path := SubConfKeyPath, + is_propagated := true, callback := propagated_pre_config_update }) of diff --git a/apps/emqx/test/emqx_config_handler_SUITE.erl b/apps/emqx/test/emqx_config_handler_SUITE.erl index ec24b54e6..bb91bcbe4 100644 --- a/apps/emqx/test/emqx_config_handler_SUITE.erl +++ b/apps/emqx/test/emqx_config_handler_SUITE.erl @@ -371,9 +371,13 @@ pre_config_update([sysmon, os, sysmem_high_watermark], UpdateReq, _RawConf) -> pre_config_update([sysmon, os, mem_check_interval], _UpdateReq, _RawConf) -> {error, pre_config_update_error}. -propagated_pre_config_update([sysmon, os, cpu_check_interval], <<"333s">>, _RawConf) -> +propagated_pre_config_update( + [<<"sysmon">>, <<"os">>, <<"cpu_check_interval">>], <<"333s">>, _RawConf +) -> {ok, <<"444s">>}; -propagated_pre_config_update([sysmon, os, mem_check_interval], _UpdateReq, _RawConf) -> +propagated_pre_config_update( + [<<"sysmon">>, <<"os">>, <<"mem_check_interval">>], _UpdateReq, _RawConf +) -> {error, pre_config_update_error}; propagated_pre_config_update(_ConfKeyPath, _UpdateReq, _RawConf) -> ok. diff --git a/apps/emqx_authn/src/emqx_authentication_config.erl b/apps/emqx_authn/src/emqx_authentication_config.erl index 97d082da6..95140a0e8 100644 --- a/apps/emqx_authn/src/emqx_authentication_config.erl +++ b/apps/emqx_authn/src/emqx_authentication_config.erl @@ -67,8 +67,8 @@ -spec pre_config_update(list(atom()), update_request(), emqx_config:raw_config()) -> {ok, map() | list()} | {error, term()}. -pre_config_update(Paths, UpdateReq, OldConfig) -> - try do_pre_config_update(Paths, UpdateReq, to_list(OldConfig)) of +pre_config_update(ConfPath, UpdateReq, OldConfig) -> + try do_pre_config_update(ConfPath, UpdateReq, to_list(OldConfig)) of {error, Reason} -> {error, Reason}; {ok, NewConfig} -> {ok, NewConfig} catch @@ -132,25 +132,22 @@ do_pre_config_update(_, {move_authenticator, _ChainName, AuthenticatorID, Positi end end end; -do_pre_config_update(Paths, {merge_authenticators, NewConfig}, OldConfig) -> +do_pre_config_update(ConfPath, {merge_authenticators, NewConfig}, OldConfig) -> MergeConfig = merge_authenticators(OldConfig, NewConfig), - do_pre_config_update(Paths, MergeConfig, OldConfig); + do_pre_config_update(ConfPath, MergeConfig, OldConfig); do_pre_config_update(_, OldConfig, OldConfig) -> {ok, OldConfig}; -do_pre_config_update(Paths, NewConfig, _OldConfig) -> - ChainName = chain_name(Paths), - {ok, [ - begin - CertsDir = certs_dir(ChainName, New), - convert_certs(CertsDir, New) - end - || New <- to_list(NewConfig) - ]}. +do_pre_config_update(ConfPath, NewConfig, _OldConfig) -> + convert_certs_for_conf_path(ConfPath, NewConfig). --spec propagated_pre_config_update(list(atom()), update_request(), emqx_config:raw_config()) -> +%% @doc Handle listener config changes made at higher level. + +-spec propagated_pre_config_update(list(binary()), update_request(), emqx_config:raw_config()) -> {ok, map() | list()} | {error, term()}. -propagated_pre_config_update(Paths, NewConfig, OldConfig) -> - do_pre_config_update(Paths, NewConfig, OldConfig). +propagated_pre_config_update(_, OldConfig, OldConfig) -> + {ok, OldConfig}; +propagated_pre_config_update(ConfPath, NewConfig, _OldConfig) -> + convert_certs_for_conf_path(ConfPath, NewConfig). -spec post_config_update( list(atom()), @@ -160,8 +157,8 @@ propagated_pre_config_update(Paths, NewConfig, OldConfig) -> emqx_config:app_envs() ) -> ok | {ok, map()} | {error, term()}. -post_config_update(Paths, UpdateReq, NewConfig, OldConfig, AppEnvs) -> - do_post_config_update(Paths, UpdateReq, to_list(NewConfig), OldConfig, AppEnvs). +post_config_update(ConfPath, UpdateReq, NewConfig, OldConfig, AppEnvs) -> + do_post_config_update(ConfPath, UpdateReq, to_list(NewConfig), OldConfig, AppEnvs). do_post_config_update( _, {create_authenticator, ChainName, Config}, NewConfig, _OldConfig, _AppEnvs @@ -199,8 +196,8 @@ do_post_config_update( emqx_authentication:move_authenticator(ChainName, AuthenticatorID, Position); do_post_config_update(_, _UpdateReq, OldConfig, OldConfig, _AppEnvs) -> ok; -do_post_config_update(Paths, _UpdateReq, NewConfig0, OldConfig0, _AppEnvs) -> - ChainName = chain_name(Paths), +do_post_config_update(ConfPath, _UpdateReq, NewConfig0, OldConfig0, _AppEnvs) -> + ChainName = chain_name(ConfPath), OldConfig = to_list(OldConfig0), NewConfig = to_list(NewConfig0), OldIds = lists:map(fun authenticator_id/1, OldConfig), @@ -210,6 +207,8 @@ do_post_config_update(Paths, _UpdateReq, NewConfig0, OldConfig0, _AppEnvs) -> ok = emqx_authentication:reorder_authenticator(ChainName, NewIds), ok. +%% @doc Handle listener config changes made at higher level. + -spec propagated_post_config_update( list(atom()), update_request(), @@ -218,8 +217,8 @@ do_post_config_update(Paths, _UpdateReq, NewConfig0, OldConfig0, _AppEnvs) -> emqx_config:app_envs() ) -> ok. -propagated_post_config_update(Paths, UpdateReq, NewConfig, OldConfig, AppEnvs) -> - ok = post_config_update(Paths, UpdateReq, NewConfig, OldConfig, AppEnvs), +propagated_post_config_update(ConfPath, UpdateReq, NewConfig, OldConfig, AppEnvs) -> + ok = post_config_update(ConfPath, UpdateReq, NewConfig, OldConfig, AppEnvs), ok. %% create new authenticators and update existing ones @@ -257,6 +256,17 @@ to_list(M) when M =:= #{} -> []; to_list(M) when is_map(M) -> [M]; to_list(L) when is_list(L) -> L. +convert_certs_for_conf_path(ConfPath, NewConfig) -> + ChainName = chain_name_for_filepath(ConfPath), + CovertedConfs = lists:map( + fun(Conf) -> + CertsDir = certs_dir(ChainName, Conf), + convert_certs(CertsDir, Conf) + end, + to_list(NewConfig) + ), + {ok, CovertedConfs}. + convert_certs(CertsDir, NewConfig) -> NewSSL = maps:get(<<"ssl">>, NewConfig, undefined), case emqx_tls_lib:ensure_ssl_files(CertsDir, NewSSL) of @@ -353,6 +363,14 @@ chain_name([listeners, Type, Name, authentication]) -> %% Type, Name atoms exist, so let 'Type:Name' exist too. binary_to_atom(<<(atom_to_binary(Type))/binary, ":", (atom_to_binary(Name))/binary>>). +chain_name_for_filepath(Path) -> + do_chain_name_for_filepath([to_bin(Key) || Key <- Path]). + +do_chain_name_for_filepath([<<"authentication">>]) -> + to_bin(?GLOBAL); +do_chain_name_for_filepath([<<"listeners">>, Type, Name, <<"authentication">>]) -> + <<(to_bin(Type))/binary, ":", (to_bin(Name))/binary>>. + merge_authenticators(OriginConf0, NewConf0) -> {OriginConf1, NewConf1} = lists:foldl( diff --git a/apps/emqx_conf/src/emqx_conf.app.src b/apps/emqx_conf/src/emqx_conf.app.src index ab65c03c8..a4781e6fb 100644 --- a/apps/emqx_conf/src/emqx_conf.app.src +++ b/apps/emqx_conf/src/emqx_conf.app.src @@ -1,6 +1,6 @@ {application, emqx_conf, [ {description, "EMQX configuration management"}, - {vsn, "0.1.26"}, + {vsn, "0.1.27"}, {registered, []}, {mod, {emqx_conf_app, []}}, {applications, [kernel, stdlib, emqx_ctl]},