Merge pull request #570 from dmcgowan/docker-integration

contrib: Docker integration tests
pull/650/merge
Stephen Day 2015-06-19 12:49:27 -07:00
commit d0fda14e85
7 changed files with 318 additions and 144 deletions

View File

@ -0,0 +1,46 @@
FROM debian:jessie
MAINTAINER Docker Distribution Team <distribution@docker.com>
# compile and runtime deps
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#runtime-dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
# For DIND
ca-certificates \
curl \
iptables \
procps \
e2fsprogs \
xz-utils \
# For build
build-essential \
file \
git \
net-tools \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install Docker
ENV VERSION 1.7.0-rc1
RUN curl -L -o /usr/local/bin/docker https://test.docker.com/builds/Linux/x86_64/docker-${VERSION} \
&& chmod +x /usr/local/bin/docker
# Install DIND
RUN curl -L -o /dind https://raw.githubusercontent.com/docker/docker/master/hack/dind \
&& chmod +x /dind
# Install bats
RUN cd /usr/local/src/ \
&& git clone https://github.com/sstephenson/bats.git \
&& cd bats \
&& ./install.sh /usr/local
# Install docker-compose
RUN curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose \
&& chmod +x /usr/local/bin/docker-compose
RUN mkdir -p /go/src/github.com/docker/distribution
WORKDIR /go/src/github.com/docker/distribution/contrib/docker-integration
VOLUME /var/lib/docker
ENTRYPOINT ["/dind"]

View File

@ -1,24 +0,0 @@
.PHONY: build test
build:
docker-compose build
start: build
docker-compose up -d
stop:
docker-compose stop
clean:
docker-compose kill
docker-compose rm -f
install:
sh ./install_certs.sh localhost
sh ./install_certs.sh localregistry
test:
@echo "!!!!Ensure /etc/hosts entry is updated for localregistry and make install has been run"
sh ./test_docker.sh localregistry
all: build

View File

@ -1,32 +1,88 @@
# Docker Registry Multi-Configuration Testing
# Docker Registry Integration Testing
This compose configuration is intended to setup a testing environment for Docker
These integration tests cover interactions between the Docker daemon and the
registry server. All tests are run using the docker cli.
The compose configuration is intended to setup a testing environment for Docker
using multiple registry configurations. These configurations include different
combinations of a v1 and v2 registry as well as TLS configurations.
### Limitations
## Running inside of Docker
### Get integration container
The container image to run the integation tests will need to be pulled or built
locally.
Currently this setup is configured to use localhost as the hostname which
limits the ease of testing within Docker since localhost is always treated
as an insecure registry. To treat localhost as secure the Docker code must
be modified. Without localhost as secure, the test cases will not distinguish
between a TLS configuration with a CA and self-signed.
*Building locally*
```
$ docker build -t distribution/docker-integration .
```
### Run script
Invoke the tests within Docker through the `run.sh` script.
```
$ ./run.sh
```
Run with aufs driver and tmp volume
**NOTE: Using a volume will prevent multiple runs from needing to
re-pull images**
```
$ DOCKER_GRAPHDRIVER=aufs DOCKER_VOLUME=/tmp/volume ./run.sh
```
### Example developer flow
These tests are useful for developing both as a registry and docker
core developer. The following setup may be used to do integration
testing between development versions
Insert into your `.zshrc` or `.bashrc`
```
# /usr/lib/docker for Docker-in-Docker
# Set this directory to make each invocation run much faster, without
# the need to repull images.
export DOCKER_VOLUME=$HOME/.docker-test-volume
# Use overlay for all Docker testing, try aufs if overlay not supported
export DOCKER_GRAPHDRIVER=overlay
# Name this according to personal preference
function rdtest() {
if [ "$1" != "" ]; then
DOCKER_BINARY=$GOPATH/src/github.com/docker/docker/bundles/$1/binary/docker
if [ ! -f $DOCKER_BINARY ]; then
current_version=`cat $GOPATH/src/github.com/docker/docker/VERSION`
echo "$DOCKER_BINARY does not exist"
echo "Current checked out docker version: $current_version"
echo "Checkout desired version and run 'make binary' from $GOPATH/src/github.com/docker/docker"
return 1
fi
fi
$GOPATH/src/github.com/docker/distribution/contrib/docker-integration/run.sh
}
```
Run with Docker release version
```
$ rdtest
```
Run using local development version of docker
```
$ cd $GOPATH/src/github.com/docker/docker
$ make binary
$ rdtest `cat VERSION`
```
## Running manually outside of Docker
### Install Docker Compose
1. Open a new terminal on the host with your `distribution` source.
2. Get the `docker-compose` binary.
$ sudo wget https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` -O /usr/local/bin/docker-compose
This command installs the binary in the `/usr/local/bin` directory.
3. Add executable permissions to the binary.
$ sudo chmod +x /usr/local/bin/docker-compose
## Usage
[Docker Compose Installation Guide](http://docs.docker.com/compose/install/)
### Start compose setup
```
@ -34,7 +90,8 @@ docker-compose up
```
### Install Certificates
The certificates must be installed in /etc/docker/cert.d in order to use TLS client auth and use the CA certificate.
The certificates must be installed in /etc/docker/cert.d in order to use TLS
client auth and use the CA certificate.
```
sudo sh ./install_certs.sh
```
@ -52,6 +109,16 @@ docker push localhost:5441/hello-world
# Perform login using user `testuser` and password `passpassword`
```
### Set /etc/hosts entry
Find the non-localhost ip address of local machine
### Run bats
Run the bats tests after updating /etc/hosts, installing the certificates, and
running the `docker-compose` script.
```
bats -p .
```
## Configurations
Port | V2 | V1 | TLS | Authentication
@ -59,6 +126,7 @@ Port | V2 | V1 | TLS | Authentication
5000 | yes | yes | no | none
5001 | no | yes | no | none
5002 | yes | no | no | none
5011 | no | yes | yes | none
5440 | yes | yes | yes | none
5441 | yes | yes | yes | basic (testuser/passpassword)
5442 | yes | yes | yes | TLS client

View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
# Root directory of Distribution
DISTRIBUTION_ROOT=$(cd ../..; pwd -P)
volumeMount=""
if [ "$DOCKER_VOLUME" != "" ]; then
volumeMount="-v ${DOCKER_VOLUME}:/var/lib/docker"
fi
dockerMount=""
if [ "$DOCKER_BINARY" != "" ]; then
dockerMount="-v ${DOCKER_BINARY}:/usr/local/bin/docker"
fi
# Image containing the integration tests environment.
INTEGRATION_IMAGE=${INTEGRATION_IMAGE:-distribution/docker-integration}
# Make sure we upgrade the integration environment.
docker pull $INTEGRATION_IMAGE
# Start the integration tests in a Docker container.
ID=$(docker run -d -t --privileged $volumeMount $dockerMount \
-v ${DISTRIBUTION_ROOT}:/go/src/github.com/docker/distribution \
-e "STORAGE_DRIVER=$DOCKER_GRAPHDRIVER" \
-e "EXEC_DRIVER=$EXEC_DRIVER" \
${INTEGRATION_IMAGE} \
./test_runner.sh "$@")
# Clean it up when we exit.
trap "docker rm -f -v $ID > /dev/null" EXIT
docker logs -f $ID

View File

@ -1,98 +0,0 @@
#!/bin/sh
hostname=$1
if [ "$hostname" = "" ]; then
hostname="localhost"
fi
docker pull hello-world
# TLS Configuration chart
# Username/Password: testuser/passpassword
# | ca | client | basic | notes
# 5440 | yes | no | no | Tests CA certificate
# 5441 | yes | no | yes | Tests basic auth over TLS
# 5442 | yes | yes | no | Tests client auth with client CA
# 5443 | yes | yes | no | Tests client auth without client CA
# 5444 | yes | yes | yes | Tests using basic auth + tls auth
# 5445 | no | no | no | Tests insecure using TLS
# 5446 | no | no | yes | Tests sending credentials to server with insecure TLS
# 5447 | no | yes | no | Tests client auth to insecure
# 5448 | yes | no | no | Bad SSL version
docker tag -f hello-world $hostname:5440/hello-world
docker push $hostname:5440/hello-world
if [ $? -ne 0 ]; then
echo "Fail to push"
exit 1
fi
docker login -u testuser -p passpassword -e distribution@docker.com $hostname:5441
if [ $? -ne 0 ]; then
echo "Failed to login"
exit 1
fi
docker tag -f hello-world $hostname:5441/hello-world
docker push $hostname:5441/hello-world
if [ $? -ne 0 ]; then
echo "Fail to push"
exit 1
fi
docker tag -f hello-world $hostname:5442/hello-world
docker push $hostname:5442/hello-world
if [ $? -ne 0 ]; then
echo "Fail to push"
exit 1
fi
docker tag -f hello-world $hostname:5443/hello-world
docker push $hostname:5443/hello-world
if [ $? -eq 0 ]; then
echo "Expected failure"
exit 1
fi
docker login -u testuser -p passpassword -e distribution@docker.com $hostname:5444
if [ $? -ne 0 ]; then
echo "Failed to login"
exit 1
fi
docker tag -f hello-world $hostname:5444/hello-world
docker push $hostname:5444/hello-world
if [ $? -ne 0 ]; then
echo "Fail to push"
exit 1
fi
docker tag -f hello-world $hostname:5445/hello-world
docker push $hostname:5445/hello-world
if [ $? -eq 0 ]; then
echo "Expected failure with insecure registry"
exit 1
fi
docker login -u testuser -p passpassword -e distribution@docker.com $hostname:5446
if [ $? -ne 0 ]; then
echo "Failed to login"
exit 1
fi
docker tag -f hello-world $hostname:5446/hello-world
docker push $hostname:5446/hello-world
if [ $? -eq 0 ]; then
echo "Expected failure with insecure registry"
exit 1
fi
docker tag -f hello-world $hostname:5447/hello-world
docker push $hostname:5447/hello-world
if [ $? -eq 0 ]; then
echo "Expected failure with insecure registry"
exit 1
fi
docker tag -f hello-world $hostname:5448/hello-world
docker push $hostname:5448/hello-world
if [ $? -eq 0 ]; then
echo "Expected failure contacting with sslv3"
exit 1
fi

View File

@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
# Load the helpers.
#. helpers.bash
TESTS=${@:-.}
# Drivers to use for Docker engines the tests are going to create.
STORAGE_DRIVER=${STORAGE_DRIVER:-overlay}
EXEC_DRIVER=${EXEC_DRIVER:-native}
function execute() {
>&2 echo "++ $@"
eval "$@"
}
# Set IP address in /etc/hosts for localregistry
IP=$(ifconfig eth0|grep "inet addr:"| cut -d: -f2 | awk '{ print $1}')
execute echo "$IP localregistry" >> /etc/hosts
# Setup certificates
execute sh install_certs.sh localregistry
# Start the docker engine.
execute docker --daemon --log-level=panic \
--storage-driver="$STORAGE_DRIVER" --exec-driver="$EXEC_DRIVER" &
DOCKER_PID=$!
# Wait for it to become reachable.
tries=10
until docker version &> /dev/null; do
(( tries-- ))
if [ $tries -le 0 ]; then
echo >&2 "error: daemon failed to start"
exit 1
fi
sleep 1
done
execute time docker-compose build
execute docker-compose up -d
# Run the tests.
execute time bats -p $TESTS

View File

@ -0,0 +1,96 @@
# Registry host name, should be set to non-localhost address and match
# DNS name in nginx/ssl certificates and what is installed in /etc/docker/cert.d
hostname="localregistry"
image="hello-world:latest"
# Login information, should match values in nginx/test.passwd
user="testuser"
password="passpassword"
email="distribution@docker.com"
function setup() {
docker pull $image
}
# has_digest enforces the last output line is "Digest: sha256:..."
# the input is the name of the array containing the output lines
function has_digest() {
name=$1[@]
lines=("${!name}")
length=${#lines[@]}
digest_idx=$((length-1))
value=${lines[$digest_idx]}
result=$(echo "$value"|cut -d':' -f1,2)
[ "$result" = "Digest: sha256" ]
}
function login() {
run docker login -u $user -p $password -e $email $1
[ "$status" -eq 0 ]
# First line is WARNING about credential save
[ "${lines[1]}" = "Login Succeeded" ]
}
@test "Test valid certificates" {
docker tag -f $image $hostname:5440/$image
run docker push $hostname:5440/$image
[ "$status" -eq 0 ]
has_digest lines
}
@test "Test basic auth" {
login $hostname:5441
docker tag -f $image $hostname:5441/$image
run docker push $hostname:5441/$image
[ "$status" -eq 0 ]
has_digest lines
}
@test "Test TLS client auth" {
docker tag -f $image $hostname:5442/$image
run docker push $hostname:5442/$image
[ "$status" -eq 0 ]
has_digest lines
}
@test "Test TLS client with invalid certificate authority fails" {
docker tag -f $image $hostname:5443/$image
run docker push $hostname:5443/$image
[ "$status" -ne 0 ]
}
@test "Test basic auth with TLS client auth" {
login $hostname:5444
docker tag -f $image $hostname:5444/$image
run docker push $hostname:5444/$image
[ "$status" -eq 0 ]
has_digest lines
}
@test "Test unknown certificate authority fails" {
docker tag -f $image $hostname:5445/$image
run docker push $hostname:5445/$image
[ "$status" -ne 0 ]
}
@test "Test basic auth with unknown certificate authority fails" {
run login $hostname:5446
[ "$status" -ne 0 ]
docker tag -f $image $hostname:5446/$image
run docker push $hostname:5446/$image
[ "$status" -ne 0 ]
}
@test "Test TLS client auth to server with unknown certificate authority fails" {
docker tag -f $image $hostname:5447/$image
run docker push $hostname:5447/$image
[ "$status" -ne 0 ]
}
@test "Test failure to connect to server fails to fallback to SSLv3" {
docker tag -f $image $hostname:5448/$image
run docker push $hostname:5448/$image
[ "$status" -ne 0 ]
}