class Dockershell

Public Class Methods

new(options) click to toggle source
# File lib/dockershell.rb, line 5
def initialize(options)
  @options = options
  @logger  = options[:logger]
  @gempath = File.expand_path('..', File.dirname(__FILE__))

  @options[:name] ||= wordgen
  @options[:fqdn] ||= "#{@options[:name]}.#{@options[:domain]}"
  @options[:profile][:volumes] ||= []

  @logger.formatter = proc do |severity, datetime, progname, msg|
    "#{datetime} #{severity.ljust(5)} [#{@options[:name]}] #{msg}\n"
  end
end

Public Instance Methods

detached_postrun() click to toggle source

This spawns a detached process to clean up. This is so it doesn't die when the parent is killed

# File lib/dockershell.rb, line 49
def detached_postrun
  @logger.info 'terminating and cleaning up.'
  cleaner = Process.fork do
    Process.setsid

    output, status = Open3.capture2e('docker', 'kill', @options[:name])
    @logger.debug output
    @logger.warn 'could not stop container' unless status.success?

    output, status = Open3.capture2e('docker', 'rm', '-f', @options[:name])
    @logger.debug output
    @logger.warn 'could not remove container' unless status.success?

    postrun
  end
  Process.detach cleaner
end
run!() click to toggle source
# File lib/dockershell.rb, line 19
def run!
  at_exit do
    detached_postrun
  end
  prerun
  create unless running?
  setup
  start
end
start() click to toggle source
# File lib/dockershell.rb, line 29
def start
  @logger.info 'starting Dockershell.'
  args = 'docker', 'exec', '-it', @options[:name], 'script', '-qc', 'bash', '/dev/null'
  bomb 'could not start container.' unless system(*args)
end

Private Instance Methods

bomb(message) click to toggle source
# File lib/dockershell.rb, line 120
def bomb(message)
  @logger.warn message
  raise "[#{@options[:name]}] #{message}"
end
create() click to toggle source
# File lib/dockershell.rb, line 90
def create
  @logger.info 'creating container.'
  args = [
    'docker', 'run',
    '--security-opt', 'seccomp=unconfined',
    '--stop-signal=SIGRTMIN+3',
    '--tmpfs', '/tmp', '--tmpfs', '/run',
    '--volume', '/sys/fs/cgroup:/sys/fs/cgroup:ro',
    '--hostname', "#{@options[:fqdn]}",
    '--name', @options[:name],
    "--add-host=puppet:#{@options[:docker][:ipaddr]}",
    '--expose=80', '-Ptd',
  ]

  formatvars = {
    :name => @options[:name],
    :fqdn => @options[:fqdn],
  }
  
  @options[:profile][:volumes].each do |volume|
    args << '--volume' << volume % formatvars
  end

  args << @options[:profile][:image] << '/sbin/init'

  output, status = Open3.capture2e(*args)
  @logger.debug output
  bomb 'could not create container.' unless status.success?
end
running?() click to toggle source
# File lib/dockershell.rb, line 68
def running?
  data = `docker ps -a`.split("\n")
  data.shift # remove column header

  names = data.map { |line| line.split.last }
  if names.include? @options[:name]
    output, status = Open3.capture2e('docker', 'inspect', @options[:name])
    bomb 'could not get container info.' unless status.success?

    info = JSON.parse(output)
    bomb 'multiple containers with this name exist.' unless info.size == 1

    info = info.first
    @logger.debug(info['State'].inspect)

    bomb 'Inconsistent Docker state.' unless info['State']['Running']
    true
  else
    false
  end
end
which(name) click to toggle source
# File lib/dockershell.rb, line 125
def which(name)
  ["/etc/dockershell/scripts/#{name}", "#{@gempath}/scripts/#{name}"].each do |path|
    return path if File.file? path and File.executable? path
  end
  nil
end
wordgen() click to toggle source
# File lib/dockershell.rb, line 132
def wordgen
  words = File.readlines("#{@gempath}/resources/places.txt").each { |l| l.chomp! }

  "#{words.sample}-#{words.sample}"
end