moduleDokkenmoduleHelpers# https://stackoverflow.com/questions/517219/ruby-see-if-a-port-is-openrequire'socket'require'timeout'defport_open?(ip,port)beginTimeout.timeout(1)dobegins=TCPSocket.new(ip,port)s.closereturntruerescueErrno::ECONNREFUSED,Errno::EHOSTUNREACHreturnfalseendendrescueTimeout::Errorendfalseenddefinsecure_ssh_public_key<<-EOF
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCoJwyW7qNhw+NTuOjC4+RVpESl+JBXebXzB7JqxRgKAbymq6B39azEAiNx5NzHkWcQmOyQNhFpKFSAufegcXRS4ctS1LcElEoXe9brDAqKEBSkmnXYfZXMNIG0Enw4+5W/rZxHFCAlsUSAHYtYZEs+3CgbIWuHhZ95C8UC6nGLWHNZOjcbsYZFrnFfO0qg0ene2w8LKhxqj5X0MRSdCIn1IwyxIbl5NND5Yk1Hx8JKsJtTiNTdxssiMgmM5bvTbYQUSf8pbGrRI30VQKBgQ8/UkidZbaTfvzWXYpwcDUERSbzEYCvkUytTemZIv6uhpPxqkfjl6KEOOml/iGqquPEr test-kitchen-rsa
EOFenddefinsecure_ssh_private_key<<-EOF
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqCcMlu6jYcPjU7jowuPkVaREpfiQV3m18weyasUYCgG8pqug
d/WsxAIjceTcx5FnEJjskDYRaShUgLn3oHF0UuHLUtS3BJRKF3vW6wwKihAUpJp1
2H2VzDSBtBJ8OPuVv62cRxQgJbFEgB2LWGRLPtwoGyFrh4WfeQvFAupxi1hzWTo3
G7GGRa5xXztKoNHp3tsPCyocao+V9DEUnQiJ9SMMsSG5eTTQ+WJNR8fCSrCbU4jU
3cbLIjIJjOW7022EFEn/KWxq0SN9FUCgYEPP1JInWW2k3781l2KcHA1BEUm8xGAr
5FMrU3pmSL+roaT8apH45eihDjppf4hqqrjxKwIDAQABAoIBAEj7Cb/IOykHd/ay
XnOXrVZuQU03oI4WyR19zbYBbPmK33IHM1JdUmqP8wpPpnMHbJALj0DX9p6JXoOw
MwVzuGTwkuqUYAqgwbeHjDPfugNKD2uRjmwztXw3ncOl8jxZFRloJFfFKF6znWNt
bzkh7naN3upHiv/6wsgqj4tAbZ9oRC1crO6bsNr3P6YooiG5RRNpHepiyXphyhN6
We1p5ZOQ/pUSE0Ca4wTlUhJHTUPMz7VFs/8CH0loRIsGPBROarPkoLVF+/UNyX8e
+BGMhoUtQH2XvjEzWUl5jKJOnvKRIV+0j/upWXsPQKF5glVPmPrTVUAxThfu6rAa
4Z3JveECgYEA0Pz3Hl0SlPR79r2qofh1ZNa8zvQDL+iLopULwDiil5qlUxJ+DgOl
1kWXLhjdg/NfoTBHvBjdJu274YJgaGQOfCy5747YDVsakKOm4bI9+Jr2agshPyE6
f1RNmGL8K8fNtpGq4G14o+pSQOPNrEfcFKgm3sosZWJAWaA64hmtiXcCgYEAzfp6
FbodfUypAV5Zd6PCO2eJMjLdvGaNuH/Umo80WNV7XZ6iJ6MUeQe+YwxFJigjC3ii
ifLUj3kL7+wu7sEtkzS3zNd34KfhQ5fLADttfFgjjfm7IxlDD4ABaUgjwZM2gfXi
xCwRhwwNgilF6qABJ1CLt8JSqKubkqvO1P1gQu0CgYEA0GA6AcNpYK344Eey1/bF
DntyHKN+fglPGReldM7Dh4gBabgZid2nP+N5XtQaIpPKeQyLqgfckhEecTau68dA
Dh4Gcs6pq394GFmkbotrcPMJ2SgpySlXi1fCWrvvlbON8IiDqWxdiop74wmArFOm
I86ZmzBYXeo+IV869vAFcPcCgYBrvvyh5OuMIc++YYZXaRgvTueblLQc22CDBItI
FmUBmxqfTF3ycgJBlWVoFoENhq1eUMplctrx+hXeeSPLzM10VX1X79ZLdEYHv513
D58kDk7684mKwKotr34NfqkFl2ZJ8T+f8pVwmUNvtPtX0j8IO7/6bfIjPTFyNeFJ
1QjHuQKBgQC/LE05M4eeWXihZ7c7fyWHLyddcPdH48LRF9UH9yjKF84jXRT91uMv
XuIb2Qt4MLHABySsk653LDw/jTIGV26c068nZryq5OUPxk67Xgod54jKgOwjgjZS
X8N2N9ZNnORJqK374yGj1jWUU66mQhPvn49QpG8P2HEoh2RQjNvyHA==
-----END RSA PRIVATE KEY-----
EOFenddefdata_dockerfile<<-EOF
FROM centos:7
MAINTAINER Sean OMeara \"sean@sean.io\"
ENV LANG en_US.UTF-8
RUN yum -y install tar rsync openssh-server passwd git
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
# uncomment to debug cert issues
# RUN echo 'root:dokkendokkendokken' | chpasswd
# RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
RUN mkdir -p /root/.ssh/
COPY authorized_keys /root/.ssh/authorized_keys
RUN chmod 700 /root/.ssh/
RUN chmod 600 /root/.ssh/authorized_keys
EXPOSE 22
CMD [ "/usr/sbin/sshd", "-D", "-p", "22", "-o", "UseDNS=no", "-o", "UsePrivilegeSeparation=no", "-o", "MaxAuthTries=60" ]
VOLUME /opt/kitchen
VOLUME /opt/verifier
EOFenddefcreate_data_imagereturnif::Docker::Image.exist?(data_image)tmpdir=Dir.tmpdirFileUtils.mkdir_p"#{tmpdir}/dokken"File.write("#{tmpdir}/dokken/Dockerfile",data_dockerfile)File.write("#{tmpdir}/dokken/authorized_keys",insecure_ssh_public_key)i=::Docker::Image.build_from_dir("#{tmpdir}/dokken",'nocache'=>true,'rm'=>true)i.tag('repo'=>repo(data_image),'tag'=>tag(data_image),'force'=>true)enddefdefault_docker_hostifENV['DOCKER_HOST']ENV['DOCKER_HOST']elsifFile.exist?('/var/run/docker.sock')'unix:///var/run/docker.sock'# TODO: Docker for Windows also operates over a named pipe at# //./pipe/docker_engine that can be used if named pipe support is# added to the docker-api gem.else'tcp://127.0.0.1:2375'endenddefdocker_info@docker_info||=::Docker.infoenddefdokken_create_sandboxinfo("Creating kitchen sandbox at #{dokken_kitchen_sandbox}")FileUtils.mkdir_p(dokken_kitchen_sandbox)File.chmod(0o755,dokken_kitchen_sandbox)info("Creating verifier sandbox at #{dokken_verifier_sandbox}")FileUtils.mkdir_p(dokken_verifier_sandbox)File.chmod(0o755,dokken_verifier_sandbox)enddefdokken_delete_sandboxinfo("Deleting kitchen sandbox at #{dokken_kitchen_sandbox}")beginFileUtils.rm_rf(dokken_kitchen_sandbox)rescueErrno::ENOENTdebug("Cannot delete #{dokken_kitchen_sandbox}. Does not exist")endinfo("Deleting verifier sandbox at #{dokken_verifier_sandbox}")beginFileUtils.rm_rf(dokken_verifier_sandbox)rescueErrno::ENOENTdebug("Cannot delete #{dokken_verifier_sandbox}. Does not exist")endenddefhome_dir# while dokken_binds avoid invalid bind mount spec "C:/Users/..." error by# remote docker host virtual box shared folder on boot2docker created by docker-machine in Windows# refs:# https://github.com/docker/machine/issues/1814# https://github.com/docker/toolbox/issues/607returnDir.home.sub'C:/Users','/c/Users'ifDir.home=~/^C:/&&remote_docker_host?Dir.homeenddefdokken_kitchen_sandbox"#{home_dir}/.dokken/kitchen_sandbox/#{instance_name}"enddefdokken_verifier_sandbox"#{home_dir}/.dokken/verifier_sandbox/#{instance_name}"enddefinstance_nameprefix=(Digest::SHA2.hexdigestFileUtils.pwd)[0,10]"#{prefix}-#{instance.name}"enddefexposed_portscoerce_exposed_ports(config[:ports])enddefport_bindingscoerce_port_bindings(config[:ports])enddefcoerce_exposed_ports(v)casevwhenHash,nilvelsex=Array(v).map{|a|parse_port(a)}x.flatten!x.each_with_object({})do|y,h|h[y['container_port']]={}endendenddefcoerce_port_bindings(v)casevwhenHash,nilvelsex=Array(v).map{|a|parse_port(a)}x.flatten!x.each_with_object({})do|y,h|h[y['container_port']]=[]unlessh[y['container_port']]h[y['container_port']]<<{'HostIp'=>y['host_ip'],'HostPort'=>y['host_port'],}endendenddefparse_port(v)parts=v.split(':')caseparts.lengthwhen3host_ip=parts[0]host_port=parts[1]container_port=parts[2]when2host_ip='0.0.0.0'host_port=parts[0]container_port=parts[1]when1host_ip=''host_port=''container_port=parts[0]endport_range,protocol=container_port.split('/')ifport_range.include?('-')port_range=container_port.split('-')port_range.map!(&:to_i)Chef::Log.fatal("FATAL: Invalid port range! #{container_port}")ifport_range[0]>port_range[1]port_range=(port_range[0]..port_range[1]).to_aend# qualify the port-binding protocol even when it is implicitly tcp #427.protocol='tcp'ifprotocol.nil?Array(port_range).mapdo|port|{'host_ip'=>host_ip,'host_port'=>host_port,'container_port'=>"#{port}/#{protocol}",}endenddefremote_docker_host?returnfalseifconfig[:docker_info]['OperatingSystem'].include?('Boot2Docker')returntrueifconfig[:docker_host_url]=~/^tcp:/falseenddefsandbox_path"#{Dir.home}/.dokken/verifier_sandbox/#{instance_name}"enddefsandbox_dirsDir.glob(File.join(sandbox_path,'*'))enddefcreate_sandboxinfo("Creating kitchen sandbox in #{sandbox_path}")unless::Dir.exist?(sandbox_path)FileUtils.mkdir_p(sandbox_path)File.chmod(0o755,sandbox_path)endendendendmoduleKitchenmoduleProvisionerclassBasedefcreate_sandboxinfo("Creating kitchen sandbox in #{sandbox_path}")FileUtils.mkdir_p(sandbox_path)File.chmod(0o755,sandbox_path)end# this MUST be named 'sandbox_path' because ruby.defsandbox_path"#{Dir.home}/.dokken/kitchen_sandbox/#{instance_name}"enddefinstance_nameprefix=(Digest::SHA2.hexdigestFileUtils.pwd)[0,10]"#{prefix}-#{instance.name}"endendendendmoduleKitchenmoduleVerifierclassBasedefcreate_sandboxinfo("Creating kitchen sandbox in #{sandbox_path}")unless::Dir.exist?(sandbox_path)FileUtils.mkdir_p(sandbox_path)File.chmod(0o755,sandbox_path)endenddefsandbox_path"#{Dir.home}/.dokken/verifier_sandbox/#{instance_name}"enddefinstance_nameprefix=(Digest::SHA2.hexdigestFileUtils.pwd)[0,10]"#{prefix}-#{instance.name}"enddefcall(state)create_sandboxinstance.transport.connection(state)do|conn|conn.execute(install_command)unlessstate[:data_container].nil?conn.execute(init_command)info("Transferring files to #{instance.to_str}")conn.upload(sandbox_dirs,config[:root_path])debug('Transfer complete')endconn.execute(prepare_command)conn.execute(run_command)endrescueKitchen::Transport::TransportFailed=>exraiseActionFailed,ex.messageendendendend