kitchen-dokken 2.19.1 → 2.20.1

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: be2c8c44ba41e769729ee777daf91a2d2392c923b350f8fc359305deb75c8ae6
4
- data.tar.gz: fe6adeaea1645fc26ab1117de9af06e2a212483f782d62da01a77634d03c18e3
3
+ metadata.gz: ac52c253c019253b9fe2cffdbf603ce33647e51aacb8376ae775b2158ed0ca5e
4
+ data.tar.gz: be18132016e30bae541416a33e88846d2e1a9cb72849fe3fb80d9a0b1c0941a6
5
5
  SHA512:
6
- metadata.gz: c26fc34a7c0f00c29031300be0d2d4af57fe2b3987fe543d2630588c917c4b1adef8252d737c01adc031a3a2e4329e0d5ae1a0a2291d4714f5146faffe3eb9a9
7
- data.tar.gz: 4c7235960fda3df63e8111c6a0e02ee79a3c50de37582c442b525cf61dbb685637378b8804b27075c1989e7a7929131cc922786d5ba4800116ae8e7641d085f4
6
+ metadata.gz: 01f86365eecc3ad220c0ac09e561b76fd85d47de80447ef60234ab21e0ca00549fc88b13771a1328398953c47a87cab2ee5cfddcca32b0fb1e8186ee34ba1d7e
7
+ data.tar.gz: dab5b5621092142df080ed34ad3d73449964c067ed65600cc45efed62b527da41e40da3e13c20915d07d0e0cf7c96a4a602b3cfd6efaf2b06e47b100841f67be
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in kitchen-dokken.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem "berkshelf"
8
+ gem "kitchen-inspec"
9
+ gem "rake", ">= 11.0"
10
+ end
11
+
12
+ group :development do
13
+ gem "pry"
14
+ gem "pry-byebug"
15
+ end
16
+
17
+ group :chefstyle do
18
+ gem "chefstyle", "2.2.3"
19
+ end
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "chefstyle"
3
+ require "rubocop/rake_task"
4
+
5
+ RuboCop::RakeTask.new(:style) do |task|
6
+ task.options += ["--display-cop-names", "--no-color"]
7
+ end
8
+
9
+ task default: %i{style}
@@ -0,0 +1,23 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "kitchen/driver/dokken_version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "kitchen-dokken"
7
+ spec.version = Kitchen::Driver::DOKKEN_VERSION
8
+ spec.authors = ["Sean OMeara"]
9
+ spec.email = ["sean@sean.io"]
10
+ spec.description = "A Test Kitchen Driver for Docker & Chef Infra optimized for rapid testing using Chef Infra docker images"
11
+ spec.summary = "A Test Kitchen Driver for Docker & Chef Infra optimized for rapid testing using Chef Infra docker images"
12
+ spec.homepage = "https://github.com/test-kitchen/kitchen-dokken"
13
+ spec.license = "Apache-2.0"
14
+
15
+ spec.files = %w{LICENSE kitchen-dokken.gemspec Gemfile Rakefile} + Dir.glob("lib/**/*")
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.required_ruby_version = ">= 2.7"
19
+
20
+ spec.add_dependency "docker-api", ">= 1.33", "< 3"
21
+ spec.add_dependency "lockfile", "~> 2.1"
22
+ spec.add_dependency "test-kitchen", ">= 1.15", "< 4"
23
+ end
@@ -69,6 +69,7 @@ module Kitchen
69
69
  default_config :userns_host, false
70
70
  default_config :volumes, nil
71
71
  default_config :write_timeout, 3600
72
+ default_config :user_ns_mode, nil
72
73
  default_config :creds_file, nil
73
74
  default_config :docker_config_creds, false
74
75
 
@@ -90,7 +91,7 @@ module Kitchen
90
91
  # data
91
92
  dokken_create_sandbox
92
93
 
93
- if remote_docker_host?
94
+ if remote_docker_host? || running_inside_docker?
94
95
  make_data_image
95
96
  start_data_container state
96
97
  end
@@ -106,7 +107,7 @@ module Kitchen
106
107
  end
107
108
 
108
109
  def destroy(_state)
109
- if remote_docker_host?
110
+ if remote_docker_host? || running_inside_docker?
110
111
  stop_data_container
111
112
  delete_data_container
112
113
  end
@@ -232,27 +233,13 @@ module Kitchen
232
233
  end
233
234
 
234
235
  def work_image
235
- return "#{image_prefix}/#{instance_name}" unless image_prefix.nil?
236
-
237
- instance_name
238
- end
239
-
240
- def dokken_binds
241
- ret = []
242
- ret << "#{dokken_kitchen_sandbox}:/opt/kitchen" unless dokken_kitchen_sandbox.nil? || remote_docker_host?
243
- ret << "#{dokken_verifier_sandbox}:/opt/verifier" unless dokken_verifier_sandbox.nil? || remote_docker_host?
244
- ret << Array(config[:binds]) unless config[:binds].nil?
245
- ret.flatten
236
+ [image_prefix, instance_name].compact.join("/").downcase
246
237
  end
247
238
 
248
239
  def dokken_tmpfs
249
240
  coerce_tmpfs(config[:tmpfs])
250
241
  end
251
242
 
252
- def dokken_volumes
253
- coerce_volumes(config[:volumes])
254
- end
255
-
256
243
  def coerce_tmpfs(v)
257
244
  case v
258
245
  when Hash, nil
@@ -265,7 +252,14 @@ module Kitchen
265
252
  end
266
253
  end
267
254
 
268
- def coerce_volumes(v)
255
+ def dokken_volumes_from
256
+ ret = []
257
+ ret << chef_container_name
258
+ ret << data_container_name if remote_docker_host? || running_inside_docker?
259
+ ret
260
+ end
261
+
262
+ def coerce_volumes(v, binds)
269
263
  case v
270
264
  when PartialHash, nil
271
265
  v
@@ -273,29 +267,38 @@ module Kitchen
273
267
  PartialHash[v]
274
268
  else
275
269
  b = []
276
- v = Array(v).to_a # in case v.is_A?(Chef::Node::ImmutableArray)
277
270
  v.delete_if do |x|
278
271
  parts = x.split(":")
279
272
  b << x if parts.length > 1
280
273
  end
281
274
  b = nil if b.empty?
282
- config[:binds].push(b) unless config[:binds].include?(b) || b.nil?
275
+ binds.push(b) unless binds.include?(b) || b.nil?
283
276
  return PartialHash.new if v.empty?
284
277
 
285
278
  v.each_with_object(PartialHash.new) { |volume, h| h[volume] = {} }
286
279
  end
287
280
  end
288
281
 
289
- def dokken_volumes_from
290
- ret = []
291
- ret << chef_container_name
292
- ret << data_container_name if remote_docker_host?
293
- ret
282
+ def calc_volumes_binds
283
+ volumes = Array.new(Array(config[:volumes]))
284
+ binds = Array.new(Array(config[:binds]))
285
+
286
+ # Binds is mutated in-place, volumes *may* be.
287
+ volumes = coerce_volumes(volumes, binds)
288
+
289
+ binds_ret = []
290
+ binds_ret << "#{dokken_kitchen_sandbox}:/opt/kitchen" unless dokken_kitchen_sandbox.nil? || remote_docker_host? || running_inside_docker?
291
+ binds_ret << "#{dokken_verifier_sandbox}:/opt/verifier" unless dokken_verifier_sandbox.nil? || remote_docker_host? || running_inside_docker?
292
+ binds_ret << binds unless binds.nil?
293
+
294
+ [volumes, binds_ret.flatten]
294
295
  end
295
296
 
296
297
  def start_runner_container(state)
297
298
  debug "driver - starting #{runner_container_name}"
298
299
 
300
+ volumes, binds = calc_volumes_binds
301
+
299
302
  config = {
300
303
  "name" => runner_container_name,
301
304
  "Cmd" => Shellwords.shellwords(self[:pid_one_command]),
@@ -304,11 +307,11 @@ module Kitchen
304
307
  "Hostname" => self[:hostname],
305
308
  "Env" => self[:env],
306
309
  "ExposedPorts" => exposed_ports,
307
- "Volumes" => dokken_volumes,
310
+ "Volumes" => volumes,
308
311
  "HostConfig" => {
309
312
  "Privileged" => self[:privileged],
310
313
  "VolumesFrom" => dokken_volumes_from,
311
- "Binds" => dokken_binds,
314
+ "Binds" => binds,
312
315
  "Dns" => self[:dns],
313
316
  "DnsSearch" => self[:dns_search],
314
317
  "Links" => Array(self[:links]),
@@ -320,14 +323,16 @@ module Kitchen
320
323
  "Tmpfs" => dokken_tmpfs,
321
324
  "Memory" => self[:memory_limit],
322
325
  },
323
- "NetworkingConfig" => {
326
+ }
327
+ unless %w{host bridge}.include?(self[:network_mode])
328
+ config["NetworkingConfig"] = {
324
329
  "EndpointsConfig" => {
325
330
  self[:network_mode] => {
326
331
  "Aliases" => Array(self[:hostname]).concat(Array(self[:hostname_aliases])),
327
332
  },
328
333
  },
329
- },
330
- }
334
+ }
335
+ end
331
336
  unless self[:entrypoint].to_s.empty?
332
337
  config["Entrypoint"] = self[:entrypoint]
333
338
  end
@@ -337,6 +342,15 @@ module Kitchen
337
342
  if self[:userns_host]
338
343
  config["HostConfig"]["UsernsMode"] = "host"
339
344
  end
345
+
346
+ if self[:privileged]
347
+ if self[:user_ns_mode] != "host"
348
+ debug "driver - privileged mode is not supported with user namespaces enabled"
349
+ debug "driver - changing UsernsMode from '#{self[:user_ns_mode]}' to 'host'"
350
+ end
351
+ config["HostConfig"]["UsernsMode"] = "host"
352
+ end
353
+
340
354
  runner_container = run_container(config)
341
355
  state[:runner_container] = runner_container.json
342
356
  end
@@ -352,19 +366,23 @@ module Kitchen
352
366
  "PublishAllPorts" => true,
353
367
  "NetworkMode" => "bridge",
354
368
  },
355
- "NetworkingConfig" => {
369
+ }
370
+ unless %w{host bridge}.include?(self[:network_mode])
371
+ config["NetworkingConfig"] = {
356
372
  "EndpointsConfig" => {
357
373
  self[:network_mode] => {
358
374
  "Aliases" => Array(self[:hostname]),
359
375
  },
360
376
  },
361
- },
362
- }
377
+ }
378
+ end
363
379
  data_container = run_container(config)
364
380
  state[:data_container] = data_container.json
365
381
  end
366
382
 
367
383
  def make_dokken_network
384
+ return unless self[:network_mode] == "dokken"
385
+
368
386
  lockfile = Lockfile.new "#{home_dir}/.dokken-network.lock"
369
387
  begin
370
388
  lockfile.lock
@@ -441,11 +459,23 @@ module Kitchen
441
459
  @docker_config_creds = {}
442
460
  config_file = ::File.join(::Dir.home, ".docker", "config.json")
443
461
  if ::File.exist?(config_file)
444
- JSON.load_file!(config_file)["auths"].each do |k, v|
445
- next if v["auth"].nil?
462
+ config = JSON.load_file!(config_file)
463
+ if config["auths"]
464
+ config["auths"].each do |k, v|
465
+ next if v["auth"].nil?
466
+
467
+ username, password = Base64.decode64(v["auth"]).split(":")
468
+ @docker_config_creds[k] = { serveraddress: k, username: username, password: password }
469
+ end
470
+ end
446
471
 
447
- username, password = Base64.decode64(v["auth"]).split(":")
448
- @docker_config_creds[k] = { serveraddress: k, username: username, password: password }
472
+ if config["credHelpers"]
473
+ config["credHelpers"].each do |k, v|
474
+ @docker_config_creds[k] = Proc.new do
475
+ c = JSON.parse(`echo #{k} | docker-credential-#{v} get`)
476
+ { serveraddress: c["ServerURL"], username: c["Username"], password: c["Secret"] }
477
+ end
478
+ end
449
479
  end
450
480
  else
451
481
  debug("~/.docker/config.json does not exist")
@@ -462,7 +492,8 @@ module Kitchen
462
492
  # NOTE: Try to use DockerHub auth if exact registry match isn't found
463
493
  default_registry = "https://index.docker.io/v1/"
464
494
  if docker_config_creds.key?(image_registry)
465
- docker_config_creds[image_registry]
495
+ c = docker_config_creds[image_registry]
496
+ c.respond_to?(:call) ? c.call : c
466
497
  elsif docker_config_creds.key?(default_registry)
467
498
  docker_config_creds[default_registry]
468
499
  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.19.1".freeze
21
+ DOKKEN_VERSION = "2.20.1".freeze
22
22
  end
23
23
  end
@@ -3,6 +3,7 @@ module Dokken
3
3
  # https://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-open
4
4
  require "socket" unless defined?(Socket)
5
5
  require "timeout" unless defined?(Timeout)
6
+ require "resolv" unless defined?(Resolv)
6
7
 
7
8
  def port_open?(ip, port)
8
9
  begin
@@ -170,7 +171,7 @@ module Dokken
170
171
 
171
172
  def instance_name
172
173
  prefix = (Digest::SHA2.hexdigest FileUtils.pwd)[0, 10]
173
- "#{prefix}-#{instance.name}"
174
+ "#{prefix}-#{instance.name}".downcase
174
175
  end
175
176
 
176
177
  def exposed_ports
@@ -268,6 +269,17 @@ module Dokken
268
269
  false
269
270
  end
270
271
 
272
+ def running_inside_docker?
273
+ File.file?("/.dockerenv")
274
+ end
275
+
276
+ def running_inside_docker_desktop?
277
+ Resolv.getaddress "host.docker.internal."
278
+ true
279
+ rescue
280
+ false
281
+ end
282
+
271
283
  def sandbox_path
272
284
  "#{Dir.home}/.dokken/verifier_sandbox/#{instance_name}"
273
285
  end
@@ -300,7 +312,7 @@ module Kitchen
300
312
 
301
313
  def instance_name
302
314
  prefix = (Digest::SHA2.hexdigest FileUtils.pwd)[0, 10]
303
- "#{prefix}-#{instance.name}"
315
+ "#{prefix}-#{instance.name}".downcase
304
316
  end
305
317
  end
306
318
  end
@@ -322,7 +334,7 @@ module Kitchen
322
334
 
323
335
  def instance_name
324
336
  prefix = (Digest::SHA2.hexdigest FileUtils.pwd)[0, 10]
325
- "#{prefix}-#{instance.name}"
337
+ "#{prefix}-#{instance.name}".downcase
326
338
  end
327
339
 
328
340
  def call(state)
@@ -58,7 +58,7 @@ module Kitchen
58
58
  create_sandbox
59
59
  write_run_command(run_command)
60
60
  instance.transport.connection(state) do |conn|
61
- if remote_docker_host?
61
+ if remote_docker_host? || running_inside_docker?
62
62
  info("Transferring files to #{instance.to_str}")
63
63
  conn.upload(sandbox_dirs, config[:root_path])
64
64
  end
@@ -45,7 +45,13 @@ module Kitchen
45
45
  default_config :write_timeout, 3600
46
46
  default_config :login_command, "docker"
47
47
  default_config :host_ip_override do |transport|
48
- transport.docker_for_mac_or_win? ? "localhost" : false
48
+ if running_inside_docker_desktop?
49
+ "host.docker.internal"
50
+ elsif transport.docker_for_mac_or_win?
51
+ "localhost"
52
+ else
53
+ false
54
+ end
49
55
  end
50
56
 
51
57
  # (see Base#connection)
@@ -212,7 +218,7 @@ module Kitchen
212
218
  #
213
219
  # @return [TrueClass,FalseClass]
214
220
  def docker_for_mac_or_win?
215
- ::Docker.info(::Docker::Connection.new(config[:docker_host_url], {}))["Name"] == "moby"
221
+ ::Docker.info(::Docker::Connection.new(config[:docker_host_url], {}))["Name"] == "docker-desktop"
216
222
  rescue
217
223
  false
218
224
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-dokken
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.19.1
4
+ version: 2.20.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean OMeara
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-07 00:00:00.000000000 Z
11
+ date: 2023-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -72,7 +72,10 @@ executables: []
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
+ - Gemfile
75
76
  - LICENSE
77
+ - Rakefile
78
+ - kitchen-dokken.gemspec
76
79
  - lib/kitchen/driver/dokken.rb
77
80
  - lib/kitchen/driver/dokken_version.rb
78
81
  - lib/kitchen/helpers.rb
@@ -97,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
100
  - !ruby/object:Gem::Version
98
101
  version: '0'
99
102
  requirements: []
100
- rubygems_version: 3.3.3
103
+ rubygems_version: 3.4.10
101
104
  signing_key:
102
105
  specification_version: 4
103
106
  summary: A Test Kitchen Driver for Docker & Chef Infra optimized for rapid testing