aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--priv/templates/builtin_hook_status3
-rwxr-xr-xpriv/templates/extended_bin28
-rw-r--r--src/rlx_prv_assembler.erl18
-rw-r--r--test/rlx_extended_bin_SUITE.erl79
4 files changed, 114 insertions, 14 deletions
diff --git a/priv/templates/builtin_hook_status b/priv/templates/builtin_hook_status
new file mode 100644
index 0000000..e5dd792
--- /dev/null
+++ b/priv/templates/builtin_hook_status
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo $(relx_nodetool eval "application:which_applications().")
diff --git a/priv/templates/extended_bin b/priv/templates/extended_bin
index f05fb31..ed68748 100755
--- a/priv/templates/extended_bin
+++ b/priv/templates/extended_bin
@@ -40,12 +40,13 @@ ERL_OPTS="{{ erl_opts }}"
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}"
# start/stop/install/upgrade pre/post hooks
-PRE_START_HOOKS="{{ pre_start_hooks }}"
-POST_START_HOOKS="{{ post_start_hooks }}"
-PRE_STOP_HOOKS="{{ pre_stop_hooks }}"
-POST_STOP_HOOKS="{{ post_stop_hooks }}"
-PRE_INSTALL_UPGRADE_HOOKS="{{ pre_install_upgrade_hooks }}"
-POST_INSTALL_UPGRADE_HOOKS="{{ post_install_upgrade_hooks }}"
+PRE_START_HOOKS="{{{ pre_start_hooks }}}"
+POST_START_HOOKS="{{{ post_start_hooks }}}"
+PRE_STOP_HOOKS="{{{ pre_stop_hooks }}}"
+POST_STOP_HOOKS="{{{ post_stop_hooks }}}"
+PRE_INSTALL_UPGRADE_HOOKS="{{{ pre_install_upgrade_hooks }}}"
+POST_INSTALL_UPGRADE_HOOKS="{{{ post_install_upgrade_hooks }}}"
+STATUS_HOOK="{{{ status_hook }}}"
relx_usage() {
command="$1"
@@ -101,8 +102,12 @@ relx_usage() {
echo " --no-permanent Install release package VERSION but"
echo " don't make it permanent"
;;
+ status)
+ echo "Usage: $REL_NAME status"
+ echo "Obtains node status information."
+ ;;
*)
- echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|rpc|rpcterms|eval}"
+ echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|rpc|rpcterms|eval|status}"
;;
esac
}
@@ -584,6 +589,15 @@ case "$1" in
shift
relx_nodetool "eval" $@
;;
+ status)
+ # Make sure a node IS running
+ if ! relx_nodetool "ping" > /dev/null; then
+ echo "Node is not running!"
+ exit 1
+ fi
+
+ [ "$SCRIPT_DIR/$STATUS_HOOK" ] && . "$SCRIPT_DIR/$STATUS_HOOK" $@
+ ;;
help)
if [ -z "$2" ]; then
relx_usage
diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl
index f40a0c2..278756d 100644
--- a/src/rlx_prv_assembler.erl
+++ b/src/rlx_prv_assembler.erl
@@ -398,7 +398,8 @@ write_bin_file(State, Release, OutputDir, RelDir) ->
include_nodetool(BinDir),
Hooks = expand_hooks(BinDir,
rlx_state:get(State,
- extended_start_script_hooks, []),
+ extended_start_script_hooks,
+ [{status, [builtin_status]}]),
State),
extended_bin_file_contents(OsFamily, RelName, RelVsn,
rlx_release:erts(Release), ErlOpts,
@@ -475,6 +476,8 @@ validate_hook(post_start, wait_for_vm_start) -> true;
validate_hook(post_start, {wait_for_process, _}) -> true;
%% custom hooks are allowed in all phases
validate_hook(_Phase, {custom, _}) -> true;
+%% as well as status hooks
+validate_hook(status, _) -> true;
%% deny all others
validate_hook(_, _) -> false.
@@ -482,7 +485,8 @@ hook_filename({custom, CustomScript}) -> CustomScript;
hook_filename(pid) -> "hooks/builtin/pid";
hook_filename({pid, _}) -> "hooks/builtin/pid";
hook_filename(wait_for_vm_start) -> "hooks/builtin/wait_for_vm_start";
-hook_filename({wait_for_process, _}) -> "hooks/builtin/wait_for_process".
+hook_filename({wait_for_process, _}) -> "hooks/builtin/wait_for_process";
+hook_filename(builtin_status) -> "hooks/builtin/status".
hook_invocation({custom, CustomScript}) -> CustomScript;
%% the pid builtin hook with no arguments writes to pid file
@@ -496,13 +500,15 @@ hook_invocation({wait_for_process, Name}) ->
%% wait_for_process takes an atom as argument
%% which is the process name to wait for
string:join(["hooks/builtin/wait_for_process",
- atom_to_list(Name)], "|").
+ atom_to_list(Name)], "|");
+hook_invocation(builtin_status) -> "hooks/builtin/status".
hook_template({custom, _}) -> custom;
hook_template(pid) -> builtin_hook_pid;
hook_template({pid, _}) -> builtin_hook_pid;
hook_template(wait_for_vm_start) -> builtin_hook_wait_for_vm_start;
-hook_template({wait_for_process, _}) -> builtin_hook_wait_for_process.
+hook_template({wait_for_process, _}) -> builtin_hook_wait_for_process;
+hook_template(builtin_status) -> builtin_hook_status.
%% custom hooks are not rendered, they should
%% be copied by the release overlays
@@ -795,6 +801,7 @@ extended_bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts, Hooks) -
Hooks, []), " "),
PostInstallUpgradeHooks = string:join(proplists:get_value(post_install_upgrade,
Hooks, []), " "),
+ StatusHook = string:join(proplists:get_value(status, Hooks, []), " "),
render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn},
{erts_vsn, ErtsVsn}, {erl_opts, ErlOpts},
{pre_start_hooks, PreStartHooks},
@@ -802,7 +809,8 @@ extended_bin_file_contents(OsFamily, RelName, RelVsn, ErtsVsn, ErlOpts, Hooks) -
{pre_stop_hooks, PreStopHooks},
{post_stop_hooks, PostStopHooks},
{pre_install_upgrade_hooks, PreInstallUpgradeHooks},
- {post_install_upgrade_hooks, PostInstallUpgradeHooks}]).
+ {post_install_upgrade_hooks, PostInstallUpgradeHooks},
+ {status_hook, StatusHook}]).
erl_ini(OutputDir, ErtsVsn) ->
ErtsDirName = string:concat("erts-", ErtsVsn),
diff --git a/test/rlx_extended_bin_SUITE.erl b/test/rlx_extended_bin_SUITE.erl
index c3f534a..c049209 100644
--- a/test/rlx_extended_bin_SUITE.erl
+++ b/test/rlx_extended_bin_SUITE.erl
@@ -41,7 +41,8 @@
builtin_wait_for_vm_start_script_hook/1,
builtin_pid_start_script_hook/1,
builtin_wait_for_process_start_script_hook/1,
- mixed_custom_and_builtin_start_script_hooks/1]).
+ mixed_custom_and_builtin_start_script_hooks/1,
+ builtin_status_script/1, custom_status_script/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -70,7 +71,8 @@ all() ->
remote_console, replace_os_vars, replace_os_vars_multi_node, replace_os_vars_included_config,
replace_os_vars_custom_location, replace_os_vars_dev_mode, replace_os_vars_twice, custom_start_script_hooks,
builtin_wait_for_vm_start_script_hook, builtin_pid_start_script_hook,
- builtin_wait_for_process_start_script_hook, mixed_custom_and_builtin_start_script_hooks].
+ builtin_wait_for_process_start_script_hook, mixed_custom_and_builtin_start_script_hooks,
+ builtin_status_script, custom_status_script].
ping(Config) ->
LibDir1 = proplists:get_value(lib1, Config),
@@ -1318,6 +1320,79 @@ mixed_custom_and_builtin_start_script_hooks(Config) ->
{pre_stop, foo, _, foo},
{post_stop, foo, _, foo}]} = file:consult(filename:join([OutputDir, "foo", "test"])).
+builtin_status_script(Config) ->
+ LibDir1 = proplists:get_value(lib1, Config),
+
+ rlx_test_utils:create_full_app(LibDir1, "goal_app", "0.0.1",
+ [stdlib,kernel], []),
+
+ OutputDir = filename:join([proplists:get_value(priv_dir, Config),
+ rlx_test_utils:create_random_name("relx-output")]),
+
+ ConfigFile = filename:join([LibDir1, "relx.config"]),
+ rlx_test_utils:write_config(ConfigFile,
+ [{release, {foo, "0.0.1"},
+ [goal_app]},
+ {lib_dirs, [filename:join(LibDir1, "*")]},
+ {generate_start_script, true},
+ {extended_start_script, true}
+ ]),
+
+ {ok, _State} = relx:do(foo, undefined, [], [LibDir1], 3,
+ OutputDir, ConfigFile),
+ os:cmd(filename:join([OutputDir, "foo", "bin", "foo start"])),
+ timer:sleep(2000),
+ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])),
+ %% write the status to a file
+ {ok, StatusStr} = sh(filename:join([OutputDir, "foo", "bin", "foo status"])),
+ ec_file:write(filename:join([OutputDir, "status.txt"]),
+ StatusStr ++ ".\n"),
+ os:cmd(filename:join([OutputDir, "foo", "bin", "foo stop"])),
+ {ok, [Status]} = file:consult(filename:join([OutputDir, "status.txt"])),
+ Apps = lists:map(fun({App, _, _}) -> App end, Status),
+ {ok, [goal_app, kernel, stdlib] = lists:sort(Apps)}.
+
+custom_status_script(Config) ->
+ LibDir1 = proplists:get_value(lib1, Config),
+
+ rlx_test_utils:create_full_app(LibDir1, "goal_app", "0.0.1",
+ [stdlib,kernel], []),
+
+ OutputDir = filename:join([proplists:get_value(priv_dir, Config),
+ rlx_test_utils:create_random_name("relx-output")]),
+
+ ConfigFile = filename:join([LibDir1, "relx.config"]),
+ rlx_test_utils:write_config(ConfigFile,
+ [{release, {foo, "0.0.1"},
+ [goal_app]},
+ {lib_dirs, [filename:join(LibDir1, "*")]},
+ {generate_start_script, true},
+ {extended_start_script, true},
+ {extended_start_script_hooks, [
+ {status, [
+ {custom, "hooks/status"}
+ ]}
+ ]},
+ {overlay, [
+ {copy, "./status", "bin/hooks/status"}]}
+ ]),
+
+ %% write the hook status script
+ ok = file:write_file(filename:join([LibDir1, "./status"]),
+ "#!/bin/bash\n# $*\necho \\{status, $REL_NAME, \\'$NAME\\', $COOKIE\\}."),
+
+ {ok, _State} = relx:do(foo, undefined, [], [LibDir1], 3,
+ OutputDir, ConfigFile),
+ os:cmd(filename:join([OutputDir, "foo", "bin", "foo start"])),
+ timer:sleep(2000),
+ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"])),
+ %% write the status to a file
+ {ok, StatusStr} = sh(filename:join([OutputDir, "foo", "bin", "foo status"])),
+ ec_file:write(filename:join([OutputDir, "status.txt"]), StatusStr),
+ os:cmd(filename:join([OutputDir, "foo", "bin", "foo stop"])),
+ {ok, [Status]} = file:consult(filename:join([OutputDir, "status.txt"])),
+ {ok, {status, foo, _, foo} = Status}.
+
%%%===================================================================
%%% Helper Functions
%%%===================================================================