kitchen-dokken 2.9.1 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []