1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
require "docker"
module Train::Transports
class Docker < Train.plugin(1)
name "docker"
include_options Train::Extras::CommandWrapper
option :host, required: true
def connection(state = {}, &block)
opts = merge_options(options, state || {})
validate_options(opts)
if @connection && @connection_options == opts
reuse_connection(&block)
else
create_new_connection(opts, &block)
end
end
private
# Creates a new Docker connection instance and save it for potential future
# reuse.
#
# @param options [Hash] connection options
# @return [Docker::Connection] a Docker connection instance
# @api private
def create_new_connection(options, &block)
if @connection
logger.debug("[Docker] shutting previous connection #{@connection}")
@connection.close
end
@connection_options = options
@connection = Connection.new(options, &block)
end
# Return the last saved Docker connection instance.
#
# @return [Docker::Connection] a Docker connection instance
# @api private
def reuse_connection
logger.debug("[Docker] reusing existing connection #{@connection}")
yield @connection if block_given?
@connection
end
end
end
class Train::Transports::Docker
class Connection < BaseConnection
def initialize(conf)
super(conf)
@id = options[:host]
@container = ::Docker::Container.get(@id) ||
raise("Can't find Docker container #{@id}")
@cmd_wrapper = nil
@cmd_wrapper = CommandWrapper.load(self, @options)
end
def close
# nothing to do at the moment
end
def uri
if @container.nil?
"docker://#{@id}"
else
"docker://#{@container.id}"
end
end
private
def file_via_connection(path)
if os.aix?
Train::File::Remote::Aix.new(self, path)
elsif os.solaris?
Train::File::Remote::Unix.new(self, path)
else
Train::File::Remote::Linux.new(self, path)
end
end
def run_command_via_connection(cmd, &_data_handler)
cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
stdout, stderr, exit_status = @container.exec(
[
"/bin/sh", "-c", cmd
]
)
CommandResult.new(stdout.join, stderr.join, exit_status)
rescue ::Docker::Error::DockerError => _
raise
rescue => _
# @TODO: differentiate any other error
raise
end
end
end
|