Skip to content

Commit 889c966

Browse files
committed
No longer require hooks/extensions must be added to overlays
No longer demand that developers add a hook/extension and also correctly configure the required overlay copy instructions as this now gets automatically added. Start script extensions now also support descriptions. Extensions: previous: {extended_start_script_extensions, [ {bar, "extensions/bar"}, {foo, "extensions/foo"}, {baz, "extensions/baz"}]}, {overlay, [ {copy, "./bar", "bin/extensions/bar"}, {copy, "./foo", "bin/extensions/foo"}, {copy, "./baz", "bin/extensions/baz"}]} after: {extended_start_script_extensions, [ % auto copied over to `bin/extensions/bar` with empty description {bar, "./bar"}, % auto copied over to `bin/extensions/foo` with description `"foo description"` {foo, "./foo", "foo description"}, % auto copied over to `bin/extensions/baz` with description `"baz description"` {baz, "./baz", "bin/extensions/baz", "baz description"} ]} Hooks: previous: {extended_start_script_hooks, [ {pre_start, [ {custom, "hooks/pre_start"} ]}, {post_start, [ wait_for_vm_start, {pid, "foo.pid"}, wait_for_vm_start, {custom, "hooks/post_start"} ]}, {pre_stop, [ {custom, "hooks/pre_stop"} ]}, {post_stop, [ {custom, "hooks/post_stop"} ]}, {status, [ {custom, "hooks/status"} ]} ]}, {overlay, [ {copy, "./hooks/status", "bin/hooks/status"}, {copy, "./hooks/{pre,post}_{start,stop}", "bin/hooks/"} ]} after: {extended_start_script_hooks, [ {pre_start, [ % auto copied over to `bin/hooks/pre_start` {custom, "hooks/pre_start"} ]}, {post_start, [ wait_for_vm_start, {pid, "foo.pid"}, wait_for_vm_start, {custom, "hooks/post_start"}, % auto copied over to `bin/hooks/extra/post_start` {custom, "hooks/post_start2", "bin/hooks/extra/post_start"} ]}, {pre_stop, [ {custom, "hooks/pre_stop"} ]}, {post_stop, [ {custom, "hooks/post_stop"} ]}, {status, [ {custom, "hooks/status"} ]} ]}
1 parent 6e8b874 commit 889c966

File tree

6 files changed

+143
-77
lines changed

6 files changed

+143
-77
lines changed

priv/templates/extended_bin

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ PRE_INSTALL_UPGRADE_HOOKS="{{{ pre_install_upgrade_hooks }}}"
6969
POST_INSTALL_UPGRADE_HOOKS="{{{ post_install_upgrade_hooks }}}"
7070
STATUS_HOOK="{{{ status_hook }}}"
7171
EXTENSIONS="{{{ extensions }}}"
72+
EXTENSION_DESCRIPTIONS="{{{ extension_descriptions }}}"
7273

7374
relx_usage() {
7475
command="$1"
@@ -188,7 +189,7 @@ Commands:
188189
versions Print versions of the release available
189190
escript Run an escript in the same environment as the release
190191
status Verify node is running and then run status hook scripts
191-
$EXTENSIONS"
192+
$(relx_extension_descriptions)"
192193
fi
193194
;;
194195
esac
@@ -496,9 +497,9 @@ relx_run_hooks() {
496497
set $(echo "$hook" | sed -e 's/|/ /g')
497498
HOOK_SCRIPT=$1; shift
498499
# all hook locations are expected to be
499-
# relative to the start script location
500+
# relative to the release root
500501
# shellcheck disable=SC1090,SC2240
501-
[ -f "$SCRIPT_DIR/$HOOK_SCRIPT" ] && . "$SCRIPT_DIR/$HOOK_SCRIPT" "$@"
502+
[ -f "$RELEASE_ROOT_DIR/$HOOK_SCRIPT" ] && . "$RELEASE_ROOT_DIR/$HOOK_SCRIPT" "$@"
502503
done
503504
}
504505

@@ -542,9 +543,23 @@ relx_run_extension() {
542543
EXTENSION_SCRIPT=$1
543544
shift
544545
# all extension script locations are expected to be
545-
# relative to the start script location
546+
# relative to the release root
546547
# shellcheck disable=SC1090,SC2240
547-
[ -f "$SCRIPT_DIR/$EXTENSION_SCRIPT" ] && . "$SCRIPT_DIR/$EXTENSION_SCRIPT" "$@"
548+
[ -f "$RELEASE_ROOT_DIR/$EXTENSION_SCRIPT" ] && . "$RELEASE_ROOT_DIR/$EXTENSION_SCRIPT" "$@"
549+
}
550+
551+
relx_extension_descriptions() {
552+
IFS0=$IFS
553+
IFS='|'
554+
for description in $EXTENSION_DESCRIPTIONS
555+
do
556+
cmd=$(echo "$description" |cut -d '=' -f1)
557+
descr=$(echo "$description" |cut -d '=' -f2)
558+
# 23 is the magic number of spaces that take up
559+
# the space between a command and it's description
560+
printf ' %-23s %s\n' "$cmd" "$descr"
561+
done
562+
IFS=$IFS0
548563
}
549564

550565
# given a list of arguments, identify the internal ones
@@ -979,7 +994,7 @@ case "$1" in
979994
ping_or_exit
980995

981996
# shellcheck disable=SC1090,SC2240
982-
[ -n "${STATUS_HOOK}" ] && [ -f "$SCRIPT_DIR/$STATUS_HOOK" ] && . "$SCRIPT_DIR/$STATUS_HOOK" "$@"
997+
[ -n "${STATUS_HOOK}" ] && [ -f "$RELEASE_ROOT_DIR/$STATUS_HOOK" ] && . "$RELEASE_ROOT_DIR/$STATUS_HOOK" "$@"
983998
;;
984999
help)
9851000
if [ -z "$2" ]; then

shelltests/extension_tests/rebar.config

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
{relx, [{release, {extension_tests, "0.1.0"},
55
[extension_tests]},
6-
{extended_start_script_extensions, [{bar, "extensions/bar"},
7-
{foo, "extensions/foo"},
8-
{baz, "extensions/baz"}]},
9-
{overlay, [{copy, "./bar", "bin/extensions/bar"},
10-
{copy, "./foo", "bin/extensions/foo"},
11-
{copy, "./baz", "bin/extensions/baz"}]}
6+
{extended_start_script_extensions, [
7+
% auto copied over to `bin/extensions/bar` with empty description
8+
{bar, "./bar"},
9+
% auto copied over to `bin/extensions/foo` with description `"foo description"`
10+
{foo, "./foo", "foo description"},
11+
% auto copied over to `bin/extensions/baz` with description `"baz description"`
12+
{baz, "./baz", "bin/extensions/baz", "baz description"}
13+
]}
1214
]}.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
# $*
3+
echo \{post_start2, $REL_NAME, \'$NAME\', $COOKIE\}. >> test

shelltests/hooks_tests/hooks_tests.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ $ cat ./_build/default/rel/hooks_tests/test
2929
>
3030
{pre_start, hooks_tests, 'hooks_tests@localhost', hooks_tests}.
3131
{post_start, hooks_tests, 'hooks_tests@localhost', hooks_tests}.
32+
{post_start2, hooks_tests, 'hooks_tests@localhost', hooks_tests}.
3233
{pre_stop, hooks_tests, 'hooks_tests@localhost', hooks_tests}.
3334
{post_stop, hooks_tests, 'hooks_tests@localhost', hooks_tests}.
3435
>= 0

shelltests/hooks_tests/rebar.config

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
[hooks_tests]},
66
{vm_args, "config/vm.args"},
77
{extended_start_script_hooks, [
8-
{pre_start, [
9-
{custom, "hooks/pre_start"}
10-
]},
11-
{post_start, [
12-
wait_for_vm_start,
13-
{pid, "foo.pid"},
14-
wait_for_vm_start,
15-
{custom, "hooks/post_start"}
16-
]},
17-
{pre_stop, [
18-
{custom, "hooks/pre_stop"}
19-
]},
20-
{post_stop, [
21-
{custom, "hooks/post_stop"}
22-
]},
23-
{status, [
24-
{custom, "hooks/status"}
25-
]}
26-
]},
27-
28-
{overlay, [{copy, "./hooks/status", "bin/hooks/status"},
29-
{copy, "./hooks/{pre,post}_{start,stop}", "bin/hooks/"}]}]}.
8+
{pre_start, [
9+
{custom, "hooks/pre_start"}
10+
]},
11+
{post_start, [
12+
wait_for_vm_start,
13+
{pid, "foo.pid"},
14+
wait_for_vm_start,
15+
{custom, "hooks/post_start"},
16+
{custom, "hooks/post_start2", "bin/hooks/extra/post_start"}
17+
]},
18+
{pre_stop, [
19+
{custom, "hooks/pre_stop"}
20+
]},
21+
{post_stop, [
22+
{custom, "hooks/post_stop"}
23+
]},
24+
{status, [
25+
{custom, "hooks/status"}
26+
]}
27+
]}
28+
]}.

src/rlx_assemble.erl

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,25 @@ create_release(State0, Release0, OutputDir) ->
273273
ok = rlx_file_utils:write_term(StartCleanFile, StartCleanMeta),
274274
ok = rlx_file_utils:write_term(NoDotErlFile, NoDotErlMeta),
275275
write_bin_file(State1, Release1, OutputDir, ReleaseDir),
276-
{ok, State1}.
276+
% check for existing start script extensions and append
277+
% the overlays necessary for them to be copied over to the
278+
% release
279+
State2 = apply_extension_overlays(
280+
rlx_state:extended_start_script_extensions(State1), State1),
281+
{ok, State2}.
282+
283+
apply_extension_overlays([], State) -> State;
284+
apply_extension_overlays([{Name, ExtensionSrc} | Rest], State) ->
285+
ExtensionTarget = extension_default_target(ExtensionSrc),
286+
apply_extension_overlays([{Name, ExtensionSrc, ExtensionTarget} | Rest], State);
287+
apply_extension_overlays([{Name, ExtensionSrc, _ExtensionDescription} | Rest], State) ->
288+
ExtensionTarget = extension_default_target(ExtensionSrc),
289+
apply_extension_overlays([{Name, ExtensionSrc, ExtensionTarget, _ExtensionDescription} | Rest], State);
290+
apply_extension_overlays([{_, ExtensionSrc, ExtensionTarget, _} | Rest], State0) ->
291+
State1 = rlx_state:overlay(State0,
292+
[{copy, ExtensionSrc, ExtensionTarget} | rlx_state:overlay(State0)]),
293+
% create the overlay instruction that will copy the extension script to it's release location
294+
apply_extension_overlays(Rest, State1).
277295

278296
write_bin_file(State, Release, OutputDir, RelDir) ->
279297
BinDir = filename:join([OutputDir, "bin"]),
@@ -317,7 +335,7 @@ write_start_scripts_for(Type, Release, OutputDir, State) ->
317335
%% extended start script needs nodetool so it's
318336
%% always included
319337
include_nodetool(BinDir),
320-
Hooks = expand_hooks(BinDir,
338+
Hooks = expand_hooks(OutputDir,
321339
rlx_state:extended_start_script_hooks(State),
322340
State),
323341
Extensions = rlx_state:extended_start_script_extensions(State),
@@ -361,20 +379,20 @@ write_start_script(BaseName, Type, StartFile) ->
361379
ok = file:write_file(RelStartFile, StartFile),
362380
ok = file:change_mode(RelStartFile, 8#755).
363381

364-
expand_hooks(_Bindir, [], _State) -> [];
365-
expand_hooks(BinDir, Hooks, _State) ->
366-
expand_hooks(BinDir, Hooks, [], _State).
382+
expand_hooks(_OutputDir, [], _State) -> [];
383+
expand_hooks(OutputDir, Hooks, _State) ->
384+
expand_hooks(OutputDir, Hooks, [], _State).
367385

368-
expand_hooks(_BinDir, [], Acc, _State) -> Acc;
369-
expand_hooks(BinDir, [{Phase, Hooks0} | Rest], Acc, State) ->
386+
expand_hooks(_OutputDir, [], Acc, _State) -> Acc;
387+
expand_hooks(OutputDir, [{Phase, Hooks0} | Rest], Acc, State) ->
370388
%% filter and expand hooks to their respective shell scripts
371389
Hooks =
372390
lists:foldl(
373391
fun(Hook, Acc0) ->
374392
case validate_hook(Phase, Hook) of
375393
true ->
376-
%% all hooks are relative to the bin dir
377-
HookScriptFilename = filename:join([BinDir,
394+
%% all hooks are relative to the release root dir
395+
HookScriptFilename = filename:join([OutputDir,
378396
hook_filename(Hook)]),
379397
%% write the hook script file to it's proper location
380398
ok = render_hook(hook_template(Hook), HookScriptFilename, State),
@@ -386,7 +404,7 @@ expand_hooks(BinDir, [{Phase, Hooks0} | Rest], Acc, State) ->
386404
Acc0
387405
end
388406
end, [], Hooks0),
389-
expand_hooks(BinDir, Rest, Acc ++ [{Phase, Hooks}], State).
407+
expand_hooks(OutputDir, Rest, Acc ++ [{Phase, Hooks}], State).
390408

391409
%% the pid script hook is only allowed in the
392410
%% post_start phase
@@ -399,43 +417,48 @@ validate_hook(post_start, wait_for_vm_start) -> true;
399417
validate_hook(post_start, {wait_for_process, _}) -> true;
400418
%% custom hooks are allowed in all phases
401419
validate_hook(_Phase, {custom, _}) -> true;
420+
validate_hook(_Phase, {custom, _, _}) -> true;
402421
%% as well as status hooks
403422
validate_hook(status, _) -> true;
404423
%% deny all others
405424
validate_hook(_, _) -> false.
406425

407-
hook_filename({custom, CustomScript}) -> CustomScript;
408-
hook_filename(pid) -> "hooks/builtin/pid";
409-
hook_filename({pid, _}) -> "hooks/builtin/pid";
410-
hook_filename(wait_for_vm_start) -> "hooks/builtin/wait_for_vm_start";
411-
hook_filename({wait_for_process, _}) -> "hooks/builtin/wait_for_process";
412-
hook_filename(builtin_status) -> "hooks/builtin/status".
413-
414-
hook_invocation({custom, CustomScript}) -> CustomScript;
426+
% custom hook target location defaults to `bin/hooks`
427+
hook_filename({custom, Src}) ->
428+
filename:join(["bin/hooks", filename:basename(Src)]);
429+
hook_filename({custom, _, Target}) -> Target;
430+
hook_filename(pid) -> "bin/hooks/builtin/pid";
431+
hook_filename({pid, _}) -> "bin/hooks/builtin/pid";
432+
hook_filename(wait_for_vm_start) -> "bin/hooks/builtin/wait_for_vm_start";
433+
hook_filename({wait_for_process, _}) -> "bin/hooks/builtin/wait_for_process";
434+
hook_filename(builtin_status) -> "bin/hooks/builtin/status".
435+
436+
hook_invocation({custom, Src}) ->
437+
filename:join(["bin/hooks", filename:basename(Src)]);
438+
hook_invocation({custom, _, Target}) ->
439+
Target;
415440
%% the pid builtin hook with no arguments writes to pid file
416441
%% at /var/run/{{ rel_name }}.pid
417-
hook_invocation(pid) -> rlx_string:join(["hooks/builtin/pid",
442+
hook_invocation(pid) -> rlx_string:join(["bin/hooks/builtin/pid",
418443
"/var/run/$REL_NAME.pid"], "|");
419-
hook_invocation({pid, PidFile}) -> rlx_string:join(["hooks/builtin/pid",
444+
hook_invocation({pid, PidFile}) -> rlx_string:join(["bin/hooks/builtin/pid",
420445
PidFile], "|");
421-
hook_invocation(wait_for_vm_start) -> "hooks/builtin/wait_for_vm_start";
446+
hook_invocation(wait_for_vm_start) -> "bin/hooks/builtin/wait_for_vm_start";
422447
hook_invocation({wait_for_process, Name}) ->
423448
%% wait_for_process takes an atom as argument
424449
%% which is the process name to wait for
425-
rlx_string:join(["hooks/builtin/wait_for_process",
450+
rlx_string:join(["bin/hooks/builtin/wait_for_process",
426451
atom_to_list(Name)], "|");
427-
hook_invocation(builtin_status) -> "hooks/builtin/status".
452+
hook_invocation(builtin_status) -> "bin/hooks/builtin/status".
428453

429-
hook_template({custom, _}) -> custom;
454+
hook_template({custom, Src}) -> {file, Src};
455+
hook_template({custom, Src, _}) -> {file, Src};
430456
hook_template(pid) -> builtin_hook_pid;
431457
hook_template({pid, _}) -> builtin_hook_pid;
432458
hook_template(wait_for_vm_start) -> builtin_hook_wait_for_vm_start;
433459
hook_template({wait_for_process, _}) -> builtin_hook_wait_for_process;
434460
hook_template(builtin_status) -> builtin_hook_status.
435461

436-
%% custom hooks are not rendered, they should
437-
%% be copied by the release overlays
438-
render_hook(custom, _, _) -> ok;
439462
render_hook(TemplateName, Script, _State) ->
440463
?log_info("rendering ~p hook to ~s", [TemplateName, rlx_file_utils:print_path(Script)]),
441464
Template = render(TemplateName),
@@ -966,6 +989,38 @@ bin_file_contents(Type, RelName, RelVsn, ErtsVsn) ->
966989
render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn},
967990
{erts_vsn, ErtsVsn}]).
968991

992+
extension_default_target(Src) ->
993+
filename:join("bin/extensions", filename:basename(Src)).
994+
995+
extension_default_description(_) ->
996+
"".
997+
998+
extensions(Extensions) ->
999+
extensions(Extensions, {[], [], []}).
1000+
1001+
extensions([], {ExtensionsList0, ExtensionDeclarations0, ExtensionDescriptions0}) ->
1002+
% pipe separated string of extensions
1003+
% (eg. foo|bar|baz|undefined)
1004+
ExtensionsList = rlx_string:join(ExtensionsList0 ++ ["undefined"], "|"),
1005+
% command separated string of extension script declarations
1006+
% (eg. foo_extension="path/to/foo_script:bar_extension="path/to/bar_script")
1007+
ExtensionDeclarations = rlx_string:join(ExtensionDeclarations0, ";"),
1008+
% (eg. baz=baz description|foo=foo description|bar=)
1009+
ExtensionDescriptions = rlx_string:join(ExtensionDescriptions0, "|"),
1010+
{ExtensionsList, ExtensionDeclarations, ExtensionDescriptions};
1011+
extensions([{Name, Src} | Rest], Acc) ->
1012+
extensions([{Name, Src, extension_default_target(Src), extension_default_description(Name)} | Rest], Acc);
1013+
extensions([{Name, Src, Description} | Rest], Acc) ->
1014+
extensions([{Name, Src, extension_default_target(Src), Description} | Rest], Acc);
1015+
extensions([{Name, _Src, Target, Description} | Rest],
1016+
{Acc0, Acc1, Acc2}) ->
1017+
NameStr = atom_to_list(Name),
1018+
% eg. bar_extension=bin/extensions/bar
1019+
ExtensionDeclaration = NameStr ++ "_extension=\"" ++ Target ++ "\"",
1020+
% eg. bar=bar description
1021+
ExtensionDescription = NameStr ++ "=" ++ Description,
1022+
extensions(Rest, {[atom_to_list(Name) | Acc0], [ExtensionDeclaration | Acc1], [ExtensionDescription | Acc2]}).
1023+
9691024
extended_bin_file_contents(Type, RelName, RelVsn, ErtsVsn, Hooks, Extensions) ->
9701025
Template = case Type of
9711026
unix -> extended_bin;
@@ -982,21 +1037,7 @@ extended_bin_file_contents(Type, RelName, RelVsn, ErtsVsn, Hooks, Extensions) ->
9821037
PostInstallUpgradeHooks = rlx_string:join(proplists:get_value(post_install_upgrade,
9831038
Hooks, []), " "),
9841039
StatusHook = rlx_string:join(proplists:get_value(status, Hooks, []), " "),
985-
{ExtensionsList1, ExtensionDeclarations1} =
986-
lists:foldl(fun({Name, Script},
987-
{ExtensionsList0, ExtensionDeclarations0}) ->
988-
ExtensionDeclaration = atom_to_list(Name) ++
989-
"_extension=\"" ++
990-
Script ++ "\"",
991-
{ExtensionsList0 ++ [atom_to_list(Name)],
992-
ExtensionDeclarations0 ++ [ExtensionDeclaration]}
993-
end, {[], []}, Extensions),
994-
% pipe separated string of extensions, to show on the start script usage
995-
% (eg. foo|bar)
996-
ExtensionsList = rlx_string:join(ExtensionsList1 ++ ["undefined"], "|"),
997-
% command separated string of extension script declarations
998-
% (eg. foo_extension="path/to/foo_script")
999-
ExtensionDeclarations = rlx_string:join(ExtensionDeclarations1, ";"),
1040+
{ExtensionsList, ExtensionDeclarations, ExtensionDescriptions} = extensions(Extensions),
10001041
render(Template, [{rel_name, RelName}, {rel_vsn, RelVsn},
10011042
{erts_vsn, ErtsVsn},
10021043
{pre_start_hooks, PreStartHooks},
@@ -1007,7 +1048,8 @@ extended_bin_file_contents(Type, RelName, RelVsn, ErtsVsn, Hooks, Extensions) ->
10071048
{post_install_upgrade_hooks, PostInstallUpgradeHooks},
10081049
{status_hook, StatusHook},
10091050
{extensions, ExtensionsList},
1010-
{extension_declarations, ExtensionDeclarations}]).
1051+
{extension_declarations, ExtensionDeclarations},
1052+
{extension_descriptions, ExtensionDescriptions}]).
10111053

10121054
install_upgrade_escript_contents() ->
10131055
render(install_upgrade_escript).
@@ -1027,6 +1069,10 @@ vm_args_file(RelName) ->
10271069
render(Template) ->
10281070
render(Template, []).
10291071

1072+
render({file, Name}, Data) ->
1073+
{ok, Tpl} = file:read_file(Name),
1074+
{ok, Content} = rlx_util:render(Tpl, Data),
1075+
Content;
10301076
render(Template, Data) ->
10311077
Files = rlx_util:template_files(),
10321078
Tpl = rlx_util:load_file(Files, escript, atom_to_list(Template)),

0 commit comments

Comments
 (0)