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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f64096aa934f3502dd1427249a5d15db1371855534522ecb20b4ea4e928f7a5b
4
- data.tar.gz: 013667f1b55015399185c490cae0c3cd5e899e9fb8678af3fcb42d74c5c9e5d8
3
+ metadata.gz: be40fecdd59251c4d7b1a20de831bd939fd7018ce19d19a2a2f205ac2464f4fb
4
+ data.tar.gz: 04b4579a2569e8be9f943d77eca1d4fd9f5e72e2aefc2ad3009855bf1e565935
5
5
  SHA512:
6
- metadata.gz: 414439ff16eeffb9f0288925cd6579da33f60968efe4ead0fa85d6454d98499f634dfed7bfe90ff2131c2a519c2b5f109fdefd7cb854a917f7ff756f539a7f24
7
- data.tar.gz: 72446a19d4951a3b1b87b66a3c604f13f67cac6395588e1698c4a9dc4ab7cd8f9f3edaa31c1c5ecc7ed5477a26a0e40639d217290ae48c74fb368daadc555b45
6
+ metadata.gz: d14d1fcddd8c823cc51231351311d2130bb9e9dd8355bb09e0551635a982a38b8abc52fca32cb03b5813d484bc256a688574ad8da6ef44a3d20525bdeac8fb21
7
+ data.tar.gz: 93f7faf2b089f727c6c78808b6c3e4d3fc9234e22a4defa21a0b463b61992324d8ecd26fb5bb9bfbc7da415d00234c67815d7bc20e889c563da50324c76c1040
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "3.3.3"
2
+ ".": "3.3.4"
3
3
  }
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
 
@@ -18,6 +18,6 @@ module Kitchen
18
18
  # Everything belonging to the kitchen-docker plugin.
19
19
  module Docker
20
20
  # The version of the kitchen-docker gem.
21
- DOCKER_VERSION = "3.3.3".freeze
21
+ DOCKER_VERSION = "3.3.4".freeze
22
22
  end
23
23
  end
@@ -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).strip
263
- rescue
264
- raise ActionFailed, "Error getting internal IP of Docker container"
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.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.3
4
+ version: 3.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Porter