kitchen-docker 3.3.3 → 3.3.4
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/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/lib/kitchen/docker/docker_version.rb +1 -1
- data/lib/kitchen/docker/helpers/container_helper.rb +37 -4
- data/spec/container_helper_spec.rb +52 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be40fecdd59251c4d7b1a20de831bd939fd7018ce19d19a2a2f205ac2464f4fb
|
|
4
|
+
data.tar.gz: 04b4579a2569e8be9f943d77eca1d4fd9f5e72e2aefc2ad3009855bf1e565935
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d14d1fcddd8c823cc51231351311d2130bb9e9dd8355bb09e0551635a982a38b8abc52fca32cb03b5813d484bc256a688574ad8da6ef44a3d20525bdeac8fb21
|
|
7
|
+
data.tar.gz: 93f7faf2b089f727c6c78808b6c3e4d3fc9234e22a4defa21a0b463b61992324d8ecd26fb5bb9bfbc7da415d00234c67815d7bc20e889c563da50324c76c1040
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ Future CHANGELOG notes will be in GitHub release notes
|
|
|
6
6
|
|
|
7
7
|
* Docs: document the last four options and split contributor docs ([#463](https://github.com/test-kitchen/kitchen-docker/pull/463)) ([4818bce](https://github.com/test-kitchen/kitchen-docker/commit/4818bce))
|
|
8
8
|
|
|
9
|
+
## [3.3.4](https://github.com/test-kitchen/kitchen-docker/compare/v3.3.3...v3.3.4) (2026-08-23)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* read the container IP from NetworkSettings.Networks ([#479](https://github.com/test-kitchen/kitchen-docker/issues/479)) ([98b3337](https://github.com/test-kitchen/kitchen-docker/commit/98b3337d9c03e7cdde6d6d28d9e311b87f37c64f))
|
|
15
|
+
|
|
9
16
|
## [3.3.3](https://github.com/test-kitchen/kitchen-docker/compare/v3.3.2...v3.3.3) (2026-08-23)
|
|
10
17
|
|
|
11
18
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# limitations under the License.
|
|
13
13
|
|
|
14
14
|
require "erb" unless defined?(Erb)
|
|
15
|
+
require "ipaddr" unless defined?(IPAddr)
|
|
15
16
|
require "json" unless defined?(JSON)
|
|
16
17
|
require "shellwords" unless defined?(Shellwords)
|
|
17
18
|
require "tempfile" unless defined?(Tempfile)
|
|
@@ -253,15 +254,47 @@ module Kitchen
|
|
|
253
254
|
parse_container_id(output)
|
|
254
255
|
end
|
|
255
256
|
|
|
257
|
+
# The container's address on the Docker network.
|
|
258
|
+
#
|
|
259
|
+
# Read from +NetworkSettings.Networks+ rather than the top-level
|
|
260
|
+
# +NetworkSettings.IPAddress+. That field was only ever populated for
|
|
261
|
+
# the default bridge, and Docker 29 removed it altogether -- asking for
|
|
262
|
+
# it there fails the whole `docker inspect` with "map has no entry for
|
|
263
|
+
# key \"IPAddress\"", which took +use_internal_docker_network+ with it.
|
|
264
|
+
# +Networks+ has been present since Docker 1.9, so reading it works on
|
|
265
|
+
# both.
|
|
266
|
+
#
|
|
267
|
+
# A container attached to several networks has an address on each; the
|
|
268
|
+
# first is used, which is the only one for the single-network case this
|
|
269
|
+
# option is for.
|
|
270
|
+
#
|
|
256
271
|
# @param state [Hash] instance state naming the container
|
|
257
272
|
# @return [String] the container's address on the Docker network
|
|
258
273
|
# @raise [Kitchen::ActionFailed] if it cannot be determined
|
|
259
274
|
def container_ip_address(state)
|
|
260
|
-
cmd = "inspect --format '{{ .NetworkSettings.IPAddress }}'"
|
|
275
|
+
cmd = "inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}} {{end}}'"
|
|
261
276
|
cmd << " #{state[:container_id]}"
|
|
262
|
-
docker_command(cmd)
|
|
263
|
-
|
|
264
|
-
|
|
277
|
+
output = docker_command(cmd, suppress_output: !logger.debug?)
|
|
278
|
+
|
|
279
|
+
# Picked by parsing rather than by taking the first word, so that a
|
|
280
|
+
# warning docker writes to stderr is not returned as an address.
|
|
281
|
+
address = output.split(/\s+/).find { |token| ip_address?(token) }
|
|
282
|
+
raise ActionFailed, "Docker reports no IP address for the container" if address.nil?
|
|
283
|
+
|
|
284
|
+
address
|
|
285
|
+
rescue => e
|
|
286
|
+
raise ActionFailed, "Error getting internal IP of Docker container. #{e}"
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# @param token [String] a candidate address
|
|
290
|
+
# @return [Boolean] whether it parses as an IPv4 or IPv6 address
|
|
291
|
+
def ip_address?(token)
|
|
292
|
+
return false if token.nil? || token.empty?
|
|
293
|
+
|
|
294
|
+
IPAddr.new(token)
|
|
295
|
+
true
|
|
296
|
+
rescue IPAddr::Error
|
|
297
|
+
false
|
|
265
298
|
end
|
|
266
299
|
|
|
267
300
|
# Stops and removes the container.
|
|
@@ -270,6 +270,58 @@ describe Kitchen::Docker::Helpers::ContainerHelper do
|
|
|
270
270
|
end
|
|
271
271
|
end
|
|
272
272
|
|
|
273
|
+
describe "#container_ip_address" do
|
|
274
|
+
def helper_inspecting(output)
|
|
275
|
+
h = helper
|
|
276
|
+
@asked = nil
|
|
277
|
+
allow(h).to receive(:docker_command) { |cmd, _opts = {}| @asked = cmd; output }
|
|
278
|
+
h
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
let(:state) { { container_id: "abc123abc123" } }
|
|
282
|
+
|
|
283
|
+
it "returns the address docker reports" do
|
|
284
|
+
expect(helper_inspecting("172.17.0.7 \n").container_ip_address(state)).to eq "172.17.0.7"
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "reads Networks rather than the removed top-level IPAddress" do
|
|
288
|
+
# Docker 29 dropped NetworkSettings.IPAddress. Asking for it does not
|
|
289
|
+
# return empty -- it fails the whole inspect with a template error, which
|
|
290
|
+
# took use_internal_docker_network down with it.
|
|
291
|
+
helper_inspecting("172.17.0.7\n").container_ip_address(state)
|
|
292
|
+
expect(@asked).to include(".NetworkSettings.Networks")
|
|
293
|
+
expect(@asked).not_to include(".NetworkSettings.IPAddress")
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "takes the first address when the container is on several networks" do
|
|
297
|
+
expect(helper_inspecting("172.17.0.7 172.19.0.2 \n").container_ip_address(state))
|
|
298
|
+
.to eq "172.17.0.7"
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "handles an IPv6 address" do
|
|
302
|
+
expect(helper_inspecting("2001:db8::2 \n").container_ip_address(state)).to eq "2001:db8::2"
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it "ignores a warning docker wrote to stderr" do
|
|
306
|
+
expect(helper_inspecting("WARNING: something happened\n172.17.0.7 \n").container_ip_address(state))
|
|
307
|
+
.to eq "172.17.0.7"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "fails loudly when docker reports no address" do
|
|
311
|
+
# Returning "" here would be recorded as the instance hostname, and the
|
|
312
|
+
# connection would fail somewhere far from the cause.
|
|
313
|
+
expect { helper_inspecting(" \n").container_ip_address(state) }
|
|
314
|
+
.to raise_error(Kitchen::ActionFailed, /no IP address/)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
it "fails loudly when the inspect itself fails" do
|
|
318
|
+
h = helper
|
|
319
|
+
allow(h).to receive(:docker_command).and_raise(Kitchen::ShellOut::ShellCommandFailed, "boom")
|
|
320
|
+
expect { h.container_ip_address(state) }
|
|
321
|
+
.to raise_error(Kitchen::ActionFailed, /Error getting internal IP/)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
273
325
|
describe "#remove_container" do
|
|
274
326
|
it "stops the container before removing it" do
|
|
275
327
|
# `docker rm` refuses to remove a running container, so the order matters.
|