Browse Source

Merge pull request #1176 from infosiftr/test-in-containers

Convert the tests to use "docker build" instead of explicit bind-mounts
yosifkit 10 years ago
parent
commit
e71b2d6003

+ 6 - 0
bashbrew/bashbrew.sh

@@ -186,6 +186,12 @@ for repoTag in "${repos[@]}"; do
 			repoFile="$library/$repo"
 		fi
 		
+		if [ ! -f "$repoFile" ]; then
+			echo >&2 "error: '$repoFile' does not exist!"
+			didFail=1
+			continue
+		fi
+		
 		repoFile="$(readlink -f "$repoFile")"
 		echo "$repoTag ($repoFile)" >> "$logDir/repos.txt"
 		

+ 47 - 15
test-pr.sh

@@ -1,13 +1,14 @@
 #!/bin/bash
 set -eo pipefail
 
-cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
+dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 
 usage() {
 	cat <<-EOUSAGE
 		usage: $0 [PR number] [repo[:tag]]
 		   ie: $0 1024
 		       $0 9001 debian php django
+		       $0 0 hylang # special case that runs against local directory
 		
 		This script builds and tests the specified pull request to official-images and
 		provides ouput in markdown for commenting on the pull request.
@@ -17,14 +18,51 @@ usage() {
 pull="$1"
 shift || { usage >&2 && exit 1; }
 
-url="https://github.com/docker-library/official-images/pull/$pull.patch"
-pat="$(curl -fsSL --compressed "$url")"
-commit="$(echo "$pat" | grep -E '^From [0-9a-f]+ ' | tail -n1 | cut -d' ' -f2)"
+if [ -z "$BASHBREW_SECOND_STAGE" ]; then
+	docker build --pull -t bashbrew "$dir" > /dev/null
+	if [ "$pull" = '0' ]; then
+		name="bashbrew-test-local-$RANDOM"
+	else
+		name="bashbrew-test-pr-$pull"
+	fi
+	exec docker run \
+		-it --rm \
+		--name "$name" \
+		-e BASHBREW_SECOND_STAGE=1 \
+		-v /var/run/docker.sock:/var/run/docker.sock \
+		-w /usr/src/pr \
+		bashbrew /usr/src/official-images/test-pr.sh "$pull" "$@"
+fi
+
+if [ -d .git ]; then
+	echo >&2 'error: something has gone horribly wrong; .git already exists'
+	echo >&2 '  why do you have BASHBREW_SECOND_STAGE set?'
+	exit 1
+fi
+
+if [ "$pull" = '0' ]; then
+	cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
+	commit='FAKE'
+else
+	# TODO we only have "git version 2.4.1" which doesn't support "clone -q" :(
+	git init -q .
+	git remote add origin https://github.com/docker-library/official-images.git
+	git fetch -q origin
+	git reset -q --hard origin/master
+	git config user.name 'nobody'
+	git config user.email '[email protected]'
+	git fetch -q origin "pull/$pull/head:pr-$pull"
+	git merge -q --no-edit "pr-$pull"
+
+	commit="$(git log -1 --format=format:%h "pr-$pull")"
+fi
 
 if [ "$#" -eq 0 ]; then
 	IFS=$'\n'
-	files=( $(echo "$pat" | awk -F '/' '$1 == "+++ b" && $2 == "library" { print $3 }' | sort -u) )
+	files=( $(git diff --name-only origin/master...HEAD -- library | xargs -n1 basename) )
 	unset IFS
+
+	# TODO narrow this down into groups of the exact tags for each image that changed >:)
 else
 	files=( "$@" )
 fi
@@ -34,11 +72,6 @@ if [ ${#files[@]} -eq 0 ]; then
 	exit 0
 fi
 
-urls=()
-for f in "${files[@]}"; do
-	urls+=( "https://raw.githubusercontent.com/docker-library/official-images/$commit/library/$f" )
-done
-
 join() {
 	sep="$1"
 	arg1="$2"
@@ -49,14 +82,13 @@ join() {
 
 echo 'Build test of' '#'"$pull"';' "$commit" '(`'"$(join '`, `' "${files[@]}")"'`):'
 failed=
-for url in "${urls[@]}"; do
+for img in "${files[@]}"; do
 	echo
 	echo '```console'
-	echo '$ url="'"$url"'"'
-	echo '$ bashbrew build "$url"'
-	if ./bashbrew/bashbrew.sh build "$url"; then
+	echo '$ bashbrew build "'"$img"'"'
+	if ./bashbrew/bashbrew.sh build "$img"; then
 		echo '$ bashbrew list --uniq "$url" | xargs test/run.sh'
-		if ! ./bashbrew/bashbrew.sh list --uniq "$url" | xargs ./test/run.sh; then
+		if ! ./bashbrew/bashbrew.sh list --uniq "$img" | xargs ./test/run.sh; then
 			failed=1
 		fi
 	else

+ 24 - 0
test/tests/docker-build.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+set -e
+
+# wrapper around "docker build" that creates a temporary directory and copies files into it first so that arbitrary host directories can be copied into containers without bind mounts, but accepts a Dockerfile on stdin
+
+# usage: ./docker-build.sh some-host-directory -t some-new-image:some-tag <<EOD
+#        FROM ...
+#        COPY dir/... /.../
+#        EOD
+#    ie: ./docker-build.sh .../hylang-hello-world -t librarytest/hylang <<EOD
+#        FROM hylang
+#        COPY dir/container.hy /dir/
+#        CMD ["hy", "/dir/container.hy"]
+#        EOD
+
+dir="$1"; shift
+[ -d "$dir" ]
+
+tmp="$(mktemp -t -d docker-library-test-build-XXXXXXXXXX)"
+trap "rm -rf '$tmp'" EXIT
+
+cat > "$tmp/Dockerfile"
+cp -a "$dir" "$tmp/dir"
+docker build "$@" "$tmp" > /dev/null

+ 10 - 0
test/tests/image-name.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+
+# usage: ./image-name.sh librarytest/something some/image:some-tag
+# output: librarytest/something:some-image-some-tag
+
+base="$1"; shift
+tag="$1"; shift
+
+echo "$base:$(echo "$tag" | sed 's![:/]!-!g')"

+ 6 - 1
test/tests/jetty-hello-web/run.sh

@@ -12,7 +12,12 @@ image="$1"
 clientImage="$image"
 
 # Create an instance of the container-under-test
-cid="$(docker run -d -v "$dir/index.jsp":/var/lib/jetty/webapps/ROOT/index.jsp:ro "$image")"
+serverImage="$("$dir/../image-name.sh" librarytest/jetty-hello-web "$image")"
+"$dir/../docker-build.sh" "$dir" -t "$serverImage" <<EOD
+FROM $image
+COPY dir/index.jsp /var/lib/jetty/webapps/ROOT/
+EOD
+cid="$(docker run -d "$serverImage")"
 trap "docker rm -vf $cid > /dev/null" EXIT
 
 _request() {

+ 7 - 2
test/tests/mysql-initdb/run.sh

@@ -5,6 +5,12 @@ dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 
 image="$1"
 
+serverImage="$("$dir/../image-name.sh" librarytest/mysql-initdb "$image")"
+"$dir/../docker-build.sh" "$dir" -t "$serverImage" <<EOD
+FROM $image
+COPY dir/initdb.sql /docker-entrypoint-initdb.d/
+EOD
+
 export MYSQL_ROOT_PASSWORD='this is an example test password'
 export MYSQL_USER='0123456789012345' # "ERROR: 1470  String 'my cool mysql user' is too long for user name (should be no longer than 16)"
 export MYSQL_PASSWORD='my cool mysql password'
@@ -18,8 +24,7 @@ cid="$(
 		-e MYSQL_PASSWORD \
 		-e MYSQL_DATABASE \
 		--name "$cname" \
-		-v "$dir/initdb.sql:/docker-entrypoint-initdb.d/test.sql":ro \
-		"$image"
+		"$serverImage"
 )"
 trap "docker rm -vf $cid > /dev/null" EXIT
 

+ 8 - 2
test/tests/php-fpm-hello-web/run.sh

@@ -7,7 +7,7 @@ dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 image="$1"
 
 # Build a client image with cgi-fcgi for testing
-clientImage='librarytest/php-fpm-hello-web:fcgi'
+clientImage='librarytest/php-fpm-hello-web:fcgi-client'
 docker build -t "$clientImage" - > /dev/null <<'EOF'
 FROM debian:jessie
 
@@ -16,8 +16,14 @@ RUN set -x && apt-get update && apt-get install -y libfcgi0ldbl && rm -rf /var/l
 ENTRYPOINT ["cgi-fcgi"]
 EOF
 
+serverImage="$("$dir/../image-name.sh" librarytest/php-fpm-hello-web "$image")"
+"$dir/../docker-build.sh" "$dir" -t "$serverImage" <<EOD
+FROM $image
+COPY dir/index.php /var/www/html/
+EOD
+
 # Create an instance of the container-under-test
-cid="$(docker run -d -v "$dir/index.php":/var/www/html/index.php:ro "$image")"
+cid="$(docker run -d "$serverImage")"
 trap "docker rm -vf $cid > /dev/null" EXIT
 
 # RACY TESTS ARE RACY

+ 7 - 2
test/tests/postgres-initdb/run.sh

@@ -5,6 +5,12 @@ dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 
 image="$1"
 
+serverImage="$("$dir/../image-name.sh" librarytest/postgres-initdb "$image")"
+"$dir/../docker-build.sh" "$dir" -t "$serverImage" <<EOD
+FROM $image
+COPY dir/initdb.sql /docker-entrypoint-initdb.d/
+EOD
+
 export POSTGRES_USER='my cool postgres user'
 export POSTGRES_PASSWORD='my cool postgres password'
 export POSTGRES_DB='my cool postgres database'
@@ -16,8 +22,7 @@ cid="$(
 		-e POSTGRES_PASSWORD \
 		-e POSTGRES_DB \
 		--name "$cname" \
-		-v "$dir/initdb.sql:/docker-entrypoint-initdb.d/test.sql":ro \
-		"$image"
+		"$serverImage"
 )"
 trap "docker rm -vf $cid > /dev/null" EXIT
 

+ 12 - 2
test/tests/run-in-container.sh

@@ -13,10 +13,20 @@ entrypoint="$1"
 shift
 
 # do some fancy footwork so that if testDir is /a/b/c, we mount /a/b and use c as the working directory (so relative symlinks work one level up)
+thisDir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
 testDir="$(readlink -f "$testDir")"
+testBase="$(basename "$testDir")"
 hostMount="$(dirname "$testDir")"
 containerMount="/tmp/test-dir"
-workdir="$containerMount/$(basename "$testDir")"
+workdir="$containerMount/$testBase"
 # TODO should we be doing something fancy with $BASH_SOURCE instead so we can be arbitrarily deep and mount the top level always?
 
-exec docker run --rm -v "$hostMount":"$containerMount":ro -w "$workdir" --entrypoint "$entrypoint" "$image" "$@"
+newImage="$("$thisDir/image-name.sh" librarytest/run-in-container "$image--$testBase")"
+"$thisDir/docker-build.sh" "$hostMount" -t "$newImage" <<EOD
+FROM $image
+COPY dir $containerMount
+WORKDIR $workdir
+ENTRYPOINT ["$entrypoint"]
+EOD
+
+exec docker run --rm "$newImage" "$@"