Class: Dockly::BuildCache::Docker

Inherits:
Base
  • Object
show all
Defined in:
lib/dockly/build_cache/docker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#base_directory, #command_directory, #connection, #file_output, #insert_cache, #insert_latest, #output_directory, #parameter_command, #pull_from_s3, #push_to_s3, #s3_object, #up_to_date?

Instance Attribute Details

#imageObject

Returns the value of attribute image.



2
3
4
# File 'lib/dockly/build_cache/docker.rb', line 2

def image
  @image
end

Instance Method Details

#copy_output_dir(container) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/dockly/build_cache/docker.rb', line 54

def copy_output_dir(container)
  ensure_present! :output_dir
  file_path = File.join(tmp_dir,s3_object(hash_output))
  FileUtils.mkdir_p(File.dirname(file_path))
  file = File.open(file_path, 'w+b')
  container.wait(3600) # 1 hour max timeout
  debug 'Restarting the container to copy the cache\'s output'
  # Restart the container so we can copy its output
  container = container.commit.run('sleep 3600').tap(&:start)
  container.copy(output_directory) { |chunk| file.write(chunk.to_s) }
  container.kill
  file.tap(&:rewind)
end

#execute!Object



4
5
6
7
8
# File 'lib/dockly/build_cache/docker.rb', line 4

def execute!
  ensure_present! :image
  super
  image
end

#hash_outputObject



68
69
70
71
72
73
74
75
# File 'lib/dockly/build_cache/docker.rb', line 68

def hash_output
  ensure_present! :image, :hash_command
  @hash_output ||= begin
    status, body, _ = run_command(hash_command)
    raise "Hash Command `#{hash_command}` failed to run" unless status.zero?
    body
  end
end

#parameter_output(command) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/dockly/build_cache/docker.rb', line 77

def parameter_output(command)
  ensure_present! :image
  raise "Parameter Command tried to run but not found" unless parameter_commands.keys.include?(command)
  @parameter_commands[command] ||= begin
    status, body, _ = run_command(command)
    raise "Parameter Command `#{command}` failed to run" unless status.zero?
    body
  end
end

#push_cache(version) ⇒ Object



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
# File 'lib/dockly/build_cache/docker.rb', line 24

def push_cache(version)
  ensure_present! :output_dir
  if cache = pull_from_s3(version)
    debug "inserting to #{output_directory}"
    path = File.expand_path(cache.path)
    path_parent = File.dirname(path)
    tar_flags = keep_old_files ? '-xkf' : 'xf'
    container = ::Docker::Container.create(
      'Image' => image.id,
      'Cmd' => ['/bin/bash', '-lc', [
          "mkdir -p #{File.dirname(output_directory)}",
          '&&',
          "tar #{tar_flags} #{File.join('/', 'host', path)} -C #{File.dirname(output_directory)}"
        ].join(' ')
      ],
      'Volumes' => {
        File.join('/', 'host', path_parent) => { path_parent => 'rw' }
      }
    )
    container.start('Binds' => ["#{path_parent}:#{File.join('/', 'host', path_parent)}"])
    result = container.wait['StatusCode']
    raise "Got bad status code when copying build cache: #{result}" unless result.zero?
    self.image = container.commit
    debug "inserted cache into #{output_directory}"
    cache.close
  else
    info "could not find #{s3_object(version)}"
  end
end

#run_buildObject



10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/dockly/build_cache/docker.rb', line 10

def run_build
  status, _, container = run_command(build_command)
  raise "Build Cache `#{build_command}` failed to run." unless status.zero?
  cache = copy_output_dir(container)
  debug "pushing #{output_directory} to s3"
  push_to_s3(cache)
  debug "pushed #{output_directory} to s3"
  cache.close
  debug "commiting the completed container with id: #{container.id}"
  image = self.image = container.commit
  debug "created image with id: #{image.id}"
  image
end

#run_command(command) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/dockly/build_cache/docker.rb', line 87

def run_command(command)
  resp = ""
  debug "running command `#{command}` on image #{image.id}"
  container = image.run(["/bin/bash", "-lc", "cd #{command_directory} && #{command}"])
  container.attach { |source,chunk| resp += chunk }
  status = container.wait['StatusCode']
  debug "`#{command}` returned the following output:"
  debug resp.strip
  debug "`#{command}` exited with status #{status}, resulting container id: #{container.id}"
  [status, resp.strip, container]
end