class DockerSpec
Documentation
Constants
- CONFIG_FILE
- CONTAINER_RUN_WAIT_TIMEOUT
- DOCKER_AUTH_FILE
- ROOT_DIR
Attributes
config[RW]
container[RW]
test_failed[RW]
Public Instance Methods
build_docker_image()
click to toggle source
# File lib/docker/spec.rb, line 153 def build_docker_image puts # Rebuild the cache filesystem build_args = '' build_args += ' --no-cache' if @config[:clear_cache] # Build the docker image build_cmd = "docker build -t #{@config[:image_name]} #{build_args} ." status = POpen4.popen4(build_cmd) do |stdout, stderr, _stdin| stdout.each { |line| puts line } stderr.each { |line| puts line.red } end if status.exitstatus != 0 puts("ERROR: #{build_cmd} failed") exit 1 end end
build_root()
click to toggle source
# File lib/docker/spec.rb, line 132 def build_root command = <<EOF bash -ec ' export WD="$(pwd)" export TMPDIR=$(mktemp -d -t docker-spec.XXXXXX) cp -r root $TMPDIR/root cd $TMPDIR sudo chown root:root -R root cd root sudo tar --mtime="1970-01-01" -c -f ../root.tar . cd ../ sudo chown -R `id -u`:`id -g` root.tar cp root.tar "${WD}" touch -t 200001010000.00 "${WD}/root.tar" sudo rm -rf $TMPDIR ' EOF system command if Dir.exist?(ROOT_DIR) end
clean_up()
click to toggle source
# File lib/docker/spec.rb, line 231 def clean_up # Keep container running if @config[:keep_running] && @config[:standard_tests] puts "\nINFO: To connect to a running container: \n\n" \ "docker exec -ti #{@container.info["Name"][1..-1]} bash" else delete_container end end
delete_container()
click to toggle source
# File lib/docker/spec.rb, line 226 def delete_container @container.kill @container.delete end
get_config(key, envvar, question, default = nil)
click to toggle source
# File lib/docker/spec.rb, line 241 def get_config(key, envvar, question, default = nil) value = ENV[envvar] value = true if value.class == String && value.match(/^(true|yes|y)$/i) value = false if value.class == String && value.match(/^(false|no|n)$/i) value = @config[key] if value.nil? if value.nil? value = default.nil? ? agree(question, 'n') : default end value end
grab_flock()
click to toggle source
# File lib/docker/spec.rb, line 40 def grab_flock @config = DockerSpec.instance.config @lock = File.join('/tmp', @config[:account] + '-' + @config[:name].gsub('/', '-') + '.lock') @f = File.open(@lock, 'w') if (not @f.flock(File::LOCK_EX | File::LOCK_NB)) puts "INFO: Another build is already running #{@lock}" end @f.flock(File::LOCK_EX) end
load_config()
click to toggle source
# File lib/docker/spec.rb, line 108 def load_config File.exist?(CONFIG_FILE) || fail('Could not load docker_spec.yml') @config = YAML.load(File.read(CONFIG_FILE)) || fail('docker_spec.yml is not a valid yml file') @config[:name] || fail('name is not defined in docker_spec.yml') @config[:account] || fail('account is not defined in docker_spec.yml') @config[:image_name] = format '%s/%s', @config[:account], @config[:name] @config[:build_image] = get_config(:build_image, 'DOCKER_SPEC_BUILD_DOCKER_IMAGE', 'Build docker image? ') @config[:build_root] = get_config(:build_root, 'DOCKER_SPEC_BUILD_ROOT', 'Rebuild root filesystem? ') if @config[:build_image] @config[:clear_cache] = get_config(:clear_cache, 'DOCKER_SPEC_CLEAR_CACHE', 'Clear docker cache? ') if @config[:build_image] @config[:tag_db] = get_config(:tag_db, 'DOCKER_SPEC_TAG_DB', 'tag db?') @config[:tag_prefix] = get_config(:tag_prefix, 'DOCKER_SPEC_TAG_PREFIX', 'tag prefix?', '') @config[:standard_tests] = get_config(:standard_tests, 'DOCKER_SPEC_STANDARD_TESTS', '', true) @config[:keep_running] = get_config(:keep_running, 'DOCKER_SPEC_KEEP_RUNNING', "\nKeep container running? ") @config[:push_container] = get_config(:push_container, 'DOCKER_SPEC_PUSH_CONTAINER', 'Push new tag? ') @config end
push()
click to toggle source
# File lib/docker/spec.rb, line 50 def push if @config[:push_container] @config[:tag_db] || fail('tag_db is not defined in docker_spec.yml') # Load credentials from config file, or default docker config if @config[:registry] @config[:registry][:username] || fail('registry->username is not defined in docker_spec.yml') @config[:registry][:password] || fail('registry->password is not defined in docker_spec.yml') @config[:registry][:email] || fail('registry->email is not defined in docker_spec.yml') else auth = @config[:auth] || 'https://index.docker.io/v1/' @config[:registry] = Hash.new docker_auth = JSON.parse(File.read(File.expand_path(DOCKER_AUTH_FILE))) auth_base64 = docker_auth['auths'][auth]['auth'] @config[:registry][:username] = Base64.decode64(auth_base64).split(':').first @config[:registry][:password] = Base64.decode64(auth_base64).split(':').last @config[:registry][:email] = docker_auth['auths'][auth]['email'] end # Open key value store and get the current tag for this repo tag_prefix = @config[:tag_prefix] store = Moneta.new(:YAML, file: File.expand_path(@config[:tag_db])) if store.key?(@config[:image_name]) && !store[@config[:image_name]].to_s.match(/#{tag_prefix}(.*)/).nil? current_tag = store[@config[:image_name]].to_s.match(/#{tag_prefix}(.*)/)[1].to_i else current_tag = 0 end new_tag = tag_prefix + (current_tag + 1).to_s image = Docker::Image.all.detect do |i| i.info['RepoTags'].include?(@config[:image_name] + ':latest') end # Login to docker hub and push latest and new_tag Docker.authenticate! username: @config[:registry][:username], password: @config[:registry][:password], email: @config[:registry][:email], serveraddress: @config[:serveraddress] || 'https://index.docker.io' image.tag repo: @config[:image_name], tag: new_tag, force: true puts "\nINFO: pushing #{@config[:image_name]}:#{new_tag} to Registry" image.push nil, tag: new_tag image.tag repo: @config[:image_name], tag: 'latest', force: true puts "INFO: pushing #{@config[:image_name]}:latest to Registry" image.push nil, tag: 'latest' # Store the new tag in the tag_db store[@config[:image_name]] = new_tag.to_s store.close end end
rspec_configure()
click to toggle source
# File lib/docker/spec.rb, line 171 def rspec_configure set :backend, :docker $docker_spec_config = @config RSpec.configure do |rc| rc.fail_fast = true rc.after(:each) do |test| DockerSpec.instance.test_failed = true if test.exception end rc.before(:suite) do DockerSpec.instance.start_container end rc.after(:suite) do DockerSpec.instance.clean_up DockerSpec.instance.push unless DockerSpec.instance.test_failed end end Docker::Spec::docker_tests end
run()
click to toggle source
# File lib/docker/spec.rb, line 29 def run @config = nil @test_failed = false load_config grab_flock if @config[:lock] build_root if @config[:build_root] build_docker_image if @config[:build_image] rspec_configure end
start_container()
click to toggle source
# File lib/docker/spec.rb, line 194 def start_container # Run the container with options opts = {} opts['HostConfig'] = { 'NetworkMode' => @config[:network_mode] } \ unless @config[:network_mode].nil? opts['env'] = @config[:env] unless @config[:env].nil? opts['Image'] = @config[:image_name] @container = Docker::Container.create(opts).start Timeout::timeout(10) do loop do @container.refresh! break if @container.info["State"]["Running"] end end if @config[:standard_tests] # Check the logs, when it stops logging we can assume the container # is fully up and running log_size_ary = [] CONTAINER_RUN_WAIT_TIMEOUT.times do log_size_ary << @container.logs(stdout: true).size break if log_size_ary.last(3).sort.uniq.size == 1 && log_size_ary.last(3).sort.uniq.last > 0 sleep 1 end if @config[:standard_tests] set :docker_container, @container.id end
to_boolean(str)
click to toggle source
# File lib/docker/spec.rb, line 252 def to_boolean(str) str == 'true' unless str.nil? end