Skip to content

Commit

Permalink
feat(hocon_schema): support set array value using env (#108)
Browse files Browse the repository at this point in the history
* feat(hocon_schema): support set array value using env

* fix(hocon_schema): rename the virtual_root to fake_key

* fix(hocon_schema): remove the try catch for read_hocon_val
  • Loading branch information
terry-xiaoyu authored Jul 15, 2021
1 parent 2eccec0 commit 7698d75
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
27 changes: 22 additions & 5 deletions src/hocon_schema.erl
Original file line number Diff line number Diff line change
Expand Up @@ -568,14 +568,14 @@ resolve_field_value(Schema, FieldValue, Opts) ->
undefined ->
resolve_default_override(Schema, FieldValue, Opts);
EnvValue ->
boxit(Opts, EnvValue, FieldValue)
maybe_mkrich(Opts, EnvValue, ?EMPTY_BOX)
end.

resolve_default_override(Schema, FieldValue, Opts) ->
case unbox(Opts, FieldValue) of
?FROM_ENV_VAR(EnvName, EnvValue) ->
log_env_override(Schema, Opts, EnvName, path(Opts), EnvValue),
boxit(Opts, EnvValue, FieldValue);
maybe_mkrich(Opts, EnvValue, ?EMPTY_BOX);
_ ->
maybe_use_default(field_schema(Schema, default), FieldValue, Opts)
end.
Expand All @@ -599,15 +599,32 @@ collect_envs() ->
collect_envs(Ns) ->
[begin
[Name, Value] = string:split(KV, "="),
{Name, Value}
{Name, read_hocon_val(Value)}
end || KV <- os:getenv(), string:prefix(KV, Ns) =/= nomatch].

read_hocon_val("") -> "";
read_hocon_val(Value) ->
case hocon:binary(Value, #{}) of
{ok, HoconVal} -> HoconVal;
{error, _} -> read_informal_hocon_val(Value)
end.

read_informal_hocon_val(Value) ->
BoxedVal = "fake_key=" ++ Value,
case hocon:binary(BoxedVal, #{}) of
{ok, HoconVal} ->
maps:get(<<"fake_key">>, HoconVal);
{error, Reason} ->
error({invalid_hocon_string, Value, Reason})
end.

apply_env(_Ns, [], _RootName, Conf, _Opts) -> Conf;
apply_env(Ns, [{VarName, V} | More], RootName, Conf, Opts) ->
K = string:prefix(VarName, Ns),
Path0 = string:split(string:lowercase(K), "__", all),
Path1 = lists:filter(fun(N) -> N =/= [] end, Path0),
NewConf = case Path1 =/= [] andalso bin(RootName) =:= bin(hd(Path1)) of
NewConf = case RootName =:= ?VIRTUAL_ROOT orelse
(Path1 =/= [] andalso bin(RootName) =:= bin(hd(Path1))) of
true ->
Path = string:join(Path1, "."),
%% it lacks schema info here, so we need to tag the value '$FROM_ENV_VAR'
Expand Down Expand Up @@ -703,7 +720,7 @@ get_override_env(Schema, Opts) ->
undefined;
V ->
log_env_override(Schema, Opts, Var, path(Opts), V),
V
read_hocon_val(V)
end
end.

Expand Down
4 changes: 2 additions & 2 deletions test/hocon_cli_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ generate_with_env_logging_test() ->
[{"ZZZ_FOO__MIN", "42"}, {"ZZZ_FOO__MAX", "43"},
{"HOCON_ENV_OVERRIDE_PREFIX", "ZZZ_"}]),
{ok, Stdout} = cuttlefish_test_group_leader:get_output(),
?assertEqual([<<"ZZZ_FOO__MAX = \"43\" -> foo.max">>,
<<"ZZZ_FOO__MIN = \"42\" -> foo.min">>],
?assertEqual([<<"ZZZ_FOO__MAX = 43 -> foo.max">>,
<<"ZZZ_FOO__MIN = 42 -> foo.min">>],
lists:sort(binary:split(iolist_to_binary(Stdout),
<<"\n">>, [global, trim])))
end).
Expand Down
12 changes: 12 additions & 0 deletions test/hocon_schema_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,18 @@ env_test_() ->
F("", [{"EMQX_FOO__GREET", "hello"}]))
].

env_array_val_test() ->
Sc = #{structs => [?VIRTUAL_ROOT],
fields => [{"val", hoconsc:array(string())}]
},
Conf = "val = [a,b]",
{ok, PlainMap} = hocon:binary(Conf, #{}),
?assertEqual(#{<<"val">> => ["c", "d"]},
with_envs(fun hocon_schema:check_plain/2, [Sc, PlainMap],
[ {"HOCON_ENV_OVERRIDE_PREFIX", "EMQX_"}
, {"EMQX_VAL", "[c, d]"}
])).

translate_test_() ->
F = fun (Str) -> {ok, M} = hocon:binary(Str, #{format => richmap}),
{Mapped, Conf} = hocon_schema:map(demo_schema, M),
Expand Down

0 comments on commit 7698d75

Please sign in to comment.