- %%% Common functions to boot/stop distributed setups for
- %%% the rebar3 script.
- -module(rebar_dist_utils).
- -export([either/3, short/2, long/2, find_options/1]).
- -include("rebar.hrl").
-
- %%%%%%%%%%%%%%%%%%
- %%% PUBLIC API %%%
- %%%%%%%%%%%%%%%%%%
-
- %% @doc allows to pick whether to use a short or long name, and
- %% starts the distributed mode for it.
- -spec either(Name::atom(), SName::atom(), Opts::[{setcookie,term()}]) -> atom().
- either(undefined, undefined, _) ->
- 'nonode@nohost';
- either(Name, undefined, Opts) ->
- long(Name, Opts),
- node();
- either(undefined, SName, Opts) ->
- short(SName, Opts),
- node();
- either(_, _, _) ->
- ?ABORT("Cannot have both short and long node names defined", []).
-
- %% @doc starts a node with a short name.
- -spec short(SName::atom(), Opts::[{setcookie,term()}]) -> term().
- short(Name, Opts) ->
- start(Name, shortnames, Opts).
-
- %% @doc starts a node with a long name.
- -spec long(Name::atom(), Opts::[{setcookie,term()}]) -> term().
- long(Name, Opts) ->
- start(Name, longnames, Opts).
-
- %% @doc utility function to extract all distribution options
- %% from a rebar3 state tuple.
- -spec find_options(rebar_state:t()) -> {Long, Short, Opts} when
- Long :: atom(),
- Short :: atom(),
- Opts :: [{setcookie,term()}].
- find_options(State) ->
- {Long, Short} = find_name_options(State),
- case find_cookie_option(State) of
- nocookie ->
- {Long, Short, []};
- Cookie ->
- {Long, Short, [{setcookie, Cookie}]}
- end.
-
- %%%%%%%%%%%%%%%
- %%% PRIVATE %%%
- %%%%%%%%%%%%%%%
- start(Name, Type, Opts) ->
- case net_adm:names() of
- {error, _} ->
- start_epmd();
- {ok, _} ->
- ok
- end,
- dist_up(net_kernel:start([Name, Type])) orelse warn_dist(),
- setup_cookie(Opts).
-
- dist_up({error,{{shutdown,{_,net_kernel,{'EXIT',nodistribution}}},_}}) -> false;
- dist_up(_) -> true.
-
- start_epmd() ->
- %% Indirectly boot EPMD through calling Erlang so that we don't risk
- %% attaching it to the current proc
- ?CONSOLE("Attempting to start epmd...", []),
- os:cmd("erl -sname a -noinput -eval \"halt(0).\"").
-
- warn_dist() ->
- ?ERROR("Erlang Distribution failed, falling back to nonode@nohost.", []).
-
-
- setup_cookie(Opts) ->
- case {node(), proplists:get_value(setcookie, Opts, nocookie)} of
- {'nonode@nohost', _} -> nocookie;
- {_, nocookie} -> nocookie;
- {Node, Name} -> erlang:set_cookie(Node, Name)
- end.
-
- find_name_options(State) ->
- {Opts, _} = rebar_state:command_parsed_args(State),
- %% First try the CLI
- case {proplists:get_value(name, Opts), proplists:get_value(sname, Opts)} of
- {undefined, undefined} ->
- %% Else try the config file
- DistOpts = rebar_state:get(State, dist_node, []),
- %% Pick the first one seen to support profile merges
- find_first_name(DistOpts);
- Res ->
- Res
- end.
-
- find_first_name([]) -> {undefined, undefined};
- find_first_name([{sname,Val}|_]) -> {undefined, Val};
- find_first_name([{name,Val}|_]) -> {Val, undefined};
- find_first_name([_|Opts]) -> find_first_name(Opts).
-
- find_cookie_option(State) ->
- {Opts, _} = rebar_state:command_parsed_args(State),
- %% First try the CLI
- case proplists:get_value(setcookie, Opts) of
- undefined ->
- %% Else try the config file
- DistOpts = rebar_state:get(State, dist_node, []),
- proplists:get_value(setcookie, DistOpts, nocookie);
- Res ->
- Res
- end.
|