lib/kitchen/driver/docker.rb in kitchen-docker-2.4.0 vs lib/kitchen/driver/docker.rb in kitchen-docker-2.5.0
- old
+ new
@@ -17,10 +17,12 @@
require 'kitchen'
require 'json'
require 'securerandom'
require 'uri'
require 'net/ssh'
+require 'tempfile'
+require 'shellwords'
require File.join(File.dirname(__FILE__), 'docker', 'erb')
module Kitchen
module Driver
@@ -49,10 +51,12 @@
default_config :tls_key, nil
default_config :publish_all, false
default_config :wait_for_sshd, true
default_config :private_key, File.join(Dir.pwd, '.kitchen', 'docker_id_rsa')
default_config :public_key, File.join(Dir.pwd, '.kitchen', 'docker_id_rsa.pub')
+ default_config :build_options, nil
+ default_config :run_options, nil
default_config :use_sudo do |driver|
!driver.remote_socket?
end
@@ -194,15 +198,19 @@
RUN yum install -y sudo openssh-server openssh-clients which curl
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
eos
when 'arch'
+ # See https://bugs.archlinux.org/task/47052 for why we
+ # blank out limits.conf.
<<-eos
- RUN pacman -Syu --noconfirm
- RUN pacman -S --noconfirm openssh sudo curl
+ RUN pacman --noconfirm -Sy archlinux-keyring
+ RUN pacman-db-upgrade
+ RUN pacman --noconfirm -Sy openssl openssh sudo curl
RUN ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key
+ RUN echo >/etc/security/limits.conf
eos
when 'gentoo'
<<-eos
RUN emerge sync
RUN emerge net-misc/openssh app-admin/sudo
@@ -229,14 +237,12 @@
base = <<-eos
RUN if ! getent passwd #{username}; then \
useradd -d #{homedir} -m -s /bin/bash #{username}; \
fi
RUN echo #{username}:#{password} | chpasswd
- RUN echo '#{username} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
- RUN mkdir -p /etc/sudoers.d
- RUN echo '#{username} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/#{username}
- RUN chmod 0440 /etc/sudoers.d/#{username}
+ RUN echo "#{username} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+ RUN echo "Defaults !requiretty" >> /etc/sudoers
RUN mkdir -p #{homedir}/.ssh
RUN chown -R #{username} #{homedir}/.ssh
RUN chmod 0700 #{homedir}/.ssh
RUN touch #{homedir}/.ssh/authorized_keys
RUN chown #{username} #{homedir}/.ssh/authorized_keys
@@ -244,11 +250,11 @@
eos
custom = ''
Array(config[:provision_command]).each do |cmd|
custom << "RUN #{cmd}\n"
end
- ssh_key = "RUN echo '#{public_key}' >> #{homedir}/.ssh/authorized_keys"
+ ssh_key = "RUN echo #{Shellwords.escape(public_key)} >> #{homedir}/.ssh/authorized_keys"
# Empty string to ensure the file ends with a newline.
[from, env_variables, platform, base, custom, ssh_key, ''].join("\n")
end
def dockerfile
@@ -266,23 +272,25 @@
if line =~ /image id|build successful|successfully built/i
return line.split(/\s+/).last
end
end
raise ActionFailed,
- 'Could not parse Docker build output for image ID'
+ 'Could not parse Docker build output for image ID'
end
def build_image(state)
cmd = "build"
cmd << " --no-cache" unless config[:use_cache]
+ extra_build_options = config_to_options(config[:build_options])
+ cmd << " #{extra_build_options}" unless extra_build_options.empty?
dockerfile_contents = dockerfile
build_context = config[:build_context] ? '.' : '-'
file = Tempfile.new('Dockerfile-kitchen', Dir.pwd)
output = begin
file.write(dockerfile)
file.close
- docker_command("#{cmd} -f #{file.path} #{build_context}", :input => dockerfile_contents)
+ docker_command("#{cmd} -f #{Shellwords.escape(file.path)} #{build_context}", :input => dockerfile_contents)
ensure
file.close unless file.closed?
file.unlink
end
parse_image_id(output)
@@ -315,10 +323,12 @@
cmd << " -e https_proxy=#{config[:https_proxy]}" if config[:https_proxy]
cmd << " --privileged" if config[:privileged]
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]
+ extra_run_options = config_to_options(config[:run_options])
+ cmd << " #{extra_run_options}" unless extra_run_options.empty?
cmd << " #{image_id} #{config[:run_command]}"
cmd
end
def run_container(state)
@@ -331,15 +341,15 @@
state[:container_id] && !!docker_command("top #{state[:container_id]}") rescue false
end
def parse_container_ssh_port(output)
begin
- host, port = output.split(':')
+ _host, port = output.split(':')
port.to_i
rescue
raise ActionFailed,
- 'Could not parse Docker port output for container SSH port'
+ 'Could not parse Docker port output for container SSH port'
end
end
def container_ssh_port(state)
begin
@@ -359,8 +369,28 @@
def rm_image(state)
image_id = state[:image_id]
docker_command("rmi #{image_id}")
end
+
+ # Convert the config input for `:build_options` or `:run_options` in to a
+ # command line string for use with Docker.
+ #
+ # @since 2.5.0
+ # @param config [nil, String, Array, Hash] Config data to convert.
+ # @return [String]
+ def config_to_options(config)
+ case config
+ when nil
+ ''
+ when String
+ config
+ when Array
+ config.map {|c| config_to_options(c) }.join(' ')
+ when Hash
+ config.map {|k, v| Array(v).map {|c| "--#{k}=#{Shellwords.escape(c)}" }.join(' ') }.join(' ')
+ end
+ end
+
end
end
end