class Kitchen::Transport::Dokken::Connection
@author Sean OMeara <sean@chef.io>
def docker_connection
def docker_connection @docker_connection ||= ::Docker::Connection.new(options[:docker_host_url], options[:docker_host_options]) end
def execute(command)
def execute(command) return if command.nil? with_retries { @runner = ::Docker::Container.get(instance_name, {}, docker_connection) } with_retries do o = @runner.exec(Shellwords.shellwords(command), 'e' => { 'TERM' => 'xterm' }) { |_stream, chunk| print chunk.to_s } @exit_code = o[2] end raise Transport::DockerExecFailed, "Docker Exec (#{@exit_code}) for command: [#{command}]" if @exit_code != 0 end
def image_prefix
def image_prefix options[:image_prefix] end
def instance_name
def instance_name options[:instance_name] end
def login_command
def login_command @runner = options[:instance_name].to_s args = ['exec', '-it', @runner, '/bin/bash', '-login', '-i'] LoginCommand.new('docker', args) end
def upload(locals, remote)
def upload(locals, remote) port = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostPort] if options[:host_ip_override] # Allow connecting to any ip/hostname to support sibling containers ip = options[:host_ip_override] elsif options[:docker_host_url] =~ /unix:/ if options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostIp] == '0.0.0.0' ip = options[:data_container][:NetworkSettings][:IPAddress] port = '22' else # we should read the proper mapped ip, since this allows us to upload the files ip = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostIp] end elsif options[:docker_host_url] =~ /tcp:/ ip = options[:docker_host_url].split('tcp://')[1].split(':')[0] else raise Kitchen::UserError, 'docker_host_url must be tcp:// or unix://' end tmpdir = Dir.tmpdir FileUtils.mkdir_p "#{tmpdir}/dokken" File.write("#{tmpdir}/dokken/id_rsa", insecure_ssh_private_key) FileUtils.chmod(0600, "#{tmpdir}/dokken/id_rsa") begin rsync_cmd = '/usr/bin/rsync -a -e' rsync_cmd << ' \'' rsync_cmd << 'ssh -2' rsync_cmd << " -i #{tmpdir}/dokken/id_rsa" rsync_cmd << ' -o CheckHostIP=no' rsync_cmd << ' -o Compression=no' rsync_cmd << ' -o PasswordAuthentication=no' rsync_cmd << ' -o StrictHostKeyChecking=no' rsync_cmd << ' -o UserKnownHostsFile=/dev/null' rsync_cmd << ' -o LogLevel=ERROR' rsync_cmd << " -p #{port}" rsync_cmd << '\'' rsync_cmd << " #{locals.join(' ')} root@#{ip}:#{remote}" `#{rsync_cmd}` rescue Errno::ENOENT debug 'Rsync is not installed. Falling back to SCP.' locals.each do |local| Net::SCP.upload!(ip, 'root', local, remote, recursive: true, ssh: { port: port, keys: ["#{tmpdir}/dokken/id_rsa"] }) end end end
def with_retries
def with_retries tries = 20 begin yield # Only catch errors that can be fixed with retries. rescue ::Docker::Error::ServerError, # 404 ::Docker::Error::UnexpectedResponseError, # 400 ::Docker::Error::TimeoutError, ::Docker::Error::IOError => e tries -= 1 retry if tries > 0 raise e end end
def work_image
def work_image return "#{image_prefix}/#{instance_name}" unless image_prefix.nil? instance_name end