Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions Dockerfile.bin
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM python:3.4-slim

RUN apt-get update -y \
&& apt-get install -y curl \
&& apt-get clean

RUN mkdir -p ~/.clusterrunner/dist \
&& cd ~/.clusterrunner \
&& curl -L https://cloud.box.com/shared/static/2pl4pi6ykvrbb9d06t4m.tgz > clusterrunner.tgz \
&& tar -zxvf clusterrunner.tgz -C ./dist \
&& cp ./dist/conf/default_clusterrunner.conf clusterrunner.conf \
&& chmod 600 clusterrunner.conf \
&& rm -f clusterrunner.tgz

EXPOSE 43000 43001

ENTRYPOINT ["/root/.clusterrunner/dist/clusterrunner"]
13 changes: 13 additions & 0 deletions Dockerfile.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM python:3.4-slim
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity -- what is the naming convention around dockerfiles? I'm assuming you created Dockerfile.src to run clusterrunner from source, and Dockerfile.bin to run it from the binary. Is this more conventional that something like Dockerfile-source/Dockerfile-binary? My main goal here is avoiding confusion around the fact that they look like file extensions.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington I have seen Dockerfile names with both dot and dash based separation. In some cases I came across Dockerfile name using both! But I agree more with the name you suggested to reduce confusion and to improve readability. Will fix that...


RUN apt-get update -y \
&& apt-get install -y gcc git \
&& apt-get clean

ADD . /src

RUN pip install --upgrade -r /src/requirements.txt

EXPOSE 43000 43001

ENTRYPOINT ["/src/main.py"]
11 changes: 11 additions & 0 deletions docker-compose-bin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: "2.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this version number come from?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington Docker Compose has a number of docker-compose.yml file formats with particular Docker Engine version dependencies. The following explains compatibility requirement and API versioning with upgrade process in details:

At the time of writing compose file for ClusterRunner in this pull request, Docker version in my CoreOS environment supported compose API version 2.1.

services:
cluserrunner:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: cluserrunner :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington Thanks! :) Will fix that...

build:
context: .
dockerfile: Dockerfile.bin
image: yamaszone/clusterrunner:bin
ports:
- "43000:43000"
- "43001:43001"

7 changes: 7 additions & 0 deletions docker-compose-src.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: "2.1"
services:
cluserrunner:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington Thanks. Will fix that...

build:
dockerfile: Dockerfile.src
image: yamaszone/clusterrunner:src

57 changes: 57 additions & 0 deletions docs/docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
## TODO for Dockerization
* Add maintainer(s)
- Maintainer for CR Dockerfile needs to be added after pull request is merged. Ideally the maintainer should be someone from official team with appropriate Docker Hub permission to tag image as `box/clusterrunner:latest`. I can volunteer if needed but that will require collaborator permission for Docker Hub.
Copy link
Contributor

@josephharrington josephharrington Apr 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on what's involved with this? We have a Docker Hub account named boxinc that I can use. I'm assuming this is something we'd have to do for every new version?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington Currently I can push CR images to Docker Hub only using my Hub username i.e. as yamaszone/clusterrunner:src. The official CR image should be tagged and pushed as boxinc/clusterrunner:latest, boxinc/clusterrunner:0.5.473, boxinc/clusterrunner:0.5.474, etc. which only users under boxinc and collaborators of a repo have permissions this action. I will include an environment variable CLUSTERRUNNER_VERSION in the Dockerfile so that there is a Docker image for every version of CR.

* Lean Docker image (consider tiny base e.g. busybox, alpine, etc.)
- Currently `Dockerfile.src` uses `python:3.4-slim` as the base. I attempted `python:alpine` as the base but it didn't feel like worth the [trouble](https://github.com/docker/docker/issues/27940). My docker version is `1.12.6` but the problem might have been fixed in `1.13.0+`. I will revisit this in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does python:3.4-slim include more than what is needed? (I assume it does from your comment, but I'm curious as to what.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington The official python:3.4-slim Dockerfile includes a bunch of dependencies but I am not sure if all of them are needed for CR. I am yet to do a research though...

* Reorganize directory structure (cleaner project root preferred)
- I was considering potential restructure of CR project root directory similar to [this](https://gist.github.com/yamaszone/6a4304069652a4a01ecdacdd4e7c7df1) so that:
- Only relevant project artefacts can be easily added into Docker image excluding non-PROD dependencies like tests, docs, Dockerfiles, docker-compose.yaml, and so on...
- Non-PROD tools/libs installation inside Docker container is excluded by splitting `requirements.txt` into `requirements-prod.txt` and `requirements-non-prod.txt` to deal with security/maintenance aspects of production dependencies as a priority basis
- Readability can be improved
- ... :)
- I will hold off on this as it will potentially require breaking changes. Also allowing more time to rethink this!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I support the reorganization idea in general and your suggested structure looks good at first glance but yes I'd want to look at it more closely.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington I will get back to this TODO at a later time with some POC.


## User Guide
#### Usage Scenarios
[ClusterRunner container](https://hub.docker.com/r/yamaszone/clusterrunner/) is a good choice if your application runtime environment supports [Docker Engine](https://docs.docker.com/engine/installation/). For example, if your application under test is running on macOS with Docker Engine installed, then you can easily use the ClusterRunner Docker container to run tests in parallel.
To see ClusterRunner CLI help, run the following command:

`docker run --rm -v /path/to/system/under/test:/sut -w /sut yamaszone/clusterrunner:bin -h`

See [Quick Start](http://www.clusterrunner.com/docs/quickstart/) guide to configure your project to use ClusterRunner.

**NOTE**: ClusterRunner container is yet to add parallel testing support easily for applications that run as containers.

## Developer Guide
Currently we are maintaining two flavors of Dockerfiles for ClusterRunner:
* `Dockerfile.bin`: Build ClusterRunner image from binary with minimal image size
* `Dockerfile.src`: Build ClusterRunner image from source
In the future, we plan to maintain `Dockerfile.src` only after simplifying some dependencies mentioned [here](https://github.com/box/ClusterRunner/issues/328).

#### Requirements
* [Docker Engine](https://docs.docker.com/engine/installation/) version 1.12.x+
* [Docker Compose](https://docs.docker.com/compose/) version 1.11.x+ with API version 2.1

#### Requirements Setup
* Install docker-compose on CoreOS
```sh
$ sudo su -
$ curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` > /opt/bin/docker-compose
$ chmod +x /opt/bin/docker-compose
```
* For other platforms, see instructions [here](https://docs.docker.com/compose/install/)
```
$ curl -L "https://github.com/docker/compose/releases/download/1.11.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
```

#### Development/Test Workflow
We use `docker-compose` to maintain two flavors of Docker images: `docker-compose-bin.yml` for `Dockerfile.bin` and `docker-compose-src.yml` for `Dockerfile.src`. Project root contains a convenient script `run-cr` to easily build/test/push Docker images (see `./run-cr help`):
* Build
- Run `./run-cr build` to build both flavors of ClusterRunner containers
* Test
- Run `./run-cr test-bats` to run sanity tests for the ClusterRunner containers. We use lightweight [BATS](https://github.com/sstephenson/bats) framework to write automated tests (see `test/bats`) for the ClusterRunner images.
* Push
- Run `./run-cr push` to push ClusterRunner images to Docker Hub
* Image Versions
- Currently [ClusterRunner images](https://hub.docker.com/r/yamaszone/clusterrunner/tags/) are tagged as `bin` and `src`. To improve maintainability of these images, we will concatenate ClusterRunner versions with the container tags in the future.
78 changes: 78 additions & 0 deletions run-cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash

# This script automates the workflow around packaging CR using Docker.

# yamaszone should be replaced with official user
DR_USR=yamaszone
CR_BIN=$DR_USR/clusterrunner:bin
CR_SRC=$DR_USR/clusterrunner:src

build_images(){
# *-src.yml only overrides 'dockerfile:' flavor and corresponding 'image:' name
docker-compose -f docker-compose-bin.yml -f docker-compose-src.yml build
}

push_images(){
# Uses Docker Hub as default
docker push $CR_BIN
docker push $CR_SRC
}

help(){
echo "Usage:"
printf "\t bin\t\t: Run ClusterRunner from binary.\n"
printf "\t build\t\t: Build ClusterRunner Docker images.\n"
printf "\t help\t\t: Show this help.\n"
printf "\t push\t\t: Push ClusterRunner images to Docker Hub.\n"
printf "\t src\t\t: Run ClusterRunner from source.\n"
printf "\t test-bats\t: Run BATS tests to validate image builds.\n"
exit 0
}

install_bats(){
# Install BATS framework if not installed already
type bats >/dev/null 2>&1
if [[ "$?" -ne "0" ]]; then
git clone -b v0.4.0 https://github.com/sstephenson/bats.git /tmp/bats
OS_NAME=$(uname -a)
echo $OS_NAME
if [[ $OS_NAME == *"coreos"* ]]; then
cd /tmp/bats && sudo ./install.sh /opt
else
cd /tmp/bats && sudo ./install.sh /usr/local
fi
cd -
rm -rf /tmp/bats
fi
}

if [[ -z $1 ]];then
help
exit 0
fi
# Inputs to pass on to CR via this script; exclude $1
INPUTS=`echo "${@:2}"`

case $1 in
bin)
docker run --rm $CR_BIN $INPUTS
;;
build)
build_images
;;
push)
push_images
;;
src)
docker run --rm $CR_SRC $INPUTS
;;
# TechDebt: Could be a target in Makefile
# CoreOS doesn't come with Make; so staying within it's limits
test-bats)
install_bats
bats test/bats/
;;
* | help)
help
;;
esac
1 change: 1 addition & 0 deletions test/bats/fixtures/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#ignore
22 changes: 22 additions & 0 deletions test/bats/helpers/assertions/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(See my comment below about potentially keeping all tests in Python, but if we did start using bats...)
If possible, I think I'd lean towards not committing the bats library to the repo and instead downloading it (potentially as part of make init) similar to how we download/install the Python dependencies externally.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephharrington It's me being lazy in the early days when I adopted BATS and not being sure if these supporting libraries will be well maintained. :) I forked these repo to address my maintenance concern. I have already fixed this for some of my other repos. I will fix that here too... Thanks for bringing this.


Copyright (c) 2015 Jason Karns

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

170 changes: 170 additions & 0 deletions test/bats/helpers/assertions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# bats-assert
Assertion library for BATS (Bash Automated Testing System)

## Installation

Recommended installation is via git submodule. Assuming your project's bats
tests are in `test`:

``` sh
git submodule add https://github.com/jasonkarns/bats-assert test/helpers/assertions
git commit -am 'added bats-assert module'
```

then in `test/test_helper.bash`:

``` bash
load helpers/assertions/all
```

(Optionally configure [sparse-checkout](http://git-scm.com/docs/git-read-tree#_sparse_checkout) if you're concerned with all the non-essential files being in your repo)

Also available as an [npm module](https://www.npmjs.com/package/bats-assert) if you're into that sort of thing.

``` sh
npm install --save-dev bats-assert
```

then in `test/test_helper.bash`:

``` bash
load ../node_modules/bats-assert/all
```

## Assertion API

### flunk
forces a test failure with an optional message

``` bash
flunk
# or
flunk "expected blue skies"
```

### assert
asserts command returns successfully

``` bash
assert my-command
assert [ 2 -eq 2 ]
```

### refute
asserts command returns unsuccessfully

``` bash
refute invalid-command
refute [ 2 -eq 3 ]
```

### assert_success
asserts successful exit `$status` with (optional) `$output`

``` bash
run my-command

assert_success
# or
assert_success "expected output"
```

### assert_failure
asserts unsuccessful exit `$status` with (optional) `$output`

``` bash
run my-command

assert_failure
# or
assert_failure "expected output"
```

### assert_equal
asserts equality

``` bash
actual="$(my-command)"
expected="my results"

assert_equal expected actual
```

### assert_contains
asserts x contains y

```
assert_contains foobar oo
```

### refute_contains
asserts x does not contain y

```
refute_contains foobar baz
```

### assert_starts_with
asserts x starts with y

```
assert_starts_with foobar foo
```

### assert_output
asserts `$output`

```
run my-command

assert_output "my results"
```

### assert_output_contains
asserts `$output` contains argument

```
run my-command

assert_output_contains "results"
```

### refute_output_contains
asserts `$output` does not contain argument

```
run my-command

refute_output_contains "unicorn"
```

### assert_line
asserts `$output` contains given line (at optional line index)

```
run my-command

assert_line "my results"
# or
assert_line 0 "my results"
```

### refute_line
asserts `$output` does *not* contain given line

```
run my-command

refute_line "thirsty rando"
```

## Credits

Assertion functions taken from the test_helpers of [rbenv][], [ruby-build][],
and [rbenv-aliases][]. Many thanks to their authors and contributors: [Sam
Stephenson](https://github.com/sstephenson), [Mislav
Marohnić](https://github.com/mislav), and [Tim Pope](https://github.com/tpope).

[rbenv]:https://github.com/sstephenson/rbenv
[ruby-build]:https://github.com/sstephenson/ruby-build
[rbenv-aliases]:https://github.com/tpope/rbenv-aliases
Loading