diff --git a/src/hocon_schema.erl b/src/hocon_schema.erl index 582a5d2..a7351b2 100644 --- a/src/hocon_schema.erl +++ b/src/hocon_schema.erl @@ -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. @@ -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' @@ -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. diff --git a/test/hocon_cli_tests.erl b/test/hocon_cli_tests.erl index 2a3e4c1..8e697ad 100644 --- a/test/hocon_cli_tests.erl +++ b/test/hocon_cli_tests.erl @@ -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). diff --git a/test/hocon_schema_tests.erl b/test/hocon_schema_tests.erl index 614dd61..5d56bf6 100644 --- a/test/hocon_schema_tests.erl +++ b/test/hocon_schema_tests.erl @@ -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),