#!/bin/bash
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
-. `dirname "$(readlink -f "$0")"`/libcloud-pin
+. `dirname "$(readlink -f "$0")"`/libcloud-pin.sh
COLUMNS=80
. `dirname "$(readlink -f "$0")"`/run-library.sh
--leave-temp Do not remove GOPATH, virtualenv, and other temp dirs at exit.
Instead, show the path to give as --temp to reuse them in
subsequent invocations.
+--repeat N Repeat each install/test step until it succeeds N times.
+--retry Prompt to retry if an install or test suite fails.
--skip-install Do not run any install steps. Just run tests.
You should provide GOPATH, GEMHOME, and VENVDIR options
from a previous invocation if you use this option.
services/keep-balance
services/login-sync
services/nodemanager
+services/nodemanager-integration
services/crunch-run
services/crunch-dispatch-local
services/crunch-dispatch-slurm
+services/ws
sdk/cli
sdk/pam
sdk/python
+sdk/python:py3
sdk/ruby
sdk/go/arvados
sdk/go/arvadosclient
+sdk/go/dispatch
sdk/go/keepclient
+sdk/go/health
sdk/go/httpserver
sdk/go/manifest
sdk/go/blockdigest
sdk/go/streamer
+sdk/go/stats
sdk/go/crunchrunner
sdk/cwl
tools/crunchstat-summary
PERLINSTALLBASE=
short=
-skip_install=
+only_install=
temp=
temp_preserve=
echo -n 'ruby: '
ruby -v \
|| fatal "No ruby. Install >=2.1.9 (using rbenv, rvm, or source)"
- echo -n 'bundler: '
- bundle version \
- || fatal "No bundler. Try: gem install bundler"
echo -n 'go: '
go version \
|| fatal "No go binary. See http://golang.org/doc/install"
- [[ $(go version) =~ go1.([0-9]+) ]] && [[ ${BASH_REMATCH[1]} -ge 7 ]] \
- || fatal "Go >= 1.7 required. See http://golang.org/doc/install"
+ [[ $(go version) =~ go1.([0-9]+) ]] && [[ ${BASH_REMATCH[1]} -ge 8 ]] \
+ || fatal "Go >= 1.8 required. See http://golang.org/doc/install"
echo -n 'gcc: '
gcc --version | egrep ^gcc \
|| fatal "No gcc. Try: apt-get install build-essential"
echo -n 'fuse.h: '
- find /usr/include -wholename '*fuse/fuse.h' \
+ find /usr/include -path '*fuse/fuse.h' | egrep --max-count=1 . \
|| fatal "No fuse/fuse.h. Try: apt-get install libfuse-dev"
- echo -n 'pyconfig.h: '
- find /usr/include -name pyconfig.h | egrep --max-count=1 . \
- || fatal "No pyconfig.h. Try: apt-get install python-dev"
+ echo -n 'gnutls.h: '
+ find /usr/include -path '*gnutls/gnutls.h' | egrep --max-count=1 . \
+ || fatal "No gnutls/gnutls.h. Try: apt-get install libgnutls28-dev"
+ echo -n 'Python2 pyconfig.h: '
+ find /usr/include -path '*/python2*/pyconfig.h' | egrep --max-count=1 . \
+ || fatal "No Python2 pyconfig.h. Try: apt-get install python2.7-dev"
+ echo -n 'Python3 pyconfig.h: '
+ find /usr/include -path '*/python3*/pyconfig.h' | egrep --max-count=1 . \
+ || fatal "No Python3 pyconfig.h. Try: apt-get install python3-dev"
echo -n 'nginx: '
PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" nginx -v \
|| fatal "No nginx. Try: apt-get install nginx"
exit 1
;;
--skip)
- skipwhat="$1"; shift
- if [[ "$skipwhat" == "apps/workbench" ]]; then
- skip["apps/workbench_units"]=1
- skip["apps/workbench_functionals"]=1
- skip["apps/workbench_integration"]=1
- else
- skip[$skipwhat]=1
- fi
+ skip[$1]=1; shift
;;
--only)
only="$1"; skip[$1]=""; shift
short=1
;;
--skip-install)
- skip_install=1
+ only_install=nothing
;;
--only-install)
- skip_install=1
only_install="$1"; shift
;;
--temp)
--leave-temp)
temp_preserve=1
;;
+ --repeat)
+ repeat=$((${1}+0)); shift
+ ;;
--retry)
retry=1
;;
&& eval $(python sdk/python/tests/run_test_server.py start --auth admin) \
&& export ARVADOS_TEST_API_HOST="$ARVADOS_API_HOST" \
&& export ARVADOS_TEST_API_INSTALLED="$$" \
+ && python sdk/python/tests/run_test_server.py start_ws \
+ && python sdk/python/tests/run_test_server.py start_nginx \
&& (env | egrep ^ARVADOS)
}
start_nginx_proxy_services() {
- echo 'Starting keepproxy, keep-web, arv-git-httpd, and nginx ssl proxy...'
+ echo 'Starting keepproxy, keep-web, ws, arv-git-httpd, and nginx ssl proxy...'
cd "$WORKSPACE" \
&& python sdk/python/tests/run_test_server.py start_keep_proxy \
&& python sdk/python/tests/run_test_server.py start_keep-web \
&& python sdk/python/tests/run_test_server.py start_arv-git-httpd \
+ && python sdk/python/tests/run_test_server.py start_ws \
&& python sdk/python/tests/run_test_server.py start_nginx \
&& export ARVADOS_TEST_PROXY_SERVICES=1
}
cd "$WORKSPACE" \
&& python sdk/python/tests/run_test_server.py stop_nginx \
&& python sdk/python/tests/run_test_server.py stop_arv-git-httpd \
+ && python sdk/python/tests/run_test_server.py stop_ws \
&& python sdk/python/tests/run_test_server.py stop_keep-web \
&& python sdk/python/tests/run_test_server.py stop_keep_proxy
fi
if [[ -n "$ARVADOS_TEST_API_HOST" ]]; then
unset ARVADOS_TEST_API_HOST
cd "$WORKSPACE" \
+ && python sdk/python/tests/run_test_server.py stop_nginx \
+ && python sdk/python/tests/run_test_server.py stop_ws \
&& python sdk/python/tests/run_test_server.py stop
fi
}
setup_ruby_environment() {
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
- source "$HOME/.rvm/scripts/rvm"
- using_rvm=true
+ source "$HOME/.rvm/scripts/rvm"
+ using_rvm=true
elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
- source "/usr/local/rvm/scripts/rvm"
- using_rvm=true
+ source "/usr/local/rvm/scripts/rvm"
+ using_rvm=true
else
- using_rvm=false
+ using_rvm=false
fi
if [[ "$using_rvm" == true ]]; then
tmpdir_gem_home="$(env - PATH="$PATH" HOME="$GEMHOME" gem env gempath | cut -f1 -d:)"
PATH="$tmpdir_gem_home/bin:$PATH"
- export GEM_PATH="$tmpdir_gem_home:$(gem env gempath)"
+ export GEM_PATH="$tmpdir_gem_home"
echo "Will install dependencies to $(gem env gemdir)"
echo "Will install arvados gems to $tmpdir_gem_home"
echo "Gem search path is GEM_PATH=$GEM_PATH"
fi
+ bundle config || gem install bundler \
+ || fatal 'install bundler'
}
with_test_gemset() {
export GOPATH
mkdir -p "$GOPATH/src/git.curoverse.com"
-ln -sfn "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
+ln -sfT "$WORKSPACE" "$GOPATH/src/git.curoverse.com/arvados.git" \
|| fatal "symlink failed"
+go get -v github.com/kardianos/govendor \
+ || fatal "govendor install failed"
setup_virtualenv "$VENVDIR" --python python2.7
. "$VENVDIR/bin/activate"
|| pip install --pre --ignore-installed https://github.com/curoverse/libcloud/archive/apache-libcloud-$LIBCLOUD_PIN.zip >/dev/null \
|| fatal "pip install apache-libcloud failed"
-# This will help people who reuse --temp dirs when we upgrade to llfuse 0.42
-if egrep -q 'llfuse.*>= *0\.42' "$WORKSPACE/services/fuse/setup.py"; then
- # Uninstall old llfuse, because services/fuse "pip install" won't
- # upgrade it by default.
- if pip freeze | egrep '^llfuse==0\.41\.'; then
- yes | pip uninstall 'llfuse<0.42'
- fi
+# Uninstall old llfuse (<1.0), because services/fuse "pip install"
+# won't upgrade it by default.
+if pip freeze | egrep '^llfuse==0'; then
+ yes | pip uninstall 'llfuse<1.0'
fi
# Deactivate Python 2 virtualenv
deactivate
+declare -a pythonstuff
+pythonstuff=(
+ sdk/pam
+ sdk/python
+ sdk/python:py3
+ sdk/cwl
+ services/dockercleaner:py3
+ services/fuse
+ services/nodemanager
+ tools/crunchstat-summary
+ )
+
# If Python 3 is available, set up its virtualenv in $VENV3DIR.
# Otherwise, skip dependent tests.
PYTHON3=$(which python3)
-if [ "0" = "$?" ]; then
+if [[ ${?} = 0 ]]; then
setup_virtualenv "$VENV3DIR" --python python3
else
PYTHON3=
- skip[services/dockercleaner]=1
cat >&2 <<EOF
-Warning: python3 could not be found
-services/dockercleaner install and tests will be skipped
+Warning: python3 could not be found. Python 3 tests will be skipped.
EOF
fi
fi
retry() {
- while ! ${@} && [[ "$retry" == 1 ]]
+ remain="${repeat}"
+ while :
do
- read -p 'Try again? [Y/n] ' x
- if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
- then
+ if ${@}; then
+ if [[ "$remain" -gt 1 ]]; then
+ remain=$((${remain}-1))
+ title "Repeating ${remain} more times"
+ else
+ break
+ fi
+ elif [[ "$retry" == 1 ]]; then
+ read -p 'Try again? [Y/n] ' x
+ if [[ "$x" != "y" ]] && [[ "$x" != "" ]]
+ then
+ break
+ fi
+ else
break
fi
done
}
do_test() {
- retry do_test_once ${@}
+ case "${1}" in
+ apps/workbench_units | apps/workbench_functionals | apps/workbench_integration)
+ suite=apps/workbench
+ ;;
+ *)
+ suite="${1}"
+ ;;
+ esac
+ if [[ -z "${skip[$suite]}" && -z "${skip[$1]}" && \
+ (-z "${only}" || "${only}" == "${suite}" || \
+ "${only}" == "${1}") ]]; then
+ retry do_test_once ${@}
+ else
+ title "Skipping ${1} tests"
+ fi
}
do_test_once() {
unset result
- to_test=$1
- if (( [[ "$only" == "apps/workbench" ]] ) &&
- ( [[ "$to_test" == "apps/workbench_units" ]] || [[ "$to_test" == "apps/workbench_functionals" ]] ||
- [[ "$to_test" == "apps/workbench_integration" ]])); then
- to_test="apps/workbench"
- fi
- if [[ -z "${skip[$1]}" ]] && ( [[ -z "$only" ]] || [[ "$only" == "$to_test" ]] )
+
+ title "Running $1 tests"
+ timer_reset
+ if [[ "$2" == "go" ]]
then
- title "Running $1 tests"
- timer_reset
- if [[ "$2" == "go" ]]
- then
- covername="coverage-$(echo "$1" | sed -e 's/\//_/g')"
- coverflags=("-covermode=count" "-coverprofile=$WORKSPACE/tmp/.$covername.tmp")
- # We do "go get -t" here to catch compilation errors
- # before trying "go test". Otherwise, coverage-reporting
- # mode makes Go show the wrong line numbers when reporting
- # compilation errors.
- go get -t "git.curoverse.com/arvados.git/$1" || return 1
- cd "$WORKSPACE/$1" || return 1
- gofmt -e -d . | egrep . && result=1
+ covername="coverage-$(echo "$1" | sed -e 's/\//_/g')"
+ coverflags=("-covermode=count" "-coverprofile=$WORKSPACE/tmp/.$covername.tmp")
+ # We do "go get -t" here to catch compilation errors
+ # before trying "go test". Otherwise, coverage-reporting
+ # mode makes Go show the wrong line numbers when reporting
+ # compilation errors.
+ go get -t "git.curoverse.com/arvados.git/$1" && \
+ cd "$GOPATH/src/git.curoverse.com/arvados.git/$1" && \
+ [[ -z "$(gofmt -e -d . | tee /dev/stderr)" ]] && \
if [[ -n "${testargs[$1]}" ]]
- then
- # "go test -check.vv giturl" doesn't work, but this
- # does:
- cd "$WORKSPACE/$1" && go test ${short:+-short} ${testargs[$1]}
- else
- # The above form gets verbose even when testargs is
- # empty, so use this form in such cases:
- go test ${short:+-short} ${coverflags[@]} "git.curoverse.com/arvados.git/$1"
- fi
- result=${result:-$?}
- if [[ -f "$WORKSPACE/tmp/.$covername.tmp" ]]
- then
- go tool cover -html="$WORKSPACE/tmp/.$covername.tmp" -o "$WORKSPACE/tmp/$covername.html"
- rm "$WORKSPACE/tmp/.$covername.tmp"
- fi
- elif [[ "$2" == "pip" ]]
then
- tries=0
- cd "$WORKSPACE/$1" && while :
- do
- tries=$((${tries}+1))
- # $3 can name a path directory for us to use, including trailing
- # slash; e.g., the bin/ subdirectory of a virtualenv.
- "${3}python" setup.py ${short:+--short-tests-only} test ${testargs[$1]}
- result=$?
- if [[ ${tries} < 3 && ${result} == 137 ]]
- then
- printf '\n*****\n%s tests killed -- retrying\n*****\n\n' "$1"
- continue
- else
- break
- fi
- done
- elif [[ "$2" != "" ]]
- then
- "test_$2"
+ # "go test -check.vv giturl" doesn't work, but this
+ # does:
+ go test ${short:+-short} ${testargs[$1]}
else
- "test_$1"
+ # The above form gets verbose even when testargs is
+ # empty, so use this form in such cases:
+ go test ${short:+-short} ${coverflags[@]} "git.curoverse.com/arvados.git/$1"
fi
result=${result:-$?}
- checkexit $result "$1 tests"
- title "End of $1 tests (`timer`)"
- return $result
+ if [[ -f "$WORKSPACE/tmp/.$covername.tmp" ]]
+ then
+ go tool cover -html="$WORKSPACE/tmp/.$covername.tmp" -o "$WORKSPACE/tmp/$covername.html"
+ rm "$WORKSPACE/tmp/.$covername.tmp"
+ fi
+ elif [[ "$2" == "pip" ]]
+ then
+ tries=0
+ cd "$WORKSPACE/$1" && while :
+ do
+ tries=$((${tries}+1))
+ # $3 can name a path directory for us to use, including trailing
+ # slash; e.g., the bin/ subdirectory of a virtualenv.
+ "${3}python" setup.py ${short:+--short-tests-only} test ${testargs[$1]}
+ result=$?
+ if [[ ${tries} < 3 && ${result} == 137 ]]
+ then
+ printf '\n*****\n%s tests killed -- retrying\n*****\n\n' "$1"
+ continue
+ else
+ break
+ fi
+ done
+ elif [[ "$2" != "" ]]
+ then
+ "test_$2"
else
- title "Skipping $1 tests"
+ "test_$1"
fi
+ result=${result:-$?}
+ checkexit $result "$1 tests"
+ title "End of $1 tests (`timer`)"
+ return $result
}
do_install() {
- retry do_install_once ${@}
+ if [[ -z "${only_install}" || "${only_install}" == "${1}" ]]; then
+ retry do_install_once ${@}
+ else
+ title "Skipping $1 install"
+ fi
}
do_install_once() {
- if [[ -z "$skip_install" || (-n "$only_install" && "$only_install" == "$1") ]]
+ title "Running $1 install"
+ timer_reset
+ if [[ "$2" == "go" ]]
then
- title "Running $1 install"
- timer_reset
- if [[ "$2" == "go" ]]
- then
- go get -t "git.curoverse.com/arvados.git/$1"
- elif [[ "$2" == "pip" ]]
- then
- # $3 can name a path directory for us to use, including trailing
- # slash; e.g., the bin/ subdirectory of a virtualenv.
-
- # Need to change to a different directory after creating
- # the source dist package to avoid a pip bug.
- # see https://arvados.org/issues/5766 for details.
-
- # Also need to install twice, because if it believes the package is
- # already installed, pip it won't install it. So the first "pip
- # install" ensures that the dependencies are met, the second "pip
- # install" ensures that we've actually installed the local package
- # we just built.
- cd "$WORKSPACE/$1" \
- && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
- && cd "$WORKSPACE" \
- && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
- && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
- elif [[ "$2" != "" ]]
- then
- "install_$2"
- else
- "install_$1"
- fi
- result=$?
- checkexit $result "$1 install"
- title "End of $1 install (`timer`)"
- return $result
+ go get -t "git.curoverse.com/arvados.git/$1"
+ elif [[ "$2" == "pip" ]]
+ then
+ # $3 can name a path directory for us to use, including trailing
+ # slash; e.g., the bin/ subdirectory of a virtualenv.
+
+ # Need to change to a different directory after creating
+ # the source dist package to avoid a pip bug.
+ # see https://arvados.org/issues/5766 for details.
+
+ # Also need to install twice, because if it believes the package is
+ # already installed, pip it won't install it. So the first "pip
+ # install" ensures that the dependencies are met, the second "pip
+ # install" ensures that we've actually installed the local package
+ # we just built.
+ cd "$WORKSPACE/$1" \
+ && "${3}python" setup.py sdist rotate --keep=1 --match .tar.gz \
+ && cd "$WORKSPACE" \
+ && "${3}pip" install --quiet "$WORKSPACE/$1/dist"/*.tar.gz \
+ && "${3}pip" install --quiet --no-deps --ignore-installed "$WORKSPACE/$1/dist"/*.tar.gz
+ elif [[ "$2" != "" ]]
+ then
+ "install_$2"
else
- title "Skipping $1 install"
+ "install_$1"
fi
+ result=$?
+ checkexit $result "$1 install"
+ title "End of $1 install (`timer`)"
+ return $result
}
bundle_install_trylocal() {
# module. We can't actually *test* the Python SDK yet though, because
# its own test suite brings up some of those other programs (like
# keepproxy).
-declare -a pythonstuff
-pythonstuff=(
- sdk/pam
- sdk/python
- sdk/cwl
- services/fuse
- services/nodemanager
- tools/crunchstat-summary
- )
for p in "${pythonstuff[@]}"
do
- do_install "$p" pip
+ dir=${p%:py3}
+ if [[ ${dir} = ${p} ]]; then
+ if [[ -z ${skip[python2]} ]]; then
+ do_install ${dir} pip
+ fi
+ elif [[ -n ${PYTHON3} ]]; then
+ if [[ -z ${skip[python3]} ]]; then
+ do_install ${dir} pip "$VENV3DIR/bin/"
+ fi
+ fi
done
-if [ -n "$PYTHON3" ]; then
- do_install services/dockercleaner pip "$VENV3DIR/bin/"
-fi
install_apiserver() {
cd "$WORKSPACE/services/api" \
if [ -n "$CONFIGSRC" ]
then
- for f in database.yml application.yml
+ for f in database.yml
do
cp "$CONFIGSRC/$f" config/ || fatal "$f"
done
fi
- # Fill in a random secret_token and blob_signing_key for testing
- SECRET_TOKEN=`echo 'puts rand(2**512).to_s(36)' |ruby`
- BLOB_SIGNING_KEY=`echo 'puts rand(2**512).to_s(36)' |ruby`
-
- sed -i'' -e "s:SECRET_TOKEN:$SECRET_TOKEN:" config/application.yml
- sed -i'' -e "s:BLOB_SIGNING_KEY:$BLOB_SIGNING_KEY:" config/application.yml
-
- # Set up empty git repo (for git tests)
- GITDIR=$(mktemp -d)
- sed -i'' -e "s:/var/cache/git:$GITDIR:" config/application.default.yml
-
- rm -rf $GITDIR
- mkdir -p $GITDIR/test
- cd $GITDIR/test \
- && git init \
- && git config user.email "jenkins@ci.curoverse.com" \
- && git config user.name "Jenkins, CI" \
- && touch tmp \
- && git add tmp \
- && git commit -m 'initial commit'
-
# Clear out any lingering postgresql connections to the test
# database, so that we can drop it. This assumes the current user
# is a postgresql superuser.
&& test_database=$(python -c "import yaml; print yaml.load(file('config/database.yml'))['test']['database']") \
&& psql "$test_database" -c "SELECT pg_terminate_backend (pg_stat_activity.procpid::int) FROM pg_stat_activity WHERE pg_stat_activity.datname = '$test_database';" 2>/dev/null
+ mkdir -p "$WORKSPACE/services/api/tmp/pids"
+
cd "$WORKSPACE/services/api" \
&& RAILS_ENV=test bundle exec rake db:drop \
&& RAILS_ENV=test bundle exec rake db:setup \
}
do_install services/api apiserver
+cd "$GOPATH/src/git.curoverse.com/arvados.git" && \
+ "$GOPATH/bin/govendor" sync -v || \
+ fatal "govendor sync failed"
declare -a gostuff
gostuff=(
sdk/go/arvados
sdk/go/arvadosclient
sdk/go/blockdigest
+ sdk/go/dispatch
+ sdk/go/health
sdk/go/httpserver
sdk/go/manifest
sdk/go/streamer
sdk/go/crunchrunner
+ sdk/go/stats
lib/crunchstat
services/arv-git-httpd
services/crunchstat
sdk/go/keepclient
services/keep-balance
services/keepproxy
- services/datamanager/summary
- services/datamanager/collection
- services/datamanager/keep
- services/datamanager
services/crunch-dispatch-local
services/crunch-dispatch-slurm
services/crunch-run
+ services/ws
tools/keep-block-check
tools/keep-exercise
tools/keep-rsync
- )
+)
for g in "${gostuff[@]}"
do
do_install "$g" go
}
do_install apps/workbench workbench
+unset http_proxy https_proxy no_proxy
+
test_doclinkchecker() {
(
set -e
exit_cleanly
fi
-start_api
+start_api || { stop_services; fatal "start_api"; }
test_ruby_sdk() {
cd "$WORKSPACE/sdk/ruby" \
}
do_test services/login-sync login-sync
+test_nodemanager-integration() {
+ cd "$WORKSPACE/services/nodemanager" \
+ && tests/integration_test.py ${testargs[services/nodemanager-integration]}
+}
+do_test services/nodemanager-integration nodemanager-integration
+
for p in "${pythonstuff[@]}"
do
- do_test "$p" pip
+ dir=${p%:py3}
+ if [[ ${dir} = ${p} ]]; then
+ if [[ -z ${skip[python2]} ]]; then
+ do_test ${dir} pip
+ fi
+ elif [[ -n ${PYTHON3} ]]; then
+ if [[ -z ${skip[python3]} ]]; then
+ do_test ${dir} pip "$VENV3DIR/bin/"
+ fi
+ fi
done
-do_test services/dockercleaner pip "$VENV3DIR/bin/"
for g in "${gostuff[@]}"
do