You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2024/07/03 22:26:23 UTC
(couchdb) branch config-reload-dot-d-dirs created (now b6ac8ecdb)
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a change to branch config-reload-dot-d-dirs
in repository https://gitbox.apache.org/repos/asf/couchdb.git
at b6ac8ecdb Make sure config reload finds new .ini files in .d directories
This branch includes the following new commits:
new b6ac8ecdb Make sure config reload finds new .ini files in .d directories
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(couchdb) 01/01: Make sure config reload finds new .ini files in .d directories
Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch config-reload-dot-d-dirs
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit b6ac8ecdbd838a49ed71840f8e3ad07ecb256138
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Wed Jul 3 18:22:11 2024 -0400
Make sure config reload finds new .ini files in .d directories
Previously we expanded the paths once at startup and then cached them.
Now we keep the directories around and re-expeand them on reload.
Fixes: https://github.com/apache/couchdb/issues/5111
---
src/config/src/config.erl | 57 ++++++++++++++++++++++++++++----------
src/config/src/config_app.erl | 15 ++--------
src/config/test/config_tests.erl | 59 +++++++++++++++++++++++++++++++++-------
3 files changed, 95 insertions(+), 36 deletions(-)
diff --git a/src/config/src/config.erl b/src/config/src/config.erl
index 417a104c5..5c7a36bd1 100644
--- a/src/config/src/config.erl
+++ b/src/config/src/config.erl
@@ -50,12 +50,16 @@
-include("config.hrl").
-record(config, {
- ini_files = undefined,
- write_filename = undefined
+ % Mix of *.ini files and *.d dirs
+ ini_files_dirs,
+ % Just *.ini files: original *.ini + expanded *.d dirs
+ ini_files,
+ % The file we write config values to
+ write_filename
}).
-start_link(IniFiles) ->
- gen_server:start_link({local, ?MODULE}, ?MODULE, IniFiles, []).
+start_link(IniFilesDirs) ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, IniFilesDirs, []).
stop() ->
gen_server:cast(?MODULE, stop).
@@ -245,22 +249,23 @@ listen_for_changes(CallbackModule, InitialState) ->
subscribe_for_changes(Subscription) ->
config_notifier:subscribe(Subscription).
-init(IniFiles) ->
+init(IniFilesDirs) ->
enable_early_features(),
ets:new(?MODULE, [named_table, set, protected, {read_concurrency, true}]),
+ IniFiles = expand_dirs(IniFilesDirs),
maps:foreach(
fun(K, V) ->
true = ets:insert(?MODULE, {K, V})
end,
ini_map(IniFiles)
),
- WriteFile =
- case IniFiles of
- [_ | _] -> lists:last(IniFiles);
- _ -> undefined
- end,
debug_config(),
- {ok, #config{ini_files = IniFiles, write_filename = WriteFile}}.
+ Config = #config{
+ ini_files_dirs = IniFilesDirs,
+ ini_files = IniFiles,
+ write_filename = get_write_file(IniFiles)
+ },
+ {ok, Config}.
handle_call(all, _From, Config) ->
Resp = lists:sort((ets:tab2list(?MODULE))),
@@ -330,9 +335,11 @@ handle_call({delete, Sec, Key, Persist, Reason}, _From, Config) ->
Else ->
{reply, Else, Config}
end;
-handle_call(reload, _From, Config) ->
+handle_call(reload, _From, #config{} = Config) ->
+ #config{ini_files_dirs = IniFilesDirs} = Config,
+ IniFiles = expand_dirs(IniFilesDirs),
% Update ets with ini values.
- IniMap = ini_map(Config#config.ini_files),
+ IniMap = ini_map(IniFiles),
maps:foreach(
fun({Sec, Key} = K, V) ->
VExisting = get(Sec, Key, V),
@@ -368,7 +375,11 @@ handle_call(reload, _From, Config) ->
nil,
?MODULE
),
- {reply, ok, Config}.
+ Config1 = Config#config{
+ ini_files = IniFiles,
+ write_filename = get_write_file(IniFiles)
+ },
+ {reply, ok, Config1}.
handle_cast(stop, State) ->
{stop, normal, State};
@@ -455,6 +466,24 @@ read_ini_file(IniFile) ->
throw({startup_error, Msg})
end.
+get_write_file([_ | _] = IniFiles) ->
+ lists:last(IniFiles);
+get_write_file(_) ->
+ undefined.
+
+% Takes a list of files and directories with *.ini files, and expands
+% the directories inline with individual *.ini files
+expand_dirs(IniFilesDirs) ->
+ lists:flatmap(fun expand_dirs_fmap/1, IniFilesDirs).
+
+expand_dirs_fmap(File) ->
+ case filelib:is_dir(File) of
+ true ->
+ lists:sort(filelib:wildcard(File ++ "/*.ini"));
+ false ->
+ [File]
+ end.
+
remove_comments(Line) ->
case trim(Line) of
[$; | _] ->
diff --git a/src/config/src/config_app.erl b/src/config/src/config_app.erl
index 8ba58e6d2..62061df08 100644
--- a/src/config/src/config_app.erl
+++ b/src/config/src/config_app.erl
@@ -22,14 +22,13 @@
%% ===================================================================
start(_StartType, _StartArgs) ->
- config_sup:start_link(get_ini_files()).
+ config_sup:start_link(get_ini_files_dirs()).
stop(_State) ->
ok.
-get_ini_files() ->
- IniFiles = hd([L || L <- [command_line(), env(), default()], L =/= skip]),
- lists:flatmap(fun expand_dirs/1, IniFiles).
+get_ini_files_dirs() ->
+ hd([L || L <- [command_line(), env(), default()], L =/= skip]).
env() ->
case application:get_env(config, ini_files) of
@@ -56,11 +55,3 @@ default() ->
filename:join(Etc, "local.d")
],
lists:filter(fun filelib:is_file/1, Default).
-
-expand_dirs(File) ->
- case filelib:is_dir(File) of
- true ->
- lists:sort(filelib:wildcard(File ++ "/*.ini"));
- false ->
- [File]
- end.
diff --git a/src/config/test/config_tests.erl b/src/config/test/config_tests.erl
index 8c0f29ec0..d4008c2b1 100644
--- a/src/config/test/config_tests.erl
+++ b/src/config/test/config_tests.erl
@@ -55,6 +55,8 @@
FileName
end).
+-define(TEMP_CONFIG_DIR, "temp_config.d").
+
setup() ->
setup(?CONFIG_CHAIN).
@@ -112,21 +114,33 @@ handle_config_terminate(Self, Reason, {Pid, State}) ->
ok.
setup_ini() ->
- Chain = [write_ini(F) || F <- ["default.ini", "local.ini"]],
+ Chain = [write_ini(F) || F <- ["default.ini", "local.ini", ?TEMP_CONFIG_DIR]],
{Chain, setup(Chain)}.
teardown_ini({Chain, Apps}) ->
- lists:foreach(
- fun(Path) -> ok = file:delete(Path) end,
- Chain
- ),
+ lists:foreach(fun delete_ini/1, Chain),
teardown(Apps).
-write_ini(FileName) ->
- Path = filename:join([?TEMPDIR, FileName]),
- Data = io_lib:format("[section]\nfile = ~s\n", [FileName]),
- ok = file:write_file(Path, Data),
- Path.
+write_ini(FileOrDir) ->
+ case filename:extension(FileOrDir) of
+ ".ini" ->
+ Path = filename:join([?TEMPDIR, FileOrDir]),
+ Data = io_lib:format("[section]\nfile = ~s\n", [FileOrDir]),
+ ok = file:write_file(Path, Data),
+ Path;
+ ".d" ->
+ Path = filename:join([?TEMPDIR, FileOrDir]),
+ ok = filelib:ensure_path(Path),
+ Path
+ end.
+
+delete_ini(FileOrDir) ->
+ case filename:extension(FileOrDir) of
+ ".ini" ->
+ ok = file:delete(FileOrDir);
+ ".d" ->
+ ok = file:del_dir_r(FileOrDir)
+ end.
config_delete_reload_restart_test_() ->
{
@@ -140,6 +154,17 @@ config_delete_reload_restart_test_() ->
]
}.
+config_reload_find_new_init_files_test_() ->
+ {
+ "Reload should find newly added .ini file in .d dirs",
+ foreach,
+ fun setup_ini/0,
+ fun teardown_ini/1,
+ [
+ fun reload_finds_new_ini_file/0
+ ]
+ }.
+
config_get_test_() ->
{
"Config get tests",
@@ -774,6 +799,20 @@ non_persistent_set_delete_reload_restart() ->
wait_config_get("section", "file", "local.ini"),
?assertEqual("local.ini", config:get("section", "file")).
+reload_finds_new_ini_file() ->
+ config:set("foo", "bar", "baz"),
+ ?assertEqual(ok, config:reload()),
+ ?assertEqual("baz", config:get("foo", "bar")),
+ DirPath = filename:join([?TEMPDIR, ?TEMP_CONFIG_DIR]),
+ ?assert(filelib:is_dir(DirPath)),
+ IniPath = filename:join(DirPath, "10-extra.ini"),
+ ok = file:write_file(IniPath, "[foo]\nbar = zab\n"),
+ ?assertEqual(ok, config:reload()),
+ wait_config_get("foo", "bar", "zab"),
+ config:set("foo", "bar", "zag"),
+ % 10-extra.ini is also the file we write to
+ ?assertEqual({ok, <<"[foo]\nbar = zag\n">>}, file:read_file(IniPath)).
+
wait_config_get(Sec, Key, Val) ->
test_util:wait(
fun() ->