diff options
author | Ulf Wiger <ulf@feuerlabs.com> | 2015-09-19 06:32:01 +0200 |
---|---|---|
committer | Ulf Wiger <ulf@feuerlabs.com> | 2015-11-20 13:41:50 -0800 |
commit | e6299ff287e767dae71fb47009f9bf4620cc3d78 (patch) | |
tree | 9265db7835ab9c5d68da4682352ef10effb2acee /deps | |
parent | 457942002c23d1fed831ce7491a3d6cc4576ce9c (diff) | |
download | rvi_core-e6299ff287e767dae71fb47009f9bf4620cc3d78.tar.gz |
Add dlink_tls
- Authorization works just like for dlink_tcp
- After authorization, the TCP session is upgraded to TLS
- Currently, hard-coded use of OTP's example certs and keys
- Test suite installs a tls client and tls backend, but doesn't start them
- Manually tested that authorization and service announcement work
Diffstat (limited to 'deps')
-rw-r--r-- | deps/setup/Makefile | 2 | ||||
-rw-r--r-- | deps/setup/src/setup.erl | 238 | ||||
-rw-r--r-- | deps/setup/src/setup_gen.erl | 14 |
3 files changed, 208 insertions, 46 deletions
diff --git a/deps/setup/Makefile b/deps/setup/Makefile index e4b0fc1..a62cec5 100644 --- a/deps/setup/Makefile +++ b/deps/setup/Makefile @@ -33,7 +33,7 @@ clean_test: eunit: compile ${REBAR} eunit -test: compile compile_test +test: eunit compile_test ./setup_gen test xtest/test.conf xtest/releases/1 -pa ${PWD}/ebin run_test: diff --git a/deps/setup/src/setup.erl b/deps/setup/src/setup.erl index 54d1ce1..881e5a7 100644 --- a/deps/setup/src/setup.erl +++ b/deps/setup/src/setup.erl @@ -64,6 +64,46 @@ %% * ``'{'$string', Var}''' - Use the string representation of the value %% * ``'{'$binary', Var}''' - Use the binary representation of the value. %% +%% Example: +%% <pre lang="erlang"> +%% 2> application:set_env(setup, vars, [{"PLUS", {apply,erlang,'+',[1,2]}}, +%% 2> {"FOO", {value, {foo,1}}}]). +%% ok +%% 3> application:set_env(stdlib, '$setup_vars', +%% 3> [{"MINUS", {apply,erlang,'-',[4,3]}}, +%% 3> {"BAR", {value, "bar"}}]). +%% ok +%% 4> application:set_env(setup, v1, "/$BAR/$PLUS/$MINUS/$FOO"). +%% ok +%% 5> setup:get_env(setup,v1). +%% {ok,"/$BAR/3/$MINUS/{foo,1}"} +%% 6> application:set_env(stdlib, v1, "/$BAR/$PLUS/$MINUS/$FOO"). +%% ok +%% 7> setup:get_env(stdlib,v1). +%% {ok,"/bar/3/1/{foo,1}"} +%% </pre> +%% +%% In the above example, the first expansion (command no. 5), leaves `$BAR' +%% and `$MINUS' unexpanded, since they are defined in the `stdlib' application, +%% and thus not known to `setup'. In command no. 6, however, they <em>are</em> +%% in context, and are expanded. The variables `$PLUS' and `$FOO' have global +%% context and are expanded in both cases. +%% +%% It is also possible to refer to environment variables in the same +%% application. These are referenced as `"$env(VarName)"'. The corresponding +%% values are expanded in turn - take care not to create expansion loops! +%% The same rules for expansion as above apply. +%% +%% Example: +%% <pre lang="erlang"> +%% 2> application:set_env(setup,foo,"foo"). +%% ok +%% 3> application:set_env(setup,foo_dir,"$HOME/$env(foo)"). +%% ok +%% 4> setup:get_env(setup,foo_dir). +%% {ok,"/Users/uwiger/git/setup/foo"} +%% </pre> +%% %% == Customizing setup == %% The following environment variables can be used to customize `setup': %% * `{home, Dir}' - The topmost directory of the running system. This should @@ -217,7 +257,7 @@ find_env_vars(Env) -> case app_get_env(A, Env) of {ok, Val} when Val =/= undefined -> NewEnv = private_env(A, GEnv), - [{A, expand_env(NewEnv, Val)}]; + [{A, expand_env(NewEnv, Val, A)}]; _ -> [] end @@ -247,7 +287,7 @@ get_env(A, Key, Default) -> %% @end get_all_env(A) -> Vars = private_env(A), - [{K, expand_env(Vars, V)} || + [{K, expand_env(Vars, V, A)} || {K, V} <- application:get_all_env(A)]. -spec expand_value(atom(), any()) -> any(). @@ -257,7 +297,7 @@ get_all_env(A) -> %% {@section Variable expansion}. %% @end expand_value(App, Value) -> - expand_env(private_env(App), Value). + expand_env(private_env(App), Value, App). global_env() -> Acc = [{K, fun() -> env_value(K) end} || @@ -265,7 +305,9 @@ global_env() -> custom_global_env(Acc). custom_global_env(Acc) -> - lists:foldl(fun custom_env1/2, Acc, + lists:foldl(fun(E, Acc1) -> + custom_env1(E, Acc1, setup) + end, Acc, [{K,V} || {K,V} <- app_get_env(setup, vars, []), is_list(K)]). @@ -278,7 +320,9 @@ private_env(A, GEnv) -> custom_private_env(A, Acc ++ GEnv). custom_private_env(A, Acc) -> - lists:foldl(fun custom_env1/2, Acc, + lists:foldl(fun(E, Acc1) -> + custom_env1(E, Acc1, A) + end, Acc, [{K, V} || {K,V} <- app_get_env(A, '$setup_vars', []), is_list(K)]). @@ -300,37 +344,121 @@ app_get_env(A, K, Default) -> app_get_key(A, K) -> application:get_key(A, K). -custom_env1({K, V}, Acc) -> - [{K, fun() -> custom_env_value(K, V, Acc) end} | Acc]. - -expand_env(Vs, {T,"$" ++ S}) when T=='$value'; T=='$string'; T=='$binary' -> +custom_env1({K, V}, Acc, A) -> + [{K, fun() -> custom_env_value(K, V, Acc, A) end} | Acc]. + +expand_env(_, {T,"$env(" ++ S} = X, A) + when T=='$value'; T=='$string'; T=='$binary' -> + try Res = case get_env_name_l(S) of + false -> undefined; + {Name,[]} -> app_get_env(A, Name) + end, + case {Res, T} of + {undefined, '$value'} -> undefined; + {undefined, '$string'} -> ""; + {undefined, '$binary'} -> <<>>; + {{ok,V} , '$value'} -> V; + {{ok,V} , '$string'} -> binary_to_list(stringify(V)); + {{ok,V} , '$binary'} -> stringify(V) + end + catch + error:_ -> X + end; +expand_env(Vs, {T,"$" ++ S}, _) when T=='$value'; T=='$string'; T=='$binary' -> case {lists:keyfind(S, 1, Vs), T} of {false, '$value'} -> undefined; {false, '$string'} -> ""; - {false, '$binary'} -> <<"">>; + {false, '$binary'} -> <<>>; {{_,V}, '$value'} -> V(); {{_,V}, '$string'} -> binary_to_list(stringify(V())); {{_,V}, '$binary'} -> stringify(V()) end; -expand_env(Vs, T) when is_tuple(T) -> - list_to_tuple([expand_env(Vs, X) || X <- tuple_to_list(T)]); -expand_env(Vs, L) when is_list(L) -> +expand_env(Vs, T, A) when is_tuple(T) -> + list_to_tuple([expand_env(Vs, X, A) || X <- tuple_to_list(T)]); +expand_env(Vs, L, A) when is_list(L) -> case setup_lib:is_string(L) of true -> - do_expand_env(L, Vs, list); + do_expand_env(L, Vs, A, list); false -> - [expand_env(Vs, X) || X <- L] + [expand_env(Vs, X, A) || X <- L] end; -expand_env(Vs, B) when is_binary(B) -> - do_expand_env(B, Vs, binary); -expand_env(_, X) -> +expand_env(Vs, B, A) when is_binary(B) -> + do_expand_env(B, Vs, A, binary); +expand_env(_, X, _) -> X. -do_expand_env(X, Vs, Type) -> - lists:foldl(fun({K, Val}, Xx) -> - re:replace(Xx, [$\\, $$ | K], - stringify(Val()), [{return,Type}]) - end, X, Vs). +%% do_expand_env(X, Vs, Type) -> +%% lists:foldl(fun({K, Val}, Xx) -> +%% re:replace(Xx, [$\\, $$ | K], +%% stringify(Val()), [{return,Type}]) +%% end, X, Vs). + +do_expand_env(X, Vs, A, binary) -> + do_expand_env_b(iolist_to_binary(X), Vs, A); +do_expand_env(X, Vs, A, list) -> + binary_to_list(do_expand_env_b(iolist_to_binary(X), Vs, A)). + +do_expand_env_b(<<"$env(", T/binary>>, Vs, A) -> + case get_env_name_b(T) of + {K, T1} -> + case app_get_env(A, K) of + {ok, V} -> + Res = expand_env(Vs, V, A), + <<(stringify(Res))/binary, + (do_expand_env_b(T1, Vs, A))/binary>>; + undefined -> + <<"$env(", (do_expand_env_b(T, Vs, A))/binary>> + end; + false -> + do_expand_env_b(T, Vs, A) + end; +do_expand_env_b(<<"$", T/binary>>, Vs, A) -> + case match_var_b(Vs, T) of + {Res, T1} -> + <<Res/binary, (do_expand_env_b(T1, Vs, A))/binary>>; + false -> + <<"$", (do_expand_env_b(T, Vs, A))/binary>> + end; +do_expand_env_b(<<H, T/binary>>, Vs, A) -> + <<H, (do_expand_env_b(T, Vs, A))/binary>>; +do_expand_env_b(<<>>, _, _) -> + <<>>. + +get_env_name_b(B) -> + get_env_name_b(B, <<>>). + +get_env_name_b(<<")", T/binary>>, Acc) -> + try {binary_to_existing_atom(Acc, latin1), T} + catch + error:_ -> false + end; +get_env_name_b(<<H, T/binary>>, Acc) -> + get_env_name_b(T, <<Acc/binary, H>>); +get_env_name_b(<<>>, _) -> + false. + +get_env_name_l(L) -> + get_env_name_l(L, []). + +get_env_name_l(")" ++ T, Acc) -> + try {list_to_existing_atom(lists:reverse(Acc)), T} + catch + error:_ -> false + end; +get_env_name_l([H|T], Acc) -> + get_env_name_l(T, [H|Acc]); +get_env_name_l([], _) -> + false. + +match_var_b([{K,V}|T], B) -> + case re:split(B, "^" ++ K, [{return, binary}]) of + [_] -> + match_var_b(T, B); + [<<>>, Rest] -> + {stringify(V()), Rest} + end; +match_var_b([], _) -> + false. env_value("LOG_DIR") -> log_dir(); env_value("DATA_DIR") -> data_dir(); @@ -340,13 +468,13 @@ env_value("APP", A) -> A; env_value("PRIV_DIR", A) -> priv_dir(A); env_value("LIB_DIR" , A) -> lib_dir(A). -custom_env_value(_K, {value, V}, _Vs) -> +custom_env_value(_K, {value, V}, _Vs, _A) -> V; -custom_env_value(_K, {expand, V}, Vs) -> - expand_env(Vs, V); -custom_env_value(K, {apply, M, F, A}, _Vs) -> +custom_env_value(_K, {expand, V}, Vs, A) -> + expand_env(Vs, V, A); +custom_env_value(K, {apply, M, F, As}, _Vs, _A) -> %% Not ideal, but don't want to introduce exceptions in get_env() - try apply(M, F, A) + try apply(M, F, As) catch error:_ -> {error, {custom_setup_env, K}} @@ -1263,15 +1391,15 @@ read_config_script(F, Name, Opts) -> {'CWD', filename:absname(Dir)}, {'OPTIONS', Opts}])) of {ok, Conf} when is_list(Conf) -> - expand_config_script(Conf, Name, lists:reverse(Opts)); + expand_config_script(Conf, Name, [], Opts); Error -> setup_lib:abort("Error reading conf (~s): ~p~n", [F, Error]) end. -expand_config_script([{include, F}|Opts], Name, Acc) -> - Acc1 = read_config_script(F, Name, lists:reverse(Acc)), - expand_config_script(Opts, Name, Acc1); -expand_config_script([{include_lib, LibF}|Opts], Name, Acc) -> +expand_config_script([{include, F}|T], Name, Acc, Opts) -> + Incl = read_config_script(F, Name, Opts), + expand_config_script(T, Name, [Incl|Acc], Opts); +expand_config_script([{include_lib, LibF}|T], Name, Acc, Opts) -> case filename:split(LibF) of [App|Tail] -> try code:lib_dir(to_atom(App)) of @@ -1281,9 +1409,9 @@ expand_config_script([{include_lib, LibF}|Opts], Name, Acc) -> [LibF, App]); LibDir when is_list(LibDir) -> FullName = filename:join([LibDir | Tail]), - Acc1 = read_config_script( - FullName, Name, lists:reverse(Acc)), - expand_config_script(Opts, Name, Acc1) + Incl = read_config_script( + FullName, Name, Opts), + expand_config_script(T, Name, [Incl|Acc], Opts) catch error:_ -> setup_lib:abort( @@ -1293,10 +1421,10 @@ expand_config_script([{include_lib, LibF}|Opts], Name, Acc) -> [] -> setup_lib:abort("Invalid include conf: no file specified~n", []) end; -expand_config_script([H|T], Name, Acc) -> - expand_config_script(T, Name, [H|Acc]); -expand_config_script([], _, Acc) -> - lists:reverse(Acc). +expand_config_script([H|T], Name, Acc, Opts) -> + expand_config_script(T, Name, [H|Acc], Opts); +expand_config_script([], _, Acc, _) -> + lists:flatten(lists:reverse(Acc)). to_atom(B) when is_binary(B) -> binary_to_existing_atom(B, latin1); @@ -1325,7 +1453,8 @@ setup_test_() -> end, [ ?_test(t_find_hooks()), - ?_test(t_expand_vars()) + ?_test(t_expand_vars()), + ?_test(t_nested_includes()) ]}. t_find_hooks() -> @@ -1356,17 +1485,40 @@ t_expand_vars() -> application:set_env(stdlib, '$setup_vars', [{"MINUS", {apply,erlang,'-',[4,3]}}, {"BAR", {value, "bar"}}]), - application:set_env(setup, v1, "/$BAR/$PLUS/$MINUS/$FOO"), + application:set_env(setup, envy, 17), + application:set_env(setup, v1, "/$BAR/$PLUS/$MINUS/$FOO/$env(envy)"), application:set_env(setup, v2, {'$value', "$FOO"}), + application:set_env(setup, v3, {'$string', "$env(envy)"}), application:set_env(stdlib, v1, {'$string', "$FOO"}), application:set_env(stdlib, v2, {'$binary', "$FOO"}), application:set_env(stdlib, v3, {"$PLUS", "$MINUS", "$BAR"}), %% $BAR and $MINUS are not in setup's context - {ok, "/$BAR/3/$MINUS/{foo,1}"} = setup:get_env(setup, v1), + {ok, "/$BAR/3/$MINUS/{foo,1}/17"} = setup:get_env(setup, v1), {ok, {foo,1}} = setup:get_env(setup, v2), + {ok, "17"} = setup:get_env(setup, v3), {ok, "{foo,1}"} = setup:get_env(stdlib, v1), {ok, <<"{foo,1}">>} = setup:get_env(stdlib,v2), {ok, {"3", "1", "bar"}} = setup:get_env(stdlib,v3), ok. +t_nested_includes() -> + to_file_("a.config", [{apps,[kernel,stdlib,setup]}, + {env,[{setup,[{a,1}]}]}]), + to_file_("b.config", [{include,"a.config"}, + {set_env, [{setup, [{a,2}]}]}]), + to_file_("c.config", [{include, "b.config"}, + {set_env, [{setup, [{a,3}]}]}]), + [{apps,[kernel,stdlib,setup]}, + {env, [{setup, [{a,1}]}]}, + {set_env, [{setup, [{a,2}]}]}, + {set_env, [{setup, [{a,3}]}]}] = + setup:read_config_script("c.config", nested, []). + +to_file_(F, Term) -> + {ok, Fd} = file:open(F, [write]), + try io:fwrite(Fd, "~p.~n", [Term]) + after + file:close(Fd) + end. + -endif. diff --git a/deps/setup/src/setup_gen.erl b/deps/setup/src/setup_gen.erl index e0137fe..7a74107 100644 --- a/deps/setup/src/setup_gen.erl +++ b/deps/setup/src/setup_gen.erl @@ -171,12 +171,13 @@ run(Options) -> ?if_verbose(io:fwrite("Options = ~p~n", [Options])), Config = read_config(Options), ?if_verbose(io:fwrite("Config = ~p~n", [Config])), - FullOpts = Options ++ Config, + FullOpts = insert_config(Config, Options), + ?if_verbose(io:fwrite("FullOpts = ~p~n", [FullOpts])), {Name, OutDir, RelDir, RelVsn, GenTarget} = name_and_target(FullOpts), ensure_dir(RelDir), Roots = roots(FullOpts), ?if_verbose(io:fwrite("Roots = ~p~n", [Roots])), - check_config(Config), + check_config(FullOpts), Env = env_vars(FullOpts), InstEnv = install_env(Env, FullOpts), add_paths(Roots, FullOpts), @@ -202,6 +203,14 @@ run(Options) -> setup_lib:write_eterm("setup_gen.eterm", FullOpts) end). +insert_config(Conf, Options) -> + lists:flatmap( + fun({conf, _} = C) -> + [C|Conf]; + (Other) -> + [Other] + end, Options). + name_and_target(FullOpts) -> Name = option(name, FullOpts), case proplists:get_value(target, FullOpts, false) of @@ -797,6 +806,7 @@ app_vsn(A, V) -> Path = code:get_path(), Found = [D || D <- Path, is_app(AppStr, D)], Sorted = setup_lib:sort_vsns(lists:usort(Found), AppStr), + ?if_verbose(io:fwrite("Sorted = ~p~n", [Sorted])), match_app_vsn(Sorted, V, AppStr). match_app_vsn(Vsns, latest, App) -> |