inspec/test/docker.rb
Dominik Richter 37ad8f9531 run test setup concurrently + only once
Instead of having RSpec re-run its world multiple times, run it only once with all tests.

Which leaves us with one more thing to solve: we want to start tests as soon as the container is up and they are set up. At the moment, the containers come up and are set up concurrently, including test registry, but the tests themselves are in simple sequence.

Signed-off-by: Dominik Richter <dominik.richter@gmail.com>
2015-09-22 02:17:27 +02:00

94 lines
2.1 KiB
Ruby

# encoding: utf-8
require 'docker'
require 'yaml'
require 'concurrent'
require_relative '../lib/vulcano'
tests = ARGV
if tests.empty?
puts 'Nothing to do.'
exit 0
end
class DockerTester
def initialize(tests)
@tests = tests
@images = docker_images_by_tag
@conf = tests_conf
end
def run
puts ['Running tests:', @tests].flatten.join("\n- ")
puts ''
# test all images
promises = @conf['images'].map { |n|
Concurrent::Promise.new {
container = prepare_image(n)
runner = test_container(container.id)
[container, runner]
}.execute
}
sleep(0.1) until promises.all?(&:fulfilled?)
runner = promises[0].value[1]
ok = runner.run
done = promises.map do |promise|
promise.then { |c, _| stop_container(c) }
end
sleep(0.1) until done.all?(&:fulfilled?)
ok or fail 'Test failures'
end
def docker_images_by_tag
# get all docker image tags
images = {}
Docker::Image.all.map do |img|
Array(img.info['RepoTags']).each do |tag|
images[tag] = img
end
end
images
end
def tests_conf
# get the test configuration
conf_path = File.join(File.dirname(__FILE__), '..', '.tests.yaml')
fail "Can't find tests config in #{conf_path}" unless File.file?(conf_path)
YAML.load(File.read(conf_path))
end
def test_container(container_id)
puts "--> run test on docker #{container_id}"
opts = { 'target' => "docker://#{container_id}" }
runner = Vulcano::Runner.new(nil, opts)
runner.add_tests(@tests)
runner
end
def prepare_image(name)
dname = "docker-#{name}:latest"
image = @images[dname]
fail "Can't find docker image #{dname}" if image.nil?
puts "--> start docker #{name}"
container = Docker::Container.create(
'Cmd' => ['/bin/bash'],
'Image' => image.id,
'OpenStdin' => true,
)
container.start
container
end
def stop_container(container)
puts "--> killrm docker #{container.id}"
container.kill
container.delete(force: true)
end
end
DockerTester.new(tests).run