From a9995e75162d553a73d2944ee9d1343f9fd98289 Mon Sep 17 00:00:00 2001 From: Dan Webb Date: Sat, 25 Nov 2023 22:27:45 +0000 Subject: [PATCH] Run chefstlye over the codebase (#408) - Run chefstyle - Move development dependencies into the Gemfile - Remove tailor and cane which are no longer maintained Signed-off-by: Dan Webb --- .cane | 0 .tailor | 4 - Gemfile | 19 +++++ Rakefile | 34 +++----- kitchen-docker.gemspec | 38 +++------ lib/docker/version.rb | 6 +- lib/kitchen/docker/container.rb | 12 +-- lib/kitchen/docker/container/linux.rb | 34 ++++---- lib/kitchen/docker/container/windows.rb | 22 ++--- lib/kitchen/docker/docker_version.rb | 2 +- lib/kitchen/docker/erb_context.rb | 6 +- lib/kitchen/docker/helpers/cli_helper.rb | 66 +++++++-------- .../docker/helpers/container_helper.rb | 42 +++++----- .../docker/helpers/dockerfile_helper.rb | 28 +++---- lib/kitchen/docker/helpers/file_helper.rb | 8 +- lib/kitchen/docker/helpers/image_helper.rb | 24 +++--- lib/kitchen/docker/helpers/inspec_helper.rb | 80 +++++++++---------- lib/kitchen/driver/docker.rb | 74 ++++++++--------- lib/kitchen/transport/docker.rb | 30 +++---- lib/train/docker.rb | 15 ++-- test/integration/inspec/inspec_spec.rb | 6 +- test/spec/docker_spec.rb | 48 +++++------ test/spec/spec_helper.rb | 22 ++--- 23 files changed, 297 insertions(+), 323 deletions(-) delete mode 100644 .cane delete mode 100644 .tailor diff --git a/.cane b/.cane deleted file mode 100644 index e69de29b..00000000 diff --git a/.tailor b/.tailor deleted file mode 100644 index b7a10780..00000000 --- a/.tailor +++ /dev/null @@ -1,4 +0,0 @@ -Tailor.config do |config| - config.formatters "text" - config.file_set 'lib/**/*.rb' -end diff --git a/Gemfile b/Gemfile index fa75df15..025550b6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,22 @@ source 'https://rubygems.org' gemspec + +group :development do + gem 'bundler' + gem 'rake' + # Style checker gems. + gem 'countloc' + + # Unit testing gems. + gem 'rspec', '~> 3.2' + gem 'rspec-its', '~> 1.2' + gem 'fuubar', '~> 2.0' + # gem 'simplecov', '~> 0.9' + gem 'codecov', '~> 0.0', '>= 0.0.2' + gem 'chefstyle', '~> 2.2', '>= 2.2.3' + + # Integration testing gems. + gem 'kitchen-inspec', '~> 2.0' + gem 'train', '>= 2.1', '< 4.0' # validate 4.x when it's released +end diff --git a/Rakefile b/Rakefile index d956b96c..f237487d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,13 +1,4 @@ require "bundler/gem_tasks" -require 'cane/rake_task' -require 'tailor/rake_task' - -desc "Run cane to check quality metrics" -Cane::RakeTask.new do |cane| - cane.canefile = './.cane' -end - -Tailor::RakeTask.new desc "Display LOC stats" task :stats do @@ -16,27 +7,20 @@ task :stats do end desc "Run all quality tasks" -task :quality => [:cane, :tailor, :stats] - -task :default => [:quality] +task quality: [:stats] -# begin -# require 'kitchen/rake_tasks' -# Kitchen::RakeTasks.new -# rescue LoadError -# puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] -# end +task default: [:quality] # Create the spec task. -require 'rspec/core/rake_task' +require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec, :tag) do |t, args| t.rspec_opts = [].tap do |a| - a << '--color' - a << "--format #{ENV['CI'] ? 'documentation' : 'Fuubar'}" - a << '--backtrace' if ENV['VERBOSE'] || ENV['DEBUG'] - a << "--seed #{ENV['SEED']}" if ENV['SEED'] + a << "--color" + a << "--format #{ENV["CI"] ? "documentation" : "Fuubar"}" + a << "--backtrace" if ENV["VERBOSE"] || ENV["DEBUG"] + a << "--seed #{ENV["SEED"]}" if ENV["SEED"] a << "--tag #{args[:tag]}" if args[:tag] a << "--default-path test" - a << '-I test/spec' - end.join(' ') + a << "-I test/spec" + end.join(" ") end diff --git a/kitchen-docker.gemspec b/kitchen-docker.gemspec index fdfa674f..d4ece27e 100644 --- a/kitchen-docker.gemspec +++ b/kitchen-docker.gemspec @@ -1,40 +1,20 @@ -lib = File.expand_path('../lib', __FILE__) +lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'kitchen/docker/docker_version' +require "kitchen/docker/docker_version" Gem::Specification.new do |spec| - spec.name = 'kitchen-docker' + spec.name = "kitchen-docker" spec.version = Kitchen::Docker::DOCKER_VERSION - spec.authors = ['Sean Porter'] - spec.email = ['portertech@gmail.com'] + spec.authors = ["Sean Porter"] + spec.email = ["portertech@gmail.com"] spec.description = %q{A Docker Driver for Test Kitchen} spec.summary = spec.description - spec.homepage = 'https://github.com/test-kitchen/kitchen-docker' - spec.license = 'Apache 2.0' + spec.homepage = "https://github.com/test-kitchen/kitchen-docker" + spec.license = "Apache 2.0" spec.files = `git ls-files`.split($/) spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) - spec.require_paths = ['lib'] + spec.require_paths = ["lib"] - spec.add_dependency 'test-kitchen', '>= 1.0.0' - - spec.add_development_dependency 'bundler' - spec.add_development_dependency 'rake' - - # Style checker gems. - spec.add_development_dependency 'cane' - spec.add_development_dependency 'tailor' - spec.add_development_dependency 'countloc' - - # Unit testing gems. - spec.add_development_dependency 'rspec', '~> 3.2' - spec.add_development_dependency 'rspec-its', '~> 1.2' - spec.add_development_dependency 'fuubar', '~> 2.0' - spec.add_development_dependency 'simplecov', '~> 0.9' - spec.add_development_dependency 'codecov', '~> 0.0', '>= 0.0.2' - spec.add_development_dependency 'chefstyle' - - # Integration testing gems. - spec.add_development_dependency 'kitchen-inspec', '~> 2.0' - spec.add_development_dependency 'train', '>= 2.1', '< 4.0' # validate 4.x when it's released + spec.add_dependency "test-kitchen", ">= 1.0.0", "< 4.0" end diff --git a/lib/docker/version.rb b/lib/docker/version.rb index 70fd25ef..1b4cb1c2 100644 --- a/lib/docker/version.rb +++ b/lib/docker/version.rb @@ -12,13 +12,13 @@ # limitations under the License. begin - require 'docker' + require "docker" # Override API_VERSION constant in docker-api gem to use version 1.24 of the Docker API # This override is for the docker-api gem to communicate to the Docker engine on Windows module Docker - VERSION = '0.0.0' - API_VERSION = '1.24' + VERSION = "0.0.0".freeze + API_VERSION = "1.24".freeze end rescue LoadError => e logger.debug("[Docker] docker-api gem not found for InSpec verifier. #{e}") diff --git a/lib/kitchen/docker/container.rb b/lib/kitchen/docker/container.rb index 2595dfed..af78ba37 100644 --- a/lib/kitchen/docker/container.rb +++ b/lib/kitchen/docker/container.rb @@ -11,10 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -require_relative 'helpers/cli_helper' -require_relative 'helpers/container_helper' -require_relative 'helpers/file_helper' -require_relative 'helpers/image_helper' +require_relative "helpers/cli_helper" +require_relative "helpers/container_helper" +require_relative "helpers/file_helper" +require_relative "helpers/image_helper" module Kitchen module Docker @@ -33,7 +33,7 @@ def create(state) info("Container ID #{state[:container_id]} already exists.") elsif !container_exists?(state) && state[:container_id] raise ActionFailed, "Container ID #{state[:container_id]} was found in the kitchen state data, "\ - 'but the container does not exist.' + "but the container does not exist." end state[:username] = @config[:username] @@ -49,7 +49,7 @@ def destroy(state) end def hostname(state) - hostname = 'localhost' + hostname = "localhost" if remote_socket? hostname = socket_uri.host diff --git a/lib/kitchen/docker/container/linux.rb b/lib/kitchen/docker/container/linux.rb index e2650b87..a95f1308 100644 --- a/lib/kitchen/docker/container/linux.rb +++ b/lib/kitchen/docker/container/linux.rb @@ -11,13 +11,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'base64' -require 'openssl' -require 'securerandom' -require 'shellwords' +require "base64" unless defined?(Base64) +require "openssl" unless defined?(OpenSSL) +require "securerandom" unless defined?(SecureRandom) +require "shellwords" unless defined?(Shellwords) -require_relative '../container' -require_relative '../helpers/dockerfile_helper' +require_relative "../container" +require_relative "../helpers/dockerfile_helper" module Kitchen module Docker @@ -34,7 +34,7 @@ def initialize(config) def create(state) super - debug('Creating Linux container') + debug("Creating Linux container") generate_keys state[:ssh_key] = @config[:private_key] @@ -58,7 +58,7 @@ def execute(command) debug("Uploading temp file #{temp_file} to #{remote_path} on container") upload(temp_file, remote_path) - debug('Deleting temp file from local filesystem') + debug("Deleting temp file from local filesystem") ::File.delete(temp_file) # Replace any environment variables used in the path and execute script file @@ -76,13 +76,13 @@ def generate_keys MUTEX_FOR_SSH_KEYS.synchronize do if !File.exist?(@config[:public_key]) || !File.exist?(@config[:private_key]) private_key = OpenSSL::PKey::RSA.new(2048) - blobbed_key = Base64.encode64(private_key.to_blob).gsub("\n", '') + blobbed_key = Base64.encode64(private_key.to_blob).gsub("\n", "") public_key = "ssh-rsa #{blobbed_key} kitchen_docker_key" - File.open(@config[:private_key], 'w') do |file| + File.open(@config[:private_key], "w") do |file| file.write(private_key) file.chmod(0600) end - File.open(@config[:public_key], 'w') do |file| + File.open(@config[:public_key], "w") do |file| file.write(public_key) file.chmod(0600) end @@ -91,7 +91,7 @@ def generate_keys end def parse_container_ssh_port(output) - _host, port = output.split(':') + _host, port = output.split(":") port.to_i rescue => e raise ActionFailed, "Could not parse Docker port output for container SSH port. #{e}" @@ -113,10 +113,10 @@ def dockerfile platform = dockerfile_platform username = @config[:username] public_key = IO.read(@config[:public_key]).strip - homedir = username == 'root' ? '/root' : "/home/#{username}" + homedir = username == "root" ? "/root" : "/home/#{username}" base = dockerfile_base_linux(username, homedir) - custom = '' + custom = "" Array(@config[:provision_command]).each do |cmd| custom << "RUN #{cmd}\n" end @@ -124,10 +124,10 @@ def dockerfile ssh_key = "RUN echo #{Shellwords.escape(public_key)} >> #{homedir}/.ssh/authorized_keys" # Empty string to ensure the file ends with a newline. - output = [from, dockerfile_proxy_config, platform, base, custom, ssh_key, ''].join("\n") - debug('--- Start Dockerfile ---') + output = [from, dockerfile_proxy_config, platform, base, custom, ssh_key, ""].join("\n") + debug("--- Start Dockerfile ---") debug(output.strip) - debug('--- End Dockerfile ---') + debug("--- End Dockerfile ---") output end end diff --git a/lib/kitchen/docker/container/windows.rb b/lib/kitchen/docker/container/windows.rb index 168dca70..f56c6539 100644 --- a/lib/kitchen/docker/container/windows.rb +++ b/lib/kitchen/docker/container/windows.rb @@ -11,9 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'securerandom' +require "securerandom" unless defined?(SecureRandom) -require_relative '../container' +require_relative "../container" module Kitchen module Docker @@ -26,7 +26,7 @@ def initialize(config) def create(state) super - debug('Creating Windows container') + debug("Creating Windows container") state[:username] = @config[:username] state[:image_id] = build_image(state, dockerfile) unless state[:image_id] state[:container_id] = run_container(state) unless state[:container_id] @@ -35,19 +35,19 @@ def create(state) def execute(command) # Create temp script file and upload files to container - debug('Executing command on Windows container') + debug("Executing command on Windows container") filename = "docker-#{::SecureRandom.uuid}.ps1" temp_file = ".\\.kitchen\\temp\\#{filename}" create_temp_file(temp_file, command) - remote_path = @config[:temp_dir].tr('/', '\\') + remote_path = @config[:temp_dir].tr("/", "\\") debug("Creating directory #{remote_path} on container") create_dir_on_container(@config, remote_path) debug("Uploading temp file #{temp_file} to #{remote_path} on container") upload(temp_file, remote_path) - debug('Deleting temp file from local filesystem') + debug("Deleting temp file from local filesystem") ::File.delete(temp_file) # Replace any environment variables used in the path and execute script file @@ -63,20 +63,20 @@ def execute(command) protected def dockerfile - raise ActionFailed, "Unknown platform '#{@config[:platform]}'" unless @config[:platform] == 'windows' + raise ActionFailed, "Unknown platform '#{@config[:platform]}'" unless @config[:platform] == "windows" return dockerfile_template if @config[:dockerfile] from = "FROM #{@config[:image]}" - custom = '' + custom = "" Array(@config[:provision_command]).each do |cmd| custom << "RUN #{cmd}\n" end - output = [from, dockerfile_proxy_config, custom, ''].join("\n") - debug('--- Start Dockerfile ---') + output = [from, dockerfile_proxy_config, custom, ""].join("\n") + debug("--- Start Dockerfile ---") debug(output.strip) - debug('--- End Dockerfile ---') + debug("--- End Dockerfile ---") output end end diff --git a/lib/kitchen/docker/docker_version.rb b/lib/kitchen/docker/docker_version.rb index 21034550..0a8aa564 100644 --- a/lib/kitchen/docker/docker_version.rb +++ b/lib/kitchen/docker/docker_version.rb @@ -16,6 +16,6 @@ module Kitchen module Docker # Version string for Docker Kitchen driver - DOCKER_VERSION = "3.0.0" + DOCKER_VERSION = "3.0.0".freeze end end diff --git a/lib/kitchen/docker/erb_context.rb b/lib/kitchen/docker/erb_context.rb index 7780e47c..97cc8a75 100644 --- a/lib/kitchen/docker/erb_context.rb +++ b/lib/kitchen/docker/erb_context.rb @@ -13,14 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'erb' +require "erb" unless defined?(Erb) module Kitchen module Docker class ERBContext - def initialize(config={}) + def initialize(config = {}) config.each do |key, value| - instance_variable_set('@' + key.to_s, value) + instance_variable_set("@" + key.to_s, value) end end diff --git a/lib/kitchen/docker/helpers/cli_helper.rb b/lib/kitchen/docker/helpers/cli_helper.rb index e4695d3b..ecccce39 100644 --- a/lib/kitchen/docker/helpers/cli_helper.rb +++ b/lib/kitchen/docker/helpers/cli_helper.rb @@ -11,10 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'kitchen' -require 'kitchen/configurable' -require 'kitchen/logging' -require 'kitchen/shell_out' +require "kitchen" +require "kitchen/configurable" +require "kitchen/logging" +require "kitchen/shell_out" module Kitchen module Docker @@ -26,11 +26,11 @@ module CliHelper include ShellOut # rubocop:disable Metrics/AbcSize - def docker_command(cmd, options={}) + def docker_command(cmd, options = {}) docker = config[:binary].dup docker << " -H #{config[:socket]}" if config[:socket] - docker << ' --tls' if config[:tls] - docker << ' --tlsverify' if config[:tls_verify] + docker << " --tls" if config[:tls] + docker << " --tlsverify" if config[:tls_verify] docker << " --tlscacert=#{config[:tls_cacert]}" if config[:tls_cacert] docker << " --tlscert=#{config[:tls_cert]}" if config[:tls_cert] docker << " --tlskey=#{config[:tls_key]}" if config[:tls_key] @@ -63,9 +63,9 @@ def run_command(cmd, options = {}) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize def build_run_command(image_id, transport_port = nil) - cmd = 'run -d' - cmd << ' -i' if config[:interactive] - cmd << ' -t' if config[:tty] + cmd = "run -d" + cmd << " -i" if config[:interactive] + cmd << " -t" if config[:tty] cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables] cmd << " -p #{transport_port}" unless transport_port.nil? Array(config[:forward]).each { |port| cmd << " -p #{port}" } @@ -75,21 +75,21 @@ def build_run_command(image_id, transport_port = nil) Array(config[:volumes_from]).each { |container| cmd << " --volumes-from #{container}" } Array(config[:links]).each { |link| cmd << " --link #{link}" } Array(config[:devices]).each { |device| cmd << " --device #{device}" } - Array(config[:mount]).each {|mount| cmd << " --mount #{mount}"} - Array(config[:tmpfs]).each {|tmpfs| cmd << " --tmpfs #{tmpfs}"} + Array(config[:mount]).each { |mount| cmd << " --mount #{mount}" } + Array(config[:tmpfs]).each { |tmpfs| cmd << " --tmpfs #{tmpfs}" } cmd << " --name #{config[:instance_name]}" if config[:instance_name] - cmd << ' -P' if config[:publish_all] + cmd << " -P" if config[:publish_all] cmd << " -h #{config[:hostname]}" if config[:hostname] cmd << " -m #{config[:memory]}" if config[:memory] cmd << " -c #{config[:cpu]}" if config[:cpu] cmd << " --gpus #{config[:gpus]}" if config[:gpus] cmd << " -e http_proxy=#{config[:http_proxy]}" if config[:http_proxy] cmd << " -e https_proxy=#{config[:https_proxy]}" if config[:https_proxy] - cmd << ' --privileged' if config[:privileged] + cmd << " --privileged" if config[:privileged] cmd << " --isolation #{config[:isolation]}" if config[:isolation] - Array(config[:cap_add]).each { |cap| cmd << " --cap-add=#{cap}"} if config[:cap_add] - Array(config[:cap_drop]).each { |cap| cmd << " --cap-drop=#{cap}"} if config[:cap_drop] - Array(config[:security_opt]).each { |opt| cmd << " --security-opt=#{opt}"} if config[:security_opt] + Array(config[:cap_add]).each { |cap| cmd << " --cap-add=#{cap}" } if config[:cap_add] + Array(config[:cap_drop]).each { |cap| cmd << " --cap-drop=#{cap}" } if config[:cap_drop] + Array(config[:security_opt]).each { |opt| cmd << " --security-opt=#{opt}" } if config[:security_opt] cmd << " --platform=#{config[:docker_platform]}" if config[:docker_platform] extra_run_options = config_to_options(config[:run_options]) cmd << " #{extra_run_options}" unless extra_run_options.empty? @@ -101,12 +101,12 @@ def build_run_command(image_id, transport_port = nil) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize def build_exec_command(state, command) - cmd = 'exec' - cmd << ' -d' if config[:detach] + cmd = "exec" + cmd << " -d" if config[:detach] cmd << build_env_variable_args(config[:env_variables]) if config[:env_variables] - cmd << ' --privileged' if config[:privileged] - cmd << ' -t' if config[:tty] - cmd << ' -i' if config[:interactive] + cmd << " --privileged" if config[:privileged] + cmd << " -t" if config[:tty] + cmd << " -i" if config[:interactive] cmd << " -u #{config[:username]}" if config[:username] cmd << " -w #{config[:working_dir]}" if config[:working_dir] cmd << " #{state[:container_id]}" @@ -117,23 +117,23 @@ def build_exec_command(state, command) # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize def build_copy_command(local_file, remote_file, opts = {}) - cmd = 'cp' - cmd << ' -a' if opts[:archive] + cmd = "cp" + cmd << " -a" if opts[:archive] cmd << " #{local_file} #{remote_file}" cmd end def build_powershell_command(args) - cmd = 'powershell -ExecutionPolicy Bypass -NoLogo ' + cmd = "powershell -ExecutionPolicy Bypass -NoLogo " cmd << args logger.debug("build_powershell_command: #{cmd}") cmd end def build_env_variable_args(vars) - raise ActionFailed, 'Environment variables are not of a Hash type' unless vars.is_a?(Hash) + raise ActionFailed, "Environment variables are not of a Hash type" unless vars.is_a?(Hash) - args = '' + args = "" vars.each do |k, v| args << " -e #{k.to_s.strip}=\"#{v.to_s.strip}\"" end @@ -142,11 +142,11 @@ def build_env_variable_args(vars) end def dev_null - case RbConfig::CONFIG['host_os'] + case RbConfig::CONFIG["host_os"] when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ - 'NUL' + "NUL" else - '/dev/null' + "/dev/null" end end @@ -167,13 +167,13 @@ def docker_shell_opts(options = {}) def config_to_options(config) case config when nil - '' + "" when String config when Array - config.map { |c| config_to_options(c) }.join(' ') + config.map { |c| config_to_options(c) }.join(" ") when Hash - config.map { |k, v| Array(v).map { |c| "--#{k}=#{Shellwords.escape(c)}" }.join(' ') }.join(' ') + config.map { |k, v| Array(v).map { |c| "--#{k}=#{Shellwords.escape(c)}" }.join(" ") }.join(" ") end end # rubocop:enable Metrics/CyclomaticComplexity diff --git a/lib/kitchen/docker/helpers/container_helper.rb b/lib/kitchen/docker/helpers/container_helper.rb index 6338cf25..00579328 100644 --- a/lib/kitchen/docker/helpers/container_helper.rb +++ b/lib/kitchen/docker/helpers/container_helper.rb @@ -11,16 +11,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'erb' -require 'json' -require 'shellwords' -require 'tempfile' -require 'uri' +require "erb" unless defined?(Erb) +require "json" unless defined?(JSON) +require "shellwords" unless defined?(Shellwords) +require "tempfile" unless defined?(Tempfile) +require "uri" unless defined?(URI) -require 'kitchen' -require 'kitchen/configurable' -require_relative '../erb_context' -require_relative 'cli_helper' +require "kitchen" +require "kitchen/configurable" +require_relative "../erb_context" +require_relative "cli_helper" module Kitchen module Docker @@ -34,7 +34,7 @@ def parse_container_id(output) container_id = output.chomp unless [12, 64].include?(container_id.size) - raise ActionFailed, 'Could not parse Docker run output for container ID' + raise ActionFailed, "Could not parse Docker run output for container ID" end container_id @@ -47,7 +47,7 @@ def dockerfile_template end def remote_socket? - config[:socket] ? socket_uri.scheme == 'tcp' : false + config[:socket] ? socket_uri.scheme == "tcp" : false end def socket_uri @@ -73,7 +73,7 @@ def create_dir_on_container(state, path) path = replace_env_variables(state, path) cmd = "mkdir -p #{path}" - if state[:platform].include?('windows') + if state[:platform].include?("windows") psh = "-Command if(-not (Test-Path \'#{path}\')) { New-Item -Path \'#{path}\' -Force }" cmd = build_powershell_command(psh) end @@ -101,15 +101,15 @@ def container_env_variables(state) # Retrieves all environment variables from inside container vars = {} - if state[:platform].include?('windows') - cmd = build_powershell_command('-Command [System.Environment]::GetEnvironmentVariables() ^| ConvertTo-Json') + if state[:platform].include?("windows") + cmd = build_powershell_command("-Command [System.Environment]::GetEnvironmentVariables() ^| ConvertTo-Json") cmd = build_exec_command(state, cmd) stdout = docker_command(cmd, suppress_output: !logger.debug?).strip vars = ::JSON.parse(stdout) else - cmd = build_exec_command(state, 'printenv') + cmd = build_exec_command(state, "printenv") stdout = docker_command(cmd, suppress_output: !logger.debug?).strip - stdout.split("\n").each { |line| vars[line.split('=')[0]] = line.split('=')[1] } + stdout.split("\n").each { |line| vars[line.split("=")[0]] = line.split("=")[1] } end vars @@ -117,12 +117,12 @@ def container_env_variables(state) # rubocop:enable Metrics/AbcSize, Metrics/MethodLength def replace_env_variables(state, str) - if str.include?('$env:') + if str.include?("$env:") key = str[/\$env:(.*?)(\\|$)/, 1] value = container_env_variables(state)[key].to_s.strip str = str.gsub("$env:#{key}", value) - elsif str.include?('$') - key = str[/\$(.*?)(\/|$)/, 1] + elsif str.include?("$") + key = str[%r{\$(.*?)(/|$)}, 1] value = container_env_variables(state)[key].to_s.strip str = str.gsub("$#{key}", value) end @@ -141,7 +141,7 @@ def container_ip_address(state) cmd << " #{state[:container_id]}" docker_command(cmd).strip rescue - raise ActionFailed, 'Error getting internal IP of Docker container' + raise ActionFailed, "Error getting internal IP of Docker container" end def remove_container(state) @@ -151,7 +151,7 @@ def remove_container(state) end def dockerfile_proxy_config - env_variables = '' + env_variables = "" if config[:http_proxy] env_variables << "ENV http_proxy #{config[:http_proxy]}\n" env_variables << "ENV HTTP_PROXY #{config[:http_proxy]}\n" diff --git a/lib/kitchen/docker/helpers/dockerfile_helper.rb b/lib/kitchen/docker/helpers/dockerfile_helper.rb index 6e290415..beabe9ba 100644 --- a/lib/kitchen/docker/helpers/dockerfile_helper.rb +++ b/lib/kitchen/docker/helpers/dockerfile_helper.rb @@ -11,38 +11,38 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'kitchen' -require 'kitchen/configurable' +require "kitchen" +require "kitchen/configurable" module Kitchen module Docker module Helpers - module DockerfileHelper + module DockerfileHelper include Configurable def dockerfile_platform case config[:platform] - when 'arch' + when "arch" arch_platform - when 'debian', 'ubuntu' + when "debian", "ubuntu" debian_platform - when 'fedora' + when "fedora" fedora_platform - when 'gentoo' + when "gentoo" gentoo_platform - when 'gentoo-paludis' + when "gentoo-paludis" gentoo_paludis_platform - when 'opensuse/tumbleweed', 'opensuse/leap', 'opensuse', 'sles' + when "opensuse/tumbleweed", "opensuse/leap", "opensuse", "sles" opensuse_platform - when 'rhel', 'centos', 'oraclelinux', 'amazonlinux' + when "rhel", "centos", "oraclelinux", "amazonlinux" rhel_platform - when 'centosstream' + when "centosstream" centosstream_platform - when 'almalinux' + when "almalinux" almalinux_platform - when 'rockylinux' + when "rockylinux" rockylinux_platform - when 'photon' + when "photon" photonos_platform else raise ActionFailed, "Unknown platform '#{config[:platform]}'" diff --git a/lib/kitchen/docker/helpers/file_helper.rb b/lib/kitchen/docker/helpers/file_helper.rb index 6dc8291d..d07a011e 100644 --- a/lib/kitchen/docker/helpers/file_helper.rb +++ b/lib/kitchen/docker/helpers/file_helper.rb @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'fileutils' +require "fileutils" unless defined?(FileUtils) module Kitchen module Docker @@ -19,14 +19,14 @@ module Helpers module FileHelper def create_temp_file(file, contents) debug("[Docker] Creating temp file #{file}") - debug('[Docker] --- Start Temp File Contents ---') + debug("[Docker] --- Start Temp File Contents ---") debug(contents) - debug('[Docker] --- End Temp File Contents ---') + debug("[Docker] --- End Temp File Contents ---") begin path = ::File.dirname(file) ::FileUtils.mkdir_p(path) unless ::Dir.exist?(path) - file = ::File.open(file, 'w') + file = ::File.open(file, "w") file.write(contents) rescue IOError => e raise "Failed to write temp file. Error Details: #{e}" diff --git a/lib/kitchen/docker/helpers/image_helper.rb b/lib/kitchen/docker/helpers/image_helper.rb index 3c0c7bee..fe75bc65 100644 --- a/lib/kitchen/docker/helpers/image_helper.rb +++ b/lib/kitchen/docker/helpers/image_helper.rb @@ -11,11 +11,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'kitchen' -require 'kitchen/configurable' -require 'pathname' -require_relative 'cli_helper' -require_relative 'container_helper' +require "kitchen" +require "kitchen/configurable" +require "pathname" unless defined?(Pathname) +require_relative "cli_helper" +require_relative "container_helper" module Kitchen module Docker @@ -28,7 +28,7 @@ module ImageHelper def parse_image_id(output) output.split("\n").reverse_each do |line| if line =~ /writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i - img_id = line[/writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i,1] + img_id = line[/writing image (sha256:[[:xdigit:]]{64})(?: \d*\.\ds)? done/i, 1] return img_id end if line =~ /image id|build successful|successfully built/i @@ -36,7 +36,7 @@ def parse_image_id(output) return img_id end end - raise ActionFailed, 'Could not parse Docker build output for image ID' + raise ActionFailed, "Could not parse Docker build output for image ID" end def remove_image(state) @@ -45,21 +45,21 @@ def remove_image(state) end def build_image(state, dockerfile) - cmd = 'build' - cmd << ' --no-cache' unless config[:use_cache] + cmd = "build" + cmd << " --no-cache" unless config[:use_cache] cmd << " --platform=#{config[:docker_platform]}" if config[:docker_platform] extra_build_options = config_to_options(config[:build_options]) cmd << " #{extra_build_options}" unless extra_build_options.empty? dockerfile_contents = dockerfile - file = Tempfile.new('Dockerfile-kitchen', Pathname.pwd + config[:build_tempdir]) + file = Tempfile.new("Dockerfile-kitchen", Pathname.pwd + config[:build_tempdir]) cmd << " -f #{Shellwords.escape(dockerfile_path(file))}" if config[:build_context] - build_context = config[:build_context] ? '.' : '-' + build_context = config[:build_context] ? "." : "-" output = begin file.write(dockerfile) file.close docker_command("#{cmd} #{build_context}", input: dockerfile_contents, - environment: { BUILDKIT_PROGRESS: 'plain' }) + environment: { BUILDKIT_PROGRESS: "plain" }) ensure file.close unless file.closed? file.unlink diff --git a/lib/kitchen/docker/helpers/inspec_helper.rb b/lib/kitchen/docker/helpers/inspec_helper.rb index 5f0d3256..63333912 100644 --- a/lib/kitchen/docker/helpers/inspec_helper.rb +++ b/lib/kitchen/docker/helpers/inspec_helper.rb @@ -1,40 +1,40 @@ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This helper should be removed when the kitchen-inspec gem has been updated to include these runner options -begin - require 'kitchen/verifier/inspec' - - # Add runner options for Docker transport for kitchen-inspec gem - module Kitchen - module Docker - module Helpers - module InspecHelper - Kitchen::Verifier::Inspec.class_eval do - def runner_options_for_docker(config_data) - opts = { - 'backend' => 'docker', - 'logger' => logger, - 'host' => config_data[:container_id], - } - logger.debug "Connect to Container: #{opts['host']}" - opts - end - end - end - end - end - end -rescue LoadError => e - logger.debug("[Docker] kitchen-inspec gem not found for InSpec verifier. #{e}") -end +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This helper should be removed when the kitchen-inspec gem has been updated to include these runner options +begin + require "kitchen/verifier/inspec" + + # Add runner options for Docker transport for kitchen-inspec gem + module Kitchen + module Docker + module Helpers + module InspecHelper + Kitchen::Verifier::Inspec.class_eval do + def runner_options_for_docker(config_data) + opts = { + "backend" => "docker", + "logger" => logger, + "host" => config_data[:container_id], + } + logger.debug "Connect to Container: #{opts["host"]}" + opts + end + end + end + end + end + end +rescue LoadError => e + logger.debug("[Docker] kitchen-inspec gem not found for InSpec verifier. #{e}") +end diff --git a/lib/kitchen/driver/docker.rb b/lib/kitchen/driver/docker.rb index 3606ee00..84a39419 100644 --- a/lib/kitchen/driver/docker.rb +++ b/lib/kitchen/driver/docker.rb @@ -13,17 +13,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'kitchen' -require 'json' -require 'securerandom' -require 'net/ssh' +require "kitchen" +require "json" unless defined?(JSON) +require "securerandom" unless defined?(SecureRandom) +require "net/ssh" unless defined?(Net::SSH) -require 'kitchen/driver/base' +require "kitchen/driver/base" -require_relative '../docker/container/linux' -require_relative '../docker/container/windows' -require_relative '../docker/helpers/cli_helper' -require_relative '../docker/helpers/container_helper' +require_relative "../docker/container/linux" +require_relative "../docker/container/windows" +require_relative "../docker/helpers/cli_helper" +require_relative "../docker/helpers/container_helper" module Kitchen module Driver @@ -35,7 +35,7 @@ class Docker < Kitchen::Driver::Base include Kitchen::Docker::Helpers::ContainerHelper include ShellOut - default_config :binary, 'docker' + default_config :binary, "docker" default_config :build_options, nil default_config :build_tempdir, Dir.pwd default_config :cap_add, nil @@ -44,9 +44,9 @@ class Docker < Kitchen::Driver::Base default_config :env_variables, nil default_config :isolation, nil default_config :interactive, false - default_config :private_key, File.join(Dir.pwd, '.kitchen', 'docker_id_rsa') + default_config :private_key, File.join(Dir.pwd, ".kitchen", "docker_id_rsa") default_config :privileged, false - default_config :public_key, File.join(Dir.pwd, '.kitchen', 'docker_id_rsa.pub') + default_config :public_key, File.join(Dir.pwd, ".kitchen", "docker_id_rsa.pub") default_config :publish_all, false default_config :remove_images, false default_config :run_options, nil @@ -66,43 +66,39 @@ class Docker < Kitchen::Driver::Base !driver.remote_socket? end - default_config :image do |driver| - driver.default_image - end + default_config :image, &:default_image default_config :instance_name do |driver| # Borrowed from kitchen-rackspace [ - driver.instance.name.gsub(/\W/, ''), - (Etc.getlogin || 'nologin').gsub(/\W/, ''), - Socket.gethostname.gsub(/\W/, '')[0..20], - Array.new(8) { rand(36).to_s(36) }.join - ].join('-').downcase + driver.instance.name.gsub(/\W/, ""), + (Etc.getlogin || "nologin").gsub(/\W/, ""), + Socket.gethostname.gsub(/\W/, "")[0..20], + Array.new(8) { rand(36).to_s(36) }.join, + ].join("-").downcase end - default_config :platform do |driver| - driver.default_platform - end + default_config :platform, &:default_platform default_config :run_command do |driver| if driver.windows_os? # Launch arbitrary process to keep the Windows container alive # If running in interactive mode, launch powershell.exe instead if driver[:interactive] - 'powershell.exe' + "powershell.exe" else - 'ping -t localhost' + "ping -t localhost" end else - '/usr/sbin/sshd -D -o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes '\ - '-o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid' + "/usr/sbin/sshd -D -o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes "\ + "-o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid" end end default_config :socket do |driver| - socket = 'unix:///var/run/docker.sock' - socket = 'npipe:////./pipe/docker_engine' if driver.windows_os? - ENV['DOCKER_HOST'] || socket + socket = "unix:///var/run/docker.sock" + socket = "npipe:////./pipe/docker_engine" if driver.windows_os? + ENV["DOCKER_HOST"] || socket end default_config :username do |driver| @@ -111,14 +107,14 @@ class Docker < Kitchen::Driver::Base if driver.windows_os? nil else - 'kitchen' + "kitchen" end end def verify_dependencies run_command("#{config[:binary]} >> #{dev_null} 2>&1", quiet: true, use_sudo: config[:use_sudo]) rescue - raise UserError, 'You must first install the Docker CLI tool https://www.docker.com/get-started' + raise UserError, "You must first install the Docker CLI tool https://www.docker.com/get-started" end def create(state) @@ -133,22 +129,20 @@ def destroy(state) def wait_for_transport(state) if config[:wait_for_transport] - instance.transport.connection(state) do |conn| - conn.wait_until_ready - end + instance.transport.connection(state, &:wait_until_ready) end end def default_image - platform, release = instance.platform.name.split('-') - if platform == 'centos' && release - release = 'centos' + release.split('.').first + platform, release = instance.platform.name.split("-") + if platform == "centos" && release + release = "centos" + release.split(".").first end - release ? [platform, release].join(':') : platform + release ? [platform, release].join(":") : platform end def default_platform - instance.platform.name.split('-').first + instance.platform.name.split("-").first end protected diff --git a/lib/kitchen/transport/docker.rb b/lib/kitchen/transport/docker.rb index de31807e..10b6e256 100644 --- a/lib/kitchen/transport/docker.rb +++ b/lib/kitchen/transport/docker.rb @@ -11,15 +11,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'kitchen' +require "kitchen" -require_relative '../docker/container/linux' -require_relative '../docker/container/windows' +require_relative "../docker/container/linux" +require_relative "../docker/container/windows" -require_relative '../docker/helpers/inspec_helper' +require_relative "../docker/helpers/inspec_helper" -require_relative '../../docker/version.rb' -require_relative '../../train/docker.rb' +require_relative "../../docker/version" +require_relative "../../train/docker" module Kitchen module Transport @@ -29,7 +29,7 @@ class DockerFailed < TransportFailed; end kitchen_transport_api_version 1 plugin_version Kitchen::VERSION - default_config :binary, 'docker' + default_config :binary, "docker" default_config :env_variables, nil default_config :interactive, false default_config :privileged, false @@ -42,16 +42,16 @@ class DockerFailed < TransportFailed; end default_config :working_dir, nil default_config :socket do |transport| - socket = 'unix:///var/run/docker.sock' - socket = 'npipe:////./pipe/docker_engine' if transport.windows_os? - ENV['DOCKER_HOST'] || socket + socket = "unix:///var/run/docker.sock" + socket = "npipe:////./pipe/docker_engine" if transport.windows_os? + ENV["DOCKER_HOST"] || socket end default_config :temp_dir do |transport| if transport.windows_os? - '$env:TEMP' + "$env:TEMP" else - '/tmp' + "/tmp" end end @@ -61,7 +61,7 @@ class DockerFailed < TransportFailed; end if transport.windows_os? nil else - 'kitchen' + "kitchen" end end @@ -73,7 +73,7 @@ def connection(state, &block) # This allows Windows systems to use the TCP socket for the InSpec verifier # See the lib/docker.rb file here: https://github.com/swipely/docker-api/blob/master/lib/docker.rb # default_socket_url is set to a Unix socket and env_url requires an environment variable to be set - ENV['DOCKER_HOST'] = options[:socket] if !options[:socket].nil? && ENV['DOCKER_HOST'].nil? + ENV["DOCKER_HOST"] = options[:socket] if !options[:socket].nil? && ENV["DOCKER_HOST"].nil? Kitchen::Transport::Docker::Connection.new(options, &block) end @@ -98,7 +98,7 @@ def upload(locals, remote) end def container - @container ||= if @options[:platform].include?('windows') + @container ||= if @options[:platform].include?("windows") Kitchen::Docker::Container::Windows.new(@options) else Kitchen::Docker::Container::Linux.new(@options) diff --git a/lib/train/docker.rb b/lib/train/docker.rb index 024caae9..a2cbd21a 100644 --- a/lib/train/docker.rb +++ b/lib/train/docker.rb @@ -14,12 +14,12 @@ # Monkey patched Docker train transport to support running the InSpec verifier on Windows begin # Requires train gem with a minimum version of 2.1.0 - require 'train' + require "train" module Train::Transports # Patched train transport with Windows support for InSpec verifier class Docker < Train.plugin(1) - name 'docker' + name "docker" include_options Train::Extras::CommandWrapper option :host, required: true @@ -71,10 +71,10 @@ def initialize(conf) super(conf) @id = options[:host] @container = ::Docker::Container.get(@id) || - fail("Can't find Docker container #{@id}") + raise("Can't find Docker container #{@id}") @cmd_wrapper = nil @cmd_wrapper = CommandWrapper.load(self, @options) - self + self # rubocop:disable Lint/Void TODO: Remove in future pass end def uri @@ -101,10 +101,11 @@ def file_via_connection(path) def platform_specific_cmd(cmd) return cmd if @container.info.nil? - if @container.info['Platform'] == 'windows' - return ['cmd.exe', '/c', cmd] + + if @container.info["Platform"] == "windows" + ["cmd.exe", "/c", cmd] else - return ['/bin/sh', '-c', cmd] + ["/bin/sh", "-c", cmd] end end diff --git a/test/integration/inspec/inspec_spec.rb b/test/integration/inspec/inspec_spec.rb index 0a128d70..06b8e84f 100644 --- a/test/integration/inspec/inspec_spec.rb +++ b/test/integration/inspec/inspec_spec.rb @@ -15,12 +15,12 @@ # # Just make sure the image launched and is reachable. -if os[:family] == 'windows' - describe command('echo 1') do +if os[:family] == "windows" + describe command("echo 1") do its(:exit_status) { is_expected.to eq 0 } end else - describe command('true') do + describe command("true") do its(:exit_status) { is_expected.to eq 0 } end end diff --git a/test/spec/docker_spec.rb b/test/spec/docker_spec.rb index f04e8f6b..6a2de282 100644 --- a/test/spec/docker_spec.rb +++ b/test/spec/docker_spec.rb @@ -14,50 +14,50 @@ # limitations under the License. # -require 'spec_helper' +require "spec_helper" describe Kitchen::Driver::Docker do - describe '#config_to_options' do - let(:config) { } + describe "#config_to_options" do + let(:config) {} subject { described_class.new.send(:config_to_options, config) } - context 'with nil' do + context "with nil" do let(:config) { nil } - it { is_expected.to eq '' } + it { is_expected.to eq "" } end # /context with nil - context 'with a string' do - let(:config) { '--foo' } - it { is_expected.to eq '--foo' } + context "with a string" do + let(:config) { "--foo" } + it { is_expected.to eq "--foo" } end # /context with a string - context 'with a string with spaces' do - let(:config) { '--foo bar' } - it { is_expected.to eq '--foo bar' } + context "with a string with spaces" do + let(:config) { "--foo bar" } + it { is_expected.to eq "--foo bar" } end # /context with a string with spaces - context 'with an array of strings' do + context "with an array of strings" do let(:config) { %w{--foo --bar} } - it { is_expected.to eq '--foo --bar' } + it { is_expected.to eq "--foo --bar" } end # /context with an array of strings - context 'with an array of hashes' do - let(:config) { [{foo: 'bar'}, {other: 'baz'}] } - it { is_expected.to eq '--foo=bar --other=baz' } + context "with an array of hashes" do + let(:config) { [{ foo: "bar" }, { other: "baz" }] } + it { is_expected.to eq "--foo=bar --other=baz" } end # /context with an array of hashes - context 'with a hash of strings' do - let(:config) { {foo: 'bar', other: 'baz'} } - it { is_expected.to eq '--foo=bar --other=baz' } + context "with a hash of strings" do + let(:config) { { foo: "bar", other: "baz" } } + it { is_expected.to eq "--foo=bar --other=baz" } end # /context with a hash of strings - context 'with a hash of arrays' do - let(:config) { {foo: %w{bar baz}} } - it { is_expected.to eq '--foo=bar --foo=baz' } + context "with a hash of arrays" do + let(:config) { { foo: %w{bar baz} } } + it { is_expected.to eq "--foo=bar --foo=baz" } end # /context with a hash of arrays - context 'with a hash of strings with spaces' do - let(:config) { {foo: 'bar two', other: 'baz'} } + context "with a hash of strings with spaces" do + let(:config) { { foo: "bar two", other: "baz" } } it { is_expected.to eq '--foo=bar\\ two --other=baz' } end # /context with a hash of strings with spaces end # /describe #config_to_options diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb index b9a91cbd..15db6b54 100644 --- a/test/spec/spec_helper.rb +++ b/test/spec/spec_helper.rb @@ -14,16 +14,16 @@ # limitations under the License. # -require 'rake' -require 'rspec' -require 'rspec/its' -require 'simplecov' +require "rake" +require "rspec" +require "rspec/its" +require "simplecov" # Check for coverage stuffs formatters = [] -if ENV['CODECOV_TOKEN'] || ENV['CI'] - require 'codecov' +if ENV["CODECOV_TOKEN"] || ENV["CI"] + require "codecov" formatters << SimpleCov::Formatter::Codecov end @@ -33,13 +33,13 @@ SimpleCov.start do # Don't get coverage on the test cases themselves. - add_filter '/spec/' - add_filter '/test/' + add_filter "/spec/" + add_filter "/test/" # Codecov doesn't automatically ignore vendored files. - add_filter '/vendor/' + add_filter "/vendor/" end -require 'kitchen/driver/docker' +require "kitchen/driver/docker" RSpec.configure do |config| # Basic configuraiton @@ -50,5 +50,5 @@ # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 - config.order = 'random' + config.order = "random" end