The DevOps 2.1 Toolkit:Docker Swarm
上QQ阅读APP看书,第一时间看更新

Running staging tests

Please note that the real purpose of this step in the CI flow is to run the tests that require the service and its dependencies to be running. Those are still not integration tests that require production or production-like environment. The idea behind those tests is to run the service together with its direct dependencies, run the tests, and, once they're finished, remove everything and free the resources for some other task. Since these are still not integration tests, some, if not all, dependencies can be mocks.

Due to the nature of these tests, we need to split the task into three actions:

  1. Run the service and all the dependencies.
  2. Run the tests.
  3. Destroy the service and all the dependencies.

The dependencies are defined as the staging-dep service inside the docker-compose-test-local.yml (https://github.com/vfarcic/go-demo/blob/master/docker-compose-test-local.yml) file. The definition is as follows:

  staging-dep:
image: go-demo
ports:
- 8080:8080
depends_on:
- db

db:
image: mongo:3.2.10

The image is go-demo, and it exposes the port 8080 (both on the host and inside the container). It depends on the service db which is a mongo image. Services defined as depends_on will be run before the service that defines the dependency. In other words, if we run the staging-dep target, Compose will run the db first.

Let's run the dependencies as shown in the following code:

docker-compose \ 
-f docker-compose-test-local.yml \
up -d staging-dep

Once the command is finished, we will have two containers running (go-demo and db). We can confirm that by listing all the processes:

docker-compose \ 
-f docker-compose-test-local.yml \
ps

The output is as follows:

Name Command State Ports
---------------------------------------------------------------------

godemo_db_1 /entrypoint.sh mongod Up 27017/tcp
godemo_staging-dep_1 go-demo Up 0.0.0.0:8080->8080/tcp

Now that the service and the database it depends on are running, we can execute the tests. They are defined as the service staging. The definition is as follows:

  staging:
extends:
service: unit
environment:
- HOST_IP=localhost:8080
network_mode: host
command: bash -c "go get -d -v -t && go test --tags integration -v"

Since the definition of the staging tests is very similar to those we run as unit tests, the staging service extends unit. By extending a service, we inherit its full definition. Further on, we defined an environment variable HOST_IP. The tests code uses that variable to determine the location of the service under test. In this case, since the go-demo service is running on the same server as tests, the IP is server's localhost. Since, by default, localhost inside a container is not the same as the one on the host, we had to define network_mode as host. Finally, we defined the command that should be executed. It will download tests dependencies go get -d -v -t and run the tests go test --tags integration -v.

Let's run the following commands:

docker-compose \ 
-f docker-compose-test-local.yml \
run --rm staging

All the tests passed, and we are one step closer to the goal of having full confidence that the service is indeed safe to be deployed to production.

We don't have any use for keeping the service and the database running so let's remove them and free the resources for some other task:

docker-compose \ 
-f docker-compose-test-local.yml \
down

The down command stops and removes all services defined in that Compose file. We can verify that by running the following  ps command:

docker-compose \ 
-f docker-compose-test-local.yml \
ps

The output is as follows:

Name Command State Ports
------------------------------

There is only one thing missing for the CI flow to be complete. At this moment we have the go-demo image that is usable only inside the go-demo server. We should store it in a registry so that it can be accessed from other servers as well.