Skip to content
This repository was archived by the owner on Nov 17, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 40 additions & 22 deletions src/rabbit_env.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
context_to_code_path/1]).

-ifdef(TEST).
-export([value_is_yes/1]).
-export([parse_conf_env_file_output2/2,
value_is_yes/1]).
-endif.

-define(USED_ENV_VARS,
Expand Down Expand Up @@ -1608,11 +1609,12 @@ parse_conf_env_file_output(Context, _, []) ->
Context;
parse_conf_env_file_output(Context, Marker, [Marker | Lines]) ->
%% Found our marker, let's parse variables.
parse_conf_env_file_output1(Context, Lines, #{});
parse_conf_env_file_output1(Context, Lines);
parse_conf_env_file_output(Context, Marker, [_ | Lines]) ->
parse_conf_env_file_output(Context, Marker, Lines).

parse_conf_env_file_output1(Context, [], Vars) ->
parse_conf_env_file_output1(Context, Lines) ->
Vars = parse_conf_env_file_output2(Lines, #{}),
%% Re-export variables.
lists:foreach(
fun(Var) ->
Expand All @@ -1628,27 +1630,30 @@ parse_conf_env_file_output1(Context, [], Vars) ->
ok
end
end, lists:sort(maps:keys(Vars))),
Context;
parse_conf_env_file_output1(Context, [Line | Lines], Vars) ->
Context.

parse_conf_env_file_output2([], Vars) ->
Vars;
parse_conf_env_file_output2([Line | Lines], Vars) ->
SetXOutput = is_sh_set_x_output(Line),
ShFunction = is_sh_function(Line, Lines),
if
SetXOutput ->
parse_conf_env_file_output1(Context, Lines, Vars);
parse_conf_env_file_output2(Lines, Vars);
ShFunction ->
skip_sh_function(Context, Lines, Vars);
skip_sh_function(Lines, Vars);
true ->
case string:split(Line, "=") of
[Var, IncompleteValue] ->
{Value, Lines1} = parse_sh_literal(IncompleteValue, Lines),
{Value, Lines1} = parse_sh_literal(IncompleteValue, Lines, ""),
Vars1 = Vars#{Var => Value},
parse_conf_env_file_output1(Context, Lines1, Vars1);
parse_conf_env_file_output2(Lines1, Vars1);
_ ->
%% Parsing failed somehow.
rabbit_log_prelaunch:warning(
"Failed to parse $RABBITMQ_CONF_ENV_FILE output: ~p",
[Line]),
Context
#{}
end
end.

Expand All @@ -1662,16 +1667,18 @@ is_sh_function(Line, Lines) ->
andalso
re:run(hd(Lines), "^\\s*\\{\\s*$", [{capture, none}]) =:= match.

parse_sh_literal("'" ++ SingleQuoted, Lines) ->
parse_single_quoted_literal(SingleQuoted, Lines, "");
parse_sh_literal("$'" ++ DollarSingleQuoted, Lines) ->
parse_dollar_single_quoted_literal(DollarSingleQuoted, Lines, "");
parse_sh_literal(Unquoted, Lines) ->
{Unquoted, Lines}.
parse_sh_literal("'" ++ SingleQuoted, Lines, Literal) ->
parse_single_quoted_literal(SingleQuoted, Lines, Literal);
parse_sh_literal("\"" ++ DoubleQuoted, Lines, Literal) ->
parse_double_quoted_literal(DoubleQuoted, Lines, Literal);
parse_sh_literal("$'" ++ DollarSingleQuoted, Lines, Literal) ->
parse_dollar_single_quoted_literal(DollarSingleQuoted, Lines, Literal);
parse_sh_literal(Unquoted, Lines, Literal) ->
{lists:reverse(Literal) ++ Unquoted, Lines}.

parse_single_quoted_literal([$'], Lines, Literal) ->
parse_single_quoted_literal([$' | Rest], Lines, Literal) ->
%% We reached the closing single quote.
{lists:reverse(Literal), Lines};
parse_sh_literal(Rest, Lines, Literal);
parse_single_quoted_literal([], [Line | Lines], Literal) ->
%% We reached the end of line before finding the closing single
%% quote. The literal continues on the next line and includes that
Expand All @@ -1680,6 +1687,17 @@ parse_single_quoted_literal([], [Line | Lines], Literal) ->
parse_single_quoted_literal([C | Rest], Lines, Literal) ->
parse_single_quoted_literal(Rest, Lines, [C | Literal]).

parse_double_quoted_literal([$" | Rest], Lines, Literal) ->
%% We reached the closing double quote.
parse_sh_literal(Rest, Lines, Literal);
parse_double_quoted_literal([], [Line | Lines], Literal) ->
%% We reached the end of line before finding the closing double
%% quote. The literal continues on the next line and includes that
%% newline character.
parse_double_quoted_literal(Line, Lines, [$\n | Literal]);
parse_double_quoted_literal([C | Rest], Lines, Literal) ->
parse_double_quoted_literal(Rest, Lines, [C | Literal]).

parse_dollar_single_quoted_literal([$'], Lines, Literal) ->
%% We reached the closing single quote.
{lists:reverse(Literal), Lines};
Expand All @@ -1691,10 +1709,10 @@ parse_dollar_single_quoted_literal([], [Line | Lines], Literal) ->
parse_dollar_single_quoted_literal([C | Rest], Lines, Literal) ->
parse_dollar_single_quoted_literal(Rest, Lines, [C | Literal]).

skip_sh_function(Context, ["}" | Lines], Vars) ->
parse_conf_env_file_output1(Context, Lines, Vars);
skip_sh_function(Context, [_ | Lines], Vars) ->
skip_sh_function(Context, Lines, Vars).
skip_sh_function(["}" | Lines], Vars) ->
parse_conf_env_file_output2(Lines, Vars);
skip_sh_function([_ | Lines], Vars) ->
skip_sh_function(Lines, Vars).

%% -------------------------------------------------------------------
%% Helpers.
Expand Down
37 changes: 35 additions & 2 deletions test/rabbit_env_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
check_value_is_yes/1,
check_log_process_env/1,
check_log_context/1,
check_get_used_env_vars/1
check_get_used_env_vars/1,
check_parse_conf_env_file_output/1
]).

all() ->
Expand Down Expand Up @@ -93,7 +94,8 @@ all() ->
check_value_is_yes,
check_log_process_env,
check_log_context,
check_get_used_env_vars
check_get_used_env_vars,
check_parse_conf_env_file_output
].

suite() ->
Expand Down Expand Up @@ -1063,3 +1065,34 @@ get_default_nodename() ->
"rabbit@\\1",
[{return, list}]),
list_to_atom(NodeS).

check_parse_conf_env_file_output(_) ->
?assertEqual(
#{},
rabbit_env:parse_conf_env_file_output2(
[],
#{}
)),
?assertEqual(
#{"UNQUOTED" => "a",
"SINGLE_QUOTED" => "b",
"DOUBLE_QUOTED" => "c",
"SINGLE_DOLLAR" => "d"},
rabbit_env:parse_conf_env_file_output2(
["UNQUOTED=a",
"SINGLE_QUOTED='b'",
"DOUBLE_QUOTED=\"c\"",
"SINGLE_DOLLAR=$'d'"],
#{}
)),
?assertEqual(
#{"A" => "a",
"B" => "b",
"MULTI_LINE" => "\n'foobar'"},
rabbit_env:parse_conf_env_file_output2(
["A=a",
"MULTI_LINE='",
"'\"'\"'foobar'\"'\"",
"B=b"],
#{}
)).