kitchen-dokken 2.9.1 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1cf6fdff38752942d8eb2ec416874255a581ce4d2e7607aa0aa10eccbe5c7c1e
4
- data.tar.gz: 5389972a3d453448c9206995302a76b6880ddfd39919cfd4f35661db83feb8f4
3
+ metadata.gz: 6e00103fefe2a49fd2630337f2a8d0bb0932484b770704b69c1fb31d9ddd0b42
4
+ data.tar.gz: 0acea78f249845712be9d1f97094f190369a1e15707ac559de27be5fc6c29e31
5
5
  SHA512:
6
- metadata.gz: 1c49b83d7bd26b2bd0e9feac76c6e36d70938ccb9e6e5a032c8fdb86ce2e28fae6f7fcee1687963035bbee34fd92ac92e9014ed08af7f7b12e812cf13af8eecb
7
- data.tar.gz: 1983818b9795b4af4294e585f58a0fd88ff048a8d2ca3ca28a39c279a063ba298526d9275258ec8ab9b8af38c8953b2dd468e7faa674fcf8de47add995a04b8a
6
+ metadata.gz: 0d84bd393b040ef4bc771a5d5c4448dff1860a9244d0818341f06c834e8133cbd9a77b0b7a4f697c8873be24b567083556f4feb47a57723782fe6575ad7b2a1a
7
+ data.tar.gz: b628d6bce7009efa94713c5c6032ec81e3258686c84f22ebd430e1710a1817cfaf3cb82420a8109e21f1506ff0e661c08da1e6fb2d5baedd6adbb216a0dedaa8
@@ -15,12 +15,12 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require 'digest'
19
- require 'kitchen'
20
- require 'tmpdir'
21
- require 'docker'
22
- require 'lockfile'
23
- require_relative '../helpers'
18
+ require "digest" unless defined?(Digest)
19
+ require "kitchen"
20
+ require "tmpdir" unless defined?(Dir.mktmpdir)
21
+ require "docker"
22
+ require "lockfile"
23
+ require_relative "../helpers"
24
24
 
25
25
  include Dokken::Helpers
26
26
 
@@ -37,30 +37,32 @@ module Kitchen
37
37
  default_config :binds, []
38
38
  default_config :cap_add, nil
39
39
  default_config :cap_drop, nil
40
- default_config :chef_image, 'chef/chef'
41
- default_config :chef_version, 'latest'
42
- default_config :data_image, 'dokken/kitchen-cache:latest'
40
+ default_config :chef_image, "chef/chef"
41
+ default_config :chef_version, "latest"
42
+ default_config :data_image, "dokken/kitchen-cache:latest"
43
43
  default_config :dns, nil
44
44
  default_config :dns_search, nil
45
+ default_config :docker_host_url, default_docker_host
45
46
  default_config :docker_info, docker_info
47
+ default_config :docker_registry, nil
46
48
  default_config :entrypoint, nil
47
49
  default_config :env, nil
48
- default_config :ports, nil
49
- default_config :docker_host_url, default_docker_host
50
- default_config :hostname, 'dokken'
50
+ default_config :hostname, "dokken"
51
51
  default_config :image_prefix, nil
52
52
  default_config :links, nil
53
- default_config :network_mode, 'dokken'
53
+ default_config :memory_limit, 0
54
+ default_config :network_mode, "dokken"
54
55
  default_config :pid_one_command, 'sh -c "trap exit 0 SIGTERM; while :; do sleep 1; done"'
56
+ default_config :ports, nil
55
57
  default_config :privileged, false
58
+ default_config :pull_chef_image, true
59
+ default_config :pull_platform_image, true
56
60
  default_config :read_timeout, 3600
57
61
  default_config :security_opt, nil
58
62
  default_config :tmpfs, {}
63
+ default_config :userns_host, false
59
64
  default_config :volumes, nil
60
65
  default_config :write_timeout, 3600
61
- default_config :userns_host, false
62
- default_config :pull_platform_image, true
63
- default_config :pull_chef_image, true
64
66
 
65
67
  # (see Base#create)
66
68
  def create(state)
@@ -125,37 +127,38 @@ module Kitchen
125
127
 
126
128
  def delete_work_image
127
129
  return unless ::Docker::Image.exist?(work_image, {}, docker_connection)
130
+
128
131
  with_retries { @work_image = ::Docker::Image.get(work_image, {}, docker_connection) }
129
132
 
130
133
  with_retries do
131
- begin
132
- with_retries { @work_image.remove(force: true) }
133
- rescue ::Docker::Error::ConflictError
134
- debug "driver - #{work_image} cannot be removed"
135
- end
134
+
135
+ with_retries { @work_image.remove(force: true) }
136
+ rescue ::Docker::Error::ConflictError
137
+ debug "driver - #{work_image} cannot be removed"
138
+
136
139
  end
137
140
  end
138
141
 
139
142
  def build_work_image(state)
140
- info('Building work image..')
143
+ info("Building work image..")
141
144
  return if ::Docker::Image.exist?(work_image, {}, docker_connection)
142
145
 
143
146
  begin
144
147
  @intermediate_image = ::Docker::Image.build(
145
148
  work_image_dockerfile,
146
149
  {
147
- 't' => work_image,
150
+ "t" => work_image,
148
151
  },
149
152
  docker_connection
150
153
  )
151
154
  # credit to https://github.com/someara/kitchen-dokken/issues/95#issue-224697526
152
155
  rescue Docker::Error::UnexpectedResponseError => e
153
- msg = 'work_image build failed: '
154
- msg += JSON.parse(e.to_s.split("\r\n").last)['error'].to_s
155
- msg += '. The common scenerios are incorrect intermediate'
156
- msg += 'instructions such as not including `-y` on an `apt-get` '
157
- msg += 'or similar. The other common scenerio is a transient '
158
- msg += 'error such as an unresponsive mirror.'
156
+ msg = "work_image build failed: "
157
+ msg += JSON.parse(e.to_s.split("\r\n").last)["error"].to_s
158
+ msg += ". The common scenarios are incorrect intermediate "
159
+ msg += "instructions such as not including `-y` on an `apt-get` "
160
+ msg += "or similar. The other common scenario is a transient "
161
+ msg += "error such as an unresponsive mirror."
159
162
  raise msg
160
163
  # fallback rescue above should catch most of the errors
161
164
  rescue => e
@@ -218,6 +221,7 @@ module Kitchen
218
221
 
219
222
  def work_image
220
223
  return "#{image_prefix}/#{instance_name}" unless image_prefix.nil?
224
+
221
225
  instance_name
222
226
  end
223
227
 
@@ -243,7 +247,7 @@ module Kitchen
243
247
  v
244
248
  else
245
249
  Array(v).each_with_object({}) do |y, h|
246
- name, opts = y.split(':', 2)
250
+ name, opts = y.split(":", 2)
247
251
  h[name.to_s] = opts.to_s
248
252
  end
249
253
  end
@@ -259,12 +263,13 @@ module Kitchen
259
263
  b = []
260
264
  v = Array(v).to_a # in case v.is_A?(Chef::Node::ImmutableArray)
261
265
  v.delete_if do |x|
262
- parts = x.split(':')
266
+ parts = x.split(":")
263
267
  b << x if parts.length > 1
264
268
  end
265
269
  b = nil if b.empty?
266
270
  config[:binds].push(b) unless config[:binds].include?(b) || b.nil?
267
271
  return PartialHash.new if v.empty?
272
+
268
273
  v.each_with_object(PartialHash.new) { |volume, h| h[volume] = {} }
269
274
  end
270
275
  end
@@ -280,40 +285,41 @@ module Kitchen
280
285
  debug "driver - starting #{runner_container_name}"
281
286
 
282
287
  config = {
283
- 'name' => runner_container_name,
284
- 'Cmd' => Shellwords.shellwords(self[:pid_one_command]),
285
- 'Image' => "#{repo(work_image)}:#{tag(work_image)}",
286
- 'Hostname' => self[:hostname],
287
- 'Env' => self[:env],
288
- 'ExposedPorts' => exposed_ports,
289
- 'Volumes' => dokken_volumes,
290
- 'HostConfig' => {
291
- 'Privileged' => self[:privileged],
292
- 'VolumesFrom' => dokken_volumes_from,
293
- 'Binds' => dokken_binds,
294
- 'Dns' => self[:dns],
295
- 'DnsSearch' => self[:dns_search],
296
- 'Links' => Array(self[:links]),
297
- 'CapAdd' => Array(self[:cap_add]),
298
- 'CapDrop' => Array(self[:cap_drop]),
299
- 'SecurityOpt' => Array(self[:security_opt]),
300
- 'NetworkMode' => self[:network_mode],
301
- 'PortBindings' => port_bindings,
302
- 'Tmpfs' => dokken_tmpfs,
288
+ "name" => runner_container_name,
289
+ "Cmd" => Shellwords.shellwords(self[:pid_one_command]),
290
+ "Image" => "#{repo(work_image)}:#{tag(work_image)}",
291
+ "Hostname" => self[:hostname],
292
+ "Env" => self[:env],
293
+ "ExposedPorts" => exposed_ports,
294
+ "Volumes" => dokken_volumes,
295
+ "HostConfig" => {
296
+ "Privileged" => self[:privileged],
297
+ "VolumesFrom" => dokken_volumes_from,
298
+ "Binds" => dokken_binds,
299
+ "Dns" => self[:dns],
300
+ "DnsSearch" => self[:dns_search],
301
+ "Links" => Array(self[:links]),
302
+ "CapAdd" => Array(self[:cap_add]),
303
+ "CapDrop" => Array(self[:cap_drop]),
304
+ "SecurityOpt" => Array(self[:security_opt]),
305
+ "NetworkMode" => self[:network_mode],
306
+ "PortBindings" => port_bindings,
307
+ "Tmpfs" => dokken_tmpfs,
308
+ "Memory" => self[:memory_limit],
303
309
  },
304
- 'NetworkingConfig' => {
305
- 'EndpointsConfig' => {
310
+ "NetworkingConfig" => {
311
+ "EndpointsConfig" => {
306
312
  self[:network_mode] => {
307
- 'Aliases' => Array(self[:hostname]),
313
+ "Aliases" => Array(self[:hostname]),
308
314
  },
309
315
  },
310
316
  },
311
317
  }
312
318
  unless self[:entrypoint].to_s.empty?
313
- config['Entrypoint'] = self[:entrypoint]
319
+ config["Entrypoint"] = self[:entrypoint]
314
320
  end
315
321
  if self[:userns_host]
316
- config['HostConfig']['UsernsMode'] = 'host'
322
+ config["HostConfig"]["UsernsMode"] = "host"
317
323
  end
318
324
  runner_container = run_container(config)
319
325
  state[:runner_container] = runner_container.json
@@ -322,17 +328,17 @@ module Kitchen
322
328
  def start_data_container(state)
323
329
  debug "driver - creating #{data_container_name}"
324
330
  config = {
325
- 'name' => data_container_name,
326
- 'Image' => "#{repo(data_image)}:#{tag(data_image)}",
327
- 'HostConfig' => {
328
- 'PortBindings' => port_bindings,
329
- 'PublishAllPorts' => true,
330
- 'NetworkMode' => 'bridge',
331
+ "name" => data_container_name,
332
+ "Image" => "#{repo(data_image)}:#{tag(data_image)}",
333
+ "HostConfig" => {
334
+ "PortBindings" => port_bindings,
335
+ "PublishAllPorts" => true,
336
+ "NetworkMode" => "bridge",
331
337
  },
332
- 'NetworkingConfig' => {
333
- 'EndpointsConfig' => {
338
+ "NetworkingConfig" => {
339
+ "EndpointsConfig" => {
334
340
  self[:network_mode] => {
335
- 'Aliases' => Array(self[:hostname]),
341
+ "Aliases" => Array(self[:hostname]),
336
342
  },
337
343
  },
338
344
  },
@@ -345,10 +351,10 @@ module Kitchen
345
351
  lockfile = Lockfile.new "#{home_dir}/.dokken-network.lock"
346
352
  begin
347
353
  lockfile.lock
348
- with_retries { ::Docker::Network.get('dokken', {}, docker_connection) }
354
+ with_retries { ::Docker::Network.get("dokken", {}, docker_connection) }
349
355
  rescue
350
356
  begin
351
- with_retries { ::Docker::Network.create('dokken', {}) }
357
+ with_retries { ::Docker::Network.create("dokken", {}) }
352
358
  rescue ::Docker::Error => e
353
359
  debug "driver - error :#{e}:"
354
360
  end
@@ -358,32 +364,39 @@ module Kitchen
358
364
  end
359
365
 
360
366
  def make_data_image
361
- debug 'driver - calling create_data_image'
362
- create_data_image
367
+ debug "driver - calling create_data_image"
368
+ create_data_image(config[:docker_registry])
363
369
  end
364
370
 
365
371
  def create_chef_container(state)
366
372
  lockfile = Lockfile.new "#{home_dir}/.dokken-#{chef_container_name}.lock"
367
373
  begin
368
374
  lockfile.lock
369
- with_retries { ::Docker::Container.get(chef_container_name, {}, docker_connection) }
375
+ with_retries {
376
+ # TEMPORARY FIX - docker-api 2.0.0 has a buggy Docker::Container.get - use .all instead
377
+ # https://github.com/swipely/docker-api/issues/566
378
+ # ::Docker::Container.get(chef_container_name, {}, docker_connection)
379
+ found = ::Docker::Container.all({ all: true }, docker_connection).select { |c| c.info["Names"].include?("/#{chef_container_name}") }
380
+ raise ::Docker::Error::NotFoundError.new(chef_container_name) if found.empty?
381
+
382
+ debug "Chef container already exists, continuing"
383
+ }
370
384
  rescue ::Docker::Error::NotFoundError
385
+ debug "Chef container does not exist, creating a new Chef container"
371
386
  with_retries do
372
- begin
373
- debug "driver - creating volume container #{chef_container_name} from #{chef_image}"
374
- config = {
375
- 'name' => chef_container_name,
376
- 'Cmd' => 'true',
377
- 'Image' => "#{repo(chef_image)}:#{tag(chef_image)}",
378
- 'HostConfig' => {
379
- 'NetworkMode' => self[:network_mode],
380
- },
381
- }
382
- chef_container = create_container(config)
383
- state[:chef_container] = chef_container.json
384
- rescue ::Docker::Error => e
385
- raise "driver - #{chef_container_name} failed to create #{e}"
386
- end
387
+ debug "driver - creating volume container #{chef_container_name} from #{chef_image}"
388
+ config = {
389
+ "name" => chef_container_name,
390
+ "Cmd" => "true",
391
+ "Image" => "#{repo(chef_image)}:#{tag(chef_image)}",
392
+ "HostConfig" => {
393
+ "NetworkMode" => self[:network_mode],
394
+ },
395
+ }
396
+ chef_container = create_container(config)
397
+ state[:chef_container] = chef_container.json
398
+ rescue ::Docker::Error => e
399
+ raise "driver - #{chef_container_name} failed to create #{e}"
387
400
  end
388
401
  ensure
389
402
  lockfile.unlock
@@ -414,13 +427,13 @@ module Kitchen
414
427
  end
415
428
 
416
429
  def parse_image_name(image)
417
- parts = image.split(':')
430
+ parts = image.split(":")
418
431
 
419
432
  if parts.size > 2
420
433
  tag = parts.pop
421
- repo = parts.join(':')
434
+ repo = parts.join(":")
422
435
  else
423
- tag = parts[1] || 'latest'
436
+ tag = parts[1] || "latest"
424
437
  repo = parts[0]
425
438
  end
426
439
 
@@ -432,27 +445,25 @@ module Kitchen
432
445
  end
433
446
 
434
447
  def create_container(args)
435
- with_retries { @container = ::Docker::Container.get(args['name'], {}, docker_connection) }
448
+ with_retries { @container = ::Docker::Container.get(args["name"], {}, docker_connection) }
436
449
  rescue
437
450
  with_retries do
438
- begin
439
- args['Env'] = [] if args['Env'].nil?
440
- args['Env'] << 'TEST_KITCHEN=1'
441
- args['Env'] << "CI=#{ENV['CI']}" if ENV.include? 'CI'
442
- info "Creating container #{args['name']}"
443
- debug "driver - create_container args #{args}"
444
- with_retries do
445
- begin
446
- @container = ::Docker::Container.create(args.clone, docker_connection)
447
- rescue ::Docker::Error::ConflictError
448
- debug "driver - rescue ConflictError: #{args['name']}"
449
- with_retries { @container = ::Docker::Container.get(args['name'], {}, docker_connection) }
450
- end
451
- end
452
- rescue ::Docker::Error => e
453
- debug "driver - error :#{e}:"
454
- raise "driver - failed to create_container #{args['name']}"
451
+ args["Env"] = [] if args["Env"].nil?
452
+ args["Env"] << "TEST_KITCHEN=1"
453
+ args["Env"] << "CI=#{ENV["CI"]}" if ENV.include? "CI"
454
+ info "Creating container #{args["name"]}"
455
+ debug "driver - create_container args #{args}"
456
+ with_retries do
457
+
458
+ @container = ::Docker::Container.create(args.clone, docker_connection)
459
+ rescue ::Docker::Error::ConflictError
460
+ debug "driver - rescue ConflictError: #{args["name"]}"
461
+ with_retries { @container = ::Docker::Container.get(args["name"], {}, docker_connection) }
455
462
  end
463
+ rescue ::Docker::Error => e
464
+ debug "driver - error :#{e}:"
465
+ raise "driver - failed to create_container #{args["name"]}"
466
+
456
467
  end
457
468
  end
458
469
 
@@ -460,14 +471,14 @@ module Kitchen
460
471
  create_container(args)
461
472
  with_retries do
462
473
  @container.start
463
- @container = ::Docker::Container.get(args['name'], {}, docker_connection)
464
- wait_running_state(args['name'], true)
474
+ @container = ::Docker::Container.get(args["name"], {}, docker_connection)
475
+ wait_running_state(args["name"], true)
465
476
  end
466
477
  @container
467
478
  end
468
479
 
469
480
  def container_state
470
- @container ? @container.info['State'] : {}
481
+ @container ? @container.info["State"] : {}
471
482
  end
472
483
 
473
484
  def stop_container(name)
@@ -491,9 +502,10 @@ module Kitchen
491
502
  @container = ::Docker::Container.get(name, {}, docker_connection)
492
503
  i = 0
493
504
  tries = 20
494
- until container_state['Running'] == v || container_state['FinishedAt'] != '0001-01-01T00:00:00Z'
505
+ until container_state["Running"] == v || container_state["FinishedAt"] != "0001-01-01T00:00:00Z"
495
506
  i += 1
496
507
  break if i == tries
508
+
497
509
  sleep 0.1
498
510
  @container = ::Docker::Container.get(name, {}, docker_connection)
499
511
  end
@@ -512,7 +524,8 @@ module Kitchen
512
524
  end
513
525
 
514
526
  def chef_version
515
- return 'latest' if config[:chef_version] == 'stable'
527
+ return "latest" if config[:chef_version] == "stable"
528
+
516
529
  config[:chef_version]
517
530
  end
518
531
 
@@ -529,27 +542,36 @@ module Kitchen
529
542
  end
530
543
 
531
544
  def platform_image_from_name
532
- platform, release = instance.platform.name.split('-')
533
- release ? [platform, release].join(':') : platform
545
+ platform, release = instance.platform.name.split("-")
546
+ release ? [platform, release].join(":") : platform
534
547
  end
535
548
 
536
549
  def pull_if_missing(image)
537
550
  return if ::Docker::Image.exist?("#{repo(image)}:#{tag(image)}", {}, docker_connection)
551
+
538
552
  pull_image image
539
553
  end
540
554
 
541
555
  # https://github.com/docker/docker/blob/4fcb9ac40ce33c4d6e08d5669af6be5e076e2574/registry/auth.go#L231
542
556
  def parse_registry_host(val)
543
- val.sub(%r{https?://}, '').split('/').first
557
+ val.sub(%r{https?://}, "").split("/").first
558
+ end
559
+
560
+ def image_path(image)
561
+ fqimage = "#{repo(image)}:#{tag(image)}"
562
+ if config[:docker_registry]
563
+ fqimage = "#{config[:docker_registry]}/#{fqimage}"
564
+ end
565
+ fqimage
544
566
  end
545
567
 
546
568
  def pull_image(image)
547
569
  with_retries do
548
- if Docker::Image.exist?("#{repo(image)}:#{tag(image)}", {}, docker_connection)
549
- original_image = Docker::Image.get("#{repo(image)}:#{tag(image)}", {}, docker_connection)
570
+ if Docker::Image.exist?(image_path(image), {}, docker_connection)
571
+ original_image = Docker::Image.get(image_path(image), {}, docker_connection)
550
572
  end
551
573
 
552
- new_image = Docker::Image.create({ 'fromImage' => "#{repo(image)}:#{tag(image)}" }, docker_connection)
574
+ new_image = Docker::Image.create({ "fromImage" => "#{repo(image)}:#{tag(image)}" }, docker_connection)
553
575
 
554
576
  !(original_image && original_image.id.start_with?(new_image.id))
555
577
  end
@@ -18,6 +18,6 @@
18
18
  module Kitchen
19
19
  module Driver
20
20
  # Version string for Dokken Kitchen driver
21
- DOKKEN_VERSION = '2.9.1'.freeze
21
+ DOKKEN_VERSION = "2.12.0".freeze
22
22
  end
23
23
  end
@@ -1,23 +1,20 @@
1
1
  module Dokken
2
2
  module Helpers
3
3
  # https://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-open
4
- require 'socket'
5
- require 'timeout'
4
+ require "socket" unless defined?(Socket)
5
+ require "timeout" unless defined?(Timeout)
6
6
 
7
7
  def port_open?(ip, port)
8
8
  begin
9
9
  Timeout.timeout(1) do
10
- begin
11
- s = TCPSocket.new(ip, port)
12
- s.close
13
- return true
14
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
15
- return false
16
- end
10
+ s = TCPSocket.new(ip, port)
11
+ s.close
12
+ return true
13
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ENETDOWN
14
+ return false
17
15
  end
18
16
  rescue Timeout::Error
19
17
  end
20
-
21
18
  false
22
19
  end
23
20
 
@@ -59,9 +56,13 @@ X8N2N9ZNnORJqK374yGj1jWUU66mQhPvn49QpG8P2HEoh2RQjNvyHA==
59
56
  EOF
60
57
  end
61
58
 
62
- def data_dockerfile
59
+ def data_dockerfile(registry)
60
+ from = "centos:7"
61
+ if registry
62
+ from = "#{registry}/#{from}"
63
+ end
63
64
  <<-EOF
64
- FROM centos:7
65
+ FROM #{from}
65
66
  MAINTAINER Sean OMeara \"sean@sean.io\"
66
67
  ENV LANG en_US.UTF-8
67
68
 
@@ -86,32 +87,32 @@ VOLUME /opt/verifier
86
87
  EOF
87
88
  end
88
89
 
89
- def create_data_image
90
+ def create_data_image(registry)
90
91
  return if ::Docker::Image.exist?(data_image)
91
92
 
92
93
  tmpdir = Dir.tmpdir
93
94
  FileUtils.mkdir_p "#{tmpdir}/dokken"
94
- File.write("#{tmpdir}/dokken/Dockerfile", data_dockerfile)
95
+ File.write("#{tmpdir}/dokken/Dockerfile", data_dockerfile(registry))
95
96
  File.write("#{tmpdir}/dokken/authorized_keys", insecure_ssh_public_key)
96
97
 
97
98
  i = ::Docker::Image.build_from_dir(
98
99
  "#{tmpdir}/dokken",
99
- 'nocache' => true,
100
- 'rm' => true
100
+ "nocache" => true,
101
+ "rm" => true
101
102
  )
102
- i.tag('repo' => repo(data_image), 'tag' => tag(data_image), 'force' => true)
103
+ i.tag("repo" => repo(data_image), "tag" => tag(data_image), "force" => true)
103
104
  end
104
105
 
105
106
  def default_docker_host
106
- if ENV['DOCKER_HOST']
107
- ENV['DOCKER_HOST']
108
- elsif File.exist?('/var/run/docker.sock')
109
- 'unix:///var/run/docker.sock'
107
+ if ENV["DOCKER_HOST"]
108
+ ENV["DOCKER_HOST"]
109
+ elsif File.exist?("/var/run/docker.sock")
110
+ "unix:///var/run/docker.sock"
110
111
  # TODO: Docker for Windows also operates over a named pipe at
111
112
  # //./pipe/docker_engine that can be used if named pipe support is
112
113
  # added to the docker-api gem.
113
114
  else
114
- 'tcp://127.0.0.1:2375'
115
+ "tcp://127.0.0.1:2375"
115
116
  end
116
117
  end
117
118
 
@@ -152,7 +153,8 @@ VOLUME /opt/verifier
152
153
  # refs:
153
154
  # https://github.com/docker/machine/issues/1814
154
155
  # https://github.com/docker/toolbox/issues/607
155
- return Dir.home.sub 'C:/Users', '/c/Users' if Dir.home =~ /^C:/ && remote_docker_host?
156
+ return Dir.home.sub "C:/Users", "/c/Users" if Dir.home =~ /^C:/ && remote_docker_host?
157
+
156
158
  Dir.home
157
159
  end
158
160
 
@@ -185,7 +187,7 @@ VOLUME /opt/verifier
185
187
  x = Array(v).map { |a| parse_port(a) }
186
188
  x.flatten!
187
189
  x.each_with_object({}) do |y, h|
188
- h[y['container_port']] = {}
190
+ h[y["container_port"]] = {}
189
191
  end
190
192
  end
191
193
  end
@@ -198,52 +200,53 @@ VOLUME /opt/verifier
198
200
  x = Array(v).map { |a| parse_port(a) }
199
201
  x.flatten!
200
202
  x.each_with_object({}) do |y, h|
201
- h[y['container_port']] = [] unless h[y['container_port']]
202
- h[y['container_port']] << {
203
- 'HostIp' => y['host_ip'],
204
- 'HostPort' => y['host_port'],
203
+ h[y["container_port"]] = [] unless h[y["container_port"]]
204
+ h[y["container_port"]] << {
205
+ "HostIp" => y["host_ip"],
206
+ "HostPort" => y["host_port"],
205
207
  }
206
208
  end
207
209
  end
208
210
  end
209
211
 
210
212
  def parse_port(v)
211
- parts = v.split(':')
213
+ parts = v.split(":")
212
214
  case parts.length
213
215
  when 3
214
216
  host_ip = parts[0]
215
217
  host_port = parts[1]
216
218
  container_port = parts[2]
217
219
  when 2
218
- host_ip = '0.0.0.0'
220
+ host_ip = "0.0.0.0"
219
221
  host_port = parts[0]
220
222
  container_port = parts[1]
221
223
  when 1
222
- host_ip = ''
223
- host_port = ''
224
+ host_ip = ""
225
+ host_port = ""
224
226
  container_port = parts[0]
225
227
  end
226
- port_range, protocol = container_port.split('/')
227
- if port_range.include?('-')
228
- port_range = container_port.split('-')
228
+ port_range, protocol = container_port.split("/")
229
+ if port_range.include?("-")
230
+ port_range = container_port.split("-")
229
231
  port_range.map!(&:to_i)
230
232
  Chef::Log.fatal("FATAL: Invalid port range! #{container_port}") if port_range[0] > port_range[1]
231
233
  port_range = (port_range[0]..port_range[1]).to_a
232
234
  end
233
235
  # qualify the port-binding protocol even when it is implicitly tcp #427.
234
- protocol = 'tcp' if protocol.nil?
236
+ protocol = "tcp" if protocol.nil?
235
237
  Array(port_range).map do |port|
236
238
  {
237
- 'host_ip' => host_ip,
238
- 'host_port' => host_port,
239
- 'container_port' => "#{port}/#{protocol}",
239
+ "host_ip" => host_ip,
240
+ "host_port" => host_port,
241
+ "container_port" => "#{port}/#{protocol}",
240
242
  }
241
243
  end
242
244
  end
243
245
 
244
246
  def remote_docker_host?
245
- return false if config[:docker_info]['OperatingSystem'].include?('Boot2Docker')
246
- return true if config[:docker_host_url] =~ /^tcp:/
247
+ return false if config[:docker_info]["OperatingSystem"].include?("Boot2Docker")
248
+ return true if /^tcp:/.match?(config[:docker_host_url])
249
+
247
250
  false
248
251
  end
249
252
 
@@ -252,13 +255,13 @@ VOLUME /opt/verifier
252
255
  end
253
256
 
254
257
  def sandbox_dirs
255
- Dir.glob(File.join(sandbox_path, '*'))
258
+ Dir.glob(File.join(sandbox_path, "*"))
256
259
  end
257
260
 
258
261
  def create_sandbox
259
262
  info("Creating kitchen sandbox in #{sandbox_path}")
260
263
  unless ::Dir.exist?(sandbox_path)
261
- FileUtils.mkdir_p(sandbox_path, :mode => 0o755)
264
+ FileUtils.mkdir_p(sandbox_path, mode: 0o755)
262
265
  end
263
266
  end
264
267
  end
@@ -269,7 +272,7 @@ module Kitchen
269
272
  class Base
270
273
  def create_sandbox
271
274
  info("Creating kitchen sandbox in #{sandbox_path}")
272
- FileUtils.mkdir_p(sandbox_path, :mode => 0o755)
275
+ FileUtils.mkdir_p(sandbox_path, mode: 0o755)
273
276
  end
274
277
 
275
278
  # this MUST be named 'sandbox_path' because ruby.
@@ -291,7 +294,7 @@ module Kitchen
291
294
  def create_sandbox
292
295
  info("Creating kitchen sandbox in #{sandbox_path}")
293
296
  unless ::Dir.exist?(sandbox_path)
294
- FileUtils.mkdir_p(sandbox_path, :mode => 0o755)
297
+ FileUtils.mkdir_p(sandbox_path, mode: 0o755)
295
298
  end
296
299
  end
297
300
 
@@ -313,7 +316,7 @@ module Kitchen
313
316
  conn.execute(init_command)
314
317
  info("Transferring files to #{instance.to_str}")
315
318
  conn.upload(sandbox_dirs, config[:root_path])
316
- debug('Transfer complete')
319
+ debug("Transfer complete")
317
320
  end
318
321
 
319
322
  conn.execute(prepare_command)
@@ -15,9 +15,9 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require 'kitchen'
19
- require 'kitchen/provisioner/chef_zero'
20
- require_relative '../helpers'
18
+ require "kitchen"
19
+ require "kitchen/provisioner/chef_zero"
20
+ require_relative "../helpers"
21
21
 
22
22
  include Dokken::Helpers
23
23
 
@@ -29,11 +29,12 @@ module Kitchen
29
29
 
30
30
  plugin_version Kitchen::VERSION
31
31
 
32
- default_config :root_path, '/opt/kitchen'
33
- default_config :chef_binary, '/opt/chef/bin/chef-client'
34
- default_config :chef_options, ' -z'
35
- default_config :chef_log_level, 'warn'
36
- default_config :chef_output_format, 'doc'
32
+ default_config :root_path, "/opt/kitchen"
33
+ default_config :chef_binary, "/opt/chef/bin/chef-client"
34
+ default_config :chef_options, " -z"
35
+ default_config :chef_log_level, "warn"
36
+ default_config :chef_output_format, "doc"
37
+ default_config :profile_ruby, false
37
38
  default_config :docker_info, docker_info
38
39
  default_config :docker_host_url, default_docker_host
39
40
 
@@ -45,7 +46,7 @@ module Kitchen
45
46
  # driver and set it here. If we remove this, users will set their chef_version
46
47
  # to 14 in the driver and still get prompted for license acceptance because
47
48
  # the ChefZero provisioner defaults product_version to 'latest'.
48
- default_config :product_name, 'chef'
49
+ default_config :product_name, "chef"
49
50
  default_config :product_version do |provisioner|
50
51
  driver = provisioner.instance.driver
51
52
  driver[:chef_version]
@@ -73,15 +74,16 @@ module Kitchen
73
74
  rescue Kitchen::Transport::TransportFailed => ex
74
75
  raise ActionFailed, ex.message
75
76
  ensure
76
- return unless config[:clean_dokken_sandbox]
77
+ return unless config[:clean_dokken_sandbox] # rubocop: disable Lint/EnsureReturn
78
+
77
79
  cleanup_dokken_sandbox
78
80
  end
79
81
 
80
82
  def validate_config
81
83
  # check if we have an space for the user provided options
82
84
  # or add it if not to avoid issues
83
- unless config[:chef_options].start_with? ' '
84
- config[:chef_options].prepend(' ')
85
+ unless config[:chef_options].start_with? " "
86
+ config[:chef_options].prepend(" ")
85
87
  end
86
88
 
87
89
  # strip spaces from all other options
@@ -91,8 +93,8 @@ module Kitchen
91
93
 
92
94
  # if the user wants to be funny and pass empty strings
93
95
  # just use the defaults
94
- config[:chef_log_level] = 'warn' if config[:chef_log_level].empty?
95
- config[:chef_output_format] = 'doc' if config[:chef_output_format].empty?
96
+ config[:chef_log_level] = "warn" if config[:chef_log_level].empty?
97
+ config[:chef_output_format] = "doc" if config[:chef_output_format].empty?
96
98
  end
97
99
 
98
100
  private
@@ -104,8 +106,9 @@ module Kitchen
104
106
  cmd << config[:chef_options].to_s
105
107
  cmd << " -l #{config[:chef_log_level]}"
106
108
  cmd << " -F #{config[:chef_output_format]}"
107
- cmd << ' -c /opt/kitchen/client.rb'
108
- cmd << ' -j /opt/kitchen/dna.json'
109
+ cmd << " -c /opt/kitchen/client.rb"
110
+ cmd << " -j /opt/kitchen/dna.json"
111
+ cmd << "--profile-ruby" if config[:profile_ruby]
109
112
 
110
113
  chef_cmd(cmd)
111
114
  end
@@ -15,11 +15,11 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require 'kitchen'
19
- require 'net/scp'
20
- require 'tmpdir'
21
- require 'digest/sha1'
22
- require_relative '../helpers'
18
+ require "kitchen"
19
+ require "net/scp"
20
+ require "tmpdir" unless defined?(Dir.mktmpdir)
21
+ require "digest/sha1" unless defined?(Digest::SHA1)
22
+ require_relative "../helpers"
23
23
 
24
24
  include Dokken::Helpers
25
25
 
@@ -44,7 +44,7 @@ module Kitchen
44
44
  default_config :read_timeout, 3600
45
45
  default_config :write_timeout, 3600
46
46
  default_config :host_ip_override do |transport|
47
- transport.docker_for_mac_or_win? ? 'localhost' : false
47
+ transport.docker_for_mac_or_win? ? "localhost" : false
48
48
  end
49
49
 
50
50
  # (see Base#connection)
@@ -69,7 +69,7 @@ module Kitchen
69
69
 
70
70
  with_retries { @runner = ::Docker::Container.get(instance_name, {}, docker_connection) }
71
71
  with_retries do
72
- o = @runner.exec(Shellwords.shellwords(command), wait: options[:timeout], 'e' => { 'TERM' => 'xterm' }) { |_stream, chunk| print chunk.to_s }
72
+ o = @runner.exec(Shellwords.shellwords(command), wait: options[:timeout], "e" => { "TERM" => "xterm" }) { |_stream, chunk| print chunk.to_s }
73
73
  @exit_code = o[2]
74
74
  end
75
75
 
@@ -82,26 +82,26 @@ module Kitchen
82
82
  ssh_ip = options[:host_ip_override]
83
83
  ssh_port = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostPort]
84
84
 
85
- elsif options[:docker_host_url] =~ /unix:/
86
- if options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostIp] == '0.0.0.0'
85
+ elsif /unix:/.match?(options[:docker_host_url])
86
+ if options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostIp] == "0.0.0.0"
87
87
  ssh_ip = options[:data_container][:NetworkSettings][:IPAddress]
88
- ssh_port = '22'
88
+ ssh_port = "22"
89
89
  else
90
90
  # we should read the proper mapped ip, since this allows us to upload the files
91
91
  ssh_ip = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostIp]
92
92
  ssh_port = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostPort]
93
93
  end
94
94
 
95
- elsif options[:docker_host_url] =~ /tcp:/
95
+ elsif /tcp:/.match?(options[:docker_host_url])
96
96
  name = options[:data_container][:Name]
97
97
 
98
98
  # DOCKER_HOST
99
- docker_host_url_ip = options[:docker_host_url].split('tcp://')[1].split(':')[0]
99
+ docker_host_url_ip = options[:docker_host_url].split("tcp://")[1].split(":")[0]
100
100
 
101
101
  # mapped IP of data container
102
- candidate_ip = ::Docker::Container.all.select do |x|
103
- x.info['Names'][0].eql?(name)
104
- end.first.info['NetworkSettings']['Networks']['dokken']['IPAddress']
102
+ candidate_ip = ::Docker::Container.all.find do |x|
103
+ x.info["Names"][0].eql?(name)
104
+ end.info["NetworkSettings"]["Networks"]["dokken"]["IPAddress"]
105
105
 
106
106
  # mapped port
107
107
  candidate_ssh_port = options[:data_container][:NetworkSettings][:Ports][:"22/tcp"][0][:HostPort]
@@ -114,22 +114,22 @@ module Kitchen
114
114
  ssh_ip = candidate_ip
115
115
  ssh_port = candidate_ssh_port
116
116
 
117
- elsif port_open?(candidate_ip, '22')
117
+ elsif port_open?(candidate_ip, "22")
118
118
  ssh_ip = candidate_ip
119
- ssh_port = '22'
119
+ ssh_port = "22"
120
120
  debug "candidate_ip - #{candidate_ip}/22 open"
121
121
  else
122
122
  ssh_ip = docker_host_url_ip
123
123
  ssh_port = candidate_ssh_port
124
124
  end
125
125
  else
126
- raise Kitchen::UserError, 'docker_host_url must be tcp:// or unix://'
126
+ raise Kitchen::UserError, "docker_host_url must be tcp:// or unix://"
127
127
  end
128
128
 
129
129
  debug "ssh_ip : #{ssh_ip}"
130
130
  debug "ssh_port : #{ssh_port}"
131
131
 
132
- tmpdir = Dir.tmpdir + '/dokken/'
132
+ tmpdir = Dir.tmpdir + "/dokken/"
133
133
  FileUtils.mkdir_p tmpdir.to_s, mode: 0o777
134
134
  tmpdir += Process.uid.to_s
135
135
  FileUtils.mkdir_p tmpdir.to_s
@@ -137,26 +137,26 @@ module Kitchen
137
137
  FileUtils.chmod(0o600, "#{tmpdir}/id_rsa")
138
138
 
139
139
  begin
140
- rsync_cmd = '/usr/bin/rsync -a -e'
141
- rsync_cmd << ' \''
142
- rsync_cmd << 'ssh -2'
140
+ rsync_cmd = "/usr/bin/rsync -a -e"
141
+ rsync_cmd << " '"
142
+ rsync_cmd << "ssh -2"
143
143
  rsync_cmd << " -i #{tmpdir}/id_rsa"
144
- rsync_cmd << ' -o CheckHostIP=no'
145
- rsync_cmd << ' -o Compression=no'
146
- rsync_cmd << ' -o PasswordAuthentication=no'
147
- rsync_cmd << ' -o StrictHostKeyChecking=no'
148
- rsync_cmd << ' -o UserKnownHostsFile=/dev/null'
149
- rsync_cmd << ' -o LogLevel=ERROR'
144
+ rsync_cmd << " -o CheckHostIP=no"
145
+ rsync_cmd << " -o Compression=no"
146
+ rsync_cmd << " -o PasswordAuthentication=no"
147
+ rsync_cmd << " -o StrictHostKeyChecking=no"
148
+ rsync_cmd << " -o UserKnownHostsFile=/dev/null"
149
+ rsync_cmd << " -o LogLevel=ERROR"
150
150
  rsync_cmd << " -p #{ssh_port}"
151
- rsync_cmd << '\''
152
- rsync_cmd << " #{locals.join(' ')} root@#{ssh_ip}:#{remote}"
151
+ rsync_cmd << "'"
152
+ rsync_cmd << " #{locals.join(" ")} root@#{ssh_ip}:#{remote}"
153
153
  debug "rsync_cmd :#{rsync_cmd}:"
154
154
  `#{rsync_cmd}`
155
155
  rescue Errno::ENOENT
156
- debug 'Rsync is not installed. Falling back to SCP.'
156
+ debug "Rsync is not installed. Falling back to SCP."
157
157
  locals.each do |local|
158
158
  Net::SCP.upload!(ssh_ip,
159
- 'root',
159
+ "root",
160
160
  local,
161
161
  remote,
162
162
  recursive: true,
@@ -169,8 +169,8 @@ module Kitchen
169
169
  @runner = options[:instance_name].to_s
170
170
  cols = `tput cols`
171
171
  lines = `tput lines`
172
- args = ['exec', '-e', "COLUMNS=#{cols}", '-e', "LINES=#{lines}", '-it', @runner, '/bin/bash', '-login', '-i']
173
- LoginCommand.new('docker', args)
172
+ args = ["exec", "-e", "COLUMNS=#{cols}", "-e", "LINES=#{lines}", "-it", @runner, "/bin/bash", "-login", "-i"]
173
+ LoginCommand.new("docker", args)
174
174
  end
175
175
 
176
176
  private
@@ -181,6 +181,7 @@ module Kitchen
181
181
 
182
182
  def work_image
183
183
  return "#{image_prefix}/#{instance_name}" unless image_prefix.nil?
184
+
184
185
  instance_name
185
186
  end
186
187
 
@@ -208,7 +209,7 @@ module Kitchen
208
209
  #
209
210
  # @return [TrueClass,FalseClass]
210
211
  def docker_for_mac_or_win?
211
- ::Docker.info(::Docker::Connection.new(config[:docker_host_url], {}))['Name'] == 'moby'
212
+ ::Docker.info(::Docker::Connection.new(config[:docker_host_url], {}))["Name"] == "moby"
212
213
  rescue
213
214
  false
214
215
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-dokken
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean OMeara
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-14 00:00:00.000000000 Z
11
+ date: 2021-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.33'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '1.33'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: lockfile
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -58,7 +64,8 @@ dependencies:
58
64
  - - "<"
59
65
  - !ruby/object:Gem::Version
60
66
  version: '3'
61
- description: A Test Kitchen Driver for Dokken
67
+ description: A Test Kitchen Driver for Docker & Chef Infra optimized for rapid testing
68
+ using Chef Infra docker images
62
69
  email:
63
70
  - sean@sean.io
64
71
  executables: []
@@ -83,16 +90,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
83
90
  requirements:
84
91
  - - ">="
85
92
  - !ruby/object:Gem::Version
86
- version: '0'
93
+ version: '2.5'
87
94
  required_rubygems_version: !ruby/object:Gem::Requirement
88
95
  requirements:
89
96
  - - ">="
90
97
  - !ruby/object:Gem::Version
91
98
  version: '0'
92
99
  requirements: []
93
- rubygems_version: 3.1.2
100
+ rubygems_version: 3.1.4
94
101
  signing_key:
95
102
  specification_version: 4
96
- summary: A Test Kitchen Driver that talks to the Docker Remote API and uses Volumes
97
- to produce sparse container images
103
+ summary: A Test Kitchen Driver for Docker & Chef Infra optimized for rapid testing
104
+ using Chef Infra docker images
98
105
  test_files: []