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



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/dockly/build_cache/docker.rb', line 71

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')
  container.archive_out(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



85
86
87
88
89
90
91
92
# File 'lib/dockly/build_cache/docker.rb', line 85

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



94
95
96
97
98
99
100
101
102
# File 'lib/dockly/build_cache/docker.rb', line 94

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
# 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}"
    if safe_push_cache
      push_cache_safe(cache)
    else
      push_cache_with_volumes(cache)
    end
    debug "inserted cache into #{output_directory}"
    cache.close
  else
    info "could not find #{s3_object(version)}"
  end
end

#push_cache_safe(cache) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/dockly/build_cache/docker.rb', line 40

def push_cache_safe(cache)
  container = image.run("mkdir -p #{File.dirname(output_directory)}")
  image_with_dir = container.tap(&:wait).commit
  self.image = image_with_dir.insert_local(
    'localPath' => cache.path,
    'outputPath' => File.dirname(output_directory)
  )
end

#push_cache_with_volumes(cache) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/dockly/build_cache/docker.rb', line 49

def push_cache_with_volumes(cache)
  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', '-c', [
        "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
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



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dockly/build_cache/docker.rb', line 104

def run_command(command)
  debug "running command `#{command}` on image #{image.id}"
  container = image.run(["/bin/bash", "-c", "cd #{command_directory} && #{command}"])
  debug "command running in container #{container.id}"
  status = container.wait(docker.timeout)['StatusCode']
  resp = container.streaming_logs(stdout: true, stderr: true)
  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