kitchen-dokken 2.23.7 → 2.24.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 +4 -4
- data/kitchen-dokken.gemspec +1 -1
- data/lib/kitchen/driver/dokken.rb +146 -17
- data/lib/kitchen/driver/dokken_version.rb +1 -1
- data/lib/kitchen/helpers.rb +88 -7
- data/lib/kitchen/provisioner/dokken.rb +15 -1
- data/lib/kitchen/transport/dokken.rb +5 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1601bf73b8bb5607d0a279d1d06e3cc5779b581616159b320ee6737210b9bd1d
|
|
4
|
+
data.tar.gz: 7e92f8c54e09f5746905496fa9388b2fe49f0ec8d7a33f63ac461a0f53c07618
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f6fee7ac1a7586664f3e67047ad994a22c059f6782c99e737a1792dd3758c778f1c8bd3c6f79f6fe1406725dad6f3c1b8d297de1fb9630c4e326d67b23de5d2c
|
|
7
|
+
data.tar.gz: 1604d52bffac5be374ac62f2a509b584ff43303a5b6c98aed2ed0c1fdcdaa8ec9a8fc8ec17c65a8c56679574ff878452e6ee587ca5bf28e12e8a005f6d845d36
|
data/kitchen-dokken.gemspec
CHANGED
|
@@ -23,6 +23,7 @@ require "docker"
|
|
|
23
23
|
require "shellwords" unless defined?(Shellwords)
|
|
24
24
|
require "base64" unless defined?(Base64)
|
|
25
25
|
require_relative "../helpers"
|
|
26
|
+
require_relative "dokken_version"
|
|
26
27
|
|
|
27
28
|
include Dokken::Helpers
|
|
28
29
|
|
|
@@ -42,6 +43,14 @@ module Kitchen
|
|
|
42
43
|
#
|
|
43
44
|
# @author Sean OMeara <sean@sean.io>
|
|
44
45
|
class Dokken < Kitchen::Driver::Base
|
|
46
|
+
kitchen_driver_api_version 2
|
|
47
|
+
|
|
48
|
+
# kitchen-dokken's own version, not test-kitchen's. `kitchen diagnose`
|
|
49
|
+
# is the first thing a bug report carries, and it used to report the
|
|
50
|
+
# test-kitchen version here -- which says nothing about the plugin the
|
|
51
|
+
# report is actually about.
|
|
52
|
+
plugin_version Kitchen::Driver::DOKKEN_VERSION
|
|
53
|
+
|
|
45
54
|
default_config :api_retries, 20
|
|
46
55
|
default_config :binds, []
|
|
47
56
|
default_config :cap_add, nil
|
|
@@ -143,8 +152,65 @@ module Kitchen
|
|
|
143
152
|
dokken_delete_sandbox
|
|
144
153
|
end
|
|
145
154
|
|
|
155
|
+
# (see Base#status)
|
|
156
|
+
#
|
|
157
|
+
# `kitchen list --live` asks the driver whether the instance is really
|
|
158
|
+
# there rather than trusting the last recorded action, which is exactly
|
|
159
|
+
# the question a docker daemon can answer precisely. Without this the
|
|
160
|
+
# driver inherited Base's "unknown", so a container that was plainly
|
|
161
|
+
# `Up` still listed as `unknown`.
|
|
162
|
+
#
|
|
163
|
+
# The runner *is* the instance. The chef container is a shared volume
|
|
164
|
+
# and the data container only exists on the remote-daemon path, so
|
|
165
|
+
# neither says anything about whether this instance is up.
|
|
166
|
+
#
|
|
167
|
+
# Deliberately not wrapped in {#with_retries}: this backs a listing, and
|
|
168
|
+
# a slow answer is worse than an honest "unknown".
|
|
169
|
+
#
|
|
170
|
+
# @param _state [Hash] mutable instance state
|
|
171
|
+
# @return [Hash] normalized status data
|
|
172
|
+
def status(_state)
|
|
173
|
+
container_status(::Docker::Container.get(runner_container_name, {}, docker_connection))
|
|
174
|
+
rescue ::Docker::Error::NotFoundError
|
|
175
|
+
{ live: false, state: "not created", source: "driver" }
|
|
176
|
+
# Every other failure -- an unreachable daemon most of all -- is an
|
|
177
|
+
# unknown rather than an exception. Kitchen would catch it either way,
|
|
178
|
+
# but it would then report the exception class instead of the daemon
|
|
179
|
+
# url that could not be reached.
|
|
180
|
+
rescue ::StandardError => e
|
|
181
|
+
{
|
|
182
|
+
live: nil,
|
|
183
|
+
state: "unknown",
|
|
184
|
+
source: "driver",
|
|
185
|
+
message: "could not ask the docker daemon at #{config[:docker_host_url]}: #{e.message}",
|
|
186
|
+
}
|
|
187
|
+
end
|
|
188
|
+
|
|
146
189
|
private
|
|
147
190
|
|
|
191
|
+
# Translate a container's `State` into kitchen's status shape.
|
|
192
|
+
#
|
|
193
|
+
# @param container [::Docker::Container] the runner container
|
|
194
|
+
# @return [Hash] normalized status data
|
|
195
|
+
def container_status(container)
|
|
196
|
+
state = container.info["State"] || {}
|
|
197
|
+
running = state["Running"] == true
|
|
198
|
+
|
|
199
|
+
status = {
|
|
200
|
+
# Docker's own vocabulary -- created, running, paused, exited,
|
|
201
|
+
# restarting, dead -- says more than a boolean, and `kitchen list`
|
|
202
|
+
# prints it verbatim.
|
|
203
|
+
live: running,
|
|
204
|
+
state: state["Status"] || (running ? "running" : "stopped"),
|
|
205
|
+
source: "driver",
|
|
206
|
+
resource_id: container.info["Id"],
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
error = state["Error"].to_s
|
|
210
|
+
status[:message] = error unless error.empty?
|
|
211
|
+
status
|
|
212
|
+
end
|
|
213
|
+
|
|
148
214
|
# Attach DNS settings to a network endpoint configuration, in place.
|
|
149
215
|
#
|
|
150
216
|
# @param endpoint_config [Hash] the EndpointsConfig entry to extend
|
|
@@ -240,17 +306,41 @@ module Kitchen
|
|
|
240
306
|
|
|
241
307
|
# Pull the human-readable reason out of a failed build response.
|
|
242
308
|
#
|
|
243
|
-
# The daemon usually answers with a JSON document carrying an "error"
|
|
244
|
-
# key, but a proxy or a plain-text 500 does not -- and a JSON::ParserError
|
|
245
|
-
# raised from inside the rescue clause would bury the real failure.
|
|
246
|
-
#
|
|
247
309
|
# @param error [Exception] the error docker-api raised
|
|
248
310
|
# @return [String] the daemon's explanation, or the raw response
|
|
249
311
|
def build_error_detail(error)
|
|
250
|
-
|
|
251
|
-
|
|
312
|
+
daemon_message(error.to_s.split("\r\n").last.to_s)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Pull the human-readable reason out of a docker-api error.
|
|
316
|
+
#
|
|
317
|
+
# docker-api raises with the daemon's response body as the message, so
|
|
318
|
+
# what reaches a rescue clause is a JSON document rather than a sentence:
|
|
319
|
+
# `{"message":"driver failed programming external connectivity ..."}`.
|
|
320
|
+
# Reporting that verbatim is barely better than reporting nothing.
|
|
321
|
+
#
|
|
322
|
+
# @param error [Exception] the error docker-api raised
|
|
323
|
+
# @return [String] the daemon's explanation, or the raw response
|
|
324
|
+
def docker_error_detail(error)
|
|
325
|
+
daemon_message(error.to_s)
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# The explanation carried in a docker daemon response body.
|
|
329
|
+
#
|
|
330
|
+
# Most endpoints answer with a "message" key and the /build stream with
|
|
331
|
+
# an "error" one. A proxy or a plain-text 500 answers with neither -- and
|
|
332
|
+
# a JSON::ParserError raised from inside a rescue clause would bury the
|
|
333
|
+
# very failure it was called on to explain -- so anything unparseable
|
|
334
|
+
# comes back unchanged.
|
|
335
|
+
#
|
|
336
|
+
# @param body [String] a response body
|
|
337
|
+
# @return [String] the explanation, or the body unchanged
|
|
338
|
+
def daemon_message(body)
|
|
339
|
+
parsed = JSON.parse(body)
|
|
340
|
+
detail = parsed["message"] || parsed["error"]
|
|
341
|
+
detail.nil? ? body : detail.to_s
|
|
252
342
|
rescue JSON::ParserError, TypeError
|
|
253
|
-
|
|
343
|
+
body
|
|
254
344
|
end
|
|
255
345
|
|
|
256
346
|
# The Dockerfile for the work image.
|
|
@@ -899,7 +989,11 @@ module Kitchen
|
|
|
899
989
|
end
|
|
900
990
|
rescue ::Docker::Error::DockerError => e
|
|
901
991
|
debug "driver - error :#{e}:"
|
|
902
|
-
|
|
992
|
+
# The daemon's reason used to be dropped here, leaving `kitchen
|
|
993
|
+
# create` to report a bare "failed to create_container <name>" with
|
|
994
|
+
# nothing to act on -- the explanation existed, but only for someone
|
|
995
|
+
# who already knew to re-run at `-l debug`.
|
|
996
|
+
raise "driver - failed to create_container #{args["name"]}: #{docker_error_detail(e)}"
|
|
903
997
|
end
|
|
904
998
|
end
|
|
905
999
|
|
|
@@ -943,15 +1037,35 @@ module Kitchen
|
|
|
943
1037
|
# @raise [Kitchen::ActionFailed] if the container will not stay running
|
|
944
1038
|
def run_container(args, platform: nil)
|
|
945
1039
|
@container = create_container(args, platform: platform)
|
|
946
|
-
|
|
947
|
-
@container.start
|
|
948
|
-
@container = ::Docker::Container.get(args["name"], {}, docker_connection)
|
|
949
|
-
wait_running_state(args["name"], true)
|
|
950
|
-
end
|
|
1040
|
+
start_container!(args["name"])
|
|
951
1041
|
assert_running!(args["name"])
|
|
952
1042
|
@container
|
|
953
1043
|
end
|
|
954
1044
|
|
|
1045
|
+
# Start a container and wait for it to be running.
|
|
1046
|
+
#
|
|
1047
|
+
# `start!`, not `start`: docker-api defines the unsuffixed form as "the
|
|
1048
|
+
# same, but rescue from ServerErrors", so every reason the daemon
|
|
1049
|
+
# refused -- a port already bound, an invalid mount, a capability the
|
|
1050
|
+
# kernel will not grant -- was swallowed on the way past. `with_retries`
|
|
1051
|
+
# then had nothing to retry and `assert_running!` was left to report a
|
|
1052
|
+
# container that "exited immediately" when in truth it had never
|
|
1053
|
+
# started, sending the user off to read `docker logs` output that does
|
|
1054
|
+
# not exist.
|
|
1055
|
+
#
|
|
1056
|
+
# @param name [String] the container name
|
|
1057
|
+
# @return [void]
|
|
1058
|
+
# @raise [Kitchen::ActionFailed] if the daemon would not start it
|
|
1059
|
+
def start_container!(name)
|
|
1060
|
+
with_retries do
|
|
1061
|
+
@container.start!
|
|
1062
|
+
@container = ::Docker::Container.get(name, {}, docker_connection)
|
|
1063
|
+
wait_running_state(name, true)
|
|
1064
|
+
end
|
|
1065
|
+
rescue ::Docker::Error::DockerError => e
|
|
1066
|
+
raise ActionFailed, "The #{name} container could not be started: #{docker_error_detail(e)}"
|
|
1067
|
+
end
|
|
1068
|
+
|
|
955
1069
|
# Fail the action when a container that has to run is not running.
|
|
956
1070
|
#
|
|
957
1071
|
# wait_running_state stops polling as soon as `FinishedAt` is set, which
|
|
@@ -970,10 +1084,25 @@ module Kitchen
|
|
|
970
1084
|
def assert_running!(name)
|
|
971
1085
|
return if container_state["Running"]
|
|
972
1086
|
|
|
973
|
-
raise ActionFailed,
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1087
|
+
raise ActionFailed, "The #{name} container is not running. #{not_running_reason(name)}"
|
|
1088
|
+
end
|
|
1089
|
+
|
|
1090
|
+
# Why a container that should be running is not.
|
|
1091
|
+
#
|
|
1092
|
+
# The daemon records its own refusal in `State.Error` and leaves
|
|
1093
|
+
# `FinishedAt` unset, which is a different failure from a pid 1 that
|
|
1094
|
+
# started and exited -- and pointing at `docker logs` for the first kind
|
|
1095
|
+
# sends the user to an empty file.
|
|
1096
|
+
#
|
|
1097
|
+
# @param name [String] the container name
|
|
1098
|
+
# @return [String] a sentence naming the likely cause
|
|
1099
|
+
def not_running_reason(name)
|
|
1100
|
+
daemon_error = container_state["Error"].to_s
|
|
1101
|
+
return "The docker daemon refused to start it: #{daemon_error}" unless daemon_error.empty?
|
|
1102
|
+
|
|
1103
|
+
"Its pid 1 exited immediately (exit code #{container_state["ExitCode"]}): " \
|
|
1104
|
+
"check `pid_one_command`, `entrypoint`, and that the image can boot " \
|
|
1105
|
+
"(`docker logs #{name}` shows why)."
|
|
977
1106
|
end
|
|
978
1107
|
|
|
979
1108
|
# The current container's `State` payload.
|
data/lib/kitchen/helpers.rb
CHANGED
|
@@ -351,10 +351,15 @@ module Dokken
|
|
|
351
351
|
# each optionally suffixed with `/protocol` and each allowing an
|
|
352
352
|
# inclusive `low-high` container port range.
|
|
353
353
|
#
|
|
354
|
-
# @param v [String] a port specification
|
|
354
|
+
# @param v [String, Integer] a port specification
|
|
355
355
|
# @return [Array<Hash>] one entry per container port
|
|
356
|
-
# @raise [Kitchen::UserError] if a port range is inverted
|
|
356
|
+
# @raise [Kitchen::UserError] if a port range is inverted or unpairable
|
|
357
357
|
def parse_port(v)
|
|
358
|
+
# `ports: [8080]` is a perfectly natural thing to write, and YAML hands
|
|
359
|
+
# it over as an Integer. That used to reach String#split and abort the
|
|
360
|
+
# create with `undefined method 'split' for an instance of Integer`,
|
|
361
|
+
# which names a type rather than the line of kitchen.yml at fault.
|
|
362
|
+
v = v.to_s
|
|
358
363
|
parts = v.split(":")
|
|
359
364
|
case parts.length
|
|
360
365
|
when 3
|
|
@@ -390,18 +395,63 @@ module Dokken
|
|
|
390
395
|
"Invalid port spec #{v.inspect}: no container port"
|
|
391
396
|
end
|
|
392
397
|
|
|
393
|
-
|
|
398
|
+
container_ports = port_range.include?("-") ? expand_port_range(port_range, v) : [port_range]
|
|
394
399
|
# qualify the port-binding protocol even when it is implicitly tcp #427.
|
|
395
400
|
protocol = "tcp" if protocol.nil?
|
|
396
|
-
|
|
401
|
+
host_ports = expand_host_ports(host_port, container_ports.length, v)
|
|
402
|
+
|
|
403
|
+
container_ports.each_with_index.map do |port, i|
|
|
397
404
|
{
|
|
398
405
|
"host_ip" => host_ip,
|
|
399
|
-
"host_port" =>
|
|
406
|
+
"host_port" => host_ports[i],
|
|
400
407
|
"container_port" => "#{port}/#{protocol}",
|
|
401
408
|
}
|
|
402
409
|
end
|
|
403
410
|
end
|
|
404
411
|
|
|
412
|
+
# Work out the host port that pairs with each container port.
|
|
413
|
+
#
|
|
414
|
+
# Docker pairs ranges off one for one -- `8080-8082:9090-9092` publishes
|
|
415
|
+
# 9090 on 8080, 9091 on 8081 and 9092 on 8082 -- but only the container
|
|
416
|
+
# side used to be expanded here, so every binding was handed the whole
|
|
417
|
+
# host range as its `HostPort`. That reads as "any free port in this
|
|
418
|
+
# range" to the daemon, which meant the mapping was only correct while the
|
|
419
|
+
# whole range happened to be free, and otherwise came out shifted or
|
|
420
|
+
# failed outright with "all ports are allocated" rather than naming the
|
|
421
|
+
# port that was taken.
|
|
422
|
+
#
|
|
423
|
+
# @param host_port [String] the host half of the spec
|
|
424
|
+
# @param count [Integer] how many container ports were asked for
|
|
425
|
+
# @param spec [String] the whole port spec, for the error message
|
|
426
|
+
# @return [Array<String>] one host port per container port
|
|
427
|
+
# @raise [Kitchen::UserError] if the two sides cannot be paired
|
|
428
|
+
def expand_host_ports(host_port, count, spec)
|
|
429
|
+
# `ports: '8080'` names no host port at all; the daemon picks one.
|
|
430
|
+
return Array.new(count, host_port) if host_port.empty?
|
|
431
|
+
|
|
432
|
+
unless host_port.include?("-")
|
|
433
|
+
return [host_port] if count == 1
|
|
434
|
+
|
|
435
|
+
raise Kitchen::UserError,
|
|
436
|
+
"Invalid port spec #{spec.inspect}: a single host port cannot be paired with " \
|
|
437
|
+
"a range of #{count} container ports. Give a host range of the same size, " \
|
|
438
|
+
"as in 8080-8082:9090-9092."
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# A host range against a single container port is docker's "publish this
|
|
442
|
+
# on any free port in the range". The daemon does the choosing, so the
|
|
443
|
+
# range is handed over untouched.
|
|
444
|
+
return [host_port] if count == 1
|
|
445
|
+
|
|
446
|
+
host_ports = expand_port_range(host_port, spec)
|
|
447
|
+
return host_ports.map(&:to_s) if host_ports.length == count
|
|
448
|
+
|
|
449
|
+
raise Kitchen::UserError,
|
|
450
|
+
"Invalid port spec #{spec.inspect}: the host range covers #{host_ports.length} " \
|
|
451
|
+
"ports and the container range covers #{count}. Docker pairs them off one for " \
|
|
452
|
+
"one, so both ranges have to be the same size."
|
|
453
|
+
end
|
|
454
|
+
|
|
405
455
|
# Expand an inclusive `low-high` container port range.
|
|
406
456
|
#
|
|
407
457
|
# @param range [String] the range, e.g. "8080-8082"
|
|
@@ -579,8 +629,39 @@ module Kitchen
|
|
|
579
629
|
|
|
580
630
|
# Run the verifier against the instance.
|
|
581
631
|
#
|
|
582
|
-
#
|
|
583
|
-
#
|
|
632
|
+
# This replaces Kitchen::Verifier::Base#call outright, so it has to be
|
|
633
|
+
# read against the upstream version it stands in for. It diverges in
|
|
634
|
+
# three places, and each divergence is deliberate:
|
|
635
|
+
#
|
|
636
|
+
# 1. *The upload is gated on the data container.* Files are only shipped
|
|
637
|
+
# when the driver built one, which it does exactly when the daemon
|
|
638
|
+
# cannot read the host filesystem. Otherwise the sandboxes are
|
|
639
|
+
# bind-mounted and are already in place. `init_command` is gated with
|
|
640
|
+
# it because for Busser it clears the verifier root, which in
|
|
641
|
+
# bind-mount mode is the host sandbox that was just populated.
|
|
642
|
+
#
|
|
643
|
+
# 2. *`cleanup_sandbox` is not called*, and must not be. Upstream can
|
|
644
|
+
# `rmtree` its sandbox because a stock one is a throwaway
|
|
645
|
+
# `Dir.mktmpdir`. Dokken's is a stable per-instance directory that
|
|
646
|
+
# the driver bind-mounts into a long-lived container, and a bind
|
|
647
|
+
# mount is bound to an inode rather than to a path: removing the
|
|
648
|
+
# directory severs it permanently, and the `mkdir_p` in the next
|
|
649
|
+
# `create_sandbox` does not restore it. Verified against Docker --
|
|
650
|
+
# after an rmtree and a recreate, the host has the file and the
|
|
651
|
+
# container cannot see it, until the container itself is replaced.
|
|
652
|
+
# Kitchen::Provisioner::Dokken#cleanup_dokken_sandbox is the shape
|
|
653
|
+
# that is safe here: empty the directory, keep the inode.
|
|
654
|
+
#
|
|
655
|
+
# 3. *`config[:downloads]` is not honoured.* Upstream downloads files
|
|
656
|
+
# off the instance after the run command. That cannot work here yet
|
|
657
|
+
# for a second reason as well: Transport::Dokken::Connection does not
|
|
658
|
+
# implement `download`, so the base class would raise. Wiring both up
|
|
659
|
+
# is worth doing, and is the one divergence here that is a gap rather
|
|
660
|
+
# than a decision.
|
|
661
|
+
#
|
|
662
|
+
# spec/kitchen/verifier_override_contract_spec.rb pins the upstream
|
|
663
|
+
# facts this reasoning rests on, so that a test-kitchen release which
|
|
664
|
+
# invalidates any of them fails loudly rather than silently.
|
|
584
665
|
#
|
|
585
666
|
# @param state [Hash] mutable instance state
|
|
586
667
|
# @return [void]
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
require "kitchen"
|
|
19
19
|
require "kitchen/provisioner/chef_infra"
|
|
20
20
|
require_relative "../helpers"
|
|
21
|
+
require_relative "../driver/dokken_version"
|
|
21
22
|
|
|
22
23
|
include Dokken::Helpers
|
|
23
24
|
|
|
@@ -35,7 +36,10 @@ module Kitchen
|
|
|
35
36
|
class Dokken < Kitchen::Provisioner::ChefInfra
|
|
36
37
|
kitchen_provisioner_api_version 2
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
# kitchen-dokken's own version. Kitchen::VERSION is test-kitchen's,
|
|
40
|
+
# so `kitchen diagnose` reported the framework version as the
|
|
41
|
+
# plugin version for every dokken plugin.
|
|
42
|
+
plugin_version Kitchen::Driver::DOKKEN_VERSION
|
|
39
43
|
|
|
40
44
|
default_config :root_path, "/opt/kitchen"
|
|
41
45
|
default_config :chef_binary do |provisioner|
|
|
@@ -166,6 +170,16 @@ module Kitchen
|
|
|
166
170
|
# just use the defaults
|
|
167
171
|
config[:chef_log_level] = "warn" if config[:chef_log_level].empty?
|
|
168
172
|
config[:chef_output_format] = "doc" if config[:chef_output_format].empty?
|
|
173
|
+
|
|
174
|
+
# ChefBase#chef_args appends `--log_level #{config[:log_level]}` to
|
|
175
|
+
# whatever base command it is handed, so the parent's flag lands
|
|
176
|
+
# *after* the `-l` built below. `-l` and `--log_level` are the same
|
|
177
|
+
# chef-client option and the last occurrence wins, which meant
|
|
178
|
+
# chef_log_level was parsed, written into the staged run_command, and
|
|
179
|
+
# then silently overridden by the parent's default of "auto".
|
|
180
|
+
# Keeping the two in step makes the documented setting the one chef
|
|
181
|
+
# actually runs at.
|
|
182
|
+
config[:log_level] = config[:chef_log_level]
|
|
169
183
|
end
|
|
170
184
|
|
|
171
185
|
private
|
|
@@ -22,6 +22,7 @@ require "digest/sha1" unless defined?(Digest::SHA1)
|
|
|
22
22
|
require "open3" unless defined?(Open3)
|
|
23
23
|
require "shellwords" unless defined?(Shellwords)
|
|
24
24
|
require_relative "../helpers"
|
|
25
|
+
require_relative "../driver/dokken_version"
|
|
25
26
|
|
|
26
27
|
include Dokken::Helpers
|
|
27
28
|
|
|
@@ -45,7 +46,10 @@ module Kitchen
|
|
|
45
46
|
class Dokken < Kitchen::Transport::Base
|
|
46
47
|
kitchen_transport_api_version 2
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
# kitchen-dokken's own version. Kitchen::VERSION is test-kitchen's,
|
|
50
|
+
# so `kitchen diagnose` reported the framework version as the
|
|
51
|
+
# plugin version for every dokken plugin.
|
|
52
|
+
plugin_version Kitchen::Driver::DOKKEN_VERSION
|
|
49
53
|
|
|
50
54
|
default_config :docker_info do |transport|
|
|
51
55
|
docker_info(transport[:docker_host_url])
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-dokken
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.24.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean OMeara
|
|
@@ -50,7 +50,7 @@ dependencies:
|
|
|
50
50
|
requirements:
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
53
|
+
version: '3.0'
|
|
54
54
|
- - "<"
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
56
|
version: '5'
|
|
@@ -60,7 +60,7 @@ dependencies:
|
|
|
60
60
|
requirements:
|
|
61
61
|
- - ">="
|
|
62
62
|
- !ruby/object:Gem::Version
|
|
63
|
-
version: '
|
|
63
|
+
version: '3.0'
|
|
64
64
|
- - "<"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
66
|
version: '5'
|