Explorar el Código

Merge pull request #9750 from zhongwencool/bootstrap-app-env

fix: save app's env when bootstrapping and reloading
Zaiming (Stone) Shi hace 3 años
padre
commit
002f5dbd89

+ 1 - 0
.gitignore

@@ -67,6 +67,7 @@ mix.lock
 apps/emqx/test/emqx_static_checks_data/master.bpapi
 # rendered configurations
 *.conf.rendered
+*.conf.rendered.*
 lux_logs/
 /.prepare
 bom.json

+ 16 - 1
apps/emqx/src/config/emqx_config_logger.erl

@@ -18,7 +18,7 @@
 -behaviour(emqx_config_handler).
 
 %% API
--export([add_handler/0, remove_handler/0]).
+-export([add_handler/0, remove_handler/0, refresh_config/0]).
 -export([post_config_update/5]).
 
 -define(LOG, [log]).
@@ -31,6 +31,21 @@ remove_handler() ->
     ok = emqx_config_handler:remove_handler(?LOG),
     ok.
 
+%% refresh logger config when booting, the override config may have changed after node start.
+%% Kernel's app env is confirmed before the node starts,
+%% but we only copy cluster-override.conf from other node after this node starts,
+%% so we need to refresh the logger config after this node starts.
+%% It will not affect the logger config when cluster-override.conf is unchanged.
+refresh_config() ->
+    case emqx:get_raw_config(?LOG, undefined) of
+        %% no logger config when CT is running.
+        undefined ->
+            ok;
+        Log ->
+            {ok, _} = emqx:update_config(?LOG, Log),
+            ok
+    end.
+
 post_config_update(?LOG, _Req, _NewConf, _OldConf, AppEnvs) ->
     Kernel = proplists:get_value(kernel, AppEnvs),
     NewHandlers = proplists:get_value(logger, Kernel, []),

+ 12 - 12
apps/emqx/src/emqx_config.erl

@@ -333,7 +333,8 @@ init_load(SchemaMod, RawConf, Opts) when is_map(RawConf) ->
     RootNames = get_root_names(),
     RawConfAll = raw_conf_with_default(SchemaMod, RootNames, RawConfWithOverrides, Opts),
     %% check configs against the schema
-    {_AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}),
+    {AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}),
+    save_to_app_env(AppEnvs),
     ok = save_to_config_map(CheckedConf, RawConfAll).
 
 %% keep the raw and non-raw conf has the same keys to make update raw conf easier.
@@ -534,23 +535,21 @@ get_root_names() ->
     maps:get(names, persistent_term:get(?PERSIS_SCHEMA_MODS, #{names => []})).
 
 -spec save_configs(app_envs(), config(), raw_config(), raw_config(), update_opts()) -> ok.
-save_configs(_AppEnvs, Conf, RawConf, OverrideConf, Opts) ->
+save_configs(AppEnvs, Conf, RawConf, OverrideConf, Opts) ->
     %% We first try to save to override.conf, because saving to files is more error prone
     %% than saving into memory.
     ok = save_to_override_conf(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_app_env(AppEnvs),
     save_to_config_map(Conf, RawConf).
 
+%% we ignore kernel app env,
+%% because the old app env will be used in emqx_config_logger:post_config_update/5
+-define(IGNORE_APPS, [kernel]).
+
 -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
-    ).
+save_to_app_env(AppEnvs0) ->
+    AppEnvs = lists:filter(fun({App, _}) -> not lists:member(App, ?IGNORE_APPS) end, AppEnvs0),
+    application:set_env(AppEnvs).
 
 -spec save_to_config_map(config(), raw_config()) -> ok.
 save_to_config_map(Conf, RawConf) ->
@@ -582,6 +581,7 @@ save_to_override_conf(RawConf, Opts) ->
 add_handlers() ->
     ok = emqx_config_logger:add_handler(),
     emqx_sys_mon:add_handler(),
+    emqx_config_logger:refresh_config(),
     ok.
 
 remove_handlers() ->

+ 3 - 1
apps/emqx/test/emqx_common_test_helpers.erl

@@ -408,7 +408,9 @@ catch_call(F) ->
         C:E:S ->
             {crashed, {C, E, S}}
     end.
-force_set_config_file_paths(emqx_conf, Paths) ->
+force_set_config_file_paths(emqx_conf, [Path] = Paths) ->
+    Bin = iolist_to_binary(io_lib:format("node.config_files = [~p]~n", [Path])),
+    ok = file:write_file(Path, Bin, [append]),
     application:set_env(emqx, config_files, Paths);
 force_set_config_file_paths(emqx, Paths) ->
     application:set_env(emqx, config_files, Paths);

+ 1 - 1
apps/emqx_conf/src/emqx_conf_schema.erl

@@ -463,7 +463,7 @@ fields("node") ->
             )},
         {"config_files",
             sc(
-                list(string()),
+                hoconsc:array(string()),
                 #{
                     mapping => "emqx.config_files",
                     default => undefined,

+ 8 - 0
apps/emqx_conf/test/emqx_conf_app_SUITE.erl

@@ -92,6 +92,14 @@ set_data_dir_env() ->
     Node = atom_to_list(node()),
     %% will create certs and authz dir
     ok = filelib:ensure_dir(Node ++ "/configs/"),
+    {ok, [ConfigFile]} = application:get_env(emqx, config_files),
+    NewConfigFile = ConfigFile ++ "." ++ Node,
+    {ok, _} = file:copy(ConfigFile, NewConfigFile),
+    Bin = iolist_to_binary(io_lib:format("node.config_files = [~p]~n", [NewConfigFile])),
+    ok = file:write_file(NewConfigFile, Bin, [append]),
+    DataDir = iolist_to_binary(io_lib:format("node.data_dir = ~p~n", [Node])),
+    ok = file:write_file(NewConfigFile, DataDir, [append]),
+    application:set_env(emqx, config_files, [NewConfigFile]),
     application:set_env(emqx, data_dir, Node),
     application:set_env(emqx, cluster_override_conf_file, Node ++ "/configs/cluster-override.conf"),
     ok.