Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acceptance test environment #88

Merged
merged 59 commits into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
614c4ec
Added a check to see if the required RELEASE_SUFFIX variable is defined
Jan 11, 2017
96e5dcc
Wrote the first very simple acceptance test
Jan 11, 2017
f20b63c
Execute the acceptance tests in the CI
Jan 11, 2017
2b62769
Fixed some description messages in the rpmbuild
Jan 12, 2017
3882455
Add a symlink to the openvdc command in /usr/bin so it's in PATH afte…
Jan 12, 2017
c8f91d2
Have the cli package own the /usr/bin/openvdc symlink
Jan 13, 2017
4ba56c0
Merge branch 'master' into acceptance-test
Jan 13, 2017
c28c95c
Added dependency handling for the acceptance tests
Jan 13, 2017
0b40419
Added a hack for jenkins to put the acceptance tests in GOPATH using …
Jan 13, 2017
7a5f268
Fixed the govendor hack to work correctly
Jan 13, 2017
317b8b1
Merge branch 'master' into acceptance-test
Jan 16, 2017
21565b9
Reverted accidental removal of vendor.json in a previous commit
Jan 16, 2017
9121ad7
Use the run_tests.sh script in the CI
Jan 16, 2017
212ddd0
Set the GOPATH on jenkins
Jan 16, 2017
ee7305b
Removed the test script and vendoring file for the acceptance test. W…
Jan 16, 2017
013a399
Added an rpm package for the acceptance test
Jan 16, 2017
72927cd
Renamed integration stages to acceptance
Jan 16, 2017
a9e44da
Added summary to the openvdc-acceptance-test package
Jan 16, 2017
840915c
Fixed some capitalization in the rpm spec file
Jan 16, 2017
204a3d1
Fixed a mistake where the description and files segment of the accept…
Jan 16, 2017
64a119a
Added Dockerfile for the integration test in a temporary directory
Jan 17, 2017
5fcb07a
Added missing dependency checks to multibox
Jan 17, 2017
674cc2c
Moved all files into a new acceptance-test directory so we can build …
Jan 17, 2017
e283b49
Add the multibox file instead of mounting it. That way any garbage cr…
Jan 17, 2017
a3a338a
Moved the acceptance test code into the new directory as well
Jan 17, 2017
ccae2aa
Disable the acceptance test stage until we've figured out exactly how…
Jan 17, 2017
6b181d0
Merge branch 'master' into acceptance-test
Jan 17, 2017
003232f
Revert "Disable the acceptance test stage until we've figured out exa…
Jan 17, 2017
e1d0c13
Run the tests more verbosely
Jan 17, 2017
9dca0c5
Re-arranged the environment variables so we don't create a new docker…
Jan 17, 2017
6c193ec
Set the BRANCH, RELEASE_SUFFIX and REBUILD variables at build time
Jan 17, 2017
addc478
Remove the old repo file that isn't used any more. Instead we're writ…
Jan 18, 2017
610d5fd
Run the tests as a regular user instead of root
Jan 18, 2017
848c118
Set the maintainer field
Jan 18, 2017
a3dbd20
Added labels to acceptance test dockerfile
Jan 18, 2017
067306a
Changed he data directory inside of docker from /data2 to /data
Jan 18, 2017
4367808
Added a required RUN argument to the run_tests.sh script so people wh…
Jan 18, 2017
a8234b4
Added a kickoff script for the acceptance test in docker
Jan 18, 2017
db200e0
Execute the docker build and run script in the Jenkinsfile
Jan 18, 2017
6cf8445
Removed todo comment that's been done
Jan 18, 2017
4992189
Trap script exit to cleanup the container we've built
Jan 18, 2017
933538e
Added openvdc-cli to the acceptance test dependencies. Since we're no…
Jan 18, 2017
97d7dd6
Fixed a brain fart where we were installing the openvdc yum repo twice
Jan 18, 2017
06a0286
Removed a comment that's no longer relevant
Jan 18, 2017
34d3fcd
Removed some unused code form multibox
Jan 18, 2017
b4b6cdd
Changed the cmd_in_path test to not go through SSH. We're installing …
Jan 18, 2017
10736c9
Added a drawing of the environment in .svg format
Jan 18, 2017
4cd6296
Jenkins complains about Acceptance Test not existing. Trying the old …
Jan 19, 2017
276b558
Skip unit tests and rpmbuild so we can debug jenkins
Jan 19, 2017
062d695
Re-enable unit tests and rpmbuild now that we're done debugging the a…
Jan 19, 2017
90d2df2
Added the first most basic part of a readme file
Jan 25, 2017
9e19d5f
Removed a TODO comment and fixed a bug where the axsh user didn't hav…
Jan 25, 2017
4804507
Wrote another part of the readme
Jan 25, 2017
ba2b331
Finished the first draft of the README file
Jan 25, 2017
4597ef5
Some minor corrections after proofreading the README and added a clea…
Jan 25, 2017
c0979a9
Added a line about bind mounting the cache in the readme
Jan 25, 2017
45c0ee0
Added the optional DATA_DIR variable to the build.env explanation and…
Jan 25, 2017
c9b4372
Grammar fix in the readme faq
Jan 25, 2017
c9a2e94
Capitalized the word Docker where it wasn't done already
Jan 25, 2017
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
16 changes: 4 additions & 12 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,12 @@ def stage_rpmbuild(label) {
}
}

def stage_integration(label) {
def stage_acceptance(label) {
node("multibox") {
stage "Acceptance Test ${label}"
checkout_and_merge()
stage "Build Integration Environment"
write_build_env(label)

try {
sh "cd ci/multibox/ ; ./build.sh"
stage "Run Tntegration Test"
// This is where the integration test will be run
} finally {
stage "Cleanup Environment"
sh "cd ci/multibox/ ; ./destroy_leaving_cache.sh"
}
sh "./ci/acceptance-test/build_and_run_in_docker.sh ./build.env"
}
}

Expand Down Expand Up @@ -112,5 +104,5 @@ if( buildParams.BUILD_OS != "all" ){
for( label in build_nodes) {
stage_unit_test(label)
stage_rpmbuild(label)
stage_integration(label)
stage_acceptance(label)
}
3 changes: 3 additions & 0 deletions ci/acceptance-test/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tests
illustrations
build_and_run_in_docker.sh
29 changes: 29 additions & 0 deletions ci/acceptance-test/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM centos:7

MAINTAINER "Axsh Co. LTD"

VOLUME /data

RUN ["yum", "install", "-y", "epel-release"]
RUN ["yum", "install", "-y", "rsync", "bridge-utils", "qemu-kvm", "qemu-system-x86", "parted", "sudo", "openssh-clients", "nmap-ncat"]

RUN groupadd -r axsh && useradd -d /home/axsh -g axsh axsh
WORKDIR /home/axsh

ARG BRANCH
ARG RELEASE_SUFFIX
ARG REBUILD

# Set the ARGs to ENV because otherwise they're not visible to the run_tests.sh script
ENV BRANCH=${BRANCH:-master} RELEASE_SUFFIX=${RELEASE_SUFFIX:-current} REBUILD=${REBUILD:-false}

LABEL "jp.axsh.vendor"="Axsh Co. LTD" \
"jp.axsh.project"="OpenVDC" \
"jp.axsh.task"="acceptance test" \
"jp.axsh.branch"="$BRANCH" \
"jp.axsh.release_suffix"="$RELEASE_SUFFIX"

COPY ["multibox", "/multibox"]
COPY ["run_tests.sh", "run_tests.sh"]

ENTRYPOINT ["./run_tests.sh", "RUN"]
141 changes: 141 additions & 0 deletions ci/acceptance-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# OpenVDC Acceptance Test

## Quick start

![Test environment drawing](illustrations/drawing.svg)

This is the environment used on the OpenVDC CI to run the integration tests. To run this environment locally first make a file containing the following environment variables.

```
# The following two lines make up the yum repository from which we'll download OpenVDC packages to test
# "https://ci.openvdc.org/repos/${BRANCH}/${RELEASE_SUFFIX}/"
BRANCH="master"
RELEASE_SUFFIX="current"

# Set to "1" if you don't want to remove the Docker container after running
REBUILD="0"

# This variable holds the directory on the *host* that will be bind mounted
# into the Docker container to place the cache for KVM images.
# If not provided, the default value is "/data2"
DATA_DIR=/data2
```

Let's save this file as `build.env`. Now kick off the `build_and_run_in_docker.sh` script, passing in that file as an argument.

```
./build_and_run_in_docker.sh build.env
```

That's it. This should build the environment and run the tests

## The nitty gritty

Here's everything you need to know about how this acceptance test works exactly.

### The actual test code

The actual test code is in the `tests` directory. This is written in go using the [Testing](https://golang.org/pkg/testing/) package. During the CI's rpmbuild stage, these tests are compiled as a binary and packaged in an rpm called `openvdc-acceptance-test`. This way we don't have to worry about installing go and setting up a GOPATH on the test environment.

### The Docker container

The test environment consists of multiple KVM machines and we've decided to put them all together in a Docker container. That way we can test multiple branches in parallel and cleanup becomes simple. We just remove the container when we're done.

The command we run inside of the Docker container is `run_tests.sh`. This script will first write the correct OpenVDC yum repository to `/etc/yum.repos.d/openvdc.repo`. The environment variables described in [Quick start](#quick-start) decide which repository is used.

Next the `run_tests.sh` script installs the `openvdc-acceptance-test` package through yum which depends on `openvdc-cli`.

Now we build the KVM environment.

### The KVM environment

The code that builds the KVM machines running inside of the Docker container is in the `multibox` directory.

If you want to run this KVM environment locally without Docker, you can do so like this.

```
BRANCH=master RELEASE_SUFFIX=current REBUILD=false ./build.sh
```

This environment uses a caching system to avoid having to constantly rebuild the images every time we test a new branch or commit. The system works as follows.

#### First time ever run

* Download seed image containing a minimal Centos 7. All images built are based on this.

#### First time run on a branch

* Build images in .raw format **without** openvdc installed. We use .raw so we can loopback mount and install packages using chroot.

* Convert images to .qcow format so we can use copy-on-write.

* Store images in cache directory.

#### Every time we run on a branch

* Copy-on-write cached images for branch to the directory we will run KVM from.

* Run KVM.

* Install OpenVDC packages on KVM VMs for the branch/commit we're testing

The cache directory is bind mounted into the Docker container so the same cache is re-used every time the tests run.

### The actual tests

Once the KVM environment is in place we can run the actual tests. This is the `run_tests.sh` script's final action.

To make sure that the `openvdc` command doesn't require root previliges, we run it as an unpreviliged `axsh` user.

### Cleanup

The `build_and_run_in_docker.sh` script traps EXIT and calls a cleanup function that will remove the Docker container unless `LEAVE_CONTAINER` is set.

The leftover KVM cache and Docker images are cleaned up periodically by a garbage collection job on Jenkins.

## FAQ

Keep in mind that all answers are true at time of writing (January 2017) and might no longer be accurate.

#### What OS has it run on successfully?

Fedora 23 and Arch Linux.

#### What Docker versions has it run on successfully?

1.10.3 on Fedora and 1.12.6 on Arch.

#### How much disk space is required?

609 MB for the KVM centos 7 seed image.

```
> du -hs openvdc-ci/boxes

609M openvdc-ci/boxes
```

About 3.9 GB KVM cache per branch

```
> du -hs openvdc-ci/branches/*

3.9G openvdc-ci/branches/acceptance-test
3.8G openvdc-ci/branches/master
```

About 470 MB per Docker image plus about 190 MB for the base Centos 7 image.

```
> sudo docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
openvdc/acceptance-test acceptance-test.current 8f53091d43bb 29 minutes ago 470.8 MB
centos 7 67591570dd29 5 weeks ago 191.8 MB
```

You do the math. :p

#### How much memory is required?

We've got 5 KVM machines with 1 GB of memory assigned to each one.
39 changes: 39 additions & 0 deletions ci/acceptance-test/build_and_run_in_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

set -ex -o pipefail

whereami="$(cd "$(dirname $(readlink -f "$0"))" && pwd -P)"

BUILD_ENV_PATH=${1:?"ERROR: env file is not given."}
if [[ -n "${BUILD_ENV_PATH}" && ! -f "${BUILD_ENV_PATH}" ]]; then
echo "ERROR: Can't find the file: ${BUILD_ENV_PATH}" >&2
exit 1
fi

set -a
. ${BUILD_ENV_PATH}
set +a

DATA_DIR="${DATA_DIR:-/data2}"
repo_and_tag="openvdc/acceptance-test:${BRANCH}.${RELEASE_SUFFIX}"

function cleanup() {
if [[ -z "${LEAVE_CONTAINER}" || "${LEAVE_CONTAINER}" == "0" ]]; then
# Clean up containers
# Images don't need to be cleaned up. Removing them immediately would slow down
# builds and they can be garbage collected later.
for CID in $(sudo docker ps -af ancestor="${repo_and_tag}" --format "{{.ID}}"); do
sudo docker rm "${CID}"
done
else
echo "LEAVE_CONTAINER was set and not 0. Skip container cleanup."
fi
}
trap "cleanup" EXIT

sudo docker build -t "${repo_and_tag}" --build-arg BRANCH="${BRANCH}" \
--build-arg RELEASE_SUFFIX="${RELEASE_SUFFIX}" \
--build-arg REBUILD="${REBUILD}" \
"${whereami}"

sudo docker run --privileged -v "${DATA_DIR}":/data "${repo_and_tag}"
Loading