Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 45 additions & 10 deletions scripts/singularity_cmd
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
set -eu

function info() {
: # echo -e "I: $@" >&2
: # echo -e "I: " "$@" >&2
}

#
Expand Down Expand Up @@ -72,17 +72,52 @@ pass_git_config "user.name" "ReproNim User"
pass_git_config "user.email" "nobody@example.com"

# Common arguments for the singularity run
SARGS=( -e -c -B "$PWD" -H "$BHOME" --pwd "$PWD" "$@" )
SARGS=( -e -B "$PWD" -H "$BHOME" --pwd "$PWD" "$@" )

# Due to https://github.com/sylabs/singularity/issues/3949
# which was fixed only in v3.3.0-rc.1-431-g40331a5b1
# for now we need to avoid using `-c` in such cases and
# just create those needed bind points manually and bind mount
# /tmp manually (apparently -W is not in effect really without -c).
# TODO: make it also check/depend on current version of singularity
need_no_c=
for d in "$PWD" "$updir"; do
if [ "${d##/tmp/}" != "$d" ]; then
# we should create that one within our $tmpdir
info "Creating $d under $tmpdir"
mkdir -p "$tmpdir/$d" "$tmpdir/var/tmp"
need_no_c=1
fi
done

if [ -z "$need_no_c" ]; then
SARGS=( -c "${SARGS[@]}" )
else
SARGS=( -B "$tmpdir/tmp:/tmp" -B "$tmpdir/var/tmp:/var/tmp" "${SARGS[@]}" )
fi

# set -x
if [ "$OSTYPE" == "linux-gnu" ] && [ -z "${REPRONIM_USE_DOCKER:-}" ]; then
singularity "$cmd" -W "$tmpdir" "${SARGS[@]}"
else
docker run --privileged --rm \
-e "UID=$(id -u)" \
-e "GID=$(id -g)" \
-v "$PWD:$PWD" \
-v "$BHOME:$BHOME" \
-w "$PWD" \
mjtravers/singularity-shim:latest \
"$cmd" "${SARGS[@]}"
DARGS=(
--privileged
--rm
-e "UID=$(id -u)"
-e "GID=$(id -g)"
-v "$PWD:$PWD"
-v "$updir:$updir"
-v "$BHOME:$BHOME"
-w "$PWD")

# Bind mount present /etc/localtime inside the docker container to be
# passed into singularity env
if [ -e "/etc/localtime" ]; then
DARGS=( "${DARGS[@]}" -v /etc/localtime )
fi

docker run \
"${DARGS[@]}" \
mjtravers/singularity-shim:latest \
"$cmd" "${SARGS[@]}"
fi
62 changes: 62 additions & 0 deletions scripts/tests/test_helpers.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Messaging
debug () {
[ -z "$DEBUG_BATS" ] || echo " DEBUG: $@" >&3
}

debug_run () {
debug "> lines=${lines[@]}"
debug "> STATUS=$status"
}

fail_msg () {
echo -e "FAIL: $@" >&3
}

fail () {
fail_msg "$@"
exit 1
}

error () {
echo -e "ERROR: $@" >&3
exit 2
}

# Assertion helpers

assert_equal () {
if [ "$#" != 2 ]; then
error "Got $# arguments to eq whenever expected 2"
fi
if [ "$1" != "$2" ]; then
fail "Arguments are not equal.\n #1=<<$1>>\n #2=<<$2>>"
fi
}

assert_python_re_match () {
if ! python -c 'import re, sys; assert re.match(sys.argv[1], sys.argv[2], flags=re.DOTALL)' "$1" "$2"; then
fail "<<$2>>\ndid not match\n<<$1>>"
fi
}

assert_clean_exit () {
assert_equal "$status" 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I'm not thrilled about referencing globals, but I can see the utility here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, me neither -- but here I liked how succinct test code then looks ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the plan to replace these custom assert functions with the ones that duplicate in the ztombol/bats-assert library?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so -- better to reuse than to rebrew ;)

}


# Misc helpers

pull_singularity_shim () {
# make sure that we have our shim docker image so its pulling does not
# leak into output of scripts/singularity_cmd
if ! docker pull mjtravers/singularity-shim:latest; then
skip "Failed to pull singularity shim"
fi
}

skip_if_travis_osx() {
if [ "$TRAVIS_OS_NAME" = osx ]
then
skip "$@"
fi
}
113 changes: 91 additions & 22 deletions scripts/tests/test_singularity_cmd.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,96 @@
# bats test_singularity_cmd.bats
# bats .

load test_helpers

arg_test_img="$BATS_TEST_DIRNAME/arg-test.simg"
topdir="$BATS_TEST_DIRNAME/../.."

cd "$BATS_TEST_DIRNAME"
git annex get "$arg_test_img"


@test "verifying arguments passed to singularity_cmd Docker shim" {
# make sure that we have the singularity image
img="$BATS_TEST_DIRNAME/arg-test.simg"
cd "$BATS_TEST_DIRNAME"
git annex get "$img"
cd ../..
# make sure that we have our shim docker image so its pulling does not
# leak into output of scripts/singularity_cmd
docker pull mjtravers/singularity-shim:latest

export REPRONIM_USE_DOCKER=1
run scripts/singularity_cmd \
exec "$img" /singularity "foo bar" blah 45.5 /dir "bar;" "foo&" '${foo}'
echo "> STATUS=$status" >&3
echo "> lines=${lines[@]}" >&3
[ "$status" -eq 0 ]
[ "${lines[0]}" = 'arg #1=<foo bar>' ]
[ "${lines[1]}" = 'arg #2=<blah>' ]
[ "${lines[2]}" = 'arg #3=<45.5>' ]
[ "${lines[3]}" = 'arg #4=</dir>' ]
[ "${lines[4]}" = 'arg #5=<bar;>' ]
[ "${lines[5]}" = 'arg #6=<foo&>' ]
[ "${lines[6]}" = 'arg #7=<${foo}>' ]
pull_singularity_shim

cd "$topdir"
export REPRONIM_USE_DOCKER=1
run scripts/singularity_cmd \
exec "$arg_test_img" /singularity "foo bar" blah 45.5 /dir "bar;" "foo&" '${foo}'

debug_run

assert_clean_exit
assert_equal "${lines[0]}" 'arg #1=<foo bar>'
assert_equal "${lines[1]}" 'arg #2=<blah>'
assert_equal "${lines[2]}" 'arg #3=<45.5>'
assert_equal "${lines[3]}" 'arg #4=</dir>'
assert_equal "${lines[4]}" 'arg #5=<bar;>'
assert_equal "${lines[5]}" 'arg #6=<foo&>'
assert_equal "${lines[6]}" 'arg #7=<${foo}>'
}


@test "verifying ability to singularity exec under /tmp subdir" {
skip_if_travis_osx "skipping Singularity directory test on Travis OSX"
check_subdir "$(_mktemp_dir_under /tmp)"
}

@test "verifying ability to singularity exec under /tmp subdir (explicit use of docker)" {
skip_if_travis_osx "skipping Singularity directory test on Travis OSX"
export REPRONIM_USE_DOCKER=1
check_subdir "$(_mktemp_dir_under /tmp)"
}

@test "verifying ability to singularity exec under $HOME subdir" {
skip_if_travis_osx "skipping Singularity directory test on Travis OSX"
check_subdir "$(_mktemp_dir_under $HOME)"
}

@test "verifying ability to singularity exec under $HOME subdir (explicit use of docker)" {
skip_if_travis_osx "skipping Singularity directory test on Travis OSX"
export REPRONIM_USE_DOCKER=1
check_subdir "$(_mktemp_dir_under $HOME)"
}


_mktemp_dir_under () {
subdir="$1/$(mktemp -t "tmp dir.XXXXXX" -u | sed -e 's,.*/,,g')"
mkdir -p "$subdir"
debug "subdir: $subdir"
echo "$subdir"
}

check_subdir () {
subdir="$1"
cd "$subdir"
echo "content" > "$subdir/file"

# Our arg_test image has no /etc/localtime so singularity might complain
# about inability to bind mount that one
# \S* to swallow ANSI coloring
target_out=( '(\S*WARNING:\S* skipping mount of /etc/localtime: no such file or directory\n)?/tmp'
"$subdir"
"$subdir/file"
/var/tmp
content )

if [ -n "${REPRONIM_USE_DOCKER:-}" ]; then
pull_singularity_shim
fi
run_cmd="find /tmp"
if [ "${subdir##/tmp/}" = "$subdir" ]; then
# We are not under /tmp so find will not find our directory, add it explicitly to the list
# for find
run_cmd+=" \"$subdir\""
fi
run_cmd+=" /var/tmp && cat \"$subdir/file\""
run "$topdir/scripts/singularity_cmd" exec "$arg_test_img" sh -c "$run_cmd"

rm -rf "$subdir" # cleanup asap

debug_run

assert_clean_exit
assert_python_re_match "${target_out[*]}" "${lines[*]}"
}
34 changes: 19 additions & 15 deletions travis/dummy_docker
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,25 @@ elif [ "$1" = "run" -a \
"$7" = "GID=20" -a \
"$8" = "-v" -a \
"${10}" = "-v" -a \
"${12}" = "-w" -a \
"${15}" = "exec" -a \
"${16}" = "-e" -a \
"${17}" = "-c" -a \
"${18}" = "-B" -a \
"${20}" = "-H" -a \
"${22}" = "--pwd" -a \
"${25}" = "/singularity" -a \
"${26}" = "foo bar" -a \
"${27}" = "blah" -a \
"${28}" = "45.5" -a \
"${29}" = "/dir" -a \
"${30}" = "bar;" -a \
"${31}" = "foo&" -a \
"${32}" = "\${foo}" ]
"${12}" = "-v" -a \
"${14}" = "-w" -a \
"${16}" = "-v" -a \
"${17}" = "/etc/localtime" -a \
"${18}" = "mjtravers/singularity-shim:latest" -a \
"${19}" = "exec" -a \
"${20}" = "-c" -a \
"${21}" = "-e" -a \
"${22}" = "-B" -a \
"${24}" = "-H" -a \
"${26}" = "--pwd" -a \
"${29}" = "/singularity" -a \
"${30}" = "foo bar" -a \
"${31}" = "blah" -a \
"${32}" = "45.5" -a \
"${33}" = "/dir" -a \
"${34}" = "bar;" -a \
"${35}" = "foo&" -a \
"${36}" = "\${foo}" ]
then
cat << EOF
arg #1=<foo bar>
Expand Down