refactor(config): load emqx.conf before all other tasks in emqx_app
This commit is contained in:
parent
1433a7e0fe
commit
2666c06232
|
@ -42,6 +42,7 @@
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
start(_Type, _Args) ->
|
start(_Type, _Args) ->
|
||||||
|
emqx_config:load(),
|
||||||
set_backtrace_depth(),
|
set_backtrace_depth(),
|
||||||
print_otp_version_warning(),
|
print_otp_version_warning(),
|
||||||
print_banner(),
|
print_banner(),
|
||||||
|
|
|
@ -17,6 +17,15 @@
|
||||||
|
|
||||||
-compile({no_auto_import, [get/0, get/1]}).
|
-compile({no_auto_import, [get/0, get/1]}).
|
||||||
|
|
||||||
|
-export([ load/0
|
||||||
|
, save_configs/2
|
||||||
|
, save_to_app_env/1
|
||||||
|
, save_to_emqx_config/2
|
||||||
|
, save_to_override_conf/1
|
||||||
|
, to_richmap/1
|
||||||
|
, to_plainmap/1
|
||||||
|
]).
|
||||||
|
|
||||||
-export([ get/0
|
-export([ get/0
|
||||||
, get/1
|
, get/1
|
||||||
, get/2
|
, get/2
|
||||||
|
@ -141,3 +150,75 @@ put_raw(Config) ->
|
||||||
-spec put_raw(emqx_map_lib:config_key_path(), term()) -> ok.
|
-spec put_raw(emqx_map_lib:config_key_path(), term()) -> ok.
|
||||||
put_raw(KeyPath, Config) ->
|
put_raw(KeyPath, Config) ->
|
||||||
put_raw(emqx_map_lib:deep_put(KeyPath, get_raw(), Config)).
|
put_raw(emqx_map_lib:deep_put(KeyPath, get_raw(), Config)).
|
||||||
|
|
||||||
|
%%============================================================================
|
||||||
|
%% Load/Update configs From/To files
|
||||||
|
%%============================================================================
|
||||||
|
load() ->
|
||||||
|
%% the app env 'config_files' should be set before emqx get started.
|
||||||
|
ConfFiles = application:get_env(emqx, config_files, []),
|
||||||
|
RawRichConf = lists:foldl(fun(ConfFile, Acc) ->
|
||||||
|
Raw = load_hocon_file(ConfFile),
|
||||||
|
emqx_map_lib:deep_merge(Acc, Raw)
|
||||||
|
end, #{}, ConfFiles),
|
||||||
|
{_MappedEnvs, RichConf} = hocon_schema:map_translate(emqx_schema, RawRichConf, #{}),
|
||||||
|
ok = save_to_emqx_config(to_plainmap(RichConf), to_plainmap(RawRichConf)).
|
||||||
|
|
||||||
|
-spec save_configs(raw_config(), Opts) -> ok | {error, term()}
|
||||||
|
when Opts :: #{overridden_keys => all | [binary()]}.
|
||||||
|
save_configs(RawConf, Opts) ->
|
||||||
|
{_MappedEnvs, RichConf} = hocon_schema:map_translate(emqx_schema, to_richmap(RawConf), #{}),
|
||||||
|
save_to_emqx_config(to_plainmap(RichConf), RawConf),
|
||||||
|
|
||||||
|
%% 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 application env
|
||||||
|
%save_to_app_env(_MappedEnvs),
|
||||||
|
|
||||||
|
%% We don't save the entire config to emqx_override.conf, but only the sub configs
|
||||||
|
%% specified by RootKeys
|
||||||
|
case maps:get(overridden_keys, Opts, all) of
|
||||||
|
all -> save_to_override_conf(RawConf);
|
||||||
|
RootKeys -> save_to_override_conf(maps:with(RootKeys, RawConf))
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec save_to_app_env([tuple()]) -> ok.
|
||||||
|
save_to_app_env(AppEnvs) ->
|
||||||
|
lists:foreach(fun({AppName, Envs}) ->
|
||||||
|
[application:set_env(AppName, Par, Val) || {Par, Val} <- Envs]
|
||||||
|
end, AppEnvs).
|
||||||
|
|
||||||
|
-spec save_to_emqx_config(config(), raw_config()) -> ok.
|
||||||
|
save_to_emqx_config(Conf, RawConf) ->
|
||||||
|
emqx_config:put(emqx_map_lib:unsafe_atom_key_map(Conf)),
|
||||||
|
emqx_config:put_raw(RawConf).
|
||||||
|
|
||||||
|
-spec save_to_override_conf(config()) -> ok | {error, term()}.
|
||||||
|
save_to_override_conf(Conf) ->
|
||||||
|
FileName = emqx_override_conf_name(),
|
||||||
|
OldConf = load_hocon_file(FileName),
|
||||||
|
MergedConf = maps:merge(OldConf, Conf),
|
||||||
|
ok = filelib:ensure_dir(FileName),
|
||||||
|
case file:write_file(FileName, jsx:prettify(jsx:encode(MergedConf))) of
|
||||||
|
ok -> ok;
|
||||||
|
{error, Reason} ->
|
||||||
|
logger:error("write to ~s failed, ~p", [FileName, Reason]),
|
||||||
|
{error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
|
load_hocon_file(FileName) ->
|
||||||
|
case filelib:is_regular(FileName) of
|
||||||
|
true ->
|
||||||
|
{ok, Raw0} = hocon:load(FileName, #{format => richmap}),
|
||||||
|
Raw0;
|
||||||
|
false -> #{}
|
||||||
|
end.
|
||||||
|
|
||||||
|
emqx_override_conf_name() ->
|
||||||
|
filename:join([emqx_config:get([node, data_dir]), "emqx_override.conf"]).
|
||||||
|
|
||||||
|
to_richmap(Map) ->
|
||||||
|
{ok, RichMap} = hocon:binary(jsx:encode(Map), #{format => richmap}),
|
||||||
|
RichMap.
|
||||||
|
|
||||||
|
to_plainmap(RichMap) ->
|
||||||
|
hocon_schema:richmap_to_map(RichMap).
|
|
@ -76,10 +76,8 @@ add_handler(ConfKeyPath, HandlerName) ->
|
||||||
|
|
||||||
-spec init(term()) -> {ok, state()}.
|
-spec init(term()) -> {ok, state()}.
|
||||||
init(_) ->
|
init(_) ->
|
||||||
RawConf = load_config_file(),
|
|
||||||
{_MappedEnvs, Conf} = hocon_schema:map_translate(emqx_schema, RawConf, #{}),
|
|
||||||
ok = save_config_to_emqx(to_plainmap(Conf), to_plainmap(RawConf)),
|
|
||||||
{ok, #{handlers => #{?MOD => ?MODULE}}}.
|
{ok, #{handlers => #{?MOD => ?MODULE}}}.
|
||||||
|
|
||||||
handle_call({add_child, ConfKeyPath, HandlerName}, _From,
|
handle_call({add_child, ConfKeyPath, HandlerName}, _From,
|
||||||
State = #{handlers := Handlers}) ->
|
State = #{handlers := Handlers}) ->
|
||||||
{reply, ok, State#{handlers =>
|
{reply, ok, State#{handlers =>
|
||||||
|
@ -89,7 +87,7 @@ handle_call({update_config, ConfKeyPath, UpdateReq, RawConf}, _From,
|
||||||
#{handlers := Handlers} = State) ->
|
#{handlers := Handlers} = State) ->
|
||||||
OldConf = emqx_config:get(),
|
OldConf = emqx_config:get(),
|
||||||
try {RootKeys, Conf} = do_update_config(ConfKeyPath, Handlers, RawConf, UpdateReq),
|
try {RootKeys, Conf} = do_update_config(ConfKeyPath, Handlers, RawConf, UpdateReq),
|
||||||
Result = save_configs(RootKeys, Conf),
|
Result = emqx_config:save_configs(Conf, #{overridden_keys => RootKeys}),
|
||||||
do_post_update_config(ConfKeyPath, Handlers, OldConf, emqx_config:get()),
|
do_post_update_config(ConfKeyPath, Handlers, OldConf, emqx_config:get()),
|
||||||
{reply, Result, State}
|
{reply, Result, State}
|
||||||
catch
|
catch
|
||||||
|
@ -165,71 +163,6 @@ merge_to_old_config(UpdateReq, RawConf) when is_map(UpdateReq), is_map(RawConf)
|
||||||
merge_to_old_config(UpdateReq, _RawConf) ->
|
merge_to_old_config(UpdateReq, _RawConf) ->
|
||||||
UpdateReq.
|
UpdateReq.
|
||||||
|
|
||||||
%%============================================================================
|
|
||||||
save_configs(RootKeys, RawConf) ->
|
|
||||||
{_MappedEnvs, Conf} = hocon_schema:map_translate(emqx_schema, to_richmap(RawConf), #{}),
|
|
||||||
%% We may need also support hot config update for the apps that use application envs.
|
|
||||||
%% If so uncomment the following line to update the configs to application env
|
|
||||||
%save_config_to_app_env(_MappedEnvs),
|
|
||||||
save_config_to_emqx(to_plainmap(Conf), RawConf),
|
|
||||||
save_config_to_disk(RootKeys, RawConf).
|
|
||||||
|
|
||||||
% save_config_to_app_env(MappedEnvs) ->
|
|
||||||
% lists:foreach(fun({AppName, Envs}) ->
|
|
||||||
% [application:set_env(AppName, Par, Val) || {Par, Val} <- Envs]
|
|
||||||
% end, MappedEnvs).
|
|
||||||
|
|
||||||
save_config_to_emqx(Conf, RawConf) ->
|
|
||||||
?LOG(debug, "set config: ~p", [Conf]),
|
|
||||||
emqx_config:put(emqx_map_lib:unsafe_atom_key_map(Conf)),
|
|
||||||
emqx_config:put_raw(RawConf).
|
|
||||||
|
|
||||||
save_config_to_disk(RootKeys, Conf) ->
|
|
||||||
FileName = emqx_override_conf_name(),
|
|
||||||
OldConf = read_old_config(FileName),
|
|
||||||
%% We don't save the overall config to file, but only the sub configs
|
|
||||||
%% under RootKeys
|
|
||||||
write_new_config(FileName,
|
|
||||||
maps:merge(OldConf, maps:with(RootKeys, Conf))).
|
|
||||||
|
|
||||||
write_new_config(FileName, Conf) ->
|
|
||||||
case file:write_file(FileName, jsx:prettify(jsx:encode(Conf))) of
|
|
||||||
ok -> ok;
|
|
||||||
{error, Reason} ->
|
|
||||||
logger:error("write to ~s failed, ~p", [FileName, Reason]),
|
|
||||||
{error, Reason}
|
|
||||||
end.
|
|
||||||
|
|
||||||
read_old_config(FileName) ->
|
|
||||||
case file:read_file(FileName) of
|
|
||||||
{ok, Text} ->
|
|
||||||
try jsx:decode(Text, [{return_maps, true}]) of
|
|
||||||
Conf when is_map(Conf) -> Conf;
|
|
||||||
_ -> #{}
|
|
||||||
catch _Err : _Reason ->
|
|
||||||
#{}
|
|
||||||
end;
|
|
||||||
_ -> #{}
|
|
||||||
end.
|
|
||||||
|
|
||||||
load_config_file() ->
|
|
||||||
lists:foldl(fun(ConfFile, Acc) ->
|
|
||||||
{ok, RawConf} = hocon:load(ConfFile, #{format => richmap}),
|
|
||||||
emqx_map_lib:deep_merge(Acc, RawConf)
|
|
||||||
end, #{}, application:get_env(emqx, config_files, [])).
|
|
||||||
|
|
||||||
emqx_override_conf_name() ->
|
|
||||||
File = filename:join([emqx_config:get([node, data_dir]), "emqx_override.conf"]),
|
|
||||||
ok = filelib:ensure_dir(File),
|
|
||||||
File.
|
|
||||||
|
|
||||||
to_richmap(Map) ->
|
|
||||||
{ok, RichMap} = hocon:binary(jsx:encode(Map), #{format => richmap}),
|
|
||||||
RichMap.
|
|
||||||
|
|
||||||
to_plainmap(RichMap) ->
|
|
||||||
hocon_schema:richmap_to_map(RichMap).
|
|
||||||
|
|
||||||
bin(A) when is_atom(A) -> list_to_binary(atom_to_list(A));
|
bin(A) when is_atom(A) -> list_to_binary(atom_to_list(A));
|
||||||
bin(B) when is_binary(B) -> B;
|
bin(B) when is_binary(B) -> B;
|
||||||
bin(S) when is_list(S) -> list_to_binary(S).
|
bin(S) when is_list(S) -> list_to_binary(S).
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
%% @doc Load all plugins when the broker started.
|
%% @doc Load all plugins when the broker started.
|
||||||
-spec(load() -> ok | ignore | {error, term()}).
|
-spec(load() -> ok | ignore | {error, term()}).
|
||||||
load() ->
|
load() ->
|
||||||
ok = load_ext_plugins(emqx_config:get([plugins, expand_plugins_dir])).
|
ok = load_ext_plugins(emqx_config:get([plugins, expand_plugins_dir], undefined)).
|
||||||
|
|
||||||
%% @doc Load a Plugin
|
%% @doc Load a Plugin
|
||||||
-spec(load(atom()) -> ok | {error, term()}).
|
-spec(load(atom()) -> ok | {error, term()}).
|
||||||
|
|
Loading…
Reference in New Issue