kitchen-docker 2.15.0 → 3.2.3

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/workflows/lint.yml +99 -0
  4. data/.github/workflows/publish.yaml +32 -0
  5. data/.gitignore +1 -0
  6. data/.markdownlint.yaml +6 -0
  7. data/.release-please-manifest.json +3 -0
  8. data/.rubocop.yml +9 -0
  9. data/.yamllint +15 -0
  10. data/CHANGELOG.md +40 -0
  11. data/Gemfile +20 -1
  12. data/README.md +16 -9
  13. data/Rakefile +13 -36
  14. data/cookbooks +1 -0
  15. data/kitchen-docker.gemspec +9 -29
  16. data/kitchen.windows.yml +31 -0
  17. data/kitchen.yml +94 -0
  18. data/lib/kitchen/docker/container/linux.rb +17 -17
  19. data/lib/kitchen/docker/container/windows.rb +11 -11
  20. data/lib/kitchen/docker/container.rb +7 -7
  21. data/lib/kitchen/docker/docker_version.rb +1 -1
  22. data/lib/kitchen/docker/erb_context.rb +3 -3
  23. data/lib/kitchen/docker/helpers/cli_helper.rb +184 -172
  24. data/lib/kitchen/docker/helpers/container_helper.rb +178 -172
  25. data/lib/kitchen/docker/helpers/dockerfile_helper.rb +34 -34
  26. data/lib/kitchen/docker/helpers/file_helper.rb +4 -4
  27. data/lib/kitchen/docker/helpers/image_helper.rb +28 -14
  28. data/lib/kitchen/docker/helpers/inspec_helper.rb +62 -40
  29. data/lib/kitchen/driver/docker.rb +34 -40
  30. data/lib/kitchen/transport/docker.rb +15 -16
  31. data/release-please-config.json +12 -0
  32. data/renovate.json +8 -0
  33. data/spec/docker_spec.rb +108 -0
  34. data/spec/dockerfile_helper_spec.rb +109 -0
  35. data/spec/inspec_helper_spec.rb +58 -0
  36. data/{test/spec → spec}/spec_helper.rb +5 -26
  37. data/test/Dockerfile +4 -5
  38. data/test/cookbooks/cinc_test/metadata.rb +2 -0
  39. data/test/cookbooks/cinc_test/recipes/default.rb +10 -0
  40. data/test/cookbooks/docker_test/attributes/default.rb +1 -0
  41. data/test/cookbooks/docker_test/metadata.rb +3 -0
  42. data/test/cookbooks/docker_test/recipes/default.rb +94 -0
  43. data/test/integration/capabilities/{serverspec → disabled}/capabilities_drop_spec.rb +7 -6
  44. data/test/integration/cinc/inspec/cinc_spec.rb +21 -0
  45. data/test/integration/default/{serverspec → disabled}/default_spec.rb +7 -6
  46. data/test/integration/default/{serverspec → disabled}/spec_helper.rb +7 -7
  47. data/test/integration/inspec/inspec_spec.rb +3 -3
  48. metadata +33 -202
  49. data/.cane +0 -0
  50. data/.github/dependabot.yml +0 -7
  51. data/.kitchen.windows.yml +0 -33
  52. data/.kitchen.yml +0 -65
  53. data/.tailor +0 -4
  54. data/.travis.yml +0 -57
  55. data/lib/docker/version.rb +0 -25
  56. data/lib/train/docker.rb +0 -125
  57. data/test/spec/docker_spec.rb +0 -64
@@ -1,172 +1,178 @@
1
- #
2
- # Licensed under the Apache License, Version 2.0 (the "License");
3
- # you may not use this file except in compliance with the License.
4
- # You may obtain a copy of the License at
5
- #
6
- # http://www.apache.org/licenses/LICENSE-2.0
7
- #
8
- # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an "AS IS" BASIS,
10
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- # See the License for the specific language governing permissions and
12
- # limitations under the License.
13
-
14
- require 'erb'
15
- require 'json'
16
- require 'shellwords'
17
- require 'tempfile'
18
- require 'uri'
19
-
20
- require 'kitchen'
21
- require 'kitchen/configurable'
22
- require_relative '../erb_context'
23
- require_relative 'cli_helper'
24
-
25
- module Kitchen
26
- module Docker
27
- module Helpers
28
- module ContainerHelper
29
- include Configurable
30
- include Kitchen::Docker::Helpers::CliHelper
31
-
32
- def parse_container_id(output)
33
- container_id = output.chomp
34
-
35
- unless [12, 64].include?(container_id.size)
36
- raise ActionFailed, 'Could not parse Docker run output for container ID'
37
- end
38
-
39
- container_id
40
- end
41
-
42
- def dockerfile_template
43
- template = IO.read(File.expand_path(config[:dockerfile]))
44
- context = Kitchen::Docker::ERBContext.new(config.to_hash)
45
- ERB.new(template).result(context.get_binding)
46
- end
47
-
48
- def remote_socket?
49
- config[:socket] ? socket_uri.scheme == 'tcp' : false
50
- end
51
-
52
- def socket_uri
53
- URI.parse(config[:socket])
54
- end
55
-
56
- def dockerfile_path(file)
57
- config[:build_context] ? Pathname.new(file.path).relative_path_from(Pathname.pwd).to_s : file.path
58
- end
59
-
60
- def container_exists?(state)
61
- state[:container_id] && !!docker_command("top #{state[:container_id]}") rescue false
62
- end
63
-
64
- def container_exec(state, command)
65
- cmd = build_exec_command(state, command)
66
- docker_command(cmd)
67
- rescue => e
68
- raise "Failed to execute command on Docker container. #{e}"
69
- end
70
-
71
- def create_dir_on_container(state, path)
72
- path = replace_env_variables(state, path)
73
- cmd = "mkdir -p #{path}"
74
-
75
- if state[:platform].include?('windows')
76
- psh = "-Command if(-not (Test-Path \'#{path}\')) { New-Item -Path \'#{path}\' -Force }"
77
- cmd = build_powershell_command(psh)
78
- end
79
-
80
- cmd = build_exec_command(state, cmd)
81
- docker_command(cmd)
82
- rescue => e
83
- raise "Failed to create directory #{path} on container. #{e}"
84
- end
85
-
86
- def copy_file_to_container(state, local_file, remote_file)
87
- debug("Copying local file #{local_file} to #{remote_file} on container")
88
-
89
- remote_file = replace_env_variables(state, remote_file)
90
-
91
- remote_file = "#{state[:container_id]}:#{remote_file}"
92
- cmd = build_copy_command(local_file, remote_file)
93
- docker_command(cmd)
94
- rescue => e
95
- raise "Failed to copy file #{local_file} to container. #{e}"
96
- end
97
-
98
- def container_env_variables(state)
99
- # Retrieves all environment variables from inside container
100
- vars = {}
101
-
102
- if state[:platform].include?('windows')
103
- cmd = build_powershell_command('-Command [System.Environment]::GetEnvironmentVariables() ^| ConvertTo-Json')
104
- cmd = build_exec_command(state, cmd)
105
- stdout = docker_command(cmd, suppress_output: !logger.debug?).strip
106
- vars = ::JSON.parse(stdout)
107
- else
108
- cmd = build_exec_command(state, 'printenv')
109
- stdout = docker_command(cmd, suppress_output: !logger.debug?).strip
110
- stdout.split("\n").each { |line| vars[line.split('=')[0]] = line.split('=')[1] }
111
- end
112
-
113
- vars
114
- end
115
-
116
- def replace_env_variables(state, str)
117
- if str.include?('$env:')
118
- key = str[/\$env:(.*?)(\\|$)/, 1]
119
- value = container_env_variables(state)[key].to_s.strip
120
- str = str.gsub("$env:#{key}", value)
121
- elsif str.include?('$')
122
- key = str[/\$(.*?)(\/|$)/, 1]
123
- value = container_env_variables(state)[key].to_s.strip
124
- str = str.gsub("$#{key}", value)
125
- end
126
-
127
- str
128
- end
129
-
130
- def run_container(state, transport_port = nil)
131
- cmd = build_run_command(state[:image_id], transport_port)
132
- output = docker_command(cmd)
133
- parse_container_id(output)
134
- end
135
-
136
- def container_ip_address(state)
137
- cmd = "inspect --format '{{ .NetworkSettings.IPAddress }}'"
138
- cmd << " #{state[:container_id]}"
139
- docker_command(cmd).strip
140
- rescue
141
- raise ActionFailed, 'Error getting internal IP of Docker container'
142
- end
143
-
144
- def remove_container(state)
145
- container_id = state[:container_id]
146
- docker_command("stop -t 0 #{container_id}")
147
- docker_command("rm #{container_id}")
148
- end
149
-
150
- def dockerfile_proxy_config
151
- env_variables = ''
152
- if config[:http_proxy]
153
- env_variables << "ENV http_proxy #{config[:http_proxy]}\n"
154
- env_variables << "ENV HTTP_PROXY #{config[:http_proxy]}\n"
155
- end
156
-
157
- if config[:https_proxy]
158
- env_variables << "ENV https_proxy #{config[:https_proxy]}\n"
159
- env_variables << "ENV HTTPS_PROXY #{config[:https_proxy]}\n"
160
- end
161
-
162
- if config[:no_proxy]
163
- env_variables << "ENV no_proxy #{config[:no_proxy]}\n"
164
- env_variables << "ENV NO_PROXY #{config[:no_proxy]}\n"
165
- end
166
-
167
- env_variables
168
- end
169
- end
170
- end
171
- end
172
- end
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require "erb" unless defined?(Erb)
15
+ require "json" unless defined?(JSON)
16
+ require "shellwords" unless defined?(Shellwords)
17
+ require "tempfile" unless defined?(Tempfile)
18
+ require "uri" unless defined?(URI)
19
+
20
+ require "kitchen"
21
+ require "kitchen/configurable"
22
+ require_relative "../erb_context"
23
+ require_relative "cli_helper"
24
+
25
+ module Kitchen
26
+ module Docker
27
+ module Helpers
28
+ # rubocop:disable Metrics/ModuleLength, Style/Documentation
29
+ module ContainerHelper
30
+ include Configurable
31
+ include Kitchen::Docker::Helpers::CliHelper
32
+
33
+ def parse_container_id(output)
34
+ container_id = output.chomp
35
+
36
+ unless [12, 64].include?(container_id.size)
37
+ raise ActionFailed, "Could not parse Docker run output for container ID"
38
+ end
39
+
40
+ container_id
41
+ end
42
+
43
+ def dockerfile_template
44
+ template = IO.read(File.expand_path(config[:dockerfile]))
45
+ context = Kitchen::Docker::ERBContext.new(config.to_hash)
46
+ ERB.new(template).result(context.get_binding)
47
+ end
48
+
49
+ def remote_socket?
50
+ config[:socket] ? socket_uri.scheme == "tcp" : false
51
+ end
52
+
53
+ def socket_uri
54
+ URI.parse(config[:socket])
55
+ end
56
+
57
+ def dockerfile_path(file)
58
+ config[:build_context] ? Pathname.new(file.path).relative_path_from(Pathname.pwd).to_s : file.path
59
+ end
60
+
61
+ def container_exists?(state)
62
+ state[:container_id] && !!docker_command("top #{state[:container_id]}") rescue false
63
+ end
64
+
65
+ def container_exec(state, command)
66
+ cmd = build_exec_command(state, command)
67
+ docker_command(cmd)
68
+ rescue => e
69
+ raise "Failed to execute command on Docker container. #{e}"
70
+ end
71
+
72
+ def create_dir_on_container(state, path)
73
+ path = replace_env_variables(state, path)
74
+ cmd = "mkdir -p #{path}"
75
+
76
+ if state[:platform].include?("windows")
77
+ psh = "-Command if(-not (Test-Path '#{path}')) { New-Item -Path '#{path}' -Force }"
78
+ cmd = build_powershell_command(psh)
79
+ end
80
+
81
+ cmd = build_exec_command(state, cmd)
82
+ docker_command(cmd)
83
+ rescue => e
84
+ raise "Failed to create directory #{path} on container. #{e}"
85
+ end
86
+
87
+ def copy_file_to_container(state, local_file, remote_file)
88
+ debug("Copying local file #{local_file} to #{remote_file} on container")
89
+
90
+ remote_file = replace_env_variables(state, remote_file)
91
+
92
+ remote_file = "#{state[:container_id]}:#{remote_file}"
93
+ cmd = build_copy_command(local_file, remote_file)
94
+ docker_command(cmd)
95
+ rescue => e
96
+ raise "Failed to copy file #{local_file} to container. #{e}"
97
+ end
98
+
99
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
100
+ def container_env_variables(state)
101
+ # Retrieves all environment variables from inside container
102
+ vars = {}
103
+
104
+ if state[:platform].include?("windows")
105
+ cmd = build_powershell_command("-Command [System.Environment]::GetEnvironmentVariables() ^| ConvertTo-Json")
106
+ cmd = build_exec_command(state, cmd)
107
+ stdout = docker_command(cmd, suppress_output: !logger.debug?).strip
108
+ vars = ::JSON.parse(stdout)
109
+ else
110
+ cmd = build_exec_command(state, "printenv")
111
+ stdout = docker_command(cmd, suppress_output: !logger.debug?).strip
112
+ stdout.split("\n").each { |line| vars[line.split("=")[0]] = line.split("=")[1] }
113
+ end
114
+
115
+ vars
116
+ end
117
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
118
+
119
+ def replace_env_variables(state, str)
120
+ if str.include?("$env:")
121
+ key = str[/\$env:(.*?)(\\|$)/, 1]
122
+ value = container_env_variables(state)[key].to_s.strip
123
+ str = str.gsub("$env:#{key}", value)
124
+ elsif str.include?("$")
125
+ key = str[%r{\$(.*?)(/|$)}, 1]
126
+ value = container_env_variables(state)[key].to_s.strip
127
+ str = str.gsub("$#{key}", value)
128
+ end
129
+
130
+ str
131
+ end
132
+
133
+ def run_container(state, transport_port = nil)
134
+ cmd = build_run_command(state[:image_id], transport_port)
135
+ output = docker_command(cmd)
136
+ parse_container_id(output)
137
+ end
138
+
139
+ def container_ip_address(state)
140
+ cmd = "inspect --format '{{ .NetworkSettings.IPAddress }}'"
141
+ cmd << " #{state[:container_id]}"
142
+ docker_command(cmd).strip
143
+ rescue
144
+ raise ActionFailed, "Error getting internal IP of Docker container"
145
+ end
146
+
147
+ def remove_container(state)
148
+ container_id = state[:container_id]
149
+ docker_command("stop -t 0 #{container_id}")
150
+ docker_command("rm #{container_id}")
151
+ end
152
+
153
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
154
+ def dockerfile_proxy_config
155
+ env_variables = ""
156
+ if config[:http_proxy]
157
+ env_variables << "ENV http_proxy=#{config[:http_proxy]}\n"
158
+ env_variables << "ENV HTTP_PROXY=#{config[:http_proxy]}\n"
159
+ end
160
+
161
+ if config[:https_proxy]
162
+ env_variables << "ENV https_proxy=#{config[:https_proxy]}\n"
163
+ env_variables << "ENV HTTPS_PROXY=#{config[:https_proxy]}\n"
164
+ end
165
+
166
+ if config[:no_proxy]
167
+ env_variables << "ENV no_proxy=#{config[:no_proxy]}\n"
168
+ env_variables << "ENV NO_PROXY=#{config[:no_proxy]}\n"
169
+ end
170
+
171
+ env_variables
172
+ end
173
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
174
+ end
175
+ # rubocop:enable Metrics/ModuleLength, Style/Documentation
176
+ end
177
+ end
178
+ end
@@ -11,38 +11,40 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
 
14
- require 'kitchen'
15
- require 'kitchen/configurable'
14
+ require "kitchen"
15
+ require "kitchen/configurable"
16
16
 
17
17
  module Kitchen
18
18
  module Docker
19
19
  module Helpers
20
- module DockerfileHelper
20
+ module DockerfileHelper
21
21
  include Configurable
22
22
 
23
23
  def dockerfile_platform
24
24
  case config[:platform]
25
- when 'arch'
25
+ when "arch"
26
26
  arch_platform
27
- when 'debian', 'ubuntu'
27
+ when "debian", "ubuntu"
28
28
  debian_platform
29
- when 'fedora'
29
+ when "fedora"
30
30
  fedora_platform
31
- when 'gentoo'
31
+ when "gentoo"
32
32
  gentoo_platform
33
- when 'gentoo-paludis'
33
+ when "gentoo-paludis"
34
34
  gentoo_paludis_platform
35
- when 'opensuse/tumbleweed', 'opensuse/leap', 'opensuse', 'sles'
35
+ when "opensuse/tumbleweed", "opensuse/leap", "opensuse", "sles"
36
36
  opensuse_platform
37
- when 'rhel', 'centos', 'oraclelinux', 'amazonlinux'
37
+ when "rhel", "centos", "oraclelinux"
38
38
  rhel_platform
39
- when 'centosstream'
39
+ when "amazonlinux"
40
+ amazonlinux_platform
41
+ when "centosstream"
40
42
  centosstream_platform
41
- when 'almalinux'
43
+ when "almalinux"
42
44
  almalinux_platform
43
- when 'rockylinux'
45
+ when "rockylinux"
44
46
  rockylinux_platform
45
- when 'photon'
47
+ when "photon"
46
48
  photonos_platform
47
49
  else
48
50
  raise ActionFailed, "Unknown platform '#{config[:platform]}'"
@@ -50,15 +52,11 @@ module Kitchen
50
52
  end
51
53
 
52
54
  def arch_platform
53
- # See https://bugs.archlinux.org/task/47052 for why we
54
- # blank out limits.conf.
55
55
  <<-CODE
56
56
  RUN pacman --noconfirm -Sy archlinux-keyring
57
57
  RUN pacman-db-upgrade
58
58
  RUN pacman --noconfirm -Syu openssl openssh sudo curl
59
59
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key
60
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key
61
- RUN echo >/etc/security/limits.conf
62
60
  CODE
63
61
  end
64
62
 
@@ -68,8 +66,8 @@ module Kitchen
68
66
  && ln -sf /bin/true /sbin/initctl
69
67
  CODE
70
68
  packages = <<-CODE
71
- ENV DEBIAN_FRONTEND noninteractive
72
- ENV container docker
69
+ ENV DEBIAN_FRONTEND=noninteractive
70
+ ENV container=docker
73
71
  RUN apt-get update
74
72
  RUN apt-get install -y sudo openssh-server curl lsb-release
75
73
  CODE
@@ -78,11 +76,10 @@ module Kitchen
78
76
 
79
77
  def fedora_platform
80
78
  <<-CODE
81
- ENV container docker
79
+ ENV container=docker
82
80
  RUN dnf clean all
83
81
  RUN dnf install -y sudo openssh-server openssh-clients which curl
84
82
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
85
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
86
83
  CODE
87
84
  end
88
85
 
@@ -91,7 +88,6 @@ module Kitchen
91
88
  RUN emerge-webrsync
92
89
  RUN emerge --quiet --noreplace net-misc/openssh app-admin/sudo
93
90
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key
94
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key
95
91
  CODE
96
92
  end
97
93
 
@@ -100,13 +96,12 @@ module Kitchen
100
96
  RUN cave sync
101
97
  RUN cave resolve -zx net-misc/openssh app-admin/sudo
102
98
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key
103
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key
104
99
  CODE
105
100
  end
106
101
 
107
102
  def opensuse_platform
108
103
  <<-CODE
109
- ENV container docker
104
+ ENV container=docker
110
105
  RUN zypper install -y sudo openssh which curl gawk
111
106
  RUN /usr/sbin/sshd-gen-keys-start
112
107
  CODE
@@ -114,47 +109,52 @@ module Kitchen
114
109
 
115
110
  def rhel_platform
116
111
  <<-CODE
117
- ENV container docker
112
+ ENV container=docker
118
113
  RUN yum clean all
119
114
  RUN yum install -y sudo openssh-server openssh-clients which curl
120
115
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
121
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
116
+ CODE
117
+ end
118
+
119
+ def amazonlinux_platform
120
+ <<-CODE
121
+ ENV container=docker
122
+ RUN yum clean all
123
+ RUN yum install -y --allowerasing sudo openssh-server openssh-clients which curl
124
+ RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
122
125
  CODE
123
126
  end
124
127
 
125
128
  def centosstream_platform
126
129
  <<-CODE
127
- ENV container docker
130
+ ENV container=docker
128
131
  RUN yum clean all
129
132
  RUN yum install -y sudo openssh-server openssh-clients which
130
133
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
131
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
132
134
  CODE
133
135
  end
134
136
 
135
137
  def almalinux_platform
136
138
  <<-CODE
137
- ENV container docker
139
+ ENV container=docker
138
140
  RUN yum clean all
139
141
  RUN yum install -y sudo openssh-server openssh-clients which
140
142
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
141
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
142
143
  CODE
143
144
  end
144
145
 
145
146
  def rockylinux_platform
146
147
  <<-CODE
147
- ENV container docker
148
+ ENV container=docker
148
149
  RUN yum clean all
149
150
  RUN yum install -y sudo openssh-server openssh-clients which
150
151
  RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
151
- RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
152
152
  CODE
153
153
  end
154
154
 
155
155
  def photonos_platform
156
156
  <<-CODE
157
- ENV container docker
157
+ ENV container=docker
158
158
  RUN tdnf clean all
159
159
  RUN tdnf install -y sudo openssh-server openssh-clients which curl
160
160
  RUN [ -f "/etc/ssh/ssh_host_ecdsa_key" ] || ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ''
@@ -11,7 +11,7 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
 
14
- require 'fileutils'
14
+ require "fileutils" unless defined?(FileUtils)
15
15
 
16
16
  module Kitchen
17
17
  module Docker
@@ -19,14 +19,14 @@ module Kitchen
19
19
  module FileHelper
20
20
  def create_temp_file(file, contents)
21
21
  debug("[Docker] Creating temp file #{file}")
22
- debug('[Docker] --- Start Temp File Contents ---')
22
+ debug("[Docker] --- Start Temp File Contents ---")
23
23
  debug(contents)
24
- debug('[Docker] --- End Temp File Contents ---')
24
+ debug("[Docker] --- End Temp File Contents ---")
25
25
 
26
26
  begin
27
27
  path = ::File.dirname(file)
28
28
  ::FileUtils.mkdir_p(path) unless ::Dir.exist?(path)
29
- file = ::File.open(file, 'w')
29
+ file = ::File.open(file, "w")
30
30
  file.write(contents)
31
31
  rescue IOError => e
32
32
  raise "Failed to write temp file. Error Details: #{e}"
@@ -11,11 +11,11 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
 
14
- require 'kitchen'
15
- require 'kitchen/configurable'
16
- require 'pathname'
17
- require_relative 'cli_helper'
18
- require_relative 'container_helper'
14
+ require "kitchen"
15
+ require "kitchen/configurable"
16
+ require "pathname" unless defined?(Pathname)
17
+ require_relative "cli_helper"
18
+ require_relative "container_helper"
19
19
 
20
20
  module Kitchen
21
21
  module Docker
@@ -28,38 +28,52 @@ module Kitchen
28
28
  def parse_image_id(output)
29
29
  output.split("\n").reverse_each do |line|
30
30
  if line =~ /writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i
31
- img_id = line[/writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i,1]
31
+ img_id = line[/writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i, 1]
32
32
  return img_id
33
33
  end
34
34
  if line =~ /image id|build successful|successfully built/i
35
35
  img_id = line.split(/\s+/).last
36
36
  return img_id
37
37
  end
38
+ # Docker ~v4.31 support
39
+ if line =~ /naming to moby-dangling@(sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i
40
+ img_id = line[/naming to moby-dangling@(sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i, 1]
41
+ return img_id
42
+ end
38
43
  end
39
- raise ActionFailed, 'Could not parse Docker build output for image ID'
44
+ raise ActionFailed, "Could not parse Docker build output for image ID"
40
45
  end
41
46
 
42
47
  def remove_image(state)
43
48
  image_id = state[:image_id]
44
- docker_command("rmi #{image_id}")
49
+ if image_in_use?(state)
50
+ info("[Docker] Image ID #{image_id} is in use. Skipping removal")
51
+ else
52
+ info("[Docker] Removing image with Image ID #{image_id}.")
53
+ docker_command("rmi #{image_id}")
54
+ end
55
+ end
56
+
57
+ def image_in_use?(state)
58
+ docker_command("ps -a", suppress_output: !logger.debug?).include?(state[:image_id])
45
59
  end
46
60
 
47
61
  def build_image(state, dockerfile)
48
- cmd = 'build'
49
- cmd << ' --no-cache' unless config[:use_cache]
62
+ cmd = "build"
63
+ cmd << " --no-cache" unless config[:use_cache]
50
64
  cmd << " --platform=#{config[:docker_platform]}" if config[:docker_platform]
51
65
  extra_build_options = config_to_options(config[:build_options])
52
66
  cmd << " #{extra_build_options}" unless extra_build_options.empty?
53
67
  dockerfile_contents = dockerfile
54
- file = Tempfile.new('Dockerfile-kitchen', Pathname.pwd + config[:build_tempdir])
68
+ file = Tempfile.new("Dockerfile-kitchen", Pathname.pwd + config[:build_tempdir])
55
69
  cmd << " -f #{Shellwords.escape(dockerfile_path(file))}" if config[:build_context]
56
- build_context = config[:build_context] ? '.' : '-'
70
+ build_context = config[:build_context] ? "." : "-"
57
71
  output = begin
58
72
  file.write(dockerfile)
59
73
  file.close
60
74
  docker_command("#{cmd} #{build_context}",
61
- input: dockerfile_contents,
62
- environment: { BUILDKIT_PROGRESS: 'plain' })
75
+ input: dockerfile_contents,
76
+ environment: { BUILDKIT_PROGRESS: "plain" })
63
77
  ensure
64
78
  file.close unless file.closed?
65
79
  file.unlink