class SSHKit::Backend::Docker
Constants
- CONTAINER_MAP
- CONTAINER_WAIT_IO
Attributes
docker_open_stdin[RW]
Public Class Methods
find_container_by_host(host)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 19 def self.find_container_by_host(host) host.docker_options[:container] || CONTAINER_MAP[host.docker_host_id] end
new(host, &block)
click to toggle source
Calls superclass method
# File lib/sshkit/backend/docker.rb, line 23 def initialize(host, &block) super @container = nil end
Public Instance Methods
container()
click to toggle source
# File lib/sshkit/backend/docker.rb, line 28 def container @container and return @container if host.docker_options[:container] @container = host.docker_options[:container] else @container = docker_run_image host.hostname.chop! << ", container: #{@container})" end if host.respond_to? :roles_array host.hostname.chop! << ", roles: #{host.roles_array.inspect})" end @container end
docker_commit(host = nil)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 151 def docker_commit(host = nil) host ||= self.host if host.is_a?(String) commit_id = host host = _deep_dup(self.host) host.docker_options[:commit] = commit_id elsif host.is_a?(Hash) commit_info = host host = _deep_dup(self.host) host.docker_options[:commit] ||= {} host.docker_options[:commit].update commit_info.symbolize_keys end host.docker_options[:commit] or return container = self.class.find_container_by_host(host) or raise "Cannot find container for host #{host.inspect}" cmd = %w(docker commit) if host.docker_options[:image] # if container is delivered from image, recover USER and CMD. image_config = {} IO.popen ['docker', 'inspect', '-f', '{{json .Config}}', host.docker_options[:image]], 'rb' do |f| image_config = JSON.parse(f.read.chomp) end if image_config["User"].to_s.length > 1 cmd << '-c' << "USER #{image_config["User"]}" end c = image_config["Cmd"] if c[0] == "/bin/sh" && c[1] == "-c" c.shift; c.shift; end unless c.empty? cmd << '-c' << "CMD #{c.join(' ')}" end end image_name = host.docker_options[:commit] if image_name.is_a?(Hash) image_name.symbolize_keys.each do |key, val| if key == :name image_name = val else [*val].each do |v| cmd << "--#{key.to_s.tr('_', '-')}" << v end end end end cmd << container image_name == true or cmd << image_name image_hash = nil pid = nil IO.popen cmd, 'rb' do |f| pid = f.pid image_hash = f.gets end image_hash.nil? and output.error "Docker: Failed to get image hash. Commit may be failed!" image_hash.chomp! ret = image_name == true ? image_hash : image_name output.info "Docker: commit #{container} as #{ret}" ret end
docker_run_image(host = nil)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 101 def docker_run_image(host = nil) host ||= self.host if host.is_a?(String) image_name = host host_id = host.__id__ host = _deep_dup(self.host) host.docker_options[:image] = image_name host.docker_host_id = host_id elsif host.is_a?(Hash) d_opts = host host = _deep_dup(self.host) host.docker_options = d_opts.symbolize_keys host.docker_host_id = d_opts.__id__ end map_key = host.docker_host_id CONTAINER_MAP[map_key] and return CONTAINER_MAP[map_key] image_name = host.docker_options[:image] cmd = %w(docker run -i) host.docker_options.each do |key, val| %w(container image env env_file commit).member?(key.to_s) and next if %w(t tty h hostname attach d detach entrypoint rm).member?(key.to_s) output.warn "Docker: run option '#{key}' is filtered." next end [*val].each do |v| cmd << "--#{key.to_s.tr('_', '-')}" << v end end merged_env.each do |key, val| cmd << "-e" << "#{key}=#{val}" end cmd += [image_name, 'sh', '-c', "# SSHkit \n hostname; read _"] cmd.unshift('sudo') if Docker.config.use_sudo io = IO.popen cmd, 'r+b' cid = io.gets if cid.nil? output.fatal "Docker: Failed to run image #{image_name}" raise "Failed to get container ID! (cmd: #{cmd.inspect})" end at_exit { io.close } CONTAINER_WAIT_IO[map_key] = io CONTAINER_MAP[map_key] = cid.strip output.info "Docker: run new container #{CONTAINER_MAP[map_key]} from image #{image_name}" CONTAINER_MAP[map_key] end
download!(remote, local=nil, _options = {})
click to toggle source
# File lib/sshkit/backend/docker.rb, line 59 def download!(remote, local=nil, _options = {}) local_io = local local_io.nil? and local_io = File.basename(remote) local_io.is_a?(String) and local_io = File.open(local_io, 'wb') with_pty(false) do IO.popen(to_docker_cmd('cat', remote), 'rb') do |f| IO.copy_stream(f, local_io) end end local.nil? || local.is_a?(String) and local_io.close end
merged_env()
click to toggle source
# File lib/sshkit/backend/docker.rb, line 76 def merged_env menv = (SSHKit.config.default_env || {}).dup.symbolize_keys [*host.docker_options[:env_file]].each do |ef| File.foreach(ef) do |line| line.include? "=" or next key, val = line.chomp.split('=', 2) menv[key.strip.to_sym] = val.strip end end if host.docker_options[:env].is_a?(Hash) host.docker_options[:env].each do |key, val| menv[key.to_sym] = val end else [*host.docker_options[:env]].each do |e| key, val = e.split('=', 2) menv[key.strip.to_sym] = val.strip end end if menv[:rails_env] menv[:RAILS_ENV] = menv.delete(:rails_env) end menv end
to_docker_cmd(*args)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 222 def to_docker_cmd(*args) cmd = %w(docker exec) cmd << '-it' if Docker.config.pty cmd << '-i' if docker_open_stdin cmd << '-u' << host.username cmd << container cmd += args cmd.unshift('sudo') if Docker.config.use_sudo cmd end
upload!(local, remote, _options = {})
click to toggle source
# File lib/sshkit/backend/docker.rb, line 42 def upload!(local, remote, _options = {}) local_io = local local_io.is_a?(String) and local_io = File.open(local_io, 'rb') @docker_open_stdin = true with_pty(false) do IO.popen(to_docker_cmd('sh', '-c', "cat > '#{remote}'"), 'wb') do |f| IO.copy_stream(local_io, f) end end @docker_open_stdin = false local.is_a?(String) and local_io.close end
Private Instance Methods
_deep_dup(obj)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 273 def _deep_dup(obj) Marshal.load Marshal.dump(obj) end
execute_command(cmd)
click to toggle source
# File lib/sshkit/backend/docker.rb, line 244 def execute_command(cmd) output.log_command_start(cmd) cmd.started = Time.now Open3.popen3(*to_docker_cmd('sh', '-c', cmd.to_command)) do |stdin, stdout, stderr, wait_thr| stdout_thread = Thread.new do while (line = stdout.gets) do cmd.on_stdout(stdin, line) output.log_command_data(cmd, :stdout, line) end end stderr_thread = Thread.new do while (line = stderr.gets) do cmd.on_stderr(stdin, line) output.log_command_data(cmd, :stderr, line) end end stdout_thread.join stderr_thread.join cmd.exit_status = wait_thr.value.to_i output.log_command_exit(cmd) end end
with_pty(flag) { || ... }
click to toggle source
# File lib/sshkit/backend/docker.rb, line 234 def with_pty(flag) orig = Docker.config.pty Docker.config.pty = flag begin yield ensure Docker.config.pty = orig end end