kitchen-docker-2.10.0/0000755000004100000410000000000013641341210014507 5ustar www-datawww-datakitchen-docker-2.10.0/.kitchen.yml0000644000004100000410000000270713641341210016743 0ustar www-datawww-data<% # Make sure the local copy of the driver is loaded %> <% lib = File.expand_path('../lib', __FILE__) %> <% $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) %> --- driver: name: docker provision_command: curl -L https://www.chef.io/chef/install.sh | bash transport: name: docker provisioner: name: dummy platforms: - name: amazonlinux-2 - name: ubuntu-16.04 - name: ubuntu-18.04 - name: fedora-latest driver: provision_command: - yum install libxcrypt-compat.x86_64 -y - curl -L https://www.chef.io/chef/install.sh | bash - name: centos-6 - name: centos-7 - name: oraclelinux-6 - name: oraclelinux-7 - name: debian-8 - name: debian-9 - name: opensuse-42.3 driver: image: opensuse/leap:42.3 - name: opensuse/leap-42 # - name: arch # driver: # image: base/archlinux # provision_command: true - name: unknown driver: image: ubuntu:16.04 platform: ubuntu - name: dockerfile driver: username: dockerfile password: dockerfile dockerfile: test/Dockerfile run_command: /sbin/init suites: - name: default excludes: [arch] - name: context excludes: [arch] driver: build_context: false - name: capabilities includes: [debian-8,debian-9,ubuntu-16.04,ubuntu-18.04] driver: provision_command: - curl -L https://www.chef.io/chef/install.sh | bash - apt-get install -y net-tools cap_drop: - NET_ADMIN - name: inspec driver: provision_command: true verifier: name: inspec kitchen-docker-2.10.0/.travis.yml0000644000004100000410000000263413641341210016625 0ustar www-datawww-datamatrix: include: - os: linux rvm: 2.4.9 dist: xenial language: ruby cache: bundler script: - bundle exec docker version - bundle exec kitchen --version - bundle exec rake spec - bundle exec kitchen test -d always - os: linux rvm: 2.5.7 dist: xenial language: ruby cache: bundler script: - bundle exec docker version - bundle exec kitchen --version - bundle exec rake spec - bundle exec kitchen test -d always - os: linux rvm: 2.6.5 dist: xenial language: ruby cache: bundler script: - bundle exec docker version - bundle exec kitchen --version - bundle exec rake spec - bundle exec kitchen test -d always - os: windows language: bash install: - choco install mingw - choco install msys2 - ridk.cmd exec pacman -S --noconfirm --needed base-devel mingw-w64-x86_64-toolchain script: - taskkill -IM "gpg-agent.exe" -F - powershell -ExecutionPolicy Bypass -NoLogo -File docker.ps1 - export KITCHEN_YAML=.kitchen.windows.yml - ruby -v - gem install bundler - bundle install - bundle exec docker version - bundle exec kitchen --version - bundle exec rake spec - bundle exec kitchen test -d always services: - docker kitchen-docker-2.10.0/test/0000755000004100000410000000000013641341210015466 5ustar www-datawww-datakitchen-docker-2.10.0/test/spec/0000755000004100000410000000000013641341210016420 5ustar www-datawww-datakitchen-docker-2.10.0/test/spec/docker_spec.rb0000644000004100000410000000417713641341210021237 0ustar www-datawww-data# # Copyright 2016, Noah Kantrowitz # # 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. # require 'spec_helper' describe Kitchen::Driver::Docker do describe '#config_to_options' do let(:config) { } subject { described_class.new.send(:config_to_options, config) } context 'with nil' do let(:config) { nil } it { is_expected.to eq '' } end # /context with nil 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' } end # /context with a string with spaces context 'with an array of strings' do let(:config) { %w{--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' } 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' } 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' } end # /context with a hash of arrays 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 end kitchen-docker-2.10.0/test/spec/spec_helper.rb0000644000004100000410000000272413641341210021243 0ustar www-datawww-data# # Copyright 2016, Noah Kantrowitz # # 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. # require 'rake' require 'rspec' require 'rspec/its' require 'simplecov' # Check for coverage stuffs formatters = [] if ENV['CODECOV_TOKEN'] || ENV['TRAVIS'] require 'codecov' formatters << SimpleCov::Formatter::Codecov end unless formatters.empty? SimpleCov.formatters = formatters end SimpleCov.start do # Don't get coverage on the test cases themselves. add_filter '/spec/' add_filter '/test/' # Codecov doesn't automatically ignore vendored files. add_filter '/vendor/' end require 'kitchen/driver/docker' RSpec.configure do |config| # Basic configuraiton config.run_all_when_everything_filtered = true config.filter_run(:focus) # Run specs in random order to surface order dependencies. If you find an # 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' end kitchen-docker-2.10.0/test/Dockerfile0000644000004100000410000000160213641341210017457 0ustar www-datawww-dataFROM centos:6 RUN yum clean all RUN yum install -y sudo openssh-server openssh-clients which curl htop RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key RUN mkdir -p /var/run/sshd RUN useradd -d /home/<%= @username %> -m -s /bin/bash <%= @username %> RUN echo <%= "#{@username}:#{@password}" %> | chpasswd RUN echo '<%= @username %> ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers RUN mkdir -p /home/<%= @username %>/.ssh RUN chown -R <%= @username %> /home/<%= @username %>/.ssh RUN chmod 0700 /home/<%= @username %>/.ssh RUN touch /home/<%= @username %>/.ssh/authorized_keys RUN chown <%= @username %> /home/<%= @username %>/.ssh/authorized_keys RUN chmod 0600 /home/<%= @username %>/.ssh/authorized_keys RUN curl -L https://www.chef.io/chef/install.sh | bash RUN echo '<%= IO.read(@public_key).strip %>' >> /home/<%= @username %>/.ssh/authorized_keys kitchen-docker-2.10.0/test/integration/0000755000004100000410000000000013641341210020011 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/default/0000755000004100000410000000000013641341210021435 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/default/serverspec/0000755000004100000410000000000013641341210023616 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/default/serverspec/default_spec.rb0000644000004100000410000000136313641341210026604 0ustar www-datawww-data# # Copyright 2016, Noah Kantrowitz # # 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. # require 'serverspec' require 'spec_helper' # Just make sure the image launched and is reachable. describe command('true') do its(:exit_status) { is_expected.to eq 0 } end kitchen-docker-2.10.0/test/integration/default/serverspec/spec_helper.rb0000644000004100000410000000130613641341210026434 0ustar www-datawww-data# # 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. # case RbConfig::CONFIG['host_os'] when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ set :backend, :cmd set :os, :family => 'windows' else set :backend, :exec end kitchen-docker-2.10.0/test/integration/inspec/0000755000004100000410000000000013641341210021272 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/inspec/inspec_spec.rb0000644000004100000410000000150613641341210024114 0ustar www-datawww-data# # Copyright 2016, Noah Kantrowitz # # 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. # # Just make sure the image launched and is reachable. if os[:family] == 'windows' describe command('echo 1') do its(:exit_status) { is_expected.to eq 0 } end else describe command('true') do its(:exit_status) { is_expected.to eq 0 } end end kitchen-docker-2.10.0/test/integration/capabilities/0000755000004100000410000000000013641341210022442 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/capabilities/serverspec/0000755000004100000410000000000013641341210024623 5ustar www-datawww-datakitchen-docker-2.10.0/test/integration/capabilities/serverspec/capabilities_drop_spec.rb0000644000004100000410000000143213641341210031637 0ustar www-datawww-data# # Copyright 2016, Noah Kantrowitz # # 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. # require 'serverspec' set :backend, :exec describe command('/sbin/ifconfig eth0 multicast') do its(:exit_status) { is_expected.to_not eq 0 } its(:stderr) { is_expected.to match /Operation not permitted/ } end kitchen-docker-2.10.0/README.md0000644000004100000410000003114113641341210015766 0ustar www-datawww-data# Kitchen-Docker [![Build Status](https://travis-ci.org/test-kitchen/kitchen-docker.svg?branch=master)](https://travis-ci.org/test-kitchen/kitchen-docker) [![Gem Version](https://img.shields.io/gem/v/kitchen-docker.svg)](https://rubygems.org/gems/kitchen-docker) [![Coverage](https://img.shields.io/codecov/c/github/test-kitchen/kitchen-docker.svg)](https://codecov.io/github/test-kitchen/kitchen-docker) [![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) A Test Kitchen Driver and Transport for Docker. ## Requirements * [Docker][docker_installation] **(>= 1.5)** ## Installation and Setup Please read the Test Kitchen [docs][test_kitchen_docs] for more details. Example (Linux) `.kitchen.local.yml`: ```yaml --- driver: name: docker env_variables: TEST_KEY: TEST_VALUE platforms: - name: ubuntu run_list: - recipe[apt] - name: centos driver_config: image: centos platform: rhel run_list: - recipe[yum] transport: name: docker ``` Example (Windows) `.kitchen.local.yml`: ```yaml --- driver: name: docker platforms: - name: windows driver_config: image: mcr.microsoft.com/windows/servercore:1607 platform: windows run_list: - recipe[chef_client] transport: name: docker env_variables: TEST_KEY: TEST_VALUE ``` ## Default Configuration This driver can determine an image and platform type for a select number of platforms. Examples: ```yaml --- platforms: - name: ubuntu-18.04 - name: centos-7 ``` This will effectively generate a configuration similar to: ```yaml --- platforms: - name: ubuntu-18.04 driver_config: image: ubuntu:18.04 platform: ubuntu - name: centos-7 driver_config: image: centos:7 platform: centos ``` ## Configuration ### binary The Docker binary to use. The default value is `docker`. Examples: ```yaml binary: docker.io ``` ```yaml binary: /opt/docker ``` ### socket The Docker daemon socket to use. By default, Docker will listen on `unix:///var/run/docker.sock` (On Windows, `npipe:////./pipe/docker_engine`), and no configuration here is required. If Docker is binding to another host/port or Unix socket, you will need to set this option. If a TCP socket is set, its host will be used for SSH access to suite containers. Examples: ```yaml socket: unix:///tmp/docker.sock ``` ```yaml socket: tcp://docker.example.com:4242 ``` If you are using the InSpec verifier on Windows, using named pipes for the Docker engine will not work with the Docker transport. Set the socket option with the TCP socket address of the Docker engine as shown below: ```yaml socket: tcp://localhost:2375 ``` The Docker engine must be configured to listen on a TCP port (default port is 2375). This can be configured by editing the configuration file (usually located in `C:\ProgramData\docker\config\daemon.json`) and adding the hosts value: ``` "hosts": ["tcp://0.0.0.0:2375"] ``` Example configuration is shown below: ``` { "registry-mirrors": [], "insecure-registries": [], "debug": true, "experimental": false, "hosts": ["tcp://0.0.0.0:2375"] } ``` If you use [Boot2Docker](https://github.com/boot2docker/boot2docker) or [docker-machine](https://docs.docker.com/machine/get-started/) set your `DOCKER_HOST` environment variable properly with `export DOCKER_HOST=tcp://192.168.59.103:2375` or `eval "$(docker-machine env $MACHINE)"` then use the following: ```yaml socket: tcp://192.168.59.103:2375 ``` ### image The Docker image to use as the base for the suite containers. You can find images using the [Docker Index][docker_index]. The default will be computed, using the platform name (see the Default Configuration section for more details). ### platform The platform of the chosen image. This is used to properly bootstrap the suite container for Test Kitchen. Kitchen Docker currently supports: * `arch` * `debian` or `ubuntu` * `amazonlinux`, `rhel`, `centos`, `fedora` or `oraclelinux` * `gentoo` or `gentoo-paludis` * `opensuse/tumbleweed`, `opensuse/leap`, `opensuse` or `sles` * `windows` The default will be computed, using the platform name (see the Default Configuration section for more details). ### require\_chef\_omnibus Determines whether or not a Chef [Omnibus package][chef_omnibus_dl] will be installed. There are several different behaviors available: * `true` - the latest release will be installed. Subsequent converges will skip re-installing if chef is present. * `latest` - the latest release will be installed. Subsequent converges will always re-install even if chef is present. * `` (ex: `10.24.0`) - the desired version string will be passed the the install.sh script. Subsequent converges will skip if the installed version and the desired version match. * `false` or `nil` - no chef is installed. The default value is `true`. ### disable\_upstart Disables upstart on Debian/Ubuntu containers, as many images do not support a working upstart. The default value is `true`. ### provision\_command Custom command(s) to be run when provisioning the base for the suite containers. Examples: ```yaml provision_command: curl -L https://www.opscode.com/chef/install.sh | bash ``` ```yaml provision_command: - apt-get install dnsutils - apt-get install telnet ``` ```yaml driver_config: provision_command: curl -L https://www.opscode.com/chef/install.sh | bash require_chef_omnibus: false ``` ### env_variables Adds environment variables to Docker container Examples: ```yaml env_variables: TEST_KEY_1: TEST_VALUE SOME_VAR: SOME_VALUE ``` ### use\_cache This determines if the Docker cache is used when provisioning the base for suite containers. The default value is `true`. ### use\_sudo This determines if Docker commands are run with `sudo`. The default value depends on the type of socket being used. For local sockets, the default value is `true`. For remote sockets, the default value is `false`. This should be set to `false` if you're using boot2docker, as every command passed into the VM runs as root by default. ### remove\_images This determines if images are automatically removed when the suite container is destroyed. The default value is `false`. ### run\_command Sets the command used to run the suite container. The default value is `/usr/sbin/sshd -D -o UseDNS=no -o UsePAM=no -o PasswordAuthentication=yes -o UsePrivilegeSeparation=no -o PidFile=/tmp/sshd.pid`. Examples: ```yaml run_command: /sbin/init ``` ### memory Sets the memory limit for the suite container in bytes. Otherwise use Dockers default. You can read more about `memory.limit_in_bytes` [here][memory_limit]. ### cpu Sets the CPU shares (relative weight) for the suite container. Otherwise use Dockers defaults. You can read more about cpu.shares [here][cpu_shares]. ### volume Adds a data volume(s) to the suite container. Examples: ```yaml volume: /ftp ``` ```yaml volume: - /ftp - /srv ``` ### volumes\_from Mount volumes managed by other containers. Examples: ```yaml volumes_from: repos ``` ```yaml volumes_from: - repos - logging - rvm ``` ### dns Adjusts `resolv.conf` to use the dns servers specified. Otherwise use Dockers defaults. Examples: ```yaml dns: 8.8.8.8 ``` ```yaml dns: - 8.8.8.8 - 8.8.4.4 ``` ### http\_proxy Sets an http proxy for the suite container using the `http_proxy` environment variable. Examples: ```yaml http_proxy: http://proxy.host.com:8080 ``` ### https\_proxy Sets an https proxy for the suite container using the `https_proxy` environment variable. Examples: ```yaml https_proxy: http://proxy.host.com:8080 ``` ### forward Set suite container port(s) to forward to the host machine. You may specify the host (public) port in the mappings, if not, Docker chooses for you. Examples: ```yaml forward: 80 ``` ```yaml forward: - 22:2222 - 80:8080 ``` ### hostname Set the suite container hostname. Otherwise use Dockers default. Examples: ```yaml hostname: foobar.local ``` ### privileged Run the suite container in privileged mode. This allows certain functionality inside the Docker container which is not otherwise permitted. The default value is `false`. Examples: ```yaml privileged: true ``` ### cap\_add Adds a capability to the running container. Examples: ```yaml cap_add: - SYS_PTRACE ``` ### cap\_drop Drops a capability from the running container. Examples: ```yaml cap_drop: - CHOWN ``` ### security\_opt Apply a security profile to the Docker container. Allowing finer granularity of access control than privileged mode, through leveraging SELinux/AppArmor profiles to grant access to specific resources. Examples: ```yaml security_opt: - apparmor:my_profile ``` ### dockerfile Use a custom Dockerfile, instead of having Kitchen-Docker build one for you. Examples: ```yaml dockerfile: test/Dockerfile ``` ### instance\_name Set the name of container to link to other container(s). Examples: ```yaml instance_name: web ``` ### links Set ```instance_name```(and alias) of other container(s) that connect from the suite container. Examples: ```yaml links: db:db ``` ```yaml links: - db:db - kvs:kvs ``` ### publish\_all Publish all exposed ports to the host interfaces. This option used to communicate between some containers. The default value is `false`. Examples: ```yaml publish_all: true ``` ### devices Share a host device with the container. Host device must be an absolute path. Examples: ``` devices: /dev/vboxdrv ``` ``` devices: - /dev/vboxdrv - /dev/vboxnetctl ``` ### build_context Transfer the cookbook directory (cwd) as build context. This is required for Dockerfile commands like ADD and COPY. When using a remote Docker server, the whole directory has to be copied, which can be slow. The default value is `true` for local Docker and `false` for remote Docker. Examples: ```yaml build_context: true ``` ### build_options Extra command-line options to pass to `docker build` when creating the image. Examples: ```yaml build_options: --rm=false ``` ```yaml build_options: rm: false build-arg: something ``` ### run_options Extra command-line options to pass to `docker run` when starting the container. Examples: ```yaml run_options: --ip=1.2.3.4 ``` ```yaml run_options: tmpfs: - /run/lock - /tmp net: br3 ``` ### use_internal_docker_network If you want to use kitchen-docker from within another Docker container you'll need to set this to true. When set to true uses port 22 as the SSH port and the IP of the container that chef is going to run in as the hostname so that you can connect to it over SSH from within another Docker container. Examples: ```yaml use_internal_docker_network: true ``` ## Development * Source hosted at [GitHub][repo] * Report issues/questions/feature requests on [GitHub Issues][issues] Pull requests are very welcome! Make sure your patches are well tested. Ideally create a topic branch for every separate change you make. For example: 1. Fork the repo 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request ## License Copyright 2013-2016, [Sean Porter](https://github.com/portertech) Copyright 2015-2016, [Noah Kantrowitz](https://github.com/coderanger) 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. [issues]: https://github.com/test-kitchen/kitchen-docker/issues [license]: https://github.com/test-kitchen/kitchen-docker/blob/master/LICENSE [repo]: https://github.com/test-kitchen/kitchen-docker [docker_installation]: https://docs.docker.com/installation/#installation [docker_upstart_issue]: https://github.com/dotcloud/docker/issues/223 [docker_index]: https://index.docker.io/ [docker_default_image]: https://index.docker.io/_/base/ [test_kitchen_docs]: http://kitchen.ci/docs/getting-started/ [chef_omnibus_dl]: https://downloads.chef.io/chef-client/ [cpu_shares]: https://docs.fedoraproject.org/en-US/Fedora/17/html/Resource_Management_Guide/sec-cpu.html [memory_limit]: https://docs.fedoraproject.org/en-US/Fedora/17/html/Resource_Management_Guide/sec-memory.html kitchen-docker-2.10.0/CHANGELOG.md0000644000004100000410000000742313641341210016326 0ustar www-datawww-data# Kitchen-Docker Changelog ## 2.10.0 - Mar 28, 2020 * Switched from require to require_relative to slightly improve load time performance * Allow for train gem 3.x * Refactor driver to include Windows support (includes new transport for all supported platforms) ## 2.9.0 - Mar 15, 2019 * Add automatic OS detection for amazonlinux, opensuse/leap, and opensuse/tumbleweed * On Fedora containers uses dnf to setup the OS not yum ## 2.8.0 - Jan 18, 2019 * Add new config option `use_internal_docker_network`, which allows running Docker within Docker. See readme for usage details. * Resolve errors while loading libraries on archlinux * Fix failures on Ubuntu 18.04 * Check if image exists before attempting to remove it so we don't fail * Add oraclelinux platform support * Prevent `uninitialized constant Kitchen::Driver::Docker::Base64` error by requiring `base64` ## 2.7.0 * Support for SUSE-based container images. * Improved support for build context shipping. * Changed `use_sudo` to default to `false` in keeping with modern Docker usage. ## 2.6.0 * Set container name with information from the run so you can identify them later on. * Upgrade to new driver base class structure. ## 2.5.0 * [#209](https://github.com/portertech/kitchen-docker/pulls/209) Fix usage with Kitchen rake tasks. * Add `run_options` and `build_options` configuration. * [#195](https://github.com/portertech/kitchen-docker/pulls/195) Fix Arch Linux support. * Fix shell escaping for build paths and SSH keys. ## 2.4.0 * [#148](https://github.com/portertech/kitchen-docker/issues/148) Restored support for older versions of Ruby. * [#149](https://github.com/portertech/kitchen-docker/pulls/149) Handle connecting to a container directly as root. * [#154](https://github.com/portertech/kitchen-docker/pulls/154) Improve container caching by reordering the build steps. * [#176](https://github.com/portertech/kitchen-docker/pulls/176) Expose proxy environment variables to the container automatically. * [#192](https://github.com/portertech/kitchen-docker/pulls/192) Set `$container=docker` for CentOS images. * [#196](https://github.com/portertech/kitchen-docker/pulls/196) Mutex SSH key generation for use with `kitchen -c`. * [#192](https://github.com/portertech/kitchen-docker/pulls/192) Don't wait when stopping a container. ## 2.3.0 * `build_context` option (boolean) to enable/disable sending the build context to Docker. ## 2.2.0 * Use a temporary file for each suite instance Docker container Dockerfile, instead of passing their contents via STDIN. This allows for the use of commands like ADD and COPY. **Users must now use Docker >= 1.5.0** * Passwordless suite instance Docker container login (SSH), using a generated key pair. * Support for sharing a host device with suite instance Docker containers. * README YAML highlighting. ## 2.1.0 * Use `NUL` instead of `/dev/null` on Windows for output redirection ## 2.0.0 * Use Docker `top` and `port` instead of `inspect` * Don't create the kitchen user if it already exists * Docker container capabilities options: cap_add, cap_drop * Docker security profile option (SELinux/AppArmor): security_opt * wait_for_sshd option (boolean) * Create `/etc/sudoers.d` if missing * Fixed option deprecation warnings, require Docker >= 1.2 ## 1.7.0 * Ensure a container id is set before attempting to inspect a container ## 1.6.0 * `publish_all` option to publish all ports to the host interface * `instance_name` option to name the Docker container * `links` option to link suite instance Docker containers * `socket` option will now default to ENV `DOCKER_HOST` if set * Fixed verify dependencies output redirection * Added `fedora` to platform names * Support for `gentoo` and `gentoo-paludis` platforms * Adding sudo rule to `/etc/sudoers.d/#{username}` in addition to `/etc/sudoers` kitchen-docker-2.10.0/.gitignore0000644000004100000410000000031513641341210016476 0ustar www-datawww-data*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp .kitchen/ .kitchen.local.yml Dockerfile* .DS_Store kitchen-docker-2.10.0/LICENSE0000644000004100000410000002613613641341210015524 0ustar www-datawww-data Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. kitchen-docker-2.10.0/.cane0000644000004100000410000000000013641341210015404 0ustar www-datawww-datakitchen-docker-2.10.0/Rakefile0000644000004100000410000000177613641341210016167 0ustar www-datawww-datarequire "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 puts "\n## Production Code Stats" sh "countloc -r lib" end desc "Run all quality tasks" task :quality => [:cane, :tailor, :stats] task :default => [:quality] # begin # require 'kitchen/rake_tasks' # Kitchen::RakeTasks.new # rescue LoadError # puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI'] # end # Create the spec 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 << "--tag #{args[:tag]}" if args[:tag] a << "--default-path test" a << '-I test/spec' end.join(' ') end kitchen-docker-2.10.0/lib/0000755000004100000410000000000013641341210015255 5ustar www-datawww-datakitchen-docker-2.10.0/lib/docker/0000755000004100000410000000000013641341210016524 5ustar www-datawww-datakitchen-docker-2.10.0/lib/docker/version.rb0000644000004100000410000000163613641341210020544 0ustar www-datawww-data# # 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. begin 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' end rescue LoadError => e logger.debug("[Docker] docker-api gem not found for InSpec verifier. #{e}") end kitchen-docker-2.10.0/lib/train/0000755000004100000410000000000013641341210016372 5ustar www-datawww-datakitchen-docker-2.10.0/lib/train/docker.rb0000644000004100000410000000734213641341210020174 0ustar www-datawww-data# # 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. # 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' module Train::Transports # Patched train transport with Windows support for InSpec verifier class Docker < Train.plugin(1) name 'docker' include_options Train::Extras::CommandWrapper option :host, required: true def connection(state = {}, &block) opts = merge_options(options, state || {}) validate_options(opts) if @connection && @connection_options == opts reuse_connection(&block) else create_new_connection(opts, &block) end end private # Creates a new Docker connection instance and save it for potential future # reuse. # # @param options [Hash] connection options # @return [Docker::Connection] a Docker connection instance # @api private def create_new_connection(options, &block) if @connection logger.debug("[Docker] shutting previous connection #{@connection}") @connection.close end @connection_options = options @connection = Connection.new(options, &block) end # Return the last saved Docker connection instance. # # @return [Docker::Connection] a Docker connection instance # @api private def reuse_connection logger.debug("[Docker] reusing existing connection #{@connection}") yield @connection if block_given? @connection end end end class Train::Transports::Docker class Connection < BaseConnection def initialize(conf) super(conf) @id = options[:host] @container = ::Docker::Container.get(@id) || fail("Can't find Docker container #{@id}") @cmd_wrapper = nil @cmd_wrapper = CommandWrapper.load(self, @options) self end def uri if @container.nil? "docker://#{@id}" else "docker://#{@container.id}" end end private def file_via_connection(path) if os.aix? Train::File::Remote::Aix.new(self, path) elsif os.solaris? Train::File::Remote::Unix.new(self, path) elsif os.windows? Train::File::Remote::Windows.new(self, path) else Train::File::Remote::Linux.new(self, path) end end def platform_specific_cmd(cmd) return cmd if @container.info.nil? if @container.info['Platform'] == 'windows' return ['cmd.exe', '/c', cmd] else return ['/bin/sh', '-c', cmd] end end def run_command_via_connection(cmd, &_data_handler) cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil? stdout, stderr, exit_status = @container.exec(platform_specific_cmd(cmd)) CommandResult.new(stdout.join, stderr.join, exit_status) rescue ::Docker::Error::DockerError => _ raise rescue => _ # @TODO: differentiate any other error raise end end end rescue LoadError => e logger.debug("[Docker] train gem not found for InSpec verifier. #{e}") end kitchen-docker-2.10.0/lib/kitchen/0000755000004100000410000000000013641341210016702 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/driver/0000755000004100000410000000000013641341210020175 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/driver/docker.rb0000644000004100000410000001241113641341210021770 0ustar www-datawww-data# # Copyright (C) 2014, Sean Porter # # 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. require 'kitchen' require 'json' require 'securerandom' require 'net/ssh' 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' module Kitchen module Driver # Docker driver for Kitchen. # # @author Sean Porter class Docker < Kitchen::Driver::Base include Kitchen::Docker::Helpers::CliHelper include Kitchen::Docker::Helpers::ContainerHelper include ShellOut default_config :binary, 'docker' default_config :build_options, nil default_config :cap_add, nil default_config :cap_drop, nil default_config :disable_upstart, true default_config :env_variables, nil default_config :interactive, false 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 :publish_all, false default_config :remove_images, false default_config :run_options, nil default_config :security_opt, nil default_config :tls, false default_config :tls_cacert, nil default_config :tls_cert, nil default_config :tls_key, nil default_config :tls_verify, false default_config :tty, false default_config :use_cache, true default_config :use_internal_docker_network, false default_config :use_sudo, false default_config :wait_for_transport, true default_config :build_context do |driver| !driver.remote_socket? end default_config :image do |driver| driver.default_image end 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('-') end default_config :platform do |driver| driver.default_platform end 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' else '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' 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 end default_config :username do |driver| # Return nil to prevent username from being added to Docker # command line args for Windows if a username was not specified if driver.windows_os? nil else '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' end def create(state) container.create(state) wait_for_transport(state) end def destroy(state) container.destroy(state) end def wait_for_transport(state) if config[:wait_for_transport] instance.transport.connection(state) do |conn| conn.wait_until_ready end end end def default_image platform, release = instance.platform.name.split('-') if platform == 'centos' && release release = 'centos' + release.split('.').first end release ? [platform, release].join(':') : platform end def default_platform instance.platform.name.split('-').first end protected def container @container ||= if windows_os? Kitchen::Docker::Container::Windows.new(config) else Kitchen::Docker::Container::Linux.new(config) end @container end end end end kitchen-docker-2.10.0/lib/kitchen/docker/0000755000004100000410000000000013641341210020151 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/docker/helpers/0000755000004100000410000000000013641341210021613 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/docker/helpers/file_helper.rb0000644000004100000410000000241313641341210024416 0ustar www-datawww-data# # 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. require 'fileutils' module Kitchen module Docker module Helpers module FileHelper def create_temp_file(file, contents) debug("[Docker] Creating temp file #{file}") debug('[Docker] --- Start Temp File Contents ---') debug(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.write(contents) rescue IOError => e raise "Failed to write temp file. Error Details: #{e}" ensure file.close unless file.nil? end end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/helpers/container_helper.rb0000644000004100000410000001344713641341210025472 0ustar www-datawww-data# # 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. require 'erb' require 'json' require 'shellwords' require 'tempfile' require 'uri' require 'kitchen' require 'kitchen/configurable' require_relative '../erb_context' require_relative 'cli_helper' module Kitchen module Docker module Helpers module ContainerHelper include Configurable include Kitchen::Docker::Helpers::CliHelper 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' end container_id end def dockerfile_template template = IO.read(File.expand_path(config[:dockerfile])) context = Kitchen::Docker::ERBContext.new(config.to_hash) ERB.new(template).result(context.get_binding) end def remote_socket? config[:socket] ? socket_uri.scheme == 'tcp' : false end def socket_uri URI.parse(config[:socket]) end def dockerfile_path(file) config[:build_context] ? Pathname.new(file.path).relative_path_from(Pathname.pwd).to_s : file.path end def container_exists?(state) state[:container_id] && !!docker_command("top #{state[:container_id]}") rescue false end def container_exec(state, command) cmd = build_exec_command(state, command) docker_command(cmd) rescue => e raise "Failed to execute command on Docker container. #{e}" end def create_dir_on_container(state, path) path = replace_env_variables(state, path) cmd = "mkdir -p #{path}" if state[:platform].include?('windows') psh = "-Command if(-not (Test-Path \'#{path}\')) { New-Item -Path \'#{path}\' -Force }" cmd = build_powershell_command(psh) end cmd = build_exec_command(state, cmd) docker_command(cmd) rescue => e raise "Failed to create directory #{path} on container. #{e}" end def copy_file_to_container(state, local_file, remote_file) debug("Copying local file #{local_file} to #{remote_file} on container") remote_file = replace_env_variables(state, remote_file) remote_file = "#{state[:container_id]}:#{remote_file}" cmd = build_copy_command(local_file, remote_file) docker_command(cmd) rescue => e raise "Failed to copy file #{local_file} to container. #{e}" end 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') 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') stdout = docker_command(cmd, suppress_output: !logger.debug?).strip stdout.split("\n").each { |line| vars[line.split('=')[0]] = line.split('=')[1] } end vars end def replace_env_variables(state, str) 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] value = container_env_variables(state)[key].to_s.strip str = str.gsub("$#{key}", value) end str end def run_container(state, transport_port = nil) cmd = build_run_command(state[:image_id], transport_port) output = docker_command(cmd) parse_container_id(output) end def container_ip_address(state) cmd = "inspect --format '{{ .NetworkSettings.IPAddress }}'" cmd << " #{state[:container_id]}" docker_command(cmd).strip rescue raise ActionFailed, 'Error getting internal IP of Docker container' end def remove_container(state) container_id = state[:container_id] docker_command("stop -t 0 #{container_id}") docker_command("rm #{container_id}") end def dockerfile_proxy_config env_variables = '' if config[:http_proxy] env_variables << "ENV http_proxy #{config[:http_proxy]}\n" env_variables << "ENV HTTP_PROXY #{config[:http_proxy]}\n" end if config[:https_proxy] env_variables << "ENV https_proxy #{config[:https_proxy]}\n" env_variables << "ENV HTTPS_PROXY #{config[:https_proxy]}\n" end if config[:no_proxy] env_variables << "ENV no_proxy #{config[:no_proxy]}\n" env_variables << "ENV NO_PROXY #{config[:no_proxy]}\n" end env_variables end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/helpers/image_helper.rb0000644000004100000410000000452413641341210024566 0ustar www-datawww-data# # 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. require 'kitchen' require 'kitchen/configurable' require_relative 'cli_helper' require_relative 'container_helper' module Kitchen module Docker module Helpers module ImageHelper include Configurable include Kitchen::Docker::Helpers::CliHelper include Kitchen::Docker::Helpers::ContainerHelper def parse_image_id(output) output.each_line do |line| 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' end def remove_image(state) image_id = state[:image_id] docker_command("rmi #{image_id}") end def build_image(state, dockerfile) 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 #{Shellwords.escape(dockerfile_path(file))} #{build_context}", input: dockerfile_contents) ensure file.close unless file.closed? file.unlink end parse_image_id(output) end def image_exists?(state) state[:image_id] && !!docker_command("inspect --type=image #{state[:image_id]}") rescue false end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/helpers/inspec_helper.rb0000644000004100000410000000261613641341210024765 0ustar www-datawww-data# # 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 kitchen-docker-2.10.0/lib/kitchen/docker/helpers/cli_helper.rb0000644000004100000410000001360213641341210024250 0ustar www-datawww-data# # 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. require 'kitchen' require 'kitchen/configurable' require 'kitchen/logging' require 'kitchen/shell_out' module Kitchen module Docker module Helpers module CliHelper include Configurable include Logging include ShellOut 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 << " --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] logger.debug("docker_command: #{docker} #{cmd} shell_opts: #{docker_shell_opts(options)}") run_command("#{docker} #{cmd}", docker_shell_opts(options)) end def build_run_command(image_id, transport_port = nil) 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}" } Array(config[:dns]).each { |dns| cmd << " --dns #{dns}" } Array(config[:add_host]).each { |host, ip| cmd << " --add-host=#{host}:#{ip}" } Array(config[:volume]).each { |volume| cmd << " -v #{volume}" } 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}" } cmd << " --name #{config[:instance_name]}" if config[:instance_name] 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 << " -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] 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]}" logger.debug("build_run_command: #{cmd}") cmd end def build_exec_command(state, command) 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 << " -u #{config[:username]}" if config[:username] cmd << " -w #{config[:working_dir]}" if config[:working_dir] cmd << " #{state[:container_id]}" cmd << " #{command}" logger.debug("build_exec_command: #{cmd}") cmd end def build_copy_command(local_file, remote_file, opts = {}) 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 << 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) args = '' vars.each do |k, v| args << " -e #{k.to_s.strip}=\"#{v.to_s.strip}\"" end args end def dev_null case RbConfig::CONFIG['host_os'] when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ 'NUL' else '/dev/null' end end def docker_shell_opts(options = {}) options[:live_stream] = nil if options[:suppress_output] options.delete(:suppress_output) options 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 end kitchen-docker-2.10.0/lib/kitchen/docker/container/0000755000004100000410000000000013641341210022133 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/docker/container/windows.rb0000644000004100000410000000551413641341210024157 0ustar www-datawww-data# # 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. require 'securerandom' require_relative '../container' module Kitchen module Docker class Container class Windows < Kitchen::Docker::Container def initialize(config) super end def create(state) super 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] end def execute(command) # Create temp script file and upload files to 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('/', '\\') 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') ::File.delete(temp_file) # Replace any environment variables used in the path and execute script file debug("Executing temp script #{remote_path}\\#{filename} on container") remote_path = replace_env_variables(@config, remote_path) cmd = build_powershell_command("-File #{remote_path}\\#{filename}") container_exec(@config, cmd) rescue => e raise "Failed to execute command on Windows container. #{e}" end protected def dockerfile raise ActionFailed, "Unknown platform '#{@config[:platform]}'" unless @config[:platform] == 'windows' return dockerfile_template if @config[:dockerfile] from = "FROM #{@config[:image]}" custom = '' Array(@config[:provision_command]).each do |cmd| custom << "RUN #{cmd}\n" end output = [from, dockerfile_proxy_config, custom, ''].join("\n") debug('--- Start Dockerfile ---') debug(output.strip) debug('--- End Dockerfile ---') output end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/container/linux.rb0000644000004100000410000002211713641341210023622 0ustar www-datawww-data# # 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. require 'base64' require 'openssl' require 'securerandom' require 'shellwords' require_relative '../container' module Kitchen module Docker class Container class Linux < Kitchen::Docker::Container MUTEX_FOR_SSH_KEYS = Mutex.new def initialize(config) super end def create(state) super debug('Creating Linux container') generate_keys state[:ssh_key] = @config[:private_key] state[:image_id] = build_image(state, dockerfile) unless state[:image_id] state[:container_id] = run_container(state, 22) unless state[:container_id] state[:hostname] = 'localhost' state[:port] = container_ssh_port(state) end def execute(command) # Create temp script file and upload files to container debug("Executing command on Linux container (Platform: #{@config[:platform]})") filename = "docker-#{::SecureRandom.uuid}.sh" temp_file = "./.kitchen/temp/#{filename}" create_temp_file(temp_file, command) remote_path = @config[:temp_dir] 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') ::File.delete(temp_file) # Replace any environment variables used in the path and execute script file debug("Executing temp script #{remote_path}/#{filename} on container") remote_path = replace_env_variables(@config, remote_path) container_exec(@config, "/bin/bash #{remote_path}/#{filename}") rescue => e raise "Failed to execute command on Linux container. #{e}" end protected 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", '') public_key = "ssh-rsa #{blobbed_key} kitchen_docker_key" 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.write(public_key) file.chmod(0600) end end end end def parse_container_ssh_port(output) _host, port = output.split(':') port.to_i rescue => e raise ActionFailed, "Could not parse Docker port output for container SSH port. #{e}" end def container_ssh_port(state) return 22 if @config[:use_internal_docker_network] output = docker_command("port #{state[:container_id]} 22/tcp") parse_container_ssh_port(output) rescue => e raise ActionFailed, "Docker reports container has no ssh port mapped. #{e}" end def dockerfile return dockerfile_template if @config[:dockerfile] from = "FROM #{@config[:image]}" platform = case @config[:platform] when 'debian', 'ubuntu' disable_upstart = <<-CODE RUN [ ! -f "/sbin/initctl" ] || dpkg-divert --local --rename --add /sbin/initctl && ln -sf /bin/true /sbin/initctl CODE packages = <<-CODE ENV DEBIAN_FRONTEND noninteractive ENV container docker RUN apt-get update RUN apt-get install -y sudo openssh-server curl lsb-release CODE @config[:disable_upstart] ? disable_upstart + packages : packages when 'rhel', 'centos', 'oraclelinux', 'amazonlinux' <<-CODE ENV container docker RUN yum clean all RUN yum install -y sudo openssh-server openssh-clients which curl RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' CODE when 'fedora' <<-CODE ENV container docker RUN dnf clean all RUN dnf install -y sudo openssh-server openssh-clients which curl RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' CODE when 'opensuse/tumbleweed', 'opensuse/leap', 'opensuse', 'sles' <<-CODE ENV container docker RUN zypper install -y sudo openssh which curl RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N '' RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N '' CODE when 'arch' # See https://bugs.archlinux.org/task/47052 for why we # blank out limits.conf. <<-CODE RUN pacman --noconfirm -Sy archlinux-keyring RUN pacman-db-upgrade RUN pacman --noconfirm -Syu openssl openssh sudo curl RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key RUN echo >/etc/security/limits.conf CODE when 'gentoo' <<-CODE RUN emerge --sync RUN emerge net-misc/openssh app-admin/sudo RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key CODE when 'gentoo-paludis' <<-CODE RUN cave sync RUN cave resolve -zx net-misc/openssh app-admin/sudo RUN [ -f "/etc/ssh/ssh_host_rsa_key" ] || ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key RUN [ -f "/etc/ssh/ssh_host_dsa_key" ] || ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key CODE else raise ActionFailed, "Unknown platform '#{@config[:platform]}'" end username = @config[:username] public_key = IO.read(@config[:public_key]).strip homedir = username == 'root' ? '/root' : "/home/#{username}" base = <<-CODE RUN if ! getent passwd #{username}; then \ useradd -d #{homedir} -m -s /bin/bash -p '*' #{username}; \ fi 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 RUN chmod 0600 #{homedir}/.ssh/authorized_keys RUN mkdir -p /run/sshd CODE custom = '' Array(@config[:provision_command]).each do |cmd| custom << "RUN #{cmd}\n" end 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 ---') debug(output.strip) debug('--- End Dockerfile ---') output end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/docker_version.rb0000644000004100000410000000127413641341210023516 0ustar www-datawww-data# # Copyright (C) 2014, Sean Porter # # 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. module Kitchen module Docker # Version string for Docker Kitchen driver DOCKER_VERSION = "2.10.0" end end kitchen-docker-2.10.0/lib/kitchen/docker/container.rb0000644000004100000410000000434513641341210022466 0ustar www-datawww-data# # 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. require_relative 'helpers/cli_helper' require_relative 'helpers/container_helper' require_relative 'helpers/file_helper' require_relative 'helpers/image_helper' module Kitchen module Docker class Container include Kitchen::Docker::Helpers::CliHelper include Kitchen::Docker::Helpers::ContainerHelper include Kitchen::Docker::Helpers::FileHelper include Kitchen::Docker::Helpers::ImageHelper def initialize(config) @config = config end def create(state) if container_exists?(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.' end state[:username] = @config[:username] state[:hostname] = 'localhost' if remote_socket? state[:hostname] = socket_uri.host elsif config[:use_internal_docker_network] state[:hostname] = container_ip_address(state) end end def upload(locals, remote) files = locals files = Array(locals) unless locals.is_a?(Array) files.each do |file| copy_file_to_container(@config, file, remote) end files end def destroy(state) info("[Docker] Destroying Docker container #{state[:container_id]}") if state[:container_id] remove_container(state) if container_exists?(state) if @config[:remove_images] && state[:image_id] remove_image(state) if image_exists?(state) end end end end end kitchen-docker-2.10.0/lib/kitchen/docker/erb_context.rb0000644000004100000410000000153513641341210023016 0ustar www-datawww-data# # Copyright (C) 2014, Sean Porter # # 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. require 'erb' module Kitchen module Docker class ERBContext def initialize(config={}) config.each do |key, value| instance_variable_set('@' + key.to_s, value) end end def get_binding binding end end end end kitchen-docker-2.10.0/lib/kitchen/transport/0000755000004100000410000000000013641341210020736 5ustar www-datawww-datakitchen-docker-2.10.0/lib/kitchen/transport/docker.rb0000644000004100000410000000737513641341210022546 0ustar www-datawww-data# # 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. require 'kitchen' require_relative '../docker/container/linux' require_relative '../docker/container/windows' require_relative '../docker/helpers/inspec_helper' require_relative '../../docker/version.rb' require_relative '../../train/docker.rb' module Kitchen module Transport class Docker < Kitchen::Transport::Base class DockerFailed < TransportFailed; end kitchen_transport_api_version 1 plugin_version Kitchen::VERSION default_config :binary, 'docker' default_config :env_variables, nil default_config :interactive, false default_config :privileged, false default_config :tls, false default_config :tls_cacert, nil default_config :tls_cert, nil default_config :tls_key, nil default_config :tls_verify, false default_config :tty, false 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 end default_config :temp_dir do |transport| if transport.windows_os? '$env:TEMP' else '/tmp' end end default_config :username do |transport| # Return an empty string to prevent username from being added to Docker # command line args for Windows if a username was not specified if transport.windows_os? nil else 'kitchen' end end def connection(state, &block) options = config.to_hash.merge(state) options[:platform] = instance.platform.name # Set value for DOCKER_HOST environment variable for the docker-api gem # 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? Kitchen::Transport::Docker::Connection.new(options, &block) end class Connection < Kitchen::Transport::Docker::Connection # Include the InSpec patches to be able to execute tests on Windows containers include Kitchen::Docker::Helpers::InspecHelper def execute(command) return if command.nil? debug("[Docker] Executing command: #{command}") info("[Docker] Executing command on container") container.execute(command) rescue => e raise DockerFailed, "Docker failed to execute command on container. Error Details: #{e}" end def upload(locals, remote) container.upload(locals, remote) end def container @container ||= if @options[:platform].include?('windows') Kitchen::Docker::Container::Windows.new(@options) else Kitchen::Docker::Container::Linux.new(@options) end @container end end end end end kitchen-docker-2.10.0/docker.ps10000644000004100000410000000112213641341210016377 0ustar www-datawww-data# This script is used to configure the Docker service for Windows builds in Travis CI Write-Host "Configuring Docker service to listen on TCP port 2375..." $dockerSvcArgs = (Get-WmiObject Win32_Service | ?{$_.Name -eq 'docker'} | Select PathName).PathName $dockerSvcArgs = "$dockerSvcArgs -H tcp://0.0.0.0:2375 -H npipe:////./pipe/docker_engine" Write-Host "Docker Service Args: $dockerSvcArgs" Get-WmiObject Win32_Service -Filter "Name='docker'" | Invoke-WmiMethod -Name Change -ArgumentList @($null,$null,$null,$null,$null, $dockerSvcArgs) | Out-Null Restart-Service docker -Force -Verbose kitchen-docker-2.10.0/.kitchen.windows.yml0000644000004100000410000000161113641341210020425 0ustar www-datawww-data<% # Make sure the local copy of the driver is loaded %> <% lib = File.expand_path('../lib', __FILE__) %> <% $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) %> --- driver: name: docker provision_command: - powershell -ExecutionPolicy Bypass -NoLogo -Command . { iwr -useb https://omnitruck.chef.io/install.ps1 } ^| iex; install - powershell -Command $path=$env:Path + ';c:\opscode\chef\embedded\bin'; Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\' -Name Path -Value $path transport: name: docker socket: tcp://localhost:2375 provisioner: name: dummy platforms: - name: windows driver_config: image: mcr.microsoft.com/windows/servercore:1803 platform: windows suites: - name: default - name: context driver: build_context: false - name: inspec driver: provision_command: echo 1 verifier: name: inspec kitchen-docker-2.10.0/Gemfile0000644000004100000410000000004713641341210016003 0ustar www-datawww-datasource 'https://rubygems.org' gemspec kitchen-docker-2.10.0/.tailor0000644000004100000410000000013113641341210015775 0ustar www-datawww-dataTailor.config do |config| config.formatters "text" config.file_set 'lib/**/*.rb' end kitchen-docker-2.10.0/kitchen-docker.gemspec0000644000004100000410000000273213641341210020752 0ustar www-datawww-datalib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'kitchen/docker/docker_version' Gem::Specification.new do |spec| spec.name = 'kitchen-docker' spec.version = Kitchen::Docker::DOCKER_VERSION 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.files = `git ls-files`.split($/) spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 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' # Integration testing gems. spec.add_development_dependency 'kitchen-inspec', '~> 1.1' spec.add_development_dependency 'train', '>= 2.1', '< 4.0' # validate 4.x when it's released end