aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge Aleynikov <[email protected]>2016-11-09 18:58:55 -0500
committerSerge Aleynikov <[email protected]>2016-11-09 18:58:55 -0500
commit103af5c657fa38e44f04c93702d0e55a3271d82b (patch)
tree5ff0e6c569051730571e49e5620f5419b31dd5d8
parentf74972a6e65fc4c2a1ba098b4cea230a4b7a63f2 (diff)
downloadrelx-103af5c657fa38e44f04c93702d0e55a3271d82b.tar.gz
relx-103af5c657fa38e44f04c93702d0e55a3271d82b.tar.bz2
relx-103af5c657fa38e44f04c93702d0e55a3271d82b.zip
Remove name collisions of replaced files in multi-node setups
-rwxr-xr-xpriv/templates/extended_bin89
-rw-r--r--test/rlx_extended_bin_SUITE.erl186
-rw-r--r--test/rlx_test_utils.erl4
3 files changed, 249 insertions, 30 deletions
diff --git a/priv/templates/extended_bin b/priv/templates/extended_bin
index 5cb1c04..acf77b9 100755
--- a/priv/templates/extended_bin
+++ b/priv/templates/extended_bin
@@ -17,13 +17,12 @@ if [ "$TERM" = "dumb" -o -z "$TERM" ]; then
export TERM=screen
fi
-SCRIPT=$(readlink $0 || true)
-if [ -z $SCRIPT ]; then
- SCRIPT=$0
-fi;
+SCRIPT=$(readlink -f $0 || true)
+[ -z $SCRIPT ] && SCRIPT=$0
SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)"
-REL_NAME="{{ rel_name }}"
+# Make the value available to variable substitution calls below
+export REL_NAME="{{ rel_name }}"
REL_VSN="{{ rel_vsn }}"
ERTS_VSN="{{ erts_vsn }}"
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
@@ -119,7 +118,9 @@ relx_get_pid() {
relx_get_nodename() {
id="longname$(relx_gen_id)-${NAME}"
- "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
+ "$BINDIR/erl" -boot start_clean \
+ -eval '[H]=tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n",[H]), halt()' \
+ -noshell ${NAME_TYPE} $id
}
# Connect to a remote node
@@ -174,7 +175,30 @@ relx_get_code_paths() {
"$BINDIR/erl" -noshell -boot start_clean -eval "$code"
}
-check_replace_os_vars() {
+make_out_file_path() {
+ # Use output directory provided in the RELX_OUT_FILE_PATH environment variable
+ # (default to the current location of vm.args and sys.config)
+ DIR=$(dirname $1)
+ [ -d "${RELX_OUT_FILE_PATH}" ] && DIR="${RELX_OUT_FILE_PATH}"
+ FILE=$(basename $1)
+ IN="${DIR}/${FILE}"
+
+ PFX=$(echo $IN | awk '{sub(/\.[^.]+$/, "", $0)}1')
+ SFX=$(echo $FILE | awk -F . '{if (NF>1) print $NF}')
+ echo "${PFX}.${NAME}.${SFX}"
+}
+
+# Replace environment variables
+replace_os_vars() {
+ awk '{
+ while(match($0,"[$]{[^}]*}")) {
+ var=substr($0,RSTART+2,RLENGTH -3)
+ gsub("[$]{"var"}",ENVIRON[var])
+ }
+ }1' < "$1" > "$2"
+}
+
+add_path() {
# Use $CWD/$1 if exists, otherwise releases/VSN/$1
IN_FILE_PATH=$2
if [ -z "$IN_FILE_PATH" ]; then
@@ -184,12 +208,16 @@ check_replace_os_vars() {
IN_FILE_PATH="$REL_DIR/$1"
fi
fi
+ echo $IN_FILE_PATH
+}
+check_replace_os_vars() {
+ IN_FILE_PATH=$(add_path $1 $2)
OUT_FILE_PATH="$IN_FILE_PATH"
ORIG_FILE_PATH="$IN_FILE_PATH.orig"
if [ $RELX_REPLACE_OS_VARS ]; then
- # Create a new file in /tmp
- OUT_FILE_PATH=$(mktemp /tmp/XXXXXX.$REL_NAME.$1)
+ # Create a new file in the same location as original
+ OUT_FILE_PATH=$(make_out_file_path $IN_FILE_PATH)
# If vm.args.orig or sys.config.orig is present then use that
if [ -f "$ORIG_FILE_PATH" ]; then
IN_FILE_PATH="$ORIG_FILE_PATH"
@@ -197,7 +225,7 @@ check_replace_os_vars() {
# apply the environment variable substitution to $IN_FILE_PATH
# the result is saved to $OUT_FILE_PATH
- awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$IN_FILE_PATH" > "$OUT_FILE_PATH"
+ replace_os_vars "$IN_FILE_PATH" "$OUT_FILE_PATH"
else
# If vm.arg.orig or sys.config.orig is present then use that
if [ -f "$ORIG_FILE_PATH" ]; then
@@ -207,14 +235,12 @@ check_replace_os_vars() {
echo $OUT_FILE_PATH
}
-VMARGS_PATH=$(check_replace_os_vars vm.args $VMARGS_PATH)
-RELX_CONFIG_PATH=$(check_replace_os_vars sys.config $RELX_CONFIG_PATH)
-
-# Make sure log directory exists
-mkdir -p "$RUNNER_LOG_DIR"
-
+VMARGS_PATH=$(add_path vm.args $VMARGS_PATH)
# Extract the target node name from node.args
NAME_ARG=$(egrep '^-s?name' "$VMARGS_PATH" || true)
+# Perform replacement of variables in ${NAME_ARG}
+NAME_ARG=$(eval echo "${NAME_ARG}")
+
if [ -z "$NAME_ARG" ]; then
echo "vm.args needs to have either -name or -sname parameter."
exit 1
@@ -224,6 +250,23 @@ fi
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
+# User can specify an sname without @hostname
+# This will fail when creating remote shell
+# So here we check for @ and add @hostname if missing
+case "${NAME}" in
+ *@*) ;; # Nothing to do
+ *) NAME=${NAME}@$(hostname -s);; # Add @hostname
+esac
+
+# Export the variable so that it's available in the 'eval' calls
+export NAME
+
+VMARGS_PATH=$(check_replace_os_vars vm.args $VMARGS_PATH)
+RELX_CONFIG_PATH=$(check_replace_os_vars sys.config $RELX_CONFIG_PATH)
+
+# Make sure log directory exists
+mkdir -p "$RUNNER_LOG_DIR"
+
PIPE_DIR="${PIPE_DIR:-/tmp/erl_pipes/$NAME/}"
# Extract the target cookie
@@ -247,22 +290,10 @@ export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
-ERTS_LIB_DIR="$ERTS_DIR/../lib"
+ERTS_LIB_DIR="$(dirname "$ERTS_DIR")/lib"
cd "$ROOTDIR"
-# User can specify an sname without @hostname
-# This will fail when creating remote shell
-# So here we check for @ and add @hostname if missing
-case $NAME in
- *@*)
- # Nothing to do
- ;;
- *)
- NAME=$NAME@$(relx_get_nodename)
- ;;
-esac
-
# Check the first argument for instructions
case "$1" in
start|start_boot)
diff --git a/test/rlx_extended_bin_SUITE.erl b/test/rlx_extended_bin_SUITE.erl
index 9a15bf8..2bd0554 100644
--- a/test/rlx_extended_bin_SUITE.erl
+++ b/test/rlx_extended_bin_SUITE.erl
@@ -30,6 +30,7 @@
escript/1,
remote_console/1,
replace_os_vars/1,
+ replace_os_vars_custom_location/1,
replace_os_vars_dev_mode/1,
replace_os_vars_twice/1]).
@@ -57,7 +58,9 @@ init_per_testcase(_, Config) ->
all() ->
[ping, attach, pid, restart, reboot, escript,
- remote_console, replace_os_vars, replace_os_vars_dev_mode].
+ remote_console,
+ replace_os_vars, replace_os_vars_custom_location,
+ replace_os_vars_dev_mode, replace_os_vars_twice].
ping(Config) ->
LibDir1 = proplists:get_value(lib1, Config),
@@ -370,6 +373,16 @@ replace_os_vars(Config) ->
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node1"},
{"COOKIE", "cookie1"}]),
+ {ok, Node1} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "releases", "0.0.1",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node1) ++
+ ".config"]))),
{ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node1"},
@@ -401,12 +414,153 @@ replace_os_vars(Config) ->
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node2"},
{"COOKIE", "cookie2"}]),
+ {ok, Node2} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "releases", "0.0.1",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node2) ++
+ ".config"]))),
{ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node2"},
{"COOKIE", "cookie2"}]),
ok.
+replace_os_vars_custom_location(Config) ->
+ LibDir1 = proplists:get_value(lib1, Config),
+
+ rlx_test_utils:create_app(LibDir1, "goal_app", "0.0.1", [stdlib,kernel], []),
+
+ ConfigFile = filename:join([LibDir1, "relx.config"]),
+ SysConfig = filename:join([LibDir1, "sys.config"]),
+ VmArgs = filename:join([LibDir1, "vm.args"]),
+
+ rlx_test_utils:write_config(ConfigFile,
+ [{release, {foo, "0.0.1"},
+ [goal_app]},
+ {lib_dirs, [filename:join(LibDir1, "*")]},
+ {sys_config, SysConfig},
+ {vm_args, VmArgs},
+ {generate_start_script, true},
+ {extended_start_script, true}
+ ]),
+
+ rlx_test_utils:write_config(SysConfig,
+ [[{goal_app, [{var1, "${VAR1}"}]}]]),
+ ec_file:write(VmArgs, "-sname ${NODENAME}\n\n"
+ "-setcookie ${COOKIE}\n"),
+
+ OutputDir = filename:join([proplists:get_value(priv_dir, Config),
+ rlx_test_utils:create_random_name("relx-output")]),
+
+ {ok, _State} = relx:do([{relname, foo},
+ {relvsn, "0.0.1"},
+ {goals, []},
+ {lib_dirs, [LibDir1]},
+ {log_level, 3},
+ {output_dir, OutputDir},
+ {config, ConfigFile}], ["release"]),
+
+ {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"},
+ {"VAR1", "v1"}]),
+ timer:sleep(2000),
+ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ {ok, "\"v1\""} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval '{ok, V} = application:get_env(goal_app, var1), V.'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ {ok, "\"node1\""} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval '[Node,_] = re:split(atom_to_list(node()), \"@\"),binary_to_list(Node).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ {ok, "cookie1"} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'erlang:get_cookie().'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ {ok, Node1} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join(["/", "tmp",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node1) ++
+ ".config"]))),
+ {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+
+ %% start the node again but this time with different env variables to replace
+ {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo start"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"},
+ {"VAR1", "v2"}]),
+ timer:sleep(2000),
+ {ok, "pong"} = sh(filename:join([OutputDir, "foo", "bin", "foo ping"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ {ok, "\"v2\""} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval '{ok, V} = application:get_env(goal_app, var1), V.'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ {ok, "\"node2\""} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval '[Node,_] = re:split(atom_to_list(node()), \"@\"),binary_to_list(Node).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ {ok, "cookie2"} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'erlang:get_cookie().'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ {ok, Node2} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join(["/", "tmp",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node2) ++
+ ".config"]))),
+ {ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"RELX_OUT_FILE_PATH", "/tmp"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ ok.
+
replace_os_vars_twice(Config) ->
LibDir1 = proplists:get_value(lib1, Config),
@@ -457,6 +611,16 @@ replace_os_vars_twice(Config) ->
{ok, "cookie"} = sh(filename:join([OutputDir, "foo", "bin",
"foo eval 'erlang:get_cookie().'"]),
[{"RELX_REPLACE_OS_VARS", "1"}]),
+ {ok, Node1} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "releases", "0.0.1",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node1) ++
+ ".config"]))),
{ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
[{"RELX_REPLACE_OS_VARS", "1"}]),
@@ -534,6 +698,16 @@ replace_os_vars_dev_mode(Config) ->
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node1"},
{"COOKIE", "cookie1"}]),
+ {ok, Node1} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"NODENAME", "node1"},
+ {"COOKIE", "cookie1"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "releases", "0.0.1",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node1) ++
+ ".config"]))),
{ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node1"},
@@ -565,6 +739,16 @@ replace_os_vars_dev_mode(Config) ->
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node2"},
{"COOKIE", "cookie2"}]),
+ {ok, Node2} = sh(filename:join([OutputDir, "foo", "bin",
+ "foo eval 'atom_to_list(node()).'"]),
+ [{"RELX_REPLACE_OS_VARS", "1"},
+ {"NODENAME", "node2"},
+ {"COOKIE", "cookie2"}]),
+ %% check that the replaced files have been created in the right place
+ ?assert(ec_file:exists(filename:join([OutputDir, "foo", "releases", "0.0.1",
+ "sys." ++
+ rlx_test_utils:unescape_string(Node2) ++
+ ".config"]))),
{ok, _} = sh(filename:join([OutputDir, "foo", "bin", "foo stop"]),
[{"RELX_REPLACE_OS_VARS", "1"},
{"NODENAME", "node2"},
diff --git a/test/rlx_test_utils.erl b/test/rlx_test_utils.erl
index b6f6d7e..3ddc134 100644
--- a/test/rlx_test_utils.erl
+++ b/test/rlx_test_utils.erl
@@ -110,3 +110,7 @@ list_to_term(String) ->
{error, Error} ->
Error
end.
+
+unescape_string(String) ->
+ re:replace(String, "\"", "",
+ [global, {return, list}]). \ No newline at end of file