kitchen-docker 2.15.0 → 3.0.0

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: 2a90dcbcb9d7867d3600976b04316ebc8bb26edc05c67913a539748bac45c52a
4
- data.tar.gz: 582e8c53e995ec7d772a8d8580f582edbbff4a64648fc4e5ac41d657c40a2a59
3
+ metadata.gz: 59f474a4b47b1241d911ba83df23847d6b172347bc0650d29191e9f473dd91ab
4
+ data.tar.gz: 31e3d8136d2787b36ea1ff0dc7abbace0f75f4cd036806f0c9c90b82c91fa31d
5
5
  SHA512:
6
- metadata.gz: 121b7a903fe8748c082b9746ed47df1a159652345f1a2e0c26aef04cf1f07e6c69b82b18fa3ab49ed17b93bddfbae69f32bb3839ccb41d3f8ffde9654bf574df
7
- data.tar.gz: be747b9b96ea67b8848f25ad77d68edf5272201daafeb3f5f93902ceac7e2899322db2ebd5bed75682a81dafa4e85642d2872efb7ad4a9f9479f8cfe2f1de627
6
+ metadata.gz: acf29b3e7719ae79e79e628465c0c2fbb5ea412fcbaf21a70155dc545b0e0eea9927b344c8f8cf18711fdb0c57ade058611008be9fba8721f7f70cb9e55c89ee
7
+ data.tar.gz: 9e475cab2c9c0abd8312865cbdfaa85c00e8f5bb70d2a052f7380513e09b5a30ca317b78a6644109721b2986f94c1f882b8c6478da745768a08275a4e9cf8b30
@@ -1,7 +1,7 @@
1
1
  version: 2
2
2
  updates:
3
- - package-ecosystem: bundler
4
- directory: "/"
5
- schedule:
6
- interval: daily
7
- open-pull-requests-limit: 10
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 10
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: Lint & Unit
3
+
4
+ "on":
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ jobs:
11
+ yamllint:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Check out code
15
+ uses: actions/checkout@v4
16
+ - name: Run yaml Lint
17
+ uses: actionshub/yamllint@main
18
+
19
+ chefstyle:
20
+ runs-on: ubuntu-latest
21
+ continue-on-error: true
22
+ strategy:
23
+ matrix:
24
+ ruby: ["3.1"]
25
+ name: Chefstyle on Ruby ${{ matrix.ruby }}
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby }}
31
+ bundler-cache: true
32
+ - uses: r7kamura/rubocop-problem-matchers-action@v1
33
+ - run: bundle exec chefstyle
34
+
35
+ unit:
36
+ name: Unit test on Ruby ${{ matrix.ruby }}
37
+ needs: [yamllint, chefstyle]
38
+ runs-on: ubuntu-latest
39
+ strategy:
40
+ matrix:
41
+ ruby: ["2.7", "3.0", "3.1"]
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: ruby/setup-ruby@v1
45
+ with:
46
+ ruby-version: ${{ matrix.ruby }}
47
+ bundler-cache: true
48
+ - run: bundle exec rake spec
49
+
50
+ integration-windows:
51
+ name: Windows ${{matrix.suite}} ${{matrix.os}}
52
+ runs-on: windows-latest
53
+ needs: unit
54
+ strategy:
55
+ fail-fast: false
56
+ matrix:
57
+ suite: [default]
58
+ os: [ubuntu-20.04]
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ - uses: ruby/setup-ruby@v1
62
+ with:
63
+ ruby-version: "3.1"
64
+ bundler-cache: true
65
+ - name: Set up Docker Buildx
66
+ uses: docker/setup-buildx-action@v3
67
+ - run: bundle exec kitchen test ${{ matrix.suite }}-${{ matrix.os }}
68
+
69
+ integration-linux:
70
+ name: Linux ${{matrix.suite}} ${{matrix.os}}
71
+ runs-on: ubuntu-latest
72
+ needs: unit
73
+ strategy:
74
+ fail-fast: false
75
+ matrix:
76
+ suite:
77
+ - default
78
+ - no-build-context
79
+ - arm64
80
+ - amd64
81
+ - inspec
82
+ os:
83
+ - amazonlinux-2
84
+ - ubuntu-1804
85
+ - ubuntu-2004
86
+ - fedora-latest
87
+ - centos-7
88
+ - oraclelinux-7
89
+ - rockylinux-8
90
+ - debian-11
91
+ - debian-12
92
+ - opensuse-15
93
+ - dockerfile
94
+ steps:
95
+ - uses: actions/checkout@v2
96
+ - uses: ruby/setup-ruby@v1
97
+ with:
98
+ ruby-version: "3.1"
99
+ bundler-cache: true
100
+ - name: Set up QEMU
101
+ uses: docker/setup-qemu-action@v3
102
+ - name: Set up Docker Buildx
103
+ uses: docker/setup-buildx-action@v3
104
+ - run: bundle exec kitchen test ${{ matrix.suite }}-${{ matrix.os }}
105
+
106
+ integration-capabilities:
107
+ name: Linux ${{matrix.suite}} ${{matrix.os}}
108
+ runs-on: ubuntu-latest
109
+ needs: unit
110
+ strategy:
111
+ fail-fast: false
112
+ matrix:
113
+ suite:
114
+ - capabilities
115
+ os: [debian-11, ubuntu-1804, ubuntu-2004]
116
+ steps:
117
+ - uses: actions/checkout@v2
118
+ - uses: ruby/setup-ruby@v1
119
+ with:
120
+ ruby-version: "3.1"
121
+ bundler-cache: true
122
+ - name: Set up Docker Buildx
123
+ uses: docker/setup-buildx-action@v3
124
+ - run: bundle exec kitchen test ${{ matrix.suite }}-${{ matrix.os }}
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ require:
2
+ - chefstyle
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 3.1
6
+ Include:
7
+ - "**/*.rb"
8
+ Exclude:
9
+ - "vendor/**/*"
10
+ - "spec/**/*"
data/.yamllint ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ extends: default
3
+ rules:
4
+ line-length:
5
+ max: 256
6
+ level: warning
7
+ document-start: disable
8
+ braces:
9
+ forbid: false
10
+ min-spaces-inside: 0
11
+ max-spaces-inside: 1
12
+ min-spaces-inside-empty: -1
13
+ max-spaces-inside-empty: -1
14
+ comments:
15
+ min-spaces-from-content: 1
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'fuubar', '~> 2.0'
33
33
  spec.add_development_dependency 'simplecov', '~> 0.9'
34
34
  spec.add_development_dependency 'codecov', '~> 0.0', '>= 0.0.2'
35
+ spec.add_development_dependency 'chefstyle'
35
36
 
36
37
  # Integration testing gems.
37
38
  spec.add_development_dependency 'kitchen-inspec', '~> 2.0'
@@ -0,0 +1,33 @@
1
+ # <% # Make sure the local copy of the driver is loaded %>
2
+ # <% lib = File.expand_path('../lib', __FILE__) %>
3
+ # <% $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) %>
4
+ ---
5
+ driver:
6
+ name: docker
7
+ provision_command:
8
+ - powershell -ExecutionPolicy Bypass -NoLogo -Command . { iwr -useb https://omnitruck.chef.io/install.ps1 } ^| iex; install
9
+ - powershell -Command $path=$env:Path + ';c:\opscode\chef\embedded\bin'; Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\' -Name Path -Value $path
10
+
11
+ transport:
12
+ name: docker
13
+ socket: tcp://localhost:2375
14
+
15
+ provisioner:
16
+ name: dummy
17
+
18
+ platforms:
19
+ - name: windows
20
+ driver_config:
21
+ image: mcr.microsoft.com/windows/servercore:1809
22
+ platform: windows
23
+
24
+ suites:
25
+ - name: default
26
+ - name: context
27
+ driver:
28
+ build_context: false
29
+ - name: inspec
30
+ driver:
31
+ provision_command: echo 1
32
+ verifier:
33
+ name: inspec
data/kitchen.yml ADDED
@@ -0,0 +1,62 @@
1
+ # <% # Make sure the local copy of the driver is loaded %>
2
+ # <% lib = File.expand_path('../lib', __FILE__) %>
3
+ # <% $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) %>
4
+ ---
5
+ driver:
6
+ name: docker
7
+ provision_command: curl -L https://www.chef.io/chef/install.sh | bash
8
+
9
+ transport:
10
+ name: docker
11
+
12
+ provisioner:
13
+ name: dummy
14
+
15
+ platforms:
16
+ - name: amazonlinux-2
17
+ - name: ubuntu-18.04
18
+ - name: ubuntu-20.04
19
+ - name: fedora-latest
20
+ driver:
21
+ provision_command:
22
+ - yum install libxcrypt-compat -y
23
+ - curl -L https://www.chef.io/chef/install.sh | bash
24
+ - name: centos-7
25
+ - name: oraclelinux-7
26
+ - name: rockylinux-8
27
+ - name: debian-11
28
+ - name: debian-12
29
+ - name: opensuse-15
30
+ driver:
31
+ image: opensuse/leap:15
32
+ - name: dockerfile
33
+ driver:
34
+ username: dockerfile
35
+ password: dockerfile
36
+ dockerfile: test/Dockerfile
37
+ run_command: /sbin/init
38
+
39
+ suites:
40
+ - name: default
41
+ - name: no_build_context
42
+ driver:
43
+ build_context: false
44
+ - name: capabilities
45
+ includes: [debian-11, ubuntu-18.04, ubuntu-20.04]
46
+ driver:
47
+ provision_command:
48
+ - curl -L https://www.chef.io/chef/install.sh | bash
49
+ - apt-get install -y net-tools
50
+ cap_drop:
51
+ - NET_ADMIN
52
+ - name: arm64
53
+ driver:
54
+ docker_platform: linux/arm64
55
+ - name: amd64
56
+ driver:
57
+ docker_platform: linux/amd64
58
+ - name: inspec
59
+ driver:
60
+ provision_command: true
61
+ verifier:
62
+ name: inspec
@@ -16,6 +16,6 @@
16
16
  module Kitchen
17
17
  module Docker
18
18
  # Version string for Docker Kitchen driver
19
- DOCKER_VERSION = "2.15.0"
19
+ DOCKER_VERSION = "3.0.0"
20
20
  end
21
21
  end
@@ -1,172 +1,184 @@
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 'kitchen'
15
- require 'kitchen/configurable'
16
- require 'kitchen/logging'
17
- require 'kitchen/shell_out'
18
-
19
- module Kitchen
20
- module Docker
21
- module Helpers
22
- module CliHelper
23
- include Configurable
24
- include Logging
25
- include ShellOut
26
-
27
- def docker_command(cmd, options={})
28
- docker = config[:binary].dup
29
- docker << " -H #{config[:socket]}" if config[:socket]
30
- docker << ' --tls' if config[:tls]
31
- docker << ' --tlsverify' if config[:tls_verify]
32
- docker << " --tlscacert=#{config[:tls_cacert]}" if config[:tls_cacert]
33
- docker << " --tlscert=#{config[:tls_cert]}" if config[:tls_cert]
34
- docker << " --tlskey=#{config[:tls_key]}" if config[:tls_key]
35
- logger.debug("docker_command: #{docker} #{cmd} shell_opts: #{docker_shell_opts(options)}")
36
- run_command("#{docker} #{cmd}", docker_shell_opts(options))
37
- end
38
-
39
- # Copied from kitchen because we need stderr
40
- def run_command(cmd, options = {})
41
- if options.fetch(:use_sudo, false)
42
- cmd = "#{options.fetch(:sudo_command, "sudo -E")} #{cmd}"
43
- end
44
- subject = "[#{options.fetch(:log_subject, "local")} command]"
45
-
46
- debug("#{subject} BEGIN (#{cmd})")
47
- sh = Mixlib::ShellOut.new(cmd, shell_opts(options))
48
- sh.run_command
49
- debug("#{subject} END #{Util.duration(sh.execution_time)}")
50
- sh.error!
51
- sh.stdout + sh.stderr
52
- rescue Mixlib::ShellOut::ShellCommandFailed => ex
53
- raise ShellCommandFailed, ex.message
54
- rescue Exception => error # rubocop:disable Lint/RescueException
55
- error.extend(Kitchen::Error)
56
- raise
57
- end
58
-
59
- def build_run_command(image_id, transport_port = nil)
60
- cmd = 'run -d'
61
- cmd << ' -i' if config[:interactive]
62
- cmd << ' -t' if config[:tty]
63
- cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables]
64
- cmd << " -p #{transport_port}" unless transport_port.nil?
65
- Array(config[:forward]).each { |port| cmd << " -p #{port}" }
66
- Array(config[:dns]).each { |dns| cmd << " --dns #{dns}" }
67
- Array(config[:add_host]).each { |host, ip| cmd << " --add-host=#{host}:#{ip}" }
68
- Array(config[:volume]).each { |volume| cmd << " -v #{volume}" }
69
- Array(config[:volumes_from]).each { |container| cmd << " --volumes-from #{container}" }
70
- Array(config[:links]).each { |link| cmd << " --link #{link}" }
71
- Array(config[:devices]).each { |device| cmd << " --device #{device}" }
72
- Array(config[:mount]).each {|mount| cmd << " --mount #{mount}"}
73
- Array(config[:tmpfs]).each {|tmpfs| cmd << " --tmpfs #{tmpfs}"}
74
- cmd << " --name #{config[:instance_name]}" if config[:instance_name]
75
- cmd << ' -P' if config[:publish_all]
76
- cmd << " -h #{config[:hostname]}" if config[:hostname]
77
- cmd << " -m #{config[:memory]}" if config[:memory]
78
- cmd << " -c #{config[:cpu]}" if config[:cpu]
79
- cmd << " --gpus #{config[:gpus]}" if config[:gpus]
80
- cmd << " -e http_proxy=#{config[:http_proxy]}" if config[:http_proxy]
81
- cmd << " -e https_proxy=#{config[:https_proxy]}" if config[:https_proxy]
82
- cmd << ' --privileged' if config[:privileged]
83
- cmd << " --isolation #{config[:isolation]}" if config[:isolation]
84
- Array(config[:cap_add]).each { |cap| cmd << " --cap-add=#{cap}"} if config[:cap_add]
85
- Array(config[:cap_drop]).each { |cap| cmd << " --cap-drop=#{cap}"} if config[:cap_drop]
86
- Array(config[:security_opt]).each { |opt| cmd << " --security-opt=#{opt}"} if config[:security_opt]
87
- cmd << " --platform=#{config[:docker_platform]}" if config[:docker_platform]
88
- extra_run_options = config_to_options(config[:run_options])
89
- cmd << " #{extra_run_options}" unless extra_run_options.empty?
90
- cmd << " #{image_id} #{config[:run_command]}"
91
- logger.debug("build_run_command: #{cmd}")
92
- cmd
93
- end
94
-
95
- def build_exec_command(state, command)
96
- cmd = 'exec'
97
- cmd << ' -d' if config[:detach]
98
- cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables]
99
- cmd << ' --privileged' if config[:privileged]
100
- cmd << ' -t' if config[:tty]
101
- cmd << ' -i' if config[:interactive]
102
- cmd << " -u #{config[:username]}" if config[:username]
103
- cmd << " -w #{config[:working_dir]}" if config[:working_dir]
104
- cmd << " #{state[:container_id]}"
105
- cmd << " #{command}"
106
- logger.debug("build_exec_command: #{cmd}")
107
- cmd
108
- end
109
-
110
- def build_copy_command(local_file, remote_file, opts = {})
111
- cmd = 'cp'
112
- cmd << ' -a' if opts[:archive]
113
- cmd << " #{local_file} #{remote_file}"
114
- cmd
115
- end
116
-
117
- def build_powershell_command(args)
118
- cmd = 'powershell -ExecutionPolicy Bypass -NoLogo '
119
- cmd << args
120
- logger.debug("build_powershell_command: #{cmd}")
121
- cmd
122
- end
123
-
124
- def build_env_variable_args(vars)
125
- raise ActionFailed, 'Environment variables are not of a Hash type' unless vars.is_a?(Hash)
126
-
127
- args = ''
128
- vars.each do |k, v|
129
- args << " -e #{k.to_s.strip}=\"#{v.to_s.strip}\""
130
- end
131
-
132
- args
133
- end
134
-
135
- def dev_null
136
- case RbConfig::CONFIG['host_os']
137
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
138
- 'NUL'
139
- else
140
- '/dev/null'
141
- end
142
- end
143
-
144
- def docker_shell_opts(options = {})
145
- options[:live_stream] = nil if options[:suppress_output]
146
- options.delete(:suppress_output)
147
-
148
- options
149
- end
150
-
151
- # Convert the config input for `:build_options` or `:run_options` in to a
152
- # command line string for use with Docker.
153
- #
154
- # @since 2.5.0
155
- # @param config [nil, String, Array, Hash] Config data to convert.
156
- # @return [String]
157
- def config_to_options(config)
158
- case config
159
- when nil
160
- ''
161
- when String
162
- config
163
- when Array
164
- config.map { |c| config_to_options(c) }.join(' ')
165
- when Hash
166
- config.map { |k, v| Array(v).map { |c| "--#{k}=#{Shellwords.escape(c)}" }.join(' ') }.join(' ')
167
- end
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 'kitchen'
15
+ require 'kitchen/configurable'
16
+ require 'kitchen/logging'
17
+ require 'kitchen/shell_out'
18
+
19
+ module Kitchen
20
+ module Docker
21
+ module Helpers
22
+ # rubocop:disable Metrics/ModuleLength, Style/Documentation
23
+ module CliHelper
24
+ include Configurable
25
+ include Logging
26
+ include ShellOut
27
+
28
+ # rubocop:disable Metrics/AbcSize
29
+ def docker_command(cmd, options={})
30
+ docker = config[:binary].dup
31
+ docker << " -H #{config[:socket]}" if config[:socket]
32
+ docker << ' --tls' if config[:tls]
33
+ docker << ' --tlsverify' if config[:tls_verify]
34
+ docker << " --tlscacert=#{config[:tls_cacert]}" if config[:tls_cacert]
35
+ docker << " --tlscert=#{config[:tls_cert]}" if config[:tls_cert]
36
+ docker << " --tlskey=#{config[:tls_key]}" if config[:tls_key]
37
+ logger.debug("docker_command: #{docker} #{cmd} shell_opts: #{docker_shell_opts(options)}")
38
+ run_command("#{docker} #{cmd}", docker_shell_opts(options))
39
+ end
40
+ # rubocop:enable Metrics/AbcSize
41
+
42
+ # Copied from kitchen because we need stderr
43
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
44
+ def run_command(cmd, options = {})
45
+ if options.fetch(:use_sudo, false)
46
+ cmd = "#{options.fetch(:sudo_command, "sudo -E")} #{cmd}"
47
+ end
48
+ subject = "[#{options.fetch(:log_subject, "local")} command]"
49
+
50
+ debug("#{subject} BEGIN (#{cmd})")
51
+ sh = Mixlib::ShellOut.new(cmd, shell_opts(options))
52
+ sh.run_command
53
+ debug("#{subject} END #{Util.duration(sh.execution_time)}")
54
+ sh.error!
55
+ sh.stdout + sh.stderr
56
+ rescue Mixlib::ShellOut::ShellCommandFailed => ex
57
+ raise ShellCommandFailed, ex.message
58
+ rescue Exception => error # rubocop:disable Lint/RescueException
59
+ error.extend(Kitchen::Error)
60
+ raise
61
+ end
62
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
63
+
64
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
65
+ def build_run_command(image_id, transport_port = nil)
66
+ cmd = 'run -d'
67
+ cmd << ' -i' if config[:interactive]
68
+ cmd << ' -t' if config[:tty]
69
+ cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables]
70
+ cmd << " -p #{transport_port}" unless transport_port.nil?
71
+ Array(config[:forward]).each { |port| cmd << " -p #{port}" }
72
+ Array(config[:dns]).each { |dns| cmd << " --dns #{dns}" }
73
+ Array(config[:add_host]).each { |host, ip| cmd << " --add-host=#{host}:#{ip}" }
74
+ Array(config[:volume]).each { |volume| cmd << " -v #{volume}" }
75
+ Array(config[:volumes_from]).each { |container| cmd << " --volumes-from #{container}" }
76
+ Array(config[:links]).each { |link| cmd << " --link #{link}" }
77
+ Array(config[:devices]).each { |device| cmd << " --device #{device}" }
78
+ Array(config[:mount]).each {|mount| cmd << " --mount #{mount}"}
79
+ Array(config[:tmpfs]).each {|tmpfs| cmd << " --tmpfs #{tmpfs}"}
80
+ cmd << " --name #{config[:instance_name]}" if config[:instance_name]
81
+ cmd << ' -P' if config[:publish_all]
82
+ cmd << " -h #{config[:hostname]}" if config[:hostname]
83
+ cmd << " -m #{config[:memory]}" if config[:memory]
84
+ cmd << " -c #{config[:cpu]}" if config[:cpu]
85
+ cmd << " --gpus #{config[:gpus]}" if config[:gpus]
86
+ cmd << " -e http_proxy=#{config[:http_proxy]}" if config[:http_proxy]
87
+ cmd << " -e https_proxy=#{config[:https_proxy]}" if config[:https_proxy]
88
+ cmd << ' --privileged' if config[:privileged]
89
+ cmd << " --isolation #{config[:isolation]}" if config[:isolation]
90
+ Array(config[:cap_add]).each { |cap| cmd << " --cap-add=#{cap}"} if config[:cap_add]
91
+ Array(config[:cap_drop]).each { |cap| cmd << " --cap-drop=#{cap}"} if config[:cap_drop]
92
+ Array(config[:security_opt]).each { |opt| cmd << " --security-opt=#{opt}"} if config[:security_opt]
93
+ cmd << " --platform=#{config[:docker_platform]}" if config[:docker_platform]
94
+ extra_run_options = config_to_options(config[:run_options])
95
+ cmd << " #{extra_run_options}" unless extra_run_options.empty?
96
+ cmd << " #{image_id} #{config[:run_command]}"
97
+ logger.debug("build_run_command: #{cmd}")
98
+ cmd
99
+ end
100
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
101
+
102
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize
103
+ def build_exec_command(state, command)
104
+ cmd = 'exec'
105
+ cmd << ' -d' if config[:detach]
106
+ cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables]
107
+ cmd << ' --privileged' if config[:privileged]
108
+ cmd << ' -t' if config[:tty]
109
+ cmd << ' -i' if config[:interactive]
110
+ cmd << " -u #{config[:username]}" if config[:username]
111
+ cmd << " -w #{config[:working_dir]}" if config[:working_dir]
112
+ cmd << " #{state[:container_id]}"
113
+ cmd << " #{command}"
114
+ logger.debug("build_exec_command: #{cmd}")
115
+ cmd
116
+ end
117
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize
118
+
119
+ def build_copy_command(local_file, remote_file, opts = {})
120
+ cmd = 'cp'
121
+ cmd << ' -a' if opts[:archive]
122
+ cmd << " #{local_file} #{remote_file}"
123
+ cmd
124
+ end
125
+
126
+ def build_powershell_command(args)
127
+ cmd = 'powershell -ExecutionPolicy Bypass -NoLogo '
128
+ cmd << args
129
+ logger.debug("build_powershell_command: #{cmd}")
130
+ cmd
131
+ end
132
+
133
+ def build_env_variable_args(vars)
134
+ raise ActionFailed, 'Environment variables are not of a Hash type' unless vars.is_a?(Hash)
135
+
136
+ args = ''
137
+ vars.each do |k, v|
138
+ args << " -e #{k.to_s.strip}=\"#{v.to_s.strip}\""
139
+ end
140
+
141
+ args
142
+ end
143
+
144
+ def dev_null
145
+ case RbConfig::CONFIG['host_os']
146
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
147
+ 'NUL'
148
+ else
149
+ '/dev/null'
150
+ end
151
+ end
152
+
153
+ def docker_shell_opts(options = {})
154
+ options[:live_stream] = nil if options[:suppress_output]
155
+ options.delete(:suppress_output)
156
+
157
+ options
158
+ end
159
+
160
+ # Convert the config input for `:build_options` or `:run_options` in to a
161
+ # command line string for use with Docker.
162
+ #
163
+ # @since 2.5.0
164
+ # @param config [nil, String, Array, Hash] Config data to convert.
165
+ # @return [String]
166
+ # rubocop:disable Metrics/CyclomaticComplexity
167
+ def config_to_options(config)
168
+ case config
169
+ when nil
170
+ ''
171
+ when String
172
+ config
173
+ when Array
174
+ config.map { |c| config_to_options(c) }.join(' ')
175
+ when Hash
176
+ config.map { |k, v| Array(v).map { |c| "--#{k}=#{Shellwords.escape(c)}" }.join(' ') }.join(' ')
177
+ end
178
+ end
179
+ # rubocop:enable Metrics/CyclomaticComplexity
180
+ end
181
+ # rubocop:enable Metrics/ModuleLength, Style/Documentation
182
+ end
183
+ end
184
+ end