Class: Buildizer::Docker

Inherits:
Object
  • Object
show all
Defined in:
lib/buildizer/docker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(builder, cache: nil) ⇒ Docker

Returns a new instance of Docker.



6
7
8
9
# File 'lib/buildizer/docker.rb', line 6

def initialize(builder, cache: nil)
  @builder = builder
  @cache = cache
end

Instance Attribute Details

#builderObject (readonly)

Returns the value of attribute builder.



3
4
5
# File 'lib/buildizer/docker.rb', line 3

def builder
  @builder
end

#cacheObject (readonly)

Returns the value of attribute cache.



4
5
6
# File 'lib/buildizer/docker.rb', line 4

def cache
  @cache
end

Instance Method Details

#_make_cmd(cmd) ⇒ Object



205
206
207
# File 'lib/buildizer/docker.rb', line 205

def _make_cmd(cmd)
  Array(cmd).join('; ')
end

#_prepare_container_params(image, env: {}) ⇒ Object



177
178
179
180
181
182
183
184
185
186
# File 'lib/buildizer/docker.rb', line 177

def _prepare_container_params(image, env: {})
  image.extra_path.mkpath
  image.build_path.mkpath

  [*env.map {|k,v| "-e #{k}=#{v}"},
   "-v #{builder.buildizer.package_path}:#{container_package_mount_path}:ro",
   "-v #{image.extra_path}:#{container_extra_path}:ro",
   "-v #{image.build_path}:#{container_build_path}",
   image.name].compact
end

#_prepare_docker_opts(docker_opts) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/buildizer/docker.rb', line 188

def _prepare_docker_opts(docker_opts)
  docker_opts.map do |k, v|
    next if v.nil?

    to_opt = ->(value) {"--#{k}=#{value}"}
    if v.is_a? Array
      v.map(&to_opt)
    else
      to_opt[v]
    end
  end.flatten.compact
end

#_wrap_docker_command(cmd) ⇒ Object



201
202
203
# File 'lib/buildizer/docker.rb', line 201

def _wrap_docker_command(cmd)
  "/bin/bash -lec '#{_make_cmd(cmd)}'"
end

#cache_build_image(build_image, cache_image) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/buildizer/docker.rb', line 77

def cache_build_image(build_image, cache_image)
  builder.buildizer.command! "docker tag -f #{build_image.name} #{cache_image.name}",
                              desc: "Tag prepared build image #{build_image.name}" +
                                    " as cache image #{cache_image.name}"
  builder.buildizer.command! "docker push #{cache_image.name}",
                              desc: "Push cache image #{cache_image.name}"
end

#cache_login!Object

Raises:



47
48
49
50
51
52
53
54
55
56
# File 'lib/buildizer/docker.rb', line 47

def cache_login!
  raise Error, error: :logical_error, message: "no docker cache account info" unless cache

  cmd = ["docker login"]
  cmd << "--email=#{cache[:email]}" if cache[:email]
  cmd << "--username=#{cache[:user]}" if cache[:user]
  cmd << "--password=#{cache[:password]}" if cache[:password]
  cmd << "--server=#{cache[:server]}" if cache[:server]
  builder.buildizer.command! cmd.join(' '), desc: "Docker cache account login"
end

#cache_logout!Object

Raises:



58
59
60
61
# File 'lib/buildizer/docker.rb', line 58

def cache_logout!
  raise Error, error: :logical_error, message: "no docker cache account info" unless cache
  builder.buildizer.command! 'docker logout', desc: "Docker cache account logout"
end

#container_build_pathObject



111
112
113
# File 'lib/buildizer/docker.rb', line 111

def container_build_path
  Pathname.new('/build')
end

#container_extra_pathObject



115
116
117
# File 'lib/buildizer/docker.rb', line 115

def container_extra_path
  Pathname.new('/extra')
end

#container_package_archive_pathObject



103
104
105
# File 'lib/buildizer/docker.rb', line 103

def container_package_archive_path
  Pathname.new('/package.tar.gz')
end

#container_package_mount_pathObject



107
108
109
# File 'lib/buildizer/docker.rb', line 107

def container_package_mount_path
  Pathname.new('/.package')
end

#container_package_pathObject



99
100
101
# File 'lib/buildizer/docker.rb', line 99

def container_package_path
  Pathname.new('/package')
end

#make_build_image(target) ⇒ Object



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

def make_build_image(target)
  pull_cache_image(target.build_image, target.cache_image) if target.cache_image

  target.build_image.dockerfile_write!

  builder.buildizer.command! "docker build " +
                             "-t #{target.build_image.name} " +
                             "-f #{target.build_image.dockerfile_path} " +
                             "#{target.build_image.dockerfile_path.dirname}",
                              desc: "Build docker image #{target.build_image.name}"

  cache_build_image(target.build_image, target.cache_image) if target.cache_image
end

#new_os(name, version, **kwargs) ⇒ Object

Raises:



27
28
29
30
31
# File 'lib/buildizer/docker.rb', line 27

def new_os(name, version, **kwargs)
  klass = os_klass(name, version)
  raise Error, message: "unknown os '#{[name, version].compact.join('-')}'" unless klass
  klass.new(self, **kwargs)
end

#os_klass(name, version) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/buildizer/docker.rb', line 11

def os_klass(name, version)
  ({
    'ubuntu' => {
      '12.04' => Os::Ubuntu1204,
      '14.04' => Os::Ubuntu1404,
      '16.04' => Os::Ubuntu1604,
      nil => Os::Ubuntu1404,
    },
    'centos' => {
      'centos6' => Os::Centos6,
      'centos7' => Os::Centos7,
      nil => Os::Centos7,
    },
  }[name] || {})[version]
end

#pull_cache_image(build_image, cache_image) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/buildizer/docker.rb', line 63

def pull_cache_image(build_image, cache_image)
  pull_cache_res = builder.buildizer.command(
    "docker pull #{cache_image.name}",
     desc: "Try to pull docker cache image #{cache_image.name}"
  )
  if pull_cache_res.status.success?
    builder.buildizer.command! "docker tag -f #{cache_image.name} #{build_image.name}",
                                desc: "Tag cache image #{cache_image.name}" +
                                      " as prepared build image #{build_image.name}"
    builder.buildizer.command! "docker rmi #{cache_image.name}",
                                desc: "Remove cache image #{cache_image.name}"
  end
end

#run_container!(name: nil, image:, env: {}, desc: nil, docker_opts: {}) ⇒ Object



119
120
121
122
123
124
125
126
127
128
# File 'lib/buildizer/docker.rb', line 119

def run_container!(name: nil, image:, env: {}, desc: nil, docker_opts: {})
  (name || SecureRandom.uuid).tap do |name|
    builder.buildizer.command! [
      "docker run --detach --name #{name}",
      *Array(_prepare_docker_opts(docker_opts)),
      *Array(_prepare_container_params(image, env: env)),
      _wrap_docker_command("while true ; do sleep 1 ; done"),
    ].join(' '), desc: desc
  end
end

#run_in_container(container:, cmd:, desc: nil, cmd_opts: {}, docker_opts: {}) ⇒ Object



148
149
150
151
152
153
154
155
# File 'lib/buildizer/docker.rb', line 148

def run_in_container(container:, cmd:, desc: nil, cmd_opts: {}, docker_opts: {})
  builder.buildizer.command [
    "docker exec",
    *Array(_prepare_docker_opts(docker_opts)),
    container,
    _wrap_docker_command(cmd),
  ].join(' '), timeout: 24*60*60, desc: desc, **cmd_opts
end

#run_in_container!(cmd_opts: {}, **kwargs) ⇒ Object



157
158
159
160
161
# File 'lib/buildizer/docker.rb', line 157

def run_in_container!(cmd_opts: {}, **kwargs)
  cmd_opts[:do_raise] = true
  cmd_opts[:log_failure] = true
  run_in_container(cmd_opts: cmd_opts, **kwargs)
end

#run_in_image(image:, cmd:, env: {}, desc: nil, cmd_opts: {}, docker_opts: {}) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/buildizer/docker.rb', line 163

def run_in_image(image:, cmd:, env: {}, desc: nil, cmd_opts: {}, docker_opts: {})
  builder.buildizer.command [
    "docker run --rm",
    *Array(_prepare_docker_opts(docker_opts)),
    *Array(_prepare_container_params(image, env: env)),
    _wrap_docker_command(cmd),
  ].join(' '), timeout: 24*60*60, desc: desc, **cmd_opts
end

#run_in_image!(cmd_opts: {}, **kwargs) ⇒ Object



172
173
174
175
# File 'lib/buildizer/docker.rb', line 172

def run_in_image!(cmd_opts: {}, **kwargs)
  cmd_opts[:do_raise] = true
  run_in_image(cmd_opts: cmd_opts, **kwargs)
end

#shell_in_container(container:) ⇒ Object



144
145
146
# File 'lib/buildizer/docker.rb', line 144

def shell_in_container(container:)
  system "docker exec -ti #{container} bash -lec 'cd #{container_package_mount_path}; bash'"
end

#shutdown_container!(container:) ⇒ Object



130
131
132
133
# File 'lib/buildizer/docker.rb', line 130

def shutdown_container!(container:)
  builder.buildizer.command! "docker kill #{container}", desc: "Kill container '#{container}'"
  builder.buildizer.command! "docker rm #{container}", desc: "Remove container '#{container}'"
end

#with_cache(&blk) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/buildizer/docker.rb', line 33

def with_cache(&blk)
  builder.buildizer.warn "No docker cache account settings " +
                         "(BUILDIZER_DOCKER_CACHE, BUILDIZER_DOCKER_CACHE_USERNAME," +
                         " BUILDIZER_DOCKER_CACHE_PASSWORD, BUILDIZER_DOCKER_CACHE_EMAIL," +
                         " BUILDIZER_DOCKER_CACHE_SERVER)" unless cache

  cache_login! if cache
  begin
    yield if block_given?
  ensure
    cache_logout! if cache
  end
end

#with_container(**kwargs, &blk) ⇒ Object



135
136
137
138
139
140
141
142
# File 'lib/buildizer/docker.rb', line 135

def with_container(**kwargs, &blk)
  container = run_container!(**kwargs)
  begin
    yield container if block_given?
  ensure
    shutdown_container!(container: container)
  end
end