#!/bin/bash # # Script for launching the Docker integration tests # #set -x SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DOCKER_DIR=/usr/src/docker SCRIPTS_DIR=$DOCKER_DIR/hack TESTS_EXE=$SCRIPTS_DIR/tests.main VERSION=$(cat $DOCKER_DIR/VERSION) # working dirs TESTS_DIR=/tmp/docker-int-tests BUNDLES_DIR=$TESTS_DIR/run/bundles FAKE_GOPATH=$TESTS_DIR/go # some test expect the containerd socket here CONTAINERD_SOCK=/run/containerd/containerd.sock EXPECTED_CONTAINERD_SOCK=/var/run/docker/libcontainerd/docker-containerd.sock # ... and some programs CONTAINERD_CTR=/usr/sbin/containerd-ctr EXPECTED_CONTAINERD_CTR=/usr/local/bin/docker-containerd-ctr CHECK_TIMEOUT="${CHECK_TIMEOUT:-5m}" TEST_TIMEOUT="${TEST_TIMEOUT:-60m}" TEST_ARGS="-check.vv -check.timeout=${CHECK_TIMEOUT} -test.timeout=${TEST_TIMEOUT}" TEST_SELECT= TEST_LOG=/tmp/docker-tests.log ENABLE_XUNIT=${ENABLE_XUNIT:-yes} # the sysconfig file for Docker SYSCFG_DOCKER=/etc/sysconfig/docker # some vars from the Dockerfile ENABLE_NOTARY=${ENABLE_NOTARY:-} ENABLE_REGISTRY=${ENABLE_REGISTRY:-} REGISTRY_COMMIT_SCHEMA1=ec87e9b6971d831f0eff752ddb54fb64693e51cd REGISTRY_COMMIT=47a064d4195a9b56133891bbb13620c3ac83a827 NOTARY_VERSION=v0.3.0 ################################################################################ log() { echo ">>> $@" ; } warn() { log "WARNING: $@" ; } error() { log "ERROR: $@" ; } abort() { log "FATAL: $@" ; exit 1 ; } usage() { echo "$USAGE" ; } abort_usage() { usage ; abort $@ ; } bundle() { local bundle="$1"; shift log "Making bundle: $(basename "$bundle") (in $DEST)" source "$SCRIPTS_DIR/make/$bundle" "$@" } set_opts() { OPT="$1" VALUE="$2" FILE=$3 perl -pi -e "s/^$OPT=.*$//g" $FILE echo "$OPT=\"$VALUE\"" >> $FILE } set_docker_opts() { set_opts "DOCKER_OPTS" "$DOCKER_OPTS" /etc/sysconfig/docker ; } set_containerd_opts() { set_opts "CONTAINERD_OPTS" "$CONTAINERD_OPTS" /etc/sysconfig/containerd ; } fix_expected() { EXPECTED=$1 EXISTING=$2 exp_base=$(basename $EXPECTED) exp_dir=$(dirname $EXPECTED) [ -d $exp_dir ] || mkdir -p $exp_dir rm -f $exp_dir/$exp_base (cd $exp_dir && ln -sf $EXISTING $exp_base) } save_backup() { for x in $@ ; do if [ ! -f $x ] ; then touch $x.nbak elif [ -f $x.bak ] ; then warn "$x.bak already exists: no backup will be done" else cp -f $x $x.bak fi done } restore_backup() { for x in $@ ; do if [ -f $x.nbak ] ; then rm -f $x.nbak else if [ -f $x.bak ] ; then mv -f $x.bak $x fi fi done } require_go() { go version >/dev/null 2>&1 ; } require_git() { git version >/dev/null 2>&1 ; } ################################################################################ [ -x $TESTS_EXE ] || abort "integration tests executable not found at $TESTS_EXE" [ $EUID -eq 0 ] || abort "this script must be run as root" [ -n "$VERSION" ] || abort "could not obtain version" [ -e $CONTAINERD_SOCK ] || abort "containerd socket not found at $CONTAINERD_SOCK" [ -x $CONTAINERD_CTR ] || abort "containerd-ctr not found at $CONTAINERD_CTR" if [ $# -gt 0 ] ; then # run only some specific tests TEST_SELECT="-check.f=$(echo $@ | tr ' ' '|')" fi # We want this to fail if the bundles already exist and cannot be removed. # This is to avoid mixing bundles from different versions of the code. mkdir -p $BUNDLES_DIR if [ -e "$BUNDLES_DIR/$VERSION" ] && [ -z "$KEEPBUNDLE" ]; then log "$BUNDLES_DIR/$VERSION already exists. Removing." rm -fr "$BUNDLES_DIR/$VERSION" && mkdir "$BUNDLES_DIR/$VERSION" || exit 1 echo fi DEST="$BUNDLES_DIR/$VERSION/" mkdir -p "$DEST" export DEST=$(realpath $DEST) # create a fake go path rm -rf $FAKE_GOPATH mkdir -p $FAKE_GOPATH/src/github.com/docker (cd $FAKE_GOPATH/src/github.com/docker && ln -sf $DOCKER_DIR docker) if [ -n "$ENABLE_REGISTRY" ] ; then # build the Docker registry if [ ! -x /usr/local/bin/registry-v2 ] ; then log "Building registry (commit:$REGISTRY_COMMIT)" require_git || abort "git is not installed" require_go || abort "the Go compiler is not installed" export GOPATH="$(mktemp -d)" git clone https://github.com/docker/distribution.git "$GOPATH/src/github.com/docker/distribution" (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT") GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \ go build -o /usr/local/bin/registry-v2 github.com/docker/distribution/cmd/registry (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT_SCHEMA1") GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \ go build -o /usr/local/bin/registry-v2-schema1 github.com/docker/distribution/cmd/registry chmod 755 /usr/local/bin/registry-v2 [ -x /usr/local/bin/registry-v2 ] || abort "registry-v2 could not be built" rm -rf "$GOPATH" export -n GOPATH fi fi if [ -n "$ENABLE_NOTARY" ] ; then # build the Docker notary if [ ! -x /usr/local/bin/notary-server ] ; then export GO15VENDOREXPERIMENT=1 export GOPATH="$(mktemp -d)" require_git || abort "git is not installed" require_go || abort "the Go compiler is not installed" log "Building notary (version:$NOTARY_VERSION)" git clone https://github.com/docker/notary.git "$GOPATH/src/github.com/docker/notary" (cd "$GOPATH/src/github.com/docker/notary" && git checkout -q "$NOTARY_VERSION") GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \ go build -o /usr/local/bin/notary-server github.com/docker/notary/cmd/notary-server GOPATH="$GOPATH/src/github.com/docker/notary/vendor:$GOPATH" \ go build -o /usr/local/bin/notary github.com/docker/notary/cmd/notary chmod 755 /usr/local/bin/notary-server [ -x /usr/local/bin/notary-server ] || abort "notary could not be built" export -n GO15VENDOREXPERIMENT rm -rf "$GOPATH" export -n GOPATH fi fi if [ -n "$ENABLE_XUNIT" ] ; then if [ ! -x /usr/local/bin/go2xunit ] ; then echo >&2 "Installing go2xunit." require_go || abort "the Go compiler is not installed" export GOPATH="$(mktemp -d)" go get -d github.com/tebeka/go2xunit cd $GOPATH/src/github.com/tebeka/go2xunit && go build -o /usr/local/bin/go2xunit . chmod 755 /usr/local/bin/go2xunit [ -x /usr/local/bin/go2xunit ] || abort "go2xunit could not be built" rm -rf "$GOPATH" export -n GOPATH fi fi # tests require this user and group /usr/sbin/groupadd -r docker >/dev/null 2>&1 || /bin/true /usr/sbin/useradd --create-home --gid docker unprivilegeduser >/dev/null 2>&1 || /bin/true # prepare some expected dirs, files, etc... fix_expected $TESTS_DIR/contrib $DOCKER_DIR/contrib fix_expected $DEST/fixtures $DOCKER_DIR/integration-cli/fixtures fix_expected $EXPECTED_CONTAINERD_SOCK $CONTAINERD_SOCK fix_expected $EXPECTED_CONTAINERD_CTR $CONTAINERD_CTR export DOCKER_TEST_HOST="tcp://127.0.0.1:2375" export PATH=/usr/local/bin:$PATH export TZ=utc export GOPATH="$FAKE_GOPATH" export DOCKER_GRAPHDRIVER="${DOCKER_GRAPHDRIVER:-vfs}" export DOCKER_USERLANDPROXY="${DOCKER_USERLANDPROXY:-true}" #export DOCKER_REMAP_ROOT=default # example usage: DOCKER_STORAGE_OPTS="dm.basesize=20G,dm.loopdatasize=200G" storage_params="" if [ -n "$DOCKER_STORAGE_OPTS" ]; then IFS=',' for i in ${DOCKER_STORAGE_OPTS}; do storage_params="--storage-opt $i $storage_params" done unset IFS fi # example usage: DOCKER_STORAGE_OPTS="dm.basesize=20G,dm.loopdatasize=200G" extra_params="" # deal with remapping save_backup /etc/subuid /etc/subgid echo "dockremap:500000:65536" > /etc/subuid echo "dockremap:500000:65536" > /etc/subgid groupadd dockremap >/dev/null 2>&1 || /bin/true useradd -g dockremap dockremap >/dev/null 2>&1 || /bin/true # make sure Docker is stopped, set our config file and then start again save_backup $SYSCFG_DOCKER cat < $SYSCFG_DOCKER DOCKER_OPTS="--log-level=debug \ --pidfile=$DEST/docker.pid \ -H tcp://127.0.0.1:2375 \ --storage-driver=$DOCKER_GRAPHDRIVER \ --userland-proxy=$DOCKER_USERLANDPROXY" DOCKER_NETWORK_OPTIONS="" SYSCFG_DOCKER_EOF systemctl reload-or-restart docker.service cleanup() { log "Restoring the Docker service..." restore_backup $SYSCFG_DOCKER systemctl reload-or-restart docker.service log "Removing extra files and restoring backups..." restore_backup /etc/subuid /etc/subgid rm -f $TESTS_DIR/contrib \ $DEST/fixtures \ $EXPECTED_CONTAINERD_SOCK \ $EXPECTED_CONTAINERD_CTR } trap cleanup EXIT cd $DOCKER_DIR log "Preparing the environment..." bundle .integration-daemon-start bundle .integration-daemon-setup log "Running integration tests..." export DOCKER_HOST=$DOCKER_TEST_HOST cd $DEST && $TESTS_EXE $TEST_ARGS $TEST_SELECT | tee $TEST_LOG || /bin/true if [ -n "$ENABLE_XUNIT" ] ; then log "Generating xunit logs..." go2xunit -fail -gocheck -input $TEST_LOG -output $TEST_LOG.xml fi export -n DOCKER_HOST bundle .integration-daemon-stop