Trust, but verify
Testing with Docker Containers
whoami
● Nan Liu
Ship Faster
Snap Container
FROM alpine:3.4
MAINTAINER Nan Liu
ENV SNAP_LOG_LEVEL
EXPOSE 8181
ADD build/snapteld /opt/snap/sbin/snapteld
ADD build/snaptel /opt/snap/sbin/snaptel
COPY snapteld.conf /etc/snap/snapteld.conf
CMD /opt/snap/sbin/snapteld -t 0 -l 1 -o ''
Snap Container
Just it.
Fail
dynamically linked (uses shared libs), not stripped
Serverspec
require "serverspec"
set :backend, (ssh/exec/cmd/...)
describe :label do
describe :resource_type("name") do
it { should be_assertions }
end
end
System
Vagrant
Ubuntu VM
Windows VM
Serverspec
Remote System
Verify
describe package("snap-telemetry") do
it { should be_installed }
end
describe command("ldd $(which snapteld)") do
its(:stdout) { should match /not a dynamic executable/ }
end
* serverspec in vagrant
Container Inspection
Docker Serverspec
require 'serverspec'
require 'dockerspec/serverspec'
describe docker_build(path: './Dockerfile') do # erb, string
# test
end
describe docker_run('intelsdi/snap:xenial', family: 'debian')
#test
end
Docker Serverspec
describe docker_build("alpine/.") do
it { should have_maintainer /Nan Liu/ }
%w[SNAP_VERSION SNAP_TRUST_LEVEL SNAP_LOG_LEVEL].each do |e|
it { should have_env e }
end
it { should have_label( "license" => "Apache 2.0" ) }
it { should have_expose '8181' }
end
Docker Serverspec
describe docker_build("alpine/.") do
describe docker_run(described_image) do
describe file('/etc/snap/snapteld.conf') do
its(:content_as_yaml) {
should include('log_path' => '/var/log/snap')
should include('control' => {
"auto_discover_path" => "/opt/snap/plugins"})
}
end
end
Demo
Travis CI
sudo: true
services:
- docker
language: ruby
before_deploy:
- docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME"
-p="$DOCKER_PASSWORD"
Travis CI
deploy:
provider: script
script: docker push intelsdi/snap:latest
on:
branch: master
Mission Accomplished
Testing Snap
● Operating systems
○ Linux: RedHat/Ubuntu
○ MacOS
● 85 Plugins
○ Databases/NoSQL
○ OpenStack
● ^^^ * Snap Version * Plugin Versions = ???
Engineer view
User view
Large Test Goals
● Matrix of Snap/Snap plugin versions
● Support multiple OS versions
● Small overhead/footprint +
● Debugging tool +
Large Test
Pros
● simple?
Cons
● script sprawl
● parsing output (jq)
● dockerfile proliferation
● no os abstraction
System
Docker
Snap
Dependency
#!/bin/bash
● launch containers
● run scripts in containers
● cleanup
#!/bin/bash
test scripts
Large Test
Pros
● Testing framework
Cons
● snowflake containers
● dockerfile proliferation
System
Docker
Snap
Dependency
#!/bin/bash
● launch containers
● run scripts in containers
● cleanup
#!/bin/env python
goss test framework
Large Test
Pros
● all in one
Cons
● ruby dependency
● need to learn serverspec
System
Docker
Snap
Dependency
docker serverspec
● build containers
● docker exec commands
● cleanup
Docker Compose
services:
snap:
image: intelsdi/snap:${OS}_test
environment:
SNAP_VERSION: "${SNAP_VERSION}"
volumes:
- "${PLUGIN_PATH}:/plugin""
Docker Compose Serverspec
describe docker_compose("../docker-compose.yml") do
its_container(:snap) do
describe command("snaptel task create -t /plugin/examples/tasks/#{t}")
do
its(:exit_status) { should eq 0 }
end
end
end
Large Test
System
Docker
Snap
Dependency
docker-compose-serverspec
● build containers
● docker exec
commands
● cleanup
Docker-inception (sibling containers)
docker run -v /var/run/docker.sock:/var/run/docker.sock 
-v "${proj_dir}":/plugin 
-e PLUGIN_PATH="${proj_dir}" 
-e SNAP_VERSION="${SNAP_VERSION}" 
-e OS="${OS}" 
-it intelsdi/serverspec:alpine 
/bin/sh -c "cd /plugin/scripts && rspec ./test/*_spec.rb"
Docker Compose Serverspec
describe docker_compose("../docker-compose.yml") do
its_container(:snap) do
describe command("snaptel task create -t /plugin/examples/tasks/#{t}")
do
its(:exit_status) { should eq 0 }
end
end
end
Large Test
its_container(:influxdb) do
describe 'wait for influxdb service' do
it do
c=cmd_retry('curl -sl -I localhost:8086/ping')
expect(c.exit_status).to eq 0
end
end
end
System
Docker
Snap
Influxdb
docker-serverspec
● build containers
● docker exec
commands
● cleanup
Large Test
describe command("#{snaptel} plugin list") do
it { load_all_plugins }
its(:exit_status) { should eq 0 }
its(:stdout) {
plugins.each do |p|
_ , name = p
should contain(/#{name}/)
end
}
end
Demo
Large Test
Cons
● Docker environment variable nesting
● pry debug output munged
System
Docker
Snap
Dependency
docker-serverspec
● build containers
● docker exec
commands
● cleanup
Ship Faster with
Confidence
Questions?
● serverspec.org
● github.com/zuazo/dockerspec
● github.com/nanliu/docker-serverspec
● github.com/intelsdi-x/snap
Next Docker Meetup
● Feb 9th @ Puppet Labs
● Mike Coleman | Docker

Trust, but verify | Testing with Docker Containers