fix(config): always fill defautls for all roots

prior to this commit, if a root existed in config files
it skips populating default values in raw config,
this made impossible to add default values for authz sources.
This commit is contained in:
Zaiming (Stone) Shi 2023-04-27 16:01:14 +02:00
parent 5acf0e281e
commit e0dc5645ab
2 changed files with 36 additions and 32 deletions

View File

@ -35,7 +35,6 @@
save_to_config_map/2, save_to_config_map/2,
save_to_override_conf/3 save_to_override_conf/3
]). ]).
-export([raw_conf_with_default/4]).
-export([merge_envs/2]). -export([merge_envs/2]).
-export([ -export([
@ -329,7 +328,7 @@ init_load(SchemaMod, ConfFiles) ->
-spec init_load(module(), [string()] | binary() | hocon:config()) -> ok. -spec init_load(module(), [string()] | binary() | hocon:config()) -> ok.
init_load(SchemaMod, Conf, Opts) when is_list(Conf) orelse is_binary(Conf) -> init_load(SchemaMod, Conf, Opts) when is_list(Conf) orelse is_binary(Conf) ->
HasDeprecatedFile = has_deprecated_file(), HasDeprecatedFile = has_deprecated_file(),
RawConf = parse_hocon(HasDeprecatedFile, Conf), RawConf = load_config_files(HasDeprecatedFile, Conf),
init_load(HasDeprecatedFile, SchemaMod, RawConf, Opts). init_load(HasDeprecatedFile, SchemaMod, RawConf, Opts).
init_load(true, SchemaMod, RawConf, Opts) when is_map(RawConf) -> init_load(true, SchemaMod, RawConf, Opts) when is_map(RawConf) ->
@ -339,18 +338,16 @@ init_load(true, SchemaMod, RawConf, Opts) when is_map(RawConf) ->
RawConfWithEnvs = merge_envs(SchemaMod, RawConf), RawConfWithEnvs = merge_envs(SchemaMod, RawConf),
Overrides = read_override_confs(), Overrides = read_override_confs(),
RawConfWithOverrides = hocon:deep_merge(RawConfWithEnvs, Overrides), RawConfWithOverrides = hocon:deep_merge(RawConfWithEnvs, Overrides),
RootNames = get_root_names(), RawConfAll = maybe_fill_defaults(SchemaMod, RawConfWithOverrides, Opts),
RawConfAll = raw_conf_with_default(SchemaMod, RootNames, RawConfWithOverrides, Opts),
%% check configs against the schema %% check configs against the schema
{AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}), {AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}),
save_to_app_env(AppEnvs), save_to_app_env(AppEnvs),
ok = save_to_config_map(CheckedConf, RawConfAll); ok = save_to_config_map(CheckedConf, RawConfAll);
init_load(false, SchemaMod, RawConf, Opts) when is_map(RawConf) -> init_load(false, SchemaMod, RawConf, Opts) when is_map(RawConf) ->
ok = save_schema_mod_and_names(SchemaMod), ok = save_schema_mod_and_names(SchemaMod),
RootNames = get_root_names(),
%% Merge environment variable overrides on top %% Merge environment variable overrides on top
RawConfWithEnvs = merge_envs(SchemaMod, RawConf), RawConfWithEnvs = merge_envs(SchemaMod, RawConf),
RawConfAll = raw_conf_with_default(SchemaMod, RootNames, RawConfWithEnvs, Opts), RawConfAll = maybe_fill_defaults(SchemaMod, RawConfWithEnvs, Opts),
%% check configs against the schema %% check configs against the schema
{AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}), {AppEnvs, CheckedConf} = check_config(SchemaMod, RawConfAll, #{}),
save_to_app_env(AppEnvs), save_to_app_env(AppEnvs),
@ -363,47 +360,53 @@ read_override_confs() ->
hocon:deep_merge(ClusterOverrides, LocalOverrides). hocon:deep_merge(ClusterOverrides, LocalOverrides).
%% keep the raw and non-raw conf has the same keys to make update raw conf easier. %% keep the raw and non-raw conf has the same keys to make update raw conf easier.
raw_conf_with_default(SchemaMod, RootNames, RawConf, #{raw_with_default := true}) -> maybe_fill_defaults(SchemaMod, RawConf0, #{raw_with_default := true}) ->
Fun = fun(Name, Acc) -> RootSchemas = hocon_schema:roots(SchemaMod),
case maps:is_key(Name, RawConf) of %% the roots which are missing from the loaded configs
true -> MissingRoots = lists:filtermap(
Acc; fun({BinName, Sc}) ->
false -> case maps:is_key(BinName, RawConf0) of
case lists:keyfind(Name, 1, hocon_schema:roots(SchemaMod)) of true -> false;
false -> false -> {true, Sc}
Acc; end
{_, {_, Schema}} -> end,
Acc#{Name => schema_default(Schema)} RootSchemas
end ),
end RawConf = lists:foldl(
end, fun({RootName, Schema}, Acc) ->
RawDefault = lists:foldl(Fun, #{}, RootNames), Acc#{bin(RootName) => seed_default(Schema)}
maps:merge(RawConf, fill_defaults(SchemaMod, RawDefault, #{})); end,
raw_conf_with_default(_SchemaMod, _RootNames, RawConf, _Opts) -> RawConf0,
MissingRoots
),
fill_defaults(RawConf);
maybe_fill_defaults(_SchemaMod, RawConf, _Opts) ->
RawConf. RawConf.
schema_default(Schema) -> %% if a root is not found in the raw conf, fill it with default values.
case hocon_schema:field_schema(Schema, type) of seed_default(Schema) ->
?ARRAY(_) -> case hocon_schema:field_schema(Schema, default) of
[]; undefined ->
_ -> %% so far all roots without a default value are objects
#{} #{};
Value ->
Value
end. end.
parse_hocon(HasDeprecatedFile, Conf) -> load_config_files(HasDeprecatedFile, Conf) ->
IncDirs = include_dirs(), IncDirs = include_dirs(),
case do_parse_hocon(HasDeprecatedFile, Conf, IncDirs) of case do_parse_hocon(HasDeprecatedFile, Conf, IncDirs) of
{ok, HoconMap} -> {ok, HoconMap} ->
HoconMap; HoconMap;
{error, Reason} -> {error, Reason} ->
?SLOG(error, #{ ?SLOG(error, #{
msg => "failed_to_load_hocon_file", msg => "failed_to_load_config_file",
reason => Reason, reason => Reason,
pwd => file:get_cwd(), pwd => file:get_cwd(),
include_dirs => IncDirs, include_dirs => IncDirs,
config_file => Conf config_file => Conf
}), }),
error(failed_to_load_hocon_file) error(failed_to_load_config_file)
end. end.
do_parse_hocon(true, Conf, IncDirs) -> do_parse_hocon(true, Conf, IncDirs) ->

View File

@ -2794,6 +2794,7 @@ authentication(Which) ->
hoconsc:mk(Type, #{ hoconsc:mk(Type, #{
desc => Desc, desc => Desc,
converter => fun ensure_array/2, converter => fun ensure_array/2,
default => [],
importance => Importance importance => Importance
}). }).