141 lines
4.0 KiB
Ruby
141 lines
4.0 KiB
Ruby
require "json"
|
|
|
|
require "log4r"
|
|
|
|
module VagrantPlugins
|
|
module DockerProvider
|
|
class Driver
|
|
# The executor is responsible for actually executing Docker commands.
|
|
# This is set by the provider, but defaults to local execution.
|
|
attr_accessor :executor
|
|
|
|
def initialize
|
|
@logger = Log4r::Logger.new("vagrant::docker::driver")
|
|
@executor = Executor::Local.new
|
|
end
|
|
|
|
def build(dir, **opts)
|
|
result = execute('docker', 'build', dir)
|
|
regexp = /Successfully built (.+)$/i
|
|
match = regexp.match(result)
|
|
if !match
|
|
# This will cause a stack trace in Vagrant, but it is a bug
|
|
# if this happens anyways.
|
|
raise "UNKNOWN OUTPUT: #{result}"
|
|
end
|
|
|
|
match[1]
|
|
end
|
|
|
|
def create(params, **opts, &block)
|
|
image = params.fetch(:image)
|
|
links = Array(params.fetch(:links))
|
|
ports = Array(params[:ports])
|
|
volumes = Array(params[:volumes])
|
|
name = params.fetch(:name)
|
|
cmd = Array(params.fetch(:cmd))
|
|
env = params.fetch(:env)
|
|
expose = Array(params[:expose])
|
|
|
|
run_cmd = %W(docker run --name #{name})
|
|
run_cmd << "-d" if params[:detach]
|
|
run_cmd += env.map { |k,v| ['-e', "#{k}=#{v}"] }
|
|
run_cmd += expose.map { |p| ['--expose', "#{p}"] }
|
|
run_cmd += links.map { |l| ['--link', "#{l}"] }
|
|
run_cmd += ports.map { |p| ['-p', p.to_s] }
|
|
run_cmd += volumes.map { |v| ['-v', v.to_s] }
|
|
run_cmd += %W(--privileged) if params[:privileged]
|
|
run_cmd += %W(-h #{params[:hostname]}) if params[:hostname]
|
|
run_cmd << "-i" << "-t" if params[:pty]
|
|
run_cmd += params[:extra_args] if params[:extra_args]
|
|
run_cmd += [image, cmd]
|
|
|
|
execute(*run_cmd.flatten, **opts, &block).chomp
|
|
end
|
|
|
|
def state(cid)
|
|
case
|
|
when running?(cid)
|
|
:running
|
|
when created?(cid)
|
|
:stopped
|
|
else
|
|
:not_created
|
|
end
|
|
end
|
|
|
|
def created?(cid)
|
|
result = execute('docker', 'ps', '-a', '-q', '--no-trunc').to_s
|
|
result =~ /^#{Regexp.escape cid}$/
|
|
end
|
|
|
|
def image?(id)
|
|
result = execute('docker', 'images', '-q').to_s
|
|
result =~ /^#{Regexp.escape(id)}$/
|
|
end
|
|
|
|
def running?(cid)
|
|
result = execute('docker', 'ps', '-q', '--no-trunc')
|
|
result =~ /^#{Regexp.escape cid}$/m
|
|
end
|
|
|
|
def privileged?(cid)
|
|
inspect_container(cid)['HostConfig']['Privileged']
|
|
end
|
|
|
|
def start(cid)
|
|
if !running?(cid)
|
|
execute('docker', 'start', cid)
|
|
# This resets the cached information we have around, allowing `vagrant reload`s
|
|
# to work properly
|
|
@data = nil
|
|
end
|
|
end
|
|
|
|
def stop(cid)
|
|
if running?(cid)
|
|
execute('docker', 'stop', '-t', '1', cid)
|
|
end
|
|
end
|
|
|
|
def rm(cid)
|
|
if created?(cid)
|
|
execute('docker', 'rm', '-v', cid)
|
|
end
|
|
end
|
|
|
|
def rmi(id)
|
|
execute('docker', 'rmi', id)
|
|
return true
|
|
rescue Exception => e
|
|
return false if e.to_s.include?("is using it")
|
|
raise if !e.to_s.include?("No such image")
|
|
end
|
|
|
|
def inspect_container(cid)
|
|
# DISCUSS: Is there a chance that this json will change after the container
|
|
# has been brought up?
|
|
@data ||= JSON.parse(execute('docker', 'inspect', cid)).first
|
|
end
|
|
|
|
def all_containers
|
|
execute('docker', 'ps', '-a', '-q', '--no-trunc').to_s.split
|
|
end
|
|
|
|
def docker_bridge_ip
|
|
output = execute('/sbin/ip', '-4', 'addr', 'show', 'scope', 'global', 'docker0')
|
|
if output =~ /^\s+inet ([0-9.]+)\/[0-9]+\s+/
|
|
return $1.to_s
|
|
else
|
|
# TODO: Raise an user friendly message
|
|
raise 'Unable to fetch docker bridge IP!'
|
|
end
|
|
end
|
|
|
|
def execute(*cmd, **opts, &block)
|
|
@executor.execute(*cmd, **opts, &block)
|
|
end
|
|
end
|
|
end
|
|
end
|