diff --git a/lib/puppet/parser/functions/docker_params_changed.rb b/lib/puppet/parser/functions/docker_params_changed.rb index 894dac8..325cbc7 100644 --- a/lib/puppet/parser/functions/docker_params_changed.rb +++ b/lib/puppet/parser/functions/docker_params_changed.rb @@ -1,76 +1,78 @@ +# frozen_string_literal: true + require 'open3' require 'json' module Puppet::Parser::Functions # Checks if at least one parammeter is changed newfunction(:docker_params_changed, type: :rvalue) do |args| opts = args[0] || {} return_value = [] if opts['sanitised_title'] && opts['osfamily'] stdout, stderr, status = Open3.capture3("docker inspect #{opts['sanitised_title']}") if stderr.to_s == '' && status.to_s.include?('exit 0') param_changed = false inspect_hash = JSON.parse(stdout)[0] # check if the image was changed param_changed = true if opts['image'] && opts['image'] != inspect_hash['Config']['Image'] # check if something on volumes or mounts was changed(a new volume/mount was added or removed) param_changed = true if opts['volumes'].is_a?(String) && opts['volumes'].include?(':') && opts['volumes'] != inspect_hash['Mounts'].to_a[0] && opts['osfamily'] != 'windows' param_changed = true if opts['volumes'].is_a?(String) && !opts['volumes'].include?(':') && opts['volumes'] != inspect_hash['Config']['Volumes'].to_a[0] && opts['osfamily'] != 'windows' param_changed = true if opts['volumes'].is_a?(String) && opts['volumes'].scan(%r{(?=:)}).count == 2 && opts['volumes'] != inspect_hash['Mounts'].to_a[0] && opts['osfamily'] == 'windows' param_changed = if opts['volumes'].is_a?(String) && opts['volumes'].scan(%r{(?=:)}).count == 1 && opts['volumes'] != inspect_hash['Config']['Volumes'].to_a[0] && opts['osfamily'] == 'windows' true else param_changed end pp_paths = opts['volumes'].reject { |item| item.include?(':') } if opts['volumes'].is_a?(Array) && opts['osfamily'] != 'windows' pp_mounts = opts['volumes'].select { |item| item.include?(':') } if opts['volumes'].is_a?(Array) && opts['osfamily'] != 'windows' pp_paths = opts['volumes'].select { |item| item.scan(%r{(?=:)}).count == 1 } if opts['volumes'].is_a?(Array) && opts['osfamily'] == 'windows' pp_mounts = opts['volumes'].select { |item| item.scan(%r{(?=:)}).count == 2 } if opts['volumes'].is_a?(Array) && opts['osfamily'] == 'windows' inspect_paths = if inspect_hash['Config']['Volumes'] inspect_hash['Config']['Volumes'].keys else [] end param_changed = true if pp_paths != inspect_paths names = inspect_hash['Mounts'].map { |item| item.values[1] } if inspect_hash['Mounts'] pp_names = pp_mounts.map { |item| item.split(':')[0] } if pp_mounts names = names.select { |item| pp_names.include?(item) } if names && pp_names destinations = inspect_hash['Mounts'].map { |item| item.values[3] } if inspect_hash['Mounts'] pp_destinations = pp_mounts.map { |item| item.split(':')[1] } if pp_mounts && opts['osfamily'] != 'windows' pp_destinations = pp_mounts.map { |item| "#{item.split(':')[1].downcase}:#{item.split(':')[2]}" } if pp_mounts && opts['osfamily'] == 'windows' destinations = destinations.select { |item| pp_destinations.include?(item) } if destinations && pp_destinations param_changed = true if pp_names != names param_changed = true if pp_destinations != destinations param_changed = true if pp_mounts != [] && inspect_hash['Mounts'].nil? # check if something on ports was changed(some ports were added or removed) ports = inspect_hash['HostConfig']['PortBindings'].keys ports = ports.map { |item| item.split('/')[0] } pp_ports = opts['ports'].sort if opts['ports'].is_a?(Array) pp_ports = [opts['ports']] if opts['ports'].is_a?(String) param_changed = true if pp_ports && pp_ports != ports return_value << if param_changed 'PARAM_CHANGED' else 'NO_CHANGE' end else return_value << 'CONTAINER_NOT_FOUND' end else return_value << 'ARG_REQUIRED_MISSING' end return_value.flatten.join(' ') end end diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index 29c8d88..7109f20 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -1,157 +1,159 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' install_dir = '/cygdrive/c/Program Files/Docker' file_extension = '.exe' docker_args = 'docker_ee => true' tmp_path = 'C:/cygwin64/tmp' test_container = if os[:release] =~ %r{2019} 'nanoserver' else 'nanoserver-sac2016' end else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end install_dir = '/usr/local/bin' file_extension = '' tmp_path = '/tmp' test_container = 'debian' end describe 'docker compose' do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_code = <<-code class { 'docker': #{docker_args} } class { 'docker::compose': version => '1.23.2', } code apply_manifest(install_code, catch_failures: true) end end context 'Creating compose v3 projects', win_broken: true do let(:install_pp) do <<-MANIFEST docker_compose { 'web': compose_files => ['#{tmp_path}/docker-compose-v3.yml'], ensure => present, } MANIFEST end it 'is idempotent' do idempotent_apply(install_pp) end it 'has docker compose installed' do run_shell('docker-compose --help', expect_failures: false) end it 'finds a docker container' do run_shell('docker inspect web_compose_test_1', expect_failures: false) end end context 'creating compose projects with multi compose files', win_broken: true do before(:all) do install_pp = <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end it "should find container with #{test_container} tag" do run_shell("docker inspect web1_compose_test_1 | grep #{test_container}", acceptable_exit_codes: [0]) end end context 'Destroying project with multiple compose files', win_broken: true do let(:destroy_pp) do <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => absent, } MANIFEST end before(:all) do install_pp = <<-MANIFEST docker_compose { 'web1': compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end it 'is idempotent' do idempotent_apply(destroy_pp) end it 'does not find a docker container' do run_shell('docker inspect web1_compose_test_1', expect_failures: true) end end context 'Requesting a specific version of compose' do let(:version) do '1.21.2' end it 'is idempotent' do pp = <<-MANIFEST class { 'docker::compose': version => '#{version}', } MANIFEST idempotent_apply(pp) end it 'has installed the requested version' do run_shell('docker-compose --version', expect_failures: false) do |r| expect(r.stdout).to match(%r{#{version}}) end end end context 'Removing docker compose' do let(:version) do '1.21.2' end it 'is idempotent' do pp = <<-MANIFEST class { 'docker::compose': ensure => absent, version => '#{version}', } MANIFEST idempotent_apply(pp) end it 'has removed the relevant files' do run_shell("test -e \"#{install_dir}/docker-compose#{file_extension}\"", expect_failures: true) run_shell("test -e \"#{install_dir}/docker-compose-#{version}#{file_extension}\"", expect_failures: true) end after(:all) do install_pp = <<-MANIFEST class { 'docker': #{docker_args}} class { 'docker::compose': } MANIFEST apply_manifest(install_pp, catch_failures: true) end end end diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index fd1c0cf..0f0f27c 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -1,105 +1,107 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' docker_args = 'docker_ee => true, docker_ee_source_location => "https://download.docker.com/components/engine/windows-server/17.06/docker-17.06.2-ee-14.zip"' default_image = 'winamd64/hello-seattle' # The default args are set because: # restart => 'always' - there is no service created to manage containers # net => 'nat' - docker uses bridged by default when running a container. When installing docker on windows the default network is NAT. default_docker_run_arg = "restart => 'always', net => 'nat'," default_run_command = 'ping 127.0.0.1 -t' docker_command = '"/cygdrive/c/Program Files/Docker/docker"' skip = false elsif os[:name] == 'Ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" default_image = 'busybox' skip = true else docker_args = '' default_image = 'busybox' skip = false end describe 'the Puppet Docker module' do context 'with download location', skip: skip do let(:pp) do "class { 'docker': #{docker_args} }" end it 'runs successfully' do apply_manifest(pp, catch_failures: true) end it 'runs idempotently' do apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'is start a docker process' do if os[:family] == 'windows' run_shell('powershell Get-Process -Name dockerd') do |r| expect(r.stdout).to match(%r{ProcessName}) end else run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match %r{dockerd -H unix:\/\/\/var\/run\/docker.sock} end end end it 'installs a working docker client' do run_shell("#{docker_command} ps", expect_failures: false) end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} ps", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container-3-6", expect_failures: true) if os[:family] == 'windows' run_shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', expect_failures: true) else run_shell('test -f /etc/systemd/system/container-3-6.service', expect_failures: true) end end end end diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 3019325..f6cf791 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -1,996 +1,998 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:kernel] == 'windows' docker_args = 'docker_ee => true' default_image = 'winamd64/hello-seattle' default_image_tag = if os[:release][:major] == '2019' 'nanoserver' else 'nanoserver-sac2016' end default_digest = 'sha256:dcba85354678b50608b8c40ec6d17cce063a224aa0e12b6a55dc47b67f039e75' default_local_digest = 'sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10' second_image = 'winamd64/hola-mundo' default_dockerfile = 'C:/Users/Administrator/AppData/Local/Temp/Dockerfile' dockerfile_test = 'C:/Windows/Dockerfile_test.txt' # The default args are set because: # restart => 'always' - there is no service created to manage containers # net => 'nat' - docker uses bridged by default when running a container. When installing docker on windows the default network is NAT. default_docker_run_arg = "restart => 'always', net => 'nat'," default_run_command = 'ping 127.0.0.1 -t' docker_command = '"/cygdrive/c/Program Files/Docker/docker"' default_docker_exec_lr_command = 'cmd /c "ping 127.0.0.1 -t > C:\Users\Public\test_file.txt"' default_docker_exec_command = 'cmd /c "echo test > C:\Users\Public\test_file.txt"' docker_mount_path = 'C:/Users/Public/DockerVolume' storage_driver = 'windowsfilter' else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end default_image = 'alpine' second_image = 'busybox' default_image_tag = '3.7' default_digest = 'sha256:3dcdb92d7432d56604d4545cbd324b14e647b313626d99b889d0626de158f73a' default_local_digest = 'sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10' default_dockerfile = '/root/Dockerfile' dockerfile_test = "#{default_dockerfile}_test.txt" docker_command = 'docker' default_docker_run_arg = '' default_run_command = 'init' default_docker_exec_lr_command = '/bin/sh -c "touch /root/test_file.txt; while true; do echo hello world; sleep 1; done"' default_docker_exec_command = 'touch /root/test_file.txt' docker_mount_path = '/root' storage_driver = 'devicemapper' storage_driver = if os[:family] == 'Debian' && os[:release][:major] =~ %r{14.04|^8$} 'aufs' elsif os[:family] == 'RedHat' 'devicemapper' else 'overlay2' end end describe 'the Puppet Docker module' do context 'clean up before each test', win_broken: true do before(:each) do retry_on_error_matching(60, 5, %r{connection failure running}) do # Stop all container using systemd run_shell('ls -D -1 /etc/systemd/system/docker-container* | sed \'s/\/etc\/systemd\/system\///g\' | sed \'s/\.service//g\' | while read container; do service $container stop; done') # Delete all running containers run_shell("#{docker_command} rm -f $(#{docker_command} ps -a -q) || true") # Delete all existing images run_shell("#{docker_command} rmi -f $(#{docker_command} images -q) || true") # Check to make sure no images are present run_shell("#{docker_command} images | wc -l") do |r| expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: end # Check to make sure no running containers are present run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: end end end describe 'docker class' do context 'without any parameters', win_broken: true do let(:pp) { "class { 'docker': #{docker_args} }" } it 'runs successfully' do apply_manifest(pp, catch_failures: true) end it 'runs idempotently' do apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'is start a docker process' do if os[:family] == 'windows' run_shell('powershell Get-Process -Name dockerd') do |r| expect(r.stdout).to match(%r{ProcessName}) end else run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match(%r{dockerd -H unix:\/\/\/var\/run\/docker.sock}) end end end it 'installs a working docker client' do run_shell("#{docker_command} ps", expect_failures: false) end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} ps", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container-3-6", expect_failures: true) if os[:family] == 'windows' run_shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', expect_failures: true) else run_shell('test -f /etc/systemd/system/container-3-6.service', expect_failures: true) end end end context 'passing a storage driver' do let(:pp) do <<-MANIFEST class {'docker': #{docker_args}, storage_driver => "#{storage_driver}", } MANIFEST end it 'applies manifest' do apply_manifest(pp, catch_failures: true) sleep 15 end it 'results in the docker daemon being configured with the specified storage driver' do run_shell("#{docker_command} info -f \"{{ .Driver}}\"") do |r| expect(r.stdout).to match %r{#{storage_driver}} end end end context 'passing a TCP address to bind to' do let(:pp) do <<-MANIFEST class { 'docker': tcp_bind => 'tcp://127.0.0.1:4444', #{docker_args} } MANIFEST end it 'runs idempotently' do idempotent_apply(pp) unless selinux == 'true' sleep 4 end it 'results in docker listening on the specified address' do if os[:family] == 'windows' run_shell('netstat -a -b') do |r| expect(r.stdout).to match(%r{127.0.0.1:4444}) end else run_shell('netstat -tulpn | grep docker') do |r| expect(r.stdout).to match(%r{tcp\s+0\s+0\s+127.0.0.1:4444\s+0.0.0.0\:\*\s+LISTEN\s+\d+\/docker}) end end end end context 'bound to a particular unix socket' do let(:pp) do <<-MANIFEST class { 'docker': socket_bind => 'unix:///var/run/docker.sock', #{docker_args} } MANIFEST end it 'runs idempotently' do idempotent_apply(pp) unless selinux == 'true' sleep 4 end it 'shows docker listening on the specified unix socket' do if os[:family] != 'windows' run_shell('ps aux | grep docker') do |r| expect(r.stdout).to match(%r{unix:\/\/\/var\/run\/docker.sock}) end end end end context 'uninstall docker' do after(:all) do pp = <<-EOS class {'docker': #{docker_args}, ensure => 'present' } EOS apply_manifest(pp, catch_failures: true) # Wait for reboot if windows sleep 300 if os[:family] == 'windows' end it 'uninstalls successfully' do pp = <<-EOS class {'docker': #{docker_args}, ensure => 'absent' } EOS apply_manifest(pp, catch_failures: true) sleep 4 run_shell('docker ps', expect_failures: true) end end end describe 'docker::image' do it 'successfullies download an image from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).to match(%r{#{default_image}}) end end it 'successfullies download an image based on a tag from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, image_tag => '#{default_image_tag}', require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).to match(%r{#{default_image}\s+#{default_image_tag}}) end end it 'successfullies download an image based on a digest from the Docker Hub' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, image_digest => '#{default_digest}', require => Class['docker'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images --digests") do |r| expect(r.stdout).to match(%r{#{default_image}.*#{default_digest}}) end end it 'creates a new image based on a Dockerfile' do run_cmd = if os[:family] == 'windows' 'RUN echo test > C:\\Users\\Public\\Dockerfile_test.txt' else "RUN echo test > #{dockerfile_test}" end pp = <<-EOS class { 'docker': #{docker_args} } docker::image { 'alpine_with_file': docker_file => "#{default_dockerfile}", require => Class['docker'], } file { '#{default_dockerfile}': ensure => present, content => "FROM #{default_image}\n#{run_cmd}", before => Docker::Image['alpine_with_file'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} run alpine_with_file cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{_test.txt}) end else run_shell("#{docker_command} run alpine_with_file ls #{dockerfile_test}") do |r| expect(r.stdout).to match(%r{#{dockerfile_test}}) end end end it 'creates a new image based on a tar', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], ensure => present, } docker::run { 'container_2_4': image => '#{default_image}', command => '/bin/sh -c "touch /root/test_file_for_tar_test.txt; while true; do echo hello world; sleep 1; done"', require => Docker::Image['alpine'], } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { 'alpine_from_commit': docker_tar => "/root/rootfs.tar" } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 # Commit currently running container as an image container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} commit #{container_id.stdout.strip} alpine_from_commit") # Stop all container using systemd run_shell('ls -D -1 /etc/systemd/system/docker-container* | sed \'s/\/etc\/systemd\/system\///g\' | sed \'s/\.service//g\' | while read container; do service $container stop; done') # Stop all running containers run_shell("#{docker_command} rm -f $(docker ps -a -q) || true") # Make sure no other containers are running run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end # Export new to a tar file run_shell("#{docker_command} save alpine_from_commit > /root/rootfs.tar") # Remove all images run_shell("#{docker_command} rmi $(docker images -q) || true") # Make sure no other images are present run_shell("#{docker_command} images | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} run alpine_from_commit ls /root") do |r| expect(r.stdout).to match(%r{test_file_for_tar_test.txt}) end end it 'successfullies delete the image' do pp1 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => present, require => Class['docker'], } EOS apply_manifest(pp1, catch_failures: true) pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': ensure => absent, } EOS apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} images") do |r| expect(r.stdout).not_to match(%r{#{default_image}}) end end end describe 'docker::run' do it 'starts a container with a configurable command' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_1': image => '#{default_image}', command => '#{default_docker_exec_lr_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| expect(r.stdout).to match(%r{test_file.txt}) end end container_name = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") expect(container_name.stdout.strip.to_s).to match(%r{(container-3-1|container_3_1)}) end it 'starts a container with port configuration' do pp = <<-EOS class { 'docker': #{docker_args}} docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_2': image => '#{default_image}', command => '#{default_run_command}', ports => ['4444'], expose => ['5555'], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps") do |r| expect(r.stdout).to match(%r{#{default_run_command}.+5555\/tcp\, 0\.0\.0.0\:\d+\-\>4444\/tcp}) end end it 'starts a container with the hostname set' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_3': image => '#{default_image}', command => '#{default_run_command}', hostname => 'testdomain.com', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} exec #{container_id.stdout.strip} hostname") do |r| expect(r.stdout).to match(%r{testdomain.com}) end end it 'starts a container while mounting local volumes' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_4': image => '#{default_image}', command => '#{default_run_command}', volumes => ["#{docker_mount_path}:#{docker_mount_path}/mnt:rw"], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } file { '#{docker_mount_path}': ensure => directory, before => File['#{docker_mount_path}/test_mount.txt'], } file { '#{docker_mount_path}/test_mount.txt': ensure => present, before => Docker::Run['container_3_4'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public\\\\DockerVolume\\\\mnt") do |r| expect(r.stdout).to match(%r{test_mount.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root/mnt") do |r| expect(r.stdout).to match(%r{test_mount.txt}) end end end # cpuset is not supported on Docker Windows # STDERR: C:/Program Files/Docker/docker.exe: Error response from daemon: invalid option: Windows does not support CpusetCpus. it 'starts a container with cpuset paramater set', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_5': image => '#{default_image}', command => '#{default_run_command}', cpuset => ['0'], require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell('#{docker_command} inspect container_3_5_5') do |r| expect(r.stdout).to match(%r{"CpusetCpus"\: "0"}) end end # leagacy container linking was not implemented on Windows. --link is a legacy Docker feature: https://docs.docker.com/network/links/ it 'starts multiple linked containers', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container1 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_5_2': image => '#{default_image}', command => '#{default_run_command}', depends => ['#{container1.stdout.strip}'], links => "#{container1.stdout.strip}:the_link", require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 container2 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") run_shell("#{docker_command} inspect -f \"{{ .HostConfig.Links }}\" #{container_id.stdout.strip}") do |r| expect(r.stdout).to match("/#{container1.stdout.strip}:/#{container2.stdout.strip}/the_link") end end it 'stops a running container', win_broken: true do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6': image => '#{default_image}', running => false, require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^2$}) end apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 run_shell("#{docker_command} ps | wc -l") do |r| expect(r.stdout).to match(%r{^1$}) end end it 'stops a running container and remove container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_3_6_1': ensure => 'absent', image => '#{default_image}', require => Docker::Image['#{default_image}'], } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container_3_6_1", expect_failures: false) apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 run_shell("#{docker_command} inspect container_3_6_1", expect_failures: true) end it 'allows dependency for ordering of independent run and image' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } docker::run { 'container_3_7_1': image => '#{default_image}', command => '#{default_run_command}', #{default_docker_run_arg} } docker::image { '#{second_image}': require => Docker::Run['container_3_7_1'], } docker::run { 'container_3_7_2': image => '#{second_image}', command => '#{default_run_command}', #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' end it 'restarts a unhealthy container' do pp5 = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', command => '#{default_run_command}', health_check_cmd => 'echo', restart_on_unhealthy => true, #{default_docker_run_arg} } EOS pp_delete = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', ensure => absent, } EOS if os[:family] == 'windows' apply_manifest(pp5, catch_failures: true) elsif os[:release] =~ %r{14.04|^8$} apply_manifest(pp5, catch_failures: true) do |r| expect(r.stdout).to match(%r{container_3_7_3}) end else apply_manifest(pp5, catch_failures: true) do |r| expect(r.stdout).to match(%r{docker-container_3_7_3-systemd-reload}) end end apply_manifest(pp_delete, catch_failures: true) end end it 'run with verify_digest' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}:#{default_image_tag}': require => Class['docker'], } docker::run { '#{default_image}': image => '#{default_image}:#{default_image_tag}', verify_digest => '#{default_local_digest}', } EOS pp_invalid = <<-EOS docker::run { '#{default_image}': image => '#{default_image}:#{default_image_tag}', verify_digest => 'sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc000', } EOS apply_manifest(pp, catch_failures: true) run_shell('/usr/local/bin/docker-run-alpine-start.sh', expect_failures: false) do |r| expect(r.stdout.include?('Digest verify failed!')).to be false end apply_manifest(pp_invalid, catch_failures: true) run_shell('/usr/local/bin/docker-run-alpine-start.sh', expect_failures: true) do |r| expect(r.stdout.include?('Digest verify failed!')).to be true end end end describe 'docker::exec', win_broken: true do it 'runs a command inside an already running container' do pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': require => Class['docker'], } docker::run { 'container_4_1': image => '#{default_image}', command => '#{default_run_command}', require => Docker::Image['#{default_image}'], #{default_docker_run_arg} } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 15 container1 = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") pp2 = <<-EOS class { 'docker': #{docker_args} } docker::exec { 'test_command': container => '#{container1.stdout.strip}', command => '#{default_docker_exec_command}', tty => true, } EOS pp_delete = <<-EOS docker::run { 'container_4_1': image => '#{default_image}', ensure => absent, } EOS apply_manifest(pp2, catch_failures: true) # A sleep to give docker time to execute properly sleep 4 container_id = run_shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| expect(r.stdout).to match(%r{test_file.txt}) end end apply_manifest(pp_delete, catch_failures: true) end it 'onlies run if notified when refreshonly is true', win_broken: true do container_name = 'container_4_2' pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } docker::run { '#{container_name}': image => '#{default_image}', command => '#{default_run_command}', #{default_docker_run_arg} } docker::exec { 'test_command': container => '#{container_name}', command => '#{default_docker_exec_command}', refreshonly => true, } EOS apply_manifest(pp, catch_failures: true) apply_manifest(pp, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_name} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).not_to match(%r{test_file.txt}) end else run_shell("#{docker_command} exec #{container_name} ls /root") do |r| expect(r.stdout).not_to match(%r{test_file.txt}) end end pp_extra = <<-EOS file { '#{default_dockerfile}_dummy_file': ensure => 'present', notify => Docker::Exec['test_command'], } EOS pp_delete = <<-EOS docker::run { '#{container_name}': image => '#{default_image}', ensure => absent, } EOS pp2 = pp + pp_extra apply_manifest(pp2, catch_failures: true) apply_manifest(pp2, catch_changes: true) unless selinux == 'true' # A sleep to give docker time to execute properly sleep 4 if os[:family] == 'windows' run_shell("#{docker_command} exec #{container_name} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{home}) end else run_shell("#{docker_command} exec #{container_name} ls /") do |r| expect(r.stdout).to match(%r{home}) end end apply_manifest(pp_delete, catch_failures: true) end end end diff --git a/spec/acceptance/docker_params_changed_spec.rb b/spec/acceptance/docker_params_changed_spec.rb index e464fed..622a702 100644 --- a/spec/acceptance/docker_params_changed_spec.rb +++ b/spec/acceptance/docker_params_changed_spec.rb @@ -1,141 +1,143 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' os_name = run_shell('systeminfo | findstr /R /C:"OS Name"') raise 'Could not retrieve systeminfo for Windows box' if os_name.exit_code != 0 os_name = os_name.stdout.split(%r{\s}).include?('2016') ? 'win-2016' : 'win-2019' docker_args = 'docker_ee => true' docker_network = 'nat' volume_location = 'C:\\' docker_image = if os_name == 'win-2016' 'stefanscherer/nanoserver:sac2016' else 'stefanscherer/nanoserver:10.0.17763.1040' end else docker_args = '' docker_network = 'bridge' volume_location = '/opt' docker_image = 'hello-world:linux' end describe 'docker trigger parammeters change' do before(:all) do if os[:family] != 'windows' install_pp = "class { 'docker': #{docker_args}}" apply_manifest(install_pp) end run_shell("mkdir #{volume_location}/volume_1") run_shell("mkdir #{volume_location}/volume_2") end context 'when image is changed' do image_changed = if os[:family] == 'windows' if os_name == 'win-2016' 'stefanscherer/nanoserver:10.0.14393.2551' else 'stefanscherer/nanoserver:1809' end else 'hello-world:latest' end let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}' } " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{image_changed}', restart => 'always', net => '#{docker_network}' } " end it 'creates servercore with first image' do idempotent_apply(pp1) end it 'detect image change and apply the change' do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect --format="{{ .Config.Image }}" servercore') do |r| expect(r.stdout).to match(%r{#{image_changed}}) end end end context 'when volumes parameter is changed' do if os[:family] == 'windows' volumes1 = "volumes => ['volume-1:C:\\volume_1']" volumes2 = "volumes => ['volume-1:C:\\volume_1', 'volume-2:C:\\volume_2']" else volumes1 = "volumes => ['volume-1:#{volume_location}/volume_1']" volumes2 = "volumes => ['volume-1:#{volume_location}/volume_1', 'volume-2:#{volume_location}/volume_2']" end let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{volumes1}} " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{volumes2}} " end it "creates servercore with #{volumes1}" do idempotent_apply(pp1) end it "creates servercore with #{volumes2}" do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect servercore --format="{{ json .Mounts }}"') do |r| inspect_result = JSON.parse(r.stdout) inspect_result = inspect_result.map { |item| item['Name'] }.sort expect(inspect_result).to eq(['volume-1', 'volume-2']) end end end context 'when ports parameter is changed' do ports1 = "ports => ['4444']" ports2 = "ports => ['4444', '4445']" let(:pp1) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{ports1}} " end let(:pp2) do " class {'docker': #{docker_args}} docker::run {'servercore': image => '#{docker_image}', restart => 'always', net => '#{docker_network}', #{ports2}} " end it 'creates servercore with ports => ["4444"]' do idempotent_apply(pp1) end it 'creates servercore with ports => ["4444", "4445"]' do apply_manifest(pp2, catch_failures: true) run_shell('docker inspect servercore --format="{{ json .HostConfig.PortBindings }}"') do |r| inspect_result = JSON.parse(r.stdout) inspect_result = inspect_result.keys.map { |item| item.split('/')[0] }.sort expect(inspect_result).to eq(['4444', '4445']) end end end after(:all) do run_shell("rm -r #{volume_location}/volume_1") run_shell("rm -r #{volume_location}/volume_2") end end diff --git a/spec/acceptance/docker_spec.rb b/spec/acceptance/docker_spec.rb index 8d99917..cbcbd94 100644 --- a/spec/acceptance/docker_spec.rb +++ b/spec/acceptance/docker_spec.rb @@ -1,318 +1,320 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false registry_port = 5000 if os[:family] == 'windows' result = run_shell("ipconfig | findstr /i 'ipv4'") raise 'Could not retrieve ip address for Windows box' if result.exit_code != 0 ip = result.stdout.split("\n")[0].split(':')[1].strip @windows_ip = ip docker_args = "docker_ee => true, extra_parameters => '\"insecure-registries\": [ \"#{@windows_ip}:5000\" ]'" root_dir = 'C:/Users/Administrator/AppData/Local/Temp' docker_registry_image = 'stefanscherer/registry-windows' docker_network = 'nat' registry_host = @windows_ip config_file = '/cygdrive/c/Users/Administrator/.docker/config.json' server_strip = "#{registry_host}_#{registry_port}" bad_server_strip = "#{registry_host}_5001" broken = true else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end docker_registry_image = 'registry' docker_network = 'bridge' registry_host = '127.0.0.1' server_strip = "#{registry_host}:#{registry_port}" bad_server_strip = "#{registry_host}:5001" config_file = '/root/.docker/config.json' root_dir = '/root' end describe 'docker' do package_name = 'docker-ce' service_name = 'docker' command = 'docker' context 'When adding system user', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args}, docker_users => ['user1'] } " end it 'the docker daemon' do apply_manifest(pp, catch_failures: true) do |r| expect(r.stdout).not_to match(%r{docker-systemd-reload-before-service}) end end end context 'When prepare_service_only param is set(prepare_service_only => true)', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args} } docker::run { 'servercore': image => 'hello-world:latest', prepare_service_only => true, } " end it 'creates the service without starting it' do apply_manifest(pp, catch_failures: true) end it 'not start the service' do run_shell('systemctl status docker-servercore', expect_failures: true) do |r| expect(r.stdout.include?('Main PID')).to be false end end end context 'When prepare_service_only param is not set(prepare_service_only => false)', win_broken: broken do let(:pp) do " class { 'docker': #{docker_args} } docker::run { 'servercore': image => 'hello-world:latest', } " end it 'creates the service and start it' do apply_manifest(pp, catch_failures: true) end it 'start the service' do run_shell('systemctl status docker-servercore', expect_failures: true) do |r| expect(r.stdout.include?('Main PID')).to be true end end end context 'When root_dir is set' do let(:pp) do "class { 'docker': #{docker_args}, root_dir => \"#{root_dir}\"}" end let(:shell_command) do if os[:family] == 'windows' 'cat C:/ProgramData/docker/config/daemon.json' else 'systemctl status docker' end end it 'works' do apply_manifest(pp, catch_failures: true) run_shell(shell_command) do |r| if os[:family] == 'windows' expect(r.stdout).to match(%r{\"data-root\": \"#{root_dir}\"}) else expect(r.stdout).to match(%r{--data-root #{root_dir}}) end end end end context 'with default parameters', win_broken: broken do let(:pp) do " class { 'docker': docker_users => [ 'testuser' ], #{docker_args} } docker::image { 'nginx': } docker::run { 'nginx': image => 'nginx', net => 'host', require => Docker::Image['nginx'], } docker::run { 'nginx2': image => 'nginx', restart => 'always', require => Docker::Image['nginx'], } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end describe package(package_name) do it { is_expected.to be_installed } end describe service(service_name) do it { is_expected.to be_enabled } it { is_expected.to be_running } end it "#{command} version" do run_shell("#{command} version", expect_failures: false) end it "#{command} images" do result = run_shell("sudo #{command} images", expect_failures: false) expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{nginx} end it "#{command} inspect nginx" do run_shell("sudo #{command} inspect nginx", expect_failures: false) end it "#{command} inspect nginx2" do run_shell("sudo #{command} inspect nginx2", expect_failures: false) end it "#{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`" do result = run_shell("sudo #{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`", expect_failures: false) expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{nginx -g 'daemon off;'} end it 'netstat -tlndp' do result = run_shell('netstat -tlndp') expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{0\.0\.0\.0\:80} end it 'id testuser | grep docker' do result = run_shell('id testuser | grep docker') expect(result[:exit_code]).to eq 0 expect(result[:stdout]).to match %r{docker} end end context 'When asked to have the latest image of something', win_broken: broken do let(:pp) do " class { 'docker': docker_users => [ 'testuser' ] } docker::image { 'busybox': ensure => latest } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end end context 'When registry_mirror is set', win_broken: broken do let(:pp) do " class { 'docker': registry_mirror => 'http://testmirror.io' } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'has a registry mirror set' do run_shell('ps -aux | grep docker') do |r| expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror.io}) end end end context 'When registry_mirror is array', win_broken: broken do let(:pp) do " class { 'docker': registry_mirror => ['http://testmirror1.io', 'http://testmirror2.io'] } " end it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'has all registry mirrors set' do run_shell('ps -aux | grep docker') do |r| expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror1.io}) expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror2.io}) end end end context 'registry' do let(:registry_address) do "#{registry_host}:#{registry_port}" end let(:registry_bad_address) do "#{registry_host}:5001" end it 'is able to run registry' do pp = <<-MANIFEST class { 'docker': #{docker_args}} docker::run { 'registry': image => '#{docker_registry_image}', pull_on_start => true, restart => 'always', net => '#{docker_network}', ports => '#{registry_port}:#{registry_port}', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest(pp, catch_failures: true) end # avoid a race condition with the registry taking time to start # on some operating systems sleep 10 end it 'is able to login to the registry', retry: 3, retry_wait: 10, win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_address}': username => 'username', password => 'password', } MANIFEST apply_manifest(pp, catch_failures: true) run_shell("grep #{registry_address} #{config_file}", expect_failures: false) run_shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{server_strip}_root\"", expect_failures: false) end it 'is able to logout from the registry', win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_address}': ensure=> absent, } MANIFEST apply_manifest(pp, catch_failures: true) run_shell("grep #{registry_address} #{config_file}", expect_failures: true) end it 'does not create receipt if registry login fails', win_broken: true do pp = <<-MANIFEST docker::registry { '#{registry_bad_address}': username => 'username', password => 'password', } MANIFEST apply_manifest(pp, catch_failures: false) run_shell("grep #{registry_bad_address} #{config_file}", expect_failures: true) run_shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{bad_server_strip}_root\"", expect_failures: true) end end end diff --git a/spec/acceptance/machine_spec.rb b/spec/acceptance/machine_spec.rb index 5ee89bf..975a2a6 100644 --- a/spec/acceptance/machine_spec.rb +++ b/spec/acceptance/machine_spec.rb @@ -1,64 +1,66 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' describe 'docker::machine', win_broken: true do context 'with default parameters' do pp = <<-EOS include docker::machine EOS it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end it 'machine configurable check of docker-machine-0.16.1' do expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_file expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_owned_by 'root' expect(file('/usr/local/bin/docker-machine-0.16.1')).to be_mode 755 end it 'machine configurable check of docker-machine' do expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.1' expect(file('/usr/local/bin/docker-machine')).to be_symlink end it 'is installed and working' do run_shell('docker-machine --help', expect_failures: false) end end context 'with url => https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine' do pp = <<-EOS class { 'docker::machine': version => '0.16.2-gitlab.3', url => 'https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.3/docker-machine', } EOS it 'applies with no errors' do apply_manifest(pp, catch_failures: true) end it 'is idempotent' do apply_manifest(pp, catch_changes: true) end it 'machine configurable check of docker-machine-0.16.2-gitlab.3' do expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_file expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_owned_by 'root' expect(file('/usr/local/bin/docker-machine-0.16.2-gitlab.3')).to be_mode 755 end it 'machine configurable check of docker-machine' do expect(file('/usr/local/bin/docker-machine')).to be_linked_to '/usr/local/bin/docker-machine-0.16.2-gitlab.3' expect(file('/usr/local/bin/docker-machine')).to be_symlink end it 'is installed and working' do run_shell('docker-machine --help', expect_failures: false) end end end diff --git a/spec/acceptance/network_spec.rb b/spec/acceptance/network_spec.rb index 174e5d1..3de738f 100644 --- a/spec/acceptance/network_spec.rb +++ b/spec/acceptance/network_spec.rb @@ -1,44 +1,46 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false command = 'docker' network_name = 'test-network' if os[:family] == 'windows' puts 'Not implemented on Windows' broken = true elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end describe 'docker network', win_broken: broken do before(:all) do install_pp = "class { 'docker': #{docker_args}}" apply_manifest(install_pp, catch_failures: true) end it "#{command} network --help" do run_shell("#{command} network --help", expect_failures: false) end context 'with a local bridge network described in Puppet' do after(:all) do run_shell("#{command} network rm #{network_name}") end it 'is idempotent' do pp = <<-MANIFEST docker_network { '#{network_name}': ensure => present, } MANIFEST idempotent_apply(pp) end it 'has created a network' do run_shell("#{command} network inspect #{network_name}", expect_failures: false) end end end diff --git a/spec/acceptance/plugin_spec.rb b/spec/acceptance/plugin_spec.rb index b9f2c74..29290b1 100644 --- a/spec/acceptance/plugin_spec.rb +++ b/spec/acceptance/plugin_spec.rb @@ -1,42 +1,44 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' broken = false command = 'docker' plugin_name = 'vieux/sshfs' if os[:family] == 'windows' puts 'Not implemented on Windows' broken = true elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end describe 'docker plugin', win_broken: broken do before(:all) do install_code = "class { 'docker': #{docker_args}}" apply_manifest(install_code, catch_failures: true) end it "#{command} plugin --help" do run_shell("#{command} plugin --help", expect_failures: false) end context 'manage a plugin' do after(:all) do run_shell("#{command} plugin rm -f #{plugin_name}") end it 'is idempotent' do pp = <<-MANIFEST docker::plugin { '#{plugin_name}':} MANIFEST idempotent_apply(pp) end it 'has installed a plugin' do run_shell("#{command} plugin inspect #{plugin_name}", expect_failures: false) end end end diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index 817dcd5..6cc8d0c 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -1,168 +1,170 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if os[:family] == 'windows' docker_args = 'docker_ee => true' tmp_path = 'C:\\tmp\\' wait_for_container_seconds = 120 else docker_args = if os[:name] == 'ubuntu' && os[:release][:full] == '14.04' "version => '18.06.1~ce~3-0~ubuntu'" else '' end tmp_path = '/tmp/' wait_for_container_seconds = 10 end describe 'docker stack', win_broken: true do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_pp = <<-MANIFEST class { 'docker': #{docker_args} } docker::swarm {'cluster_manager': init => true, ensure => 'present', advertise_addr => $facts['networking']['ip'], listen_addr => $facts['networking']['ip'], require => Class['docker'], } MANIFEST apply_manifest(install_pp, catch_failures: true) end end context 'Creating stack' do let(:install_pp) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => present, } MANIFEST end it 'deploys stack' do apply_manifest(install_pp, catch_failures: true) sleep wait_for_container_seconds end it 'is idempotent' do apply_manifest(install_pp, catch_changes: true) end it 'finds a stack' do run_shell('docker stack ls') do |r| expect(r.stdout).to match(%r{web}) end end it 'does not find a docker container' do run_shell('docker ps -a -q -f "name=web_compose_test"', expect_failures: false) end end context 'Destroying stack' do let(:install) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => present, } MANIFEST end let(:destroy) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml'], ensure => absent, } MANIFEST end it 'runs successfully' do apply_manifest(destroy, catch_failures: true) sleep 10 end it 'is idempotent' do retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy, catch_changes: true) end end it 'does not find a docker stack' do run_shell('docker stack ls') do |r| expect(r.stdout).not_to match(%r{web}) end end end context 'creating stack with multi compose files' do before(:all) do install_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) end it 'finds container with web_compose_test tag' do sleep wait_for_container_seconds run_shell('docker ps | grep web_compose_test', expect_failures: false) end end context 'Destroying project with multiple compose files' do let(:destroy_pp) do <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => absent, } MANIFEST end before(:all) do install_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => present, } MANIFEST apply_manifest(install_pp, catch_failures: true) destroy_pp = <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}docker-stack.yml', '#{tmp_path}docker-stack-override.yml'], ensure => absent, } MANIFEST retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy_pp, catch_failures: true) end sleep 15 # Wait for containers to stop and be destroyed end it 'is idempotent' do retry_on_error_matching(10, 3, %r{Removing network web_default}) do apply_manifest(destroy_pp, catch_changes: true) end end it 'does not find a docker stack' do run_shell('docker stack ls') do |r| expect(r.stdout).not_to match(%r{web}) end end it 'does not find a docker container' do run_shell('docker ps', expect_failures: false) do |r| expect(r.stdout).not_to match(%r{web_compose_test}) end end end end diff --git a/spec/acceptance/volume_spec.rb b/spec/acceptance/volume_spec.rb index b9974ce..c8e67a1 100644 --- a/spec/acceptance/volume_spec.rb +++ b/spec/acceptance/volume_spec.rb @@ -1,47 +1,49 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' volume_name = 'test-volume' if os[:family] == 'windows' docker_args = 'docker_ee => true' command = '"/cygdrive/c/Program Files/Docker/docker"' elsif os[:name] == 'ubuntu' && os[:release][:full] == '14.04' docker_args = "version => '18.06.1~ce~3-0~ubuntu'" command = 'docker' else docker_args = '' command = 'docker' end describe 'docker volume' do before(:all) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_pp = "class { 'docker': #{docker_args} }" apply_manifest(install_pp, catch_failures: true) end end it 'exposes volume subcommand' do run_shell("#{command} volume --help", expect_failures: false) end context 'with a local volume described in Puppet' do it 'applies idempotently' do pp = <<-MANIFEST docker_volume { '#{volume_name}': ensure => present, } MANIFEST idempotent_apply(pp) end it 'has created a volume' do run_shell("#{command} volume inspect #{volume_name}", expect_failures: false) end after(:all) do run_shell("#{command} volume rm #{volume_name}") end end end diff --git a/spec/acceptance_swarm/swarm_spec.rb b/spec/acceptance_swarm/swarm_spec.rb index f39a6c8..9268618 100644 --- a/spec/acceptance_swarm/swarm_spec.rb +++ b/spec/acceptance_swarm/swarm_spec.rb @@ -1,146 +1,148 @@ +# frozen_string_literal: true + require 'spec_helper_acceptance' if fact('osfamily') == 'windows' docker_args = 'docker_ee => true' test_docker_image = 'hello-seattle:nanoserver' test_docker_command = 'cmd.exe /C "ping /t 8.8.8.8"' else docker_args = '' test_docker_image = 'ubuntu:16.04' test_docker_command = '/bin/sh -c "while true; do echo hello world; sleep 1; done"' end skip_tests = false begin swarm_manager = only_host_with_role(hosts, 'swarm-manager') swarm_worker = only_host_with_role(hosts, 'swarm-worker') manager_ip = swarm_manager.ip rescue ArgumentError skip_tests = true end describe 'docker swarm', skip: skip_tests do before(:each) do retry_on_error_matching(60, 5, %r{connection failure running}) do install_code = <<-code class { 'docker': #{docker_args} } code apply_manifest_on(swarm_manager, install_code, catch_failures: true) end retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, install_code, catch_failures: true) end setup_manager_pp = <<-MANIFEST docker::swarm {'cluster_manager': init => true, advertise_addr => '#{manager_ip}', listen_addr => '#{manager_ip}', ensure => 'present', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_manager, setup_manager_pp, catch_failures: true) end if fact('osfamily') == 'windows' on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm mgmgt" dir=in action=allow protocol=TCP localport=2377', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm comm tcp" dir=in action=allow protocol=TCP localport=7946', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm comm udp" dir=in action=allow protocol=UDP localport=7946', acceptable_exit_codes: [0] on swarm_manager, 'netsh advfirewall firewall add rule name="Swarm network" dir=in action=allow protocol=UDP localport=4789', acceptable_exit_codes: [0] end end after(:each) do remove_worker = <<-code docker::swarm {'cluster_worker': ensure => 'absent', } code retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, remove_worker, catch_failures: true) end remove_mgr_pp = <<-MANIFEST docker::swarm {'cluster_manager': ensure => 'absent', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_manager, remove_mgr_pp, catch_failures: true) end end context 'Creating a swarm server' do let(:token) { shell('docker swarm join-token -q worker').stdout.strip } it 'is idempotent' do setup_manager_pp = <<-MANIFEST docker::swarm {'cluster_manager': init => true, advertise_addr => '#{manager_ip}', listen_addr => '#{manager_ip}', ensure => 'present', } MANIFEST apply_manifest_on(swarm_manager, setup_manager_pp, catch_failures: true) end it 'displays nodes' do on swarm_manager, 'docker node ls', acceptable_exit_codes: [0] do |result| expect(result.stdout).to match(%r{Leader}) end end it 'joins a node' do setup_slave_pp = <<-MANIFEST docker::swarm {'cluster_worker': join => true, advertise_addr => '#{swarm_worker.ip}', listen_addr => '#{swarm_worker.ip}', manager_ip => '#{manager_ip}', token => '#{token}', } MANIFEST retry_on_error_matching(60, 5, %r{connection failure running}) do apply_manifest_on(swarm_worker, setup_slave_pp, catch_failures: true) end retry_on_error_matching(60, 5, %r{connection failure running}) do on swarm_worker, 'docker info' do |result| expect(result.stdout).to match(%r{Swarm: active}) end end if fact('osfamily') == 'windows' on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm mgmgt" dir=in action=allow protocol=TCP localport=2377', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm comm tcp" dir=in action=allow protocol=TCP localport=7946', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm comm udp" dir=in action=allow protocol=UDP localport=7946', acceptable_exit_codes: [0] on swarm_worker, 'netsh advfirewall firewall add rule name="Swarm network" dir=in action=allow protocol=UDP localport=4789', acceptable_exit_codes: [0] end end it 'starts a container' do start_service = <<-MANIFEST docker::services {'helloworld': create => true, service_name => 'helloworld', image => '#{test_docker_image}', extra_params => ['--endpoint-mode dnsrr'], command => '#{test_docker_command}', replicas => '2', } MANIFEST apply_manifest_on(swarm_manager, start_service, catch_failures: true) # on swarm_manager, "docker service create --name=helloworld --endpoint-mode dnsrr --network=swarmnet #{test_docker_image} #{test_docker_command}", :acceptable_exit_codes => [0] on swarm_manager, 'docker service ps helloworld', acceptable_exit_codes: [0] do |result| expect(result.stdout).to match(%r{Running}) end end end end diff --git a/spec/classes/compose_spec.rb b/spec/classes/compose_spec.rb index ed17da8..b183a4c 100644 --- a/spec/classes/compose_spec.rb +++ b/spec/classes/compose_spec.rb @@ -1,90 +1,92 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default valus' => { }, 'with ensure => absent' => { 'ensure' => 'absent', }, 'with version => 1.7.0' => { 'version' => '1.7.0', }, 'when proxy is provided' => { 'version' => '1.7.0', 'proxy' => 'http://proxy.example.org:3128/', }, 'when proxy is not a http proxy' => { 'proxy' => 'this is not a URL', }, 'when proxy contains username and password' => { 'version' => '1.7.0', 'proxy' => 'http://user:password@proxy.example.org:3128/', }, 'when proxy IP is provided' => { 'version' => '1.7.0', 'proxy' => 'http://10.10.10.10:3128/', }, 'when base_url is provided' => { 'version' => '1.7.0', 'base_url' => 'http://example.org', }, 'when raw_url is provided' => { 'version' => '1.7.0', 'raw_url' => 'http://example.org', }, } describe 'docker::compose', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'version' => defaults['compose_version'], 'install_path' => defaults['compose_install_path'], 'symlink_name' => defaults['compose_symlink_name'], 'proxy' => :undef, 'base_url' => defaults['compose_base_url'], 'raw_url' => :undef, 'curl_ensure' => defaults['curl_ensure'], }.merge(local_params) let(:facts) do facts end let(:params) do params end if params['proxy'] != :undef if params['proxy'] !~ %r{^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$} it { is_expected.to compile.and_raise_error(%r{does not match}) } next end end include_examples 'compose', params, facts end end end end end diff --git a/spec/classes/images_spec.rb b/spec/classes/images_spec.rb index 99fcb2a..d952384 100644 --- a/spec/classes/images_spec.rb +++ b/spec/classes/images_spec.rb @@ -1,68 +1,70 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present' => { 'ensure' => 'present', }, 'with ensure => absent' => { 'ensure' => 'absent', }, } describe 'docker::images', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'base' => { 'ensure' => 'present', 'image_tag' => :undef, 'image_digest' => :undef, 'force' => false, 'docker_file' => :undef, 'docker_dir' => :undef, 'docker_tar' => :undef, }, } params.each do |key, values| values.merge!(local_params.merge('image' => key)) let(:facts) do facts end let(:params) do { 'images' => { key => values, }, } end include_examples 'image', values, facts, defaults it { is_expected.to contain_docker__image(key) } end end end end end end diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 0a557f7..a7bb624 100755 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1,222 +1,224 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default values' => { }, 'with docker_users set' => { 'docker_users' => [ 'some_random_user', 'foo', 'bar', ], }, 'with package_source set to docker-engine' => { 'package_source' => 'docker-engine', }, 'with package_source set to docker-ce' => { 'package_source' => 'docker-ce', }, 'with ensure set to absent' => { 'ensure' => 'absent', }, 'with ensure set to absent and given version' => { 'ensure' => 'absent', 'version' => '16', }, 'with ms parameter set' => { 'version' => '16', 'docker_msft_provider_version' => '123', 'nuget_package_provider_version' => '41', }, } describe 'docker', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## if os =~ %r{windows} facts = windows_facts.merge(os_facts) default_params = { 'docker_ee' => true, 'docker_users' => [], } else facts = os_facts default_params = { 'docker_users' => [], } end ## ## get default values based on facts ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'acknowledge_unsupported_os' => false, 'apt_source_pin_level' => defaults['apt_source_pin_level'], 'bip' => defaults['bip'], 'bridge' => defaults['bridge'], 'daemon_environment_files' => [], 'default_gateway_ipv6' => defaults['default_gateway_ipv6'], 'default_gateway' => defaults['default_gateway'], 'dependent_packages' => defaults['dependent_packages'], 'dm_basesize' => defaults['dm_basesize'], 'dm_blkdiscard' => defaults['dm_blkdiscard'], 'dm_blocksize' => defaults['dm_blocksize'], 'dm_datadev' => defaults['dm_datadev'], 'dm_fs' => defaults['dm_fs'], 'dm_loopdatasize' => defaults['dm_loopdatasize'], 'dm_loopmetadatasize' => defaults['dm_loopmetadatasize'], 'dm_metadatadev' => defaults['dm_metadatadev'], 'dm_mkfsarg' => defaults['dm_mkfsarg'], 'dm_mountopt' => defaults['dm_mountopt'], 'dm_override_udev_sync_check' => defaults['dm_override_udev_sync_check'], 'dm_thinpooldev' => defaults['dm_thinpooldev'], 'dm_use_deferred_deletion' => defaults['dm_use_deferred_deletion'], 'dm_use_deferred_removal' => defaults['dm_use_deferred_removal'], 'dns_search' => defaults['dns_search'], 'dns' => defaults['dns'], 'docker_ce_channel' => defaults['docker_ce_channel'], 'docker_ce_key_id' => defaults['package_ce_key_id'], 'docker_ce_key_source' => defaults['package_ce_key_source'], 'docker_ce_package_name' => defaults['docker_ce_package_name'], 'docker_ce_release' => defaults['package_ce_release'], 'docker_ce_source_location' => defaults['package_ce_source_location'], 'docker_ce_start_command' => defaults['docker_ce_start_command'], 'docker_ee_key_id' => defaults['package_ee_key_id'], 'docker_ee_key_source' => defaults['package_ee_key_source'], 'docker_ee_package_name' => defaults['package_ee_package_name'], 'docker_ee_release' => defaults['package_ee_release'], 'docker_ee_repos' => defaults['package_ee_repos'], 'docker_ee_source_location' => defaults['package_ee_source_location'], 'docker_ee' => defaults['docker_ee'], 'docker_engine_package_name' => defaults['docker_engine_package_name'], 'docker_engine_start_command' => defaults['docker_engine_start_command'], 'docker_group' => defaults['docker_group'], 'docker_msft_provider_version' => defaults['docker_msft_provider_version'], 'docker_package_key_check_source' => defaults['package_key_check_source'], 'docker_package_key_id' => defaults['package_key_id'], 'docker_package_key_source' => defaults['package_key_source'], 'docker_package_location' => defaults['package_source_location'], 'docker_package_release' => defaults['package_release'], 'docker_users' => [], 'ensure' => defaults['package_ensure'], 'execdriver' => defaults['execdriver'], 'extra_parameters' => :undef, 'fixed_cidr' => defaults['fixed_cidr'], 'icc' => defaults['icc'], 'ip_forward' => defaults['ip_forward'], 'ip_masq' => defaults['ip_masq'], 'iptables' => defaults['iptables'], 'ipv6_cidr' => defaults['ipv6_cidr'], 'ipv6' => defaults['ipv6'], 'labels' => defaults['labels'], 'log_driver' => defaults['log_driver'], 'log_level' => defaults['log_level'], 'log_opt' => defaults['log_opt'], 'manage_package' => defaults['manage_package'], 'manage_service' => defaults['manage_service'], 'mtu' => defaults['mtu'], 'no_proxy' => defaults['no_proxy'], 'nuget_package_provider_version' => defaults['nuget_package_provider_version'], 'os_lc' => defaults['os_lc'], 'overlay2_override_kernel_check' => defaults['overlay2_override_kernel_check'], 'package_release' => defaults['package_release'], 'package_source' => defaults['package_source'], 'pin_upstream_package_source' => defaults['pin_upstream_package_source'], 'prerequired_packages' => defaults['prerequired_packages'], 'proxy' => defaults['proxy'], 'registry_mirror' => defaults['registry_mirror'], 'repo_opt' => defaults['repo_opt'], 'root_dir' => defaults['root_dir'], 'selinux_enabled' => defaults['selinux_enabled'], 'service_after_override' => defaults['service_after_override'], 'service_config_template' => defaults['service_config_template'], 'service_config' => defaults['service_config'], 'service_enable' => defaults['service_enable'], 'service_hasrestart' => defaults['service_hasrestart'], 'service_hasstatus' => defaults['service_hasstatus'], 'service_name' => defaults['service_name'], 'service_overrides_template' => defaults['service_overrides_template'], 'service_provider' => defaults['service_provider'], 'service_state' => defaults['service_state'], 'shell_values' => :undef, 'socket_bind' => defaults['socket_bind'], 'socket_group' => defaults['socket_group'], 'socket_override' => defaults['socket_override'], 'socket_overrides_template' => defaults['socket_overrides_template'], 'storage_auto_extend_pool' => defaults['storage_auto_extend_pool'], 'storage_chunk_size' => defaults['storage_chunk_size'], 'storage_config_template' => defaults['storage_config_template'], 'storage_config' => defaults['storage_config'], 'storage_data_size' => defaults['storage_data_size'], 'storage_devs' => defaults['storage_devs'], 'storage_driver' => defaults['storage_driver'], 'storage_growpart' => defaults['storage_growpart'], 'storage_min_data_size' => defaults['storage_min_data_size'], 'storage_pool_autoextend_percent' => defaults['storage_pool_autoextend_percent'], 'storage_pool_autoextend_threshold' => defaults['storage_pool_autoextend_threshold'], 'storage_root_size' => defaults['storage_root_size'], 'storage_setup_file' => defaults['storage_setup_file'], 'storage_vg' => defaults['storage_vg'], 'tcp_bind' => defaults['tcp_bind'], 'tls_cacert' => defaults['tls_cacert'], 'tls_cert' => defaults['tls_cert'], 'tls_enable' => defaults['tls_enable'], 'tls_key' => defaults['tls_key'], 'tls_verify' => defaults['tls_verify'], 'tmp_dir_config' => defaults['tmp_dir_config'], 'tmp_dir' => defaults['tmp_dir'], 'use_upstream_package_source' => defaults['use_upstream_package_source'], 'version' => defaults['version'], }.merge(default_params).merge(local_params) let(:facts) do facts end let(:params) do params end if params['ensure'] != 'absent' if params['package_source'] != :undef && facts[:os]['family'] =~ %r{windows} it { is_expected.to compile.and_raise_error(%r{Custom package source is currently not implemented on windows.}) } else it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') is_expected.to contain_class('docker::install').that_comes_before('Class[docker::config]') is_expected.to contain_class('docker::config').that_comes_before('Class[docker::service]') is_expected.to contain_class('docker::service') } include_examples 'params', facts include_examples 'repos', params, facts include_examples 'install', params, facts include_examples 'config', params, facts include_examples 'service', params, facts end else it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') is_expected.to contain_class('docker::install') } include_examples 'params', facts include_examples 'repos', params, facts include_examples 'install', params, facts end end end end end end diff --git a/spec/classes/machine_spec.rb b/spec/classes/machine_spec.rb index 9d49732..afca070 100644 --- a/spec/classes/machine_spec.rb +++ b/spec/classes/machine_spec.rb @@ -1,59 +1,61 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default value' => { }, } describe 'docker::machine', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'version' => defaults['machine_version'], 'install_path' => defaults['machine_install_path'], 'proxy' => :undef, 'url' => :undef, 'curl_ensure' => defaults['curl_ensure'], }.merge(local_params) let(:facts) do facts end let(:params) do params end if params['proxy'] != :undef if params['proxy'] !~ '^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$' it { is_expected.to compile.and_raise_error(%r{}) } next end end include_examples 'machine', params, facts, defaults end end end end end diff --git a/spec/classes/networks_spec.rb b/spec/classes/networks_spec.rb index 6542c34..b61287e 100644 --- a/spec/classes/networks_spec.rb +++ b/spec/classes/networks_spec.rb @@ -1,66 +1,68 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'network-present' => { 'ensure' => 'present', 'driver' => 'overlay', 'subnet' => '192.168.1.0/24', 'gateway' => '192.168.1.1', 'ip_range' => '192.168.1.4/32', }, 'network-absent' => { 'ensure' => 'absent', 'driver' => 'overlay', 'subnet' => '192.168.1.0/24', 'gateway' => '192.168.1.1', 'ip_range' => '192.168.1.4/32', }, } describe 'docker::networks', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = local_params let(:facts) do facts end let(:params) do { 'networks' => { title => local_params, }, } end it { is_expected.to contain_docker_network(title).with( 'ensure' => params['ensure'], 'driver' => params['driver'], 'subnet' => params['subnet'], 'gateway' => params['gateway'], 'ip_range' => params['ip_range'], ) } end end end end end diff --git a/spec/classes/plugins_spec.rb b/spec/classes/plugins_spec.rb index 6c84369..1c32f71 100644 --- a/spec/classes/plugins_spec.rb +++ b/spec/classes/plugins_spec.rb @@ -1,78 +1,80 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'foo/enabled:latest' => { 'enabled' => true, }, 'foo/disabled:latest' => { 'enabled' => false, }, } describe 'docker::plugins', type: :class do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'base' => { 'ensure' => 'present', 'enabled' => true, 'timeout' => :undef, 'plugin_alias' => :undef, 'disable_on_install' => false, 'disable_content_trust' => true, 'grant_all_permissions' => true, 'force_remove' => true, 'settings' => [], }, } params.each do |key, values| values.merge!(local_params.merge('plugin_name' => key)) let(:facts) do facts end let(:params) do { 'plugins' => { key => values, }, } end if facts[:os]['family'] == 'windows' it { is_expected.to compile.and_raise_error(%r{Feature not implemented on windows.}) } next end include_examples 'plugin', values, facts, defaults it { is_expected.to contain_docker__plugin(key) } end end end end end end diff --git a/spec/defines/exec_spec.rb b/spec/defines/exec_spec.rb index c17102f..8706416 100644 --- a/spec/defines/exec_spec.rb +++ b/spec/defines/exec_spec.rb @@ -1,94 +1,96 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default values' => { }, 'when running detached' => { 'detach' => true, }, 'when running with tty' => { 'tty' => true, }, 'when running with interactive' => { 'interactive' => true, }, 'when running with onlyif "running"' => { 'interactive' => true, 'onlyif' => 'running', }, 'when running without onlyif custom command' => { 'interactive' => true, 'onlyif' => 'custom', }, 'when running without onlyif' => { 'interactive' => true, }, 'when running with unless' => { 'interactive' => true, 'unless' => 'some_command arg1', }, 'when running without unless' => { 'interactive' => true, }, 'with title that need sanitisation' => { 'detach' => true, 'sanitise_name' => true, }, 'with environment variables passed to exec' => { 'env' => [ 'FOO=BAR', 'FOO2=BAR2', ], }, } describe 'docker::exec', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'command' => '/bin/echo foo', 'container' => 'some_conainer_name', 'detach' => false, 'env' => [], 'interactive' => false, 'onlyif' => :undef, 'refreshonly' => false, 'sanitise_name' => true, 'tty' => false, 'unless' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end include_examples 'exec', params, facts, defaults end end end end end diff --git a/spec/defines/image_spec.rb b/spec/defines/image_spec.rb index 93c6b83..aeca24d 100644 --- a/spec/defines/image_spec.rb +++ b/spec/defines/image_spec.rb @@ -1,180 +1,182 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with default value' => { }, 'with ensure => absent' => { 'ensure' => 'absent', }, 'with ensure => absent and force => true' => { 'ensure' => 'absent', 'force' => true, }, 'with ensure => absent and image_tag => precise' => { 'ensure' => 'absent', 'image_tag' => 'precise', }, 'with docker_file => Dockerfile' => { 'docker_file' => 'Dockerfile', }, 'with ensure => present and docker_file => Dockerfile' => { 'ensure' => 'present', 'docker_file' => 'Dockerfile', }, 'with docker_dir => /tmp/docker_images/test1 and docker_file => /tmp/docker_images/test1/Dockerfile_altbuild' => { 'docker_dir' => '/tmp/docker_images/test1', 'docker_file' => '/tmp/docker_images/test1/Dockerfile_altbuild', }, 'with docker_dir => /tmp/docker_images/test1' => { 'docker_dir' => '/tmp/docker_images/test1', }, 'with ensure => present and docker_dir => /tmp/docker_images/test1' => { 'ensure' => 'present', 'docker_dir' => '/tmp/docker_images/test1', }, 'with ensure => present and image_tag => precise' => { 'ensure' => 'present', 'image_tag' => 'precise', }, 'with ensure => present and image_digest => sha256:deadbeef' => { 'ensure' => 'present', 'image_digest' => 'sha256:deadbeef', }, 'with ensure => present and image_tag => precise and docker_file => Dockerfile' => { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_file' => 'Dockerfile', }, 'with ensure => present and image_tag => precise and docker_dir => /tmp/docker_images/test1' => { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_dir' => '/tmp/docker_images/test1', }, 'with docker_tar => /tmp/docker_tars/test1.tar' => { 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with ensure => present and docker_tar => /tmp/docker_tars/test1.tar' => { 'ensure' => 'present', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with docker_file => Dockerfile and docker_tar => /tmp/docker_tars/test1.tar' => { 'docker_file' => 'Dockerfile', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with docker_tar => /tmp/docker_tars/test1.tar and docker_dir => /tmp/docker_images/test1' => { 'docker_tar' => '/tmp/docker_tars/test1.tar', 'docker_dir' => '/tmp/docker_images/test1', }, 'with image_digest => sha256:deadbeef and docker_file => Dockerfile' => { 'image_digest' => 'sha256:deadbeef', 'docker_file' => 'Dockerfile', }, 'with image_digest => sha256:deadbeef and docker_dir => /tmp/docker_images/test1' => { 'image_digest' => 'sha256:deadbeef', 'docker_dir' => '/tmp/docker_images/test1', }, 'with image_digest => sha256:deadbeef and docker_tar => /tmp/docker_tars/test1.tar' => { 'image_digest' => 'sha256:deadbeef', 'docker_tar' => '/tmp/docker_tars/test1.tar', }, 'with ensure => latest' => { 'ensure' => 'latest', }, 'with ensure => latest and image_tag => precise' => { 'ensure' => 'latest', 'image_tag' => 'precise', }, 'with ensure => latest and image_digest => sha256:deadbeef' => { 'ensure' => 'latest', 'image_digest' => 'sha256:deadbeef', }, } describe 'docker::image', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'image' => 'base', 'image_tag' => :undef, 'image_digest' => :undef, 'force' => false, 'docker_file' => :undef, 'docker_dir' => :undef, 'docker_tar' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do params['image'] end if params['docker_file'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$docker_file and \$docker_tar set}) } next end if params['docker_dir'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$docker_dir and \$docker_tar set}) } next end if params['image_digest'] != :undef && params['docker_file'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_file set}) } next end if params['image_digest'] != :undef && params['docker_dir'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_dir set}) } next end if params['image_digest'] != :undef && params['docker_tar'] != :undef it { is_expected.to compile.and_raise_error(%r{docker::image must not have both \$image_digest and \$docker_tar set}) } next end include_examples 'image', params, facts, defaults end end end end end diff --git a/spec/defines/plugin_spec.rb b/spec/defines/plugin_spec.rb index 7968eb3..8a5d74e 100644 --- a/spec/defines/plugin_spec.rb +++ b/spec/defines/plugin_spec.rb @@ -1,76 +1,78 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'foo/setting:latest' => { 'settings' => [ 'VAR1=test', 'VAR2=value', ], }, 'foo/disabled:latest' => { 'enabled' => false, }, 'foo/force_remove:latest' => { 'ensure' => 'absent', 'force_remove' => true, }, } describe 'docker::plugin', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'plugin_name' => title, 'enabled' => true, 'timeout' => :undef, 'plugin_alias' => :undef, 'disable_on_install' => false, 'disable_content_trust' => true, 'grant_all_permissions' => true, 'force_remove' => true, 'settings' => [], }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end if facts[:os]['family'] == 'windows' it { is_expected.to compile.and_raise_error(%r{Feature not implemented on windows.}) } next end include_examples 'plugin', params, facts, defaults end end end end end diff --git a/spec/defines/registry_spec.rb b/spec/defines/registry_spec.rb index 84b24ac..a41fe32 100644 --- a/spec/defines/registry_spec.rb +++ b/spec/defines/registry_spec.rb @@ -1,150 +1,152 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => absent' => { 'ensure' => 'absent', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present' => { 'ensure' => 'present', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1' => { 'ensure' => 'present', 'username' => 'user1', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and password => secret' => { 'ensure' => 'present', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and email => user1@example.io' => { 'ensure' => 'present', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1, and password => secret and email => user1@example.io' => { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with ensure => present and username => user1, and password => secret and email => user1@example.io and version < 1.11.0' => { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '1.9.0', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with username => user1, and password => secret' => { 'username' => 'user1', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, 'with username => user1, and password => secret and local_user => testuser' => { 'username' => 'user1', 'password' => 'secret', 'local_user' => 'testuser', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false, }, } describe 'docker::registry', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## if os =~ %r{windows} facts = windows_facts.merge( 'docker_home_dirs' => { 'user' => '/home/user', 'root' => '/root', }, ).merge(os_facts) docker_params = { 'docker_ee' => true, } else facts = { docker_home_dirs: { 'user' => '/home/user', 'root' => '/root', }, }.merge(os_facts) docker_params = {} end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'server' => title, 'ensure' => 'present', 'username' => :undef, 'password' => :undef, 'pass_hash' => :undef, 'email' => :undef, 'local_user' => 'root', 'version' => defaults['version'], 'receipt' => true, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end let :pre_condition do <<-MANIFEST function pw_hash($foo, $bar, $asdf) { return '$6$foobar$v8j5roVj0D8t.Ipwvk0RrMHiZfZRoBMeVQDywxUKFtdRI2EFRi2X6tbOigjpOsa9UDVzgIBtcl2ZEGcM.jnZZ.' } class { 'docker': version => "#{params['version']}", * => #{docker_params}, } MANIFEST end include_examples 'registry', title, params, facts, defaults end end end end end diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index 9087023..25471ce 100644 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -1,363 +1,365 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'default values' => {}, 'when passing depends containers' => { 'depends' => [ 'foo', 'bar', 'foo_bar/baz', ], }, 'when passing after containers' => { 'after' => [ 'foo', 'bar', 'foo_bar/baz', ], }, 'when use_name is true' => { 'use_name' => true, }, 'when stopping the service' => { 'running' => false, }, 'when passing a cpuset' => { 'cpuset' => '3', }, 'when passing a multiple cpu cpuset' => { 'cpuset' => [ '0', '3', ], }, 'when passing a links option' => { 'links' => [ 'example:one', 'example:two', ], }, 'when passing a hostname' => { 'hostname' => 'example.com', }, 'when passing a username' => { 'username' => 'bob', }, 'when passing a port number' => { 'ports' => '4444', }, 'when passing a port to expose' => { 'expose' => '4666', }, 'when passing a label' => { 'labels' => 'key=value', }, 'when passing a hostentry' => { 'hostentries' => 'dummyhost:127.0.0.2', }, 'when connecting to shared data volumes' => { 'volumes_from' => '6446ea52fbc9', }, 'when connecting to several shared data volumes' => { 'volumes_from' => [ 'sample-linked-container-1', 'sample-linked-container-2', ], }, 'when passing several port numbers' => { 'ports' => [ '4444', '4555', ], }, 'when passing several labels' => { 'labels' => [ 'key1=value1', 'key2=value2', ], }, 'when passing several ports to expose' => { 'expose' => [ '4666', '4777', ], }, 'when passing serveral environment variables' => { 'env' => [ 'FOO=BAR', 'FOO2=BAR2', ], }, 'when passing an environment variable' => { 'env' => 'FOO=BAR', }, 'when passing serveral environment files' => { 'env_file' => [ '/etc/foo.env', '/etc/bar.env', ], }, 'when passing an environment file' => { 'env_file' => '/etc/foo.env', }, 'when passing serveral dns addresses' => { 'dns' => [ '8.8.8.8', '8.8.4.4', ], }, 'when passing a dns address' => { 'dns' => '8.8.8.8', }, 'when passing serveral sockets to connect to' => { 'socket_connect' => [ 'tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567', ], }, 'when passing a socket to connect to' => { 'socket_connect' => 'tcp://127.0.0.1:4567', }, 'when passing serveral dns search domains' => { 'dns_search' => [ 'my.domain.local', 'other-domain.de', ], }, 'when passing a dns search domain' => { 'dns_search' => 'my.domain.local', }, 'when disabling network' => { 'disable_network' => true, }, 'when running privileged' => { 'privileged' => true, }, 'when passing serveral extra parameters' => { 'extra_parameters' => ['--rm', '-w /tmp'], }, 'when passing an extra parameter' => { 'extra_parameters' => '-c 4', }, 'when passing a data volume' => { 'volumes' => '/var/log', }, 'when passing serveral data volume' => { 'volumes' => [ '/var/lib/couchdb', '/var/log', ], }, 'when pull_on_start is true' => { 'pull_on_start' => true, }, 'when pull_on_start is false' => { 'pull_on_start' => false, }, 'when before_start is set' => { 'before_start' => 'echo before_start', }, 'when before_start is not set' => { 'before_start' => false, }, 'when before_stop is set' => { 'before_stop' => 'echo before_stop', }, 'when before_stop is not set' => { 'before_stop' => false, }, 'when after_start is set' => { 'after_start' => 'echo after_start', }, 'when after_start is not set' => { 'after_start' => false, }, 'when after_stop is set' => { 'after_stop' => 'echo after_stop', }, 'when after_stop is not set' => { 'after_stop' => false, }, 'when docker_service is false' => { 'docker_service' => false, }, 'when docker_service is true' => { 'docker_service' => true, }, 'when docker_service is true and restart_service_on_docker_refresh is false' => { 'docker_service' => true, 'restart_service_on_docker_refresh' => false, }, 'when docker_service is my-docker' => { 'docker_service' => 'my-docker', }, 'when docker_service is my-docker and restart_service_on_docker_refresh is false' => { 'docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false, }, } describe 'docker::run', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## if os =~ %r{windows} facts = windows_facts.merge(os_facts) os_params = { 'restart' => 'no', 'extra_parameters' => '-c 4', } docker_params = { 'docker_ee' => true, } else facts = {}.merge(os_facts) os_params = {} docker_params = {} end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'after_create' => :undef, 'after_service' => [], 'after_start' => false, 'after_stop' => false, 'after' => [], 'before_start' => false, 'before_stop' => false, 'command' => 'command', 'cpuset' => [], 'custom_unless' => [], 'depend_services' => ['docker.service'], 'depends' => [], 'detach' => :undef, 'disable_network' => false, 'dns_search' => [], 'dns' => [], 'docker_service' => false, 'ensure' => 'present', 'env_file' => [], 'env' => [], 'expose' => [], 'extra_parameters' => :undef, 'extra_systemd_parameters' => {}, 'health_check_cmd' => :undef, 'health_check_interval' => :undef, 'hostentries' => [], 'hostname' => false, 'image' => 'base', 'labels' => [], 'links' => [], 'lxc_conf' => [], 'manage_service' => true, 'memory_limit' => '0b', 'net' => 'bridge', 'ports' => [], 'privileged' => false, 'pull_on_start' => false, 'read_only' => false, 'remain_after_exit' => :undef, 'remove_container_on_start' => true, 'remove_container_on_stop' => true, 'remove_volume_on_start' => false, 'remove_volume_on_stop' => false, 'restart_on_unhealthy' => false, 'restart_service_on_docker_refresh' => true, 'restart_service' => true, 'restart' => :undef, 'running' => true, 'service_prefix' => 'docker-', 'service_provider' => :undef, 'socket_connect' => [], 'stop_wait_time' => 0, 'syslog_identifier' => :undef, 'systemd_restart' => 'on-failure', 'tty' => false, 'use_name' => false, 'username' => false, 'volumes_from' => [], 'volumes' => [], }.merge(os_params).merge(local_params) if params['docker_service'] && params['docker_service'].to_s != 'true' docker_params['service_name'] = params['docker_service'] end let(:facts) do facts end let(:params) do params end let(:title) do params['command'] end let :pre_condition do <<-MANIFEST class { 'docker': version => "#{params['version']}", * => #{docker_params}, } MANIFEST end if params['remove_volume_on_start'] && !params['remove_container_on_start'] it { is_expected.to compile.and_raise_error("In order to remove the volume on start for #{_title} you need to also remove the container") } next end if params['remove_volume_on_stop'] && !params['remove_container_on_stop'] it { is_expected.to compile.and_raise_error("In order to remove the volume on stop for #{_title} you need to also remove the container") } next end service_provider_real = case params['service_provider'] when :undef defaults['service_provider'] else params['service_provider'] end if !params['service_provider_real'] == 'systemd' && !params['service_provider_real'] == 'upstart' if facts[:os]['family'] != 'windows' it { is_expected.to compile.and_raise_error('Docker needs a Debian or RedHat based system.') } next elsif params['ensure'] == 'present' it { is_expected.to compile.and_raise_error('Restart parameter is required for Windows') } next end end include_examples 'run', params['command'], params, facts, defaults end end end end end diff --git a/spec/defines/secrets_spec.rb b/spec/defines/secrets_spec.rb index c260d4a..5e3178f 100644 --- a/spec/defines/secrets_spec.rb +++ b/spec/defines/secrets_spec.rb @@ -1,58 +1,60 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure present' => { 'secret_name' => 'test_secret', 'secret_path' => '/root/secret.txt', 'label' => ['test'], }, 'with ensure absent' => { 'ensure' => 'absent', 'secret_name' => 'test_secret', }, } describe 'docker::secrets', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'label' => [], 'secret_name' => :undef, 'secret_path' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do title end include_examples 'secrets', title, params, facts, defaults end end end end end diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index e7f9651..d07d3ec 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -1,118 +1,120 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present and service create' => { 'create' => true, 'service_name' => 'foo', 'image' => 'foo:bar', 'publish' => '80:80', 'replicas' => '5', 'extra_params' => ['--update-delay 1m', '--restart-window 30s'], 'env' => ['MY_ENV=1', 'MY_ENV2=2'], 'label' => ['com.example.foo="bar"', 'bar=baz'], 'mounts' => ['type=bind,src=/tmp/a,dst=/tmp/a', 'type=bind,src=/tmp/b,dst=/tmp/b,readonly'], 'networks' => ['overlay'], 'command' => 'echo hello world', }, 'multiple services declaration' => { 'service_name' => 'foo_2', 'image' => 'foo:bar', 'command' => ['echo', 'hello', 'world'], }, 'multiple publish ports and multiple networks' => { 'service_name' => 'foo_3', 'image' => 'foo:bar', 'publish' => ['80:8080', '9000:9000'], 'networks' => ['foo_1', 'foo_2'], }, 'with ensure => present and service update' => { 'create' => false, 'update' => true, 'service_name' => 'foo', 'image' => 'bar:latest', }, 'with ensure => present and service scale' => { 'create' => false, 'scale' => true, 'service_name' => 'bar', 'replicas' => '5', }, 'with ensure => absent' => { 'ensure' => 'absent', 'service_name' => 'foo', }, 'when adding a system user' => { 'user' => ['user1'], }, } describe 'docker::services', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'create' => true, 'update' => false, 'scale' => false, 'detach' => true, 'tty' => false, 'env' => [], 'label' => [], 'extra_params' => [], 'image' => :undef, 'service_name' => :undef, 'publish' => :undef, 'replicas' => :undef, 'user' => :undef, 'workdir' => :undef, 'host_socket' => :undef, 'registry_mirror' => :undef, 'mounts' => :undef, 'networks' => :undef, 'command' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_services' end if params['ensure'] == 'absent' if params['update'] || params['scale'] it { is_expected.to compile.and_raise_error('When removing a service you can not update it.') } next end end include_examples 'services', 'rspec_services', params, facts, defaults end end end end end diff --git a/spec/defines/stack_spec.rb b/spec/defines/stack_spec.rb index a429431..965c3ea 100644 --- a/spec/defines/stack_spec.rb +++ b/spec/defines/stack_spec.rb @@ -1,71 +1,73 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'create stack with compose file' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml'], 'resolve_image' => 'always', }, 'create stack with multiple compose files' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml', '/tmp/docker-compose-2.yaml'], 'resolve_image' => 'always', }, 'with prune' => { 'stack_name' => 'foo', 'compose_files' => ['/tmp/docker-compose.yaml'], 'prune' => true, }, 'with ensure => absent' => { 'ensure' => 'absent', 'stack_name' => 'foo', }, } describe 'docker::stack', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'stack_name' => :undef, 'bundle_file' => :undef, 'compose_files' => :undef, 'prune' => false, 'with_registry_auth' => false, 'resolve_image' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_stack' end include_examples 'stack', 'rspec_stack', params, facts, defaults end end end end end diff --git a/spec/defines/swarm_spec.rb b/spec/defines/swarm_spec.rb index 816694c..12a9433 100644 --- a/spec/defines/swarm_spec.rb +++ b/spec/defines/swarm_spec.rb @@ -1,88 +1,90 @@ +# frozen_string_literal: true + require 'spec_helper' tests = { 'with ensure => present and swarm init' => { 'init' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', }, 'with ensure => present and swarm init and default-addr-pool and default_addr_pool_mask_length' => { 'init' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'default_addr_pool' => ['30.30.0.0/16', '40.40.0.0/16'], 'default_addr_pool_mask_length' => '24', }, 'with ensure => present and swarm join' => { 'join' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'token' => 'foo', 'manager_ip' => '192.168.1.2', }, 'with ensure => absent' => { 'ensure' => 'absent', 'join' => true, 'advertise_addr' => '192.168.1.1', 'listen_addr' => '192.168.1.1', 'token' => 'foo', 'manager_ip' => '192.168.1.2', }, } describe 'docker::swarm', type: :define do on_supported_os.each do |os, os_facts| ## ## set some needed facts ## facts = if os =~ %r{windows} windows_facts.merge(os_facts) else os_facts end ## ## get defaults values from params ## defaults = get_defaults(facts) context "on #{os}" do tests.each do |title, local_params| context title do params = { 'ensure' => 'present', 'init' => false, 'join' => false, 'advertise_addr' => :undef, 'autolock' => false, 'cert_expiry' => :undef, 'default_addr_pool' => :undef, 'default_addr_pool_mask_length' => :undef, 'dispatcher_heartbeat' => :undef, 'external_ca' => :undef, 'force_new_cluster' => false, 'listen_addr' => :undef, 'max_snapshots' => :undef, 'snapshot_interval' => :undef, 'token' => :undef, 'manager_ip' => :undef, }.merge(local_params) let(:facts) do facts end let(:params) do params end let(:title) do 'rspec_swarm' end include_examples 'swarm', 'rspec_swarm', params, facts, defaults end end end end end diff --git a/spec/helper/get_defaults.rb b/spec/helper/get_defaults.rb index bb455df..ec5f6a5 100644 --- a/spec/helper/get_defaults.rb +++ b/spec/helper/get_defaults.rb @@ -1,500 +1,502 @@ +# frozen_string_literal: true + def get_defaults(_facts) bip = :undef bridge = :undef compose_base_url = 'https://github.com/docker/compose/releases/download' compose_symlink_name = 'docker-compose' curl_ensure = true default_gateway = :undef default_gateway_ipv6 = :undef dm_basesize = :undef dm_blkdiscard = :undef dm_blocksize = :undef dm_datadev = :undef dm_fs = :undef dm_loopdatasize = :undef dm_loopmetadatasize = :undef dm_metadatadev = :undef dm_mkfsarg = :undef dm_mountopt = :undef dm_override_udev_sync_check = :undef dm_thinpooldev = :undef dm_use_deferred_deletion = :undef dm_use_deferred_removal = :undef dns = :undef dns_search = :undef docker_ce_channel = 'stable' docker_ce_package_name = 'docker-ce' docker_ce_start_command = 'dockerd' docker_command = 'docker' docker_ee = false docker_ee_key_id = :undef docker_ee_key_source = :undef docker_ee_repos = 'stable' docker_ee_source_location = :undef docker_ee_start_command = 'dockerd' docker_engine_package_name = 'docker-engine' docker_engine_start_command = 'docker daemon' docker_group_default = 'docker' docker_msft_provider_version = :undef package_ensure = 'present' execdriver = :undef fixed_cidr = :undef icc = :undef ip_forward = true ip_masq = true iptables = true ipv6 = false ipv6_cidr = :undef labels = [] log_driver = :undef log_level = :undef log_opt = [] machine_version = '0.16.1' manage_package = true manage_service = true mtu = :undef no_proxy = :undef nuget_package_provider_version = :undef os_lc = _facts[:os]['name'] overlay2_override_kernel_check = false package_source = :undef proxy = :undef registry_mirror = :undef root_dir = :undef selinux_enabled = :undef service_enable = true service_name_default = 'docker' service_state = 'running' socket_bind = 'unix:///var/run/docker.sock' socket_group_default = 'docker' storage_auto_extend_pool = :undef storage_chunk_size = :undef storage_config_template = 'docker/etc/sysconfig/docker-storage.erb' storage_data_size = :undef storage_devs = :undef storage_driver = :undef storage_growpart = :undef storage_min_data_size = :undef storage_pool_autoextend_percent = :undef storage_pool_autoextend_threshold = :undef storage_root_size = :undef storage_vg = :undef tcp_bind = :undef tls_enable = false tls_verify = true tmp_dir = '/tmp/' tmp_dir_config = true version = :undef if _facts[:os]['family'] == 'windows' compose_install_path = "#{_facts['docker_program_files_path']}/Docker" compose_version = '1.21.2' docker_ee_package_name = 'Docker' machine_install_path = "#{_facts['docker_program_files_path']}/Docker" tls_cacert = "#{_facts['docker_program_data_path']}/docker/certs.d/ca.pem" tls_cert = "#{_facts['docker_program_data_path']}/docker/certs.d/server-cert.pem" tls_key = "#{_facts['docker_program_data_path']}/docker/certs.d/server-key.pem" else compose_install_path = '/usr/local/bin' compose_version = '1.9.0' docker_ee_package_name = 'docker-ee' machine_install_path = '/usr/local/bin' tls_cacert = '/etc/docker/tls/ca.pem' tls_cert = '/etc/docker/tls/cert.pem' tls_key = '/etc/docker/tls/key.pem' end case _facts[:os]['family'] when 'Debian' case _facts[:os]['name'] when 'Ubuntu' package_release = "ubuntu-#{_facts[:os]['distro']['codename']}" if _facts[:os]['release']['full'] != '14.04' service_after_override = :undef service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/default/docker-storage' else service_after_override = :undef service_config_template = 'docker/etc/default/docker.erb' service_hasrestart = false service_hasstatus = true service_overrides_template = :undef service_provider = 'upstart' socket_override = false socket_overrides_template = :undef storage_config = :undef end else package_release = "debian-#{_facts[:os]['distro']['codename']}" service_after_override = :undef service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/default/docker-storage' end apt_source_pin_level = 500 docker_group = docker_group_default pin_upstream_package_source = true repo_opt = :undef service_config = :undef service_name = service_name_default socket_group = socket_group_default storage_setup_file = :undef use_upstream_package_source = true package_ce_key_id = '9DC858229FC7DD38854AE2D88D81803C0EBFCD88' package_ce_key_source = "https://download.docker.com/linux/#{os_lc}/gpg" package_ce_release = _facts[:os]['distro']['codename'] package_ce_source_location = "https://download.docker.com/linux/#{os_lc}" package_ee_key_id = docker_ee_key_id package_ee_key_source = docker_ee_key_source package_ee_package_name = docker_ee_package_name package_ee_release = _facts[:os]['distro']['codename'] package_ee_repos = docker_ee_repos package_ee_source_location = docker_ee_source_location package_key_check_source = :undef package_key_id = '58118E89F3A912897C070ADBF76221572C52609D' package_key_source = 'https://apt.dockerproject.org/gpg' package_source_location = 'http://apt.dockerproject.org/repo' detach_service_in_init = if service_provider == 'systemd' false else true end when 'RedHat' service_after_override = :undef service_config = '/etc/sysconfig/docker' service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' service_hasrestart = true service_hasstatus = true service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb' service_provider = 'systemd' socket_override = false socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' storage_config = '/etc/sysconfig/docker-storage' storage_setup_file = '/etc/sysconfig/docker-storage-setup' use_upstream_package_source = true apt_source_pin_level = :undef detach_service_in_init = false package_ce_key_id = :undef package_ce_key_source = 'https://download.docker.com/linux/centos/gpg' package_ce_release = :undef package_ce_source_location = "https://download.docker.com/linux/centos/#{_facts[:os]['release']['major']}/#{_facts[:os]['architecture']}/#{docker_ce_channel}" package_ee_key_id = docker_ee_key_id package_ee_key_source = docker_ee_key_source package_ee_package_name = docker_ee_package_name package_ee_release = :undef package_ee_repos = docker_ee_repos package_ee_source_location = docker_ee_source_location package_key_check_source = true package_key_id = :undef package_key_source = 'https://yum.dockerproject.org/gpg' package_release = :undef package_source_location = "https://yum.dockerproject.org/repo/main/centos/#{_facts[:os]['release']['major']}" pin_upstream_package_source = :undef service_name = service_name_default if use_upstream_package_source docker_group = docker_group_default socket_group = socket_group_default else docker_group = 'dockerroot' socket_group = 'dockerroot' end # repo_opt to specify install_options for docker package repo_opt = if _facts[:os]['name'] == 'RedHat' '--enablerepo=rhel-7-server-extras-rpms' else :undef end when 'windows' msft_nuget_package_provider_version = nuget_package_provider_version msft_provider_version = docker_msft_provider_version msft_package_version = version service_config_template = 'docker/windows/config/daemon.json.erb' service_config = "#{_facts['docker_program_data_path']}/docker/config/daemon.json" docker_group = 'docker' package_ce_source_location = :undef package_ce_key_source = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_key_id = :undef package_release = :undef package_source_location = :undef package_key_source = :undef package_key_check_source = :undef package_ee_source_location = :undef package_ee_package_name = docker_ee_package_name package_ee_key_source = :undef package_ee_key_id = :undef package_ee_repos = :undef package_ee_release = :undef use_upstream_package_source = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef socket_group = :undef service_name = service_name_default repo_opt = :undef storage_config = :undef storage_setup_file = :undef service_provider = :undef service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef detach_service_in_init = true when 'Suse' docker_group = docker_group_default socket_group = socket_group_default package_key_source = :undef package_key_check_source = :undef package_source_location = :undef package_key_id = :undef package_repos = :undef package_release = :undef package_ce_key_source = :undef package_ce_source_location = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_ee_source_location = :undef package_ee_key_source = :undef package_ee_key_id = :undef package_ee_release = :undef package_ee_repos = :undef package_ee_package_name = :undef use_upstream_package_source = true service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef service_provider = 'systemd' package_name = docker_ce_package_name service_name = service_name_default detach_service_in_init = true repo_opt = :undef nowarn_kernel = false service_config = :undef storage_config = :undef storage_setup_file = :undef service_config_template = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef else docker_group = docker_group_default socket_group = socket_group_default package_key_source = :undef package_key_check_source = :undef package_source_location = :undef package_key_id = :undef package_repos = :undef package_release = :undef package_ce_key_source = :undef package_ce_source_location = :undef package_ce_key_id = :undef package_ce_repos = :undef package_ce_release = :undef package_ee_source_location = :undef package_ee_key_source = :undef package_ee_key_id = :undef package_ee_release = :undef package_ee_repos = :undef package_ee_package_name = :undef use_upstream_package_source = true service_overrides_template = :undef socket_overrides_template = :undef socket_override = false service_after_override = :undef service_hasstatus = :undef service_hasrestart = :undef service_provider = :undef package_name = docker_ce_package_name service_name = service_name_default detach_service_in_init = true repo_opt = :undef nowarn_kernel = false service_config = :undef storage_config = :undef storage_setup_file = :undef service_config_template = :undef pin_upstream_package_source = :undef apt_source_pin_level = :undef end dependent_packages = ['docker-ce-cli', 'containerd.io'] prerequired_packages = case _facts[:os]['family'] when 'Debian' case _facts[:os]['name'] when 'Debian' ['cgroupfs-mount'] when 'Ubuntu' ['cgroup-lite', 'apparmor'] else [] end when 'RedHat' ['device-mapper'] else [] end { 'apt_source_pin_level' => apt_source_pin_level, 'bip' => bip, 'bridge' => bridge, 'compose_base_url' => compose_base_url, 'compose_install_path' => compose_install_path, 'compose_symlink_name' => compose_symlink_name, 'compose_version' => compose_version, 'curl_ensure' => curl_ensure, 'default_gateway' => default_gateway, 'default_gateway_ipv6' => default_gateway_ipv6, 'dependent_packages' => dependent_packages, 'detach_service_in_init' => detach_service_in_init, 'dm_basesize' => dm_basesize, 'dm_blkdiscard' => dm_blkdiscard, 'dm_blocksize' => dm_blocksize, 'dm_datadev' => dm_datadev, 'dm_fs' => dm_fs, 'dm_loopdatasize' => dm_loopdatasize, 'dm_loopmetadatasize' => dm_loopmetadatasize, 'dm_metadatadev' => dm_metadatadev, 'dm_mkfsarg' => dm_mkfsarg, 'dm_mountopt' => dm_mountopt, 'dm_override_udev_sync_check' => dm_override_udev_sync_check, 'dm_thinpooldev' => dm_thinpooldev, 'dm_use_deferred_deletion' => dm_use_deferred_deletion, 'dm_use_deferred_removal' => dm_use_deferred_removal, 'dns' => dns, 'dns_search' => dns_search, 'docker_ce_channel' => docker_ce_channel, 'docker_ce_package_name' => docker_ce_package_name, 'docker_ce_start_command' => docker_ce_start_command, 'docker_command' => docker_command, 'docker_ee' => docker_ee, 'docker_ee_key_id' => docker_ee_key_id, 'docker_ee_key_source' => docker_ee_key_source, 'docker_ee_package_name' => docker_ee_package_name, 'docker_ee_repos' => docker_ee_repos, 'docker_ee_source_location' => docker_ee_source_location, 'docker_ee_start_command' => docker_ee_start_command, 'docker_engine_package_name' => docker_engine_package_name, 'docker_engine_start_command' => docker_engine_start_command, 'docker_group' => docker_group, 'docker_group_default' => docker_group_default, 'docker_msft_provider_version' => docker_msft_provider_version, 'execdriver' => execdriver, 'fixed_cidr' => fixed_cidr, 'icc' => icc, 'ip_forward' => ip_forward, 'ip_masq' => ip_masq, 'iptables' => iptables, 'ipv6' => ipv6, 'ipv6_cidr' => ipv6_cidr, 'labels' => labels, 'log_driver' => log_driver, 'log_level' => log_level, 'log_opt' => log_opt, 'machine_install_path' => machine_install_path, 'machine_version' => machine_version, 'manage_package' => manage_package, 'manage_service' => manage_service, 'msft_nuget_package_provider_version' => msft_nuget_package_provider_version, 'msft_package_version' => msft_package_version, 'msft_provider_version' => msft_provider_version, 'mtu' => mtu, 'no_proxy' => no_proxy, 'nowarn_kernel' => nowarn_kernel, 'nuget_package_provider_version' => nuget_package_provider_version, 'os_lc' => os_lc, 'overlay2_override_kernel_check' => overlay2_override_kernel_check, 'package_ce_key_id' => package_ce_key_id, 'package_ce_key_source' => package_ce_key_source, 'package_ce_release' => package_ce_release, 'package_ce_repos' => package_ce_repos, 'package_ce_source_location' => package_ce_source_location, 'package_ee_key_id' => package_ee_key_id, 'package_ee_key_source' => package_ee_key_source, 'package_ee_package_name' => package_ee_package_name, 'package_ee_release' => package_ee_release, 'package_ee_repos' => package_ee_repos, 'package_ee_source_location' => package_ee_source_location, 'package_ensure' => package_ensure, 'package_key_check_source' => package_key_check_source, 'package_key_id' => package_key_id, 'package_key_source' => package_key_source, 'package_name' => package_name, 'package_release' => package_release, 'package_repos' => package_repos, 'package_source' => package_source, 'package_source_location' => package_source_location, 'pin_upstream_package_source' => pin_upstream_package_source, 'prerequired_packages' => prerequired_packages, 'proxy' => proxy, 'registry_mirror' => registry_mirror, 'repo_opt' => repo_opt, 'root_dir' => root_dir, 'selinux_enabled' => selinux_enabled, 'service_after_override' => service_after_override, 'service_config' => service_config, 'service_config_template' => service_config_template, 'service_enable' => service_enable, 'service_hasrestart' => service_hasrestart, 'service_hasstatus' => service_hasstatus, 'service_name' => service_name, 'service_name_default' => service_name_default, 'service_overrides_template' => service_overrides_template, 'service_provider' => service_provider, 'service_state' => service_state, 'socket_bind' => socket_bind, 'socket_group' => socket_group, 'socket_group_default' => socket_group_default, 'socket_override' => socket_override, 'socket_overrides_template' => socket_overrides_template, 'storage_auto_extend_pool' => storage_auto_extend_pool, 'storage_chunk_size' => storage_chunk_size, 'storage_config' => storage_config, 'storage_config_template' => storage_config_template, 'storage_data_size' => storage_data_size, 'storage_devs' => storage_devs, 'storage_driver' => storage_driver, 'storage_growpart' => storage_growpart, 'storage_min_data_size' => storage_min_data_size, 'storage_pool_autoextend_threshold' => storage_pool_autoextend_percent, 'storage_pool_autoextend_percent' => storage_pool_autoextend_percent, 'storage_root_size' => storage_root_size, 'storage_setup_file' => storage_setup_file, 'storage_vg' => storage_vg, 'tcp_bind' => tcp_bind, 'tls_cacert' => tls_cacert, 'tls_cert' => tls_cert, 'tls_enable' => tls_enable, 'tls_key' => tls_key, 'tls_verify' => tls_verify, 'tmp_dir' => tmp_dir, 'tmp_dir_config' => tmp_dir_config, 'use_upstream_package_source' => use_upstream_package_source, 'version' => version, } end diff --git a/spec/helper/get_docker_exec_flags.rb b/spec/helper/get_docker_exec_flags.rb index 2c0d863..6fe692a 100644 --- a/spec/helper/get_docker_exec_flags.rb +++ b/spec/helper/get_docker_exec_flags.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + def get_docker_exec_flags(args) flags = [] if args['detach'] flags << '--detach=true' end if args['interactive'] flags << '--interactive=true' end if args['tty'] flags << '--tty=true' end unless args['env'].empty? args['env'].each do |namevaluepair| flags << "--env #{namevaluepair}" end end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_enable_flags.rb b/spec/helper/get_docker_plugin_enable_flags.rb index 9bc4b8a..9fd2166 100644 --- a/spec/helper/get_docker_plugin_enable_flags.rb +++ b/spec/helper/get_docker_plugin_enable_flags.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + def get_docker_plugin_enable_flags(args) flags = [] flags << '--force' if args['force_remove'] == true if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' flags << "'#{args['plugin_alias']}'" elsif args['plugin_name'] && args['plugin_name'].to_s != 'undef' flags << "'#{args['plugin_name']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_install_flags.rb b/spec/helper/get_docker_plugin_install_flags.rb index 6986c5d..fcdd58f 100644 --- a/spec/helper/get_docker_plugin_install_flags.rb +++ b/spec/helper/get_docker_plugin_install_flags.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + def get_docker_plugin_install_flags(args) flags = [] flags << "--alias #{args['plugin_alias']}" if args['plugin_alias'] && args['plugin_alias'].to_s != 'undef' flags << '--disable' if args['disable_on_install'] == true flags << '--disable-content-trust' if args['disable_content_trust'] == true flags << '--grant-all-permissions' if args['grant_all_permissions'] == true flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' if args['settings'].is_a? Array args['settings'].each do |setting| flags << setting.to_s end end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_plugin_remove_flags.rb b/spec/helper/get_docker_plugin_remove_flags.rb index f97c48b..3bfcf44 100644 --- a/spec/helper/get_docker_plugin_remove_flags.rb +++ b/spec/helper/get_docker_plugin_remove_flags.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + def get_docker_plugin_remove_flags(args) flags = [] flags << '--force' if args['force_remove'] == true flags << "'#{args['plugin_name']}'" if args['plugin_name'] && args['plugin_name'].to_s != 'undef' flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_run_flags.rb b/spec/helper/get_docker_run_flags.rb index f27435d..eaa4519 100644 --- a/spec/helper/get_docker_run_flags.rb +++ b/spec/helper/get_docker_run_flags.rb @@ -1,94 +1,96 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_run_flags(args) flags = [] if args['username'] flags << "-u '#{args['username'].shellescape}'" end if args['hostname'] flags << "-h '#{args['hostname'].shellescape}'" end if args['restart'] flags << "--restart '#{args['restart']}'" end if args['net'].is_a? String flags << "--net #{args['net']}" end if args['memory_limit'] flags << "-m #{args['memory_limit']}" end cpusets = [args['cpuset']].flatten.compact unless cpusets.empty? value = cpusets.join(',') flags << "--cpuset-cpus=#{value}" end if args['disable_network'] flags << '-n false' end if args['privileged'] flags << '--privileged' end if args['health_check_cmd'] && args['health_check_cmd'].to_s != 'undef' flags << "--health-cmd='#{args['health_check_cmd']}'" end if args['health_check_interval'] && args['health_check_interval'].to_s != 'undef' flags << "--health-interval=#{args['health_check_interval']}s" end if args['tty'] flags << '-t' end if args['read_only'] flags << '--read-only=true' end params_join_char = if args['osfamily'] && args['osfamily'].to_s != 'undef' args['osfamily'].casecmp('windows').zero? ? " `\n" : " \\\n" else " \\\n" end multi_flags = ->(values, fmt) { filtered = [values].flatten.compact filtered.map { |val| (fmt + params_join_char) % val } } [ ['--dns %s', 'dns'], ['--dns-search %s', 'dns_search'], ['--expose=%s', 'expose'], ['--link %s', 'links'], ['--lxc-conf="%s"', 'lxc_conf'], ['--volumes-from %s', 'volumes_from'], ['-e "%s"', 'env'], ['--env-file %s', 'env_file'], ['-p %s', 'ports'], ['-l %s', 'labels'], ['--add-host %s', 'hostentries'], ['-v %s', 'volumes'], ].each do |format, key| values = args[key] new_flags = multi_flags.call(values, format) flags << new_flags end args['extra_params'].each do |param| flags << param if args['param'].to_s != 'undef' end # Some software (inc systemd) will truncate very long lines using glibc's # max line length. Wrap options across multiple lines with '\' to avoid flags.flatten.reject { |val| val.to_s == 'undef' }.join(params_join_char) end diff --git a/spec/helper/get_docker_secrets_flags.rb b/spec/helper/get_docker_secrets_flags.rb index 07ac105..a617362 100644 --- a/spec/helper/get_docker_secrets_flags.rb +++ b/spec/helper/get_docker_secrets_flags.rb @@ -1,31 +1,33 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_secrets_flags(args) flags = [] if args['ensure'].to_s == 'present' flags << 'create' end if args['secret_name'] && args['secret_name'].to_s != 'undef' flags << "'#{args['secret_name']}'" end if args['secret_path'] && args['secret_path'].to_s != 'undef' flags << "'#{args['secret_path']}'" end multi_flags = ->(values, format) { filtered = [values].flatten.compact filtered.map { |val| format + " \\\n" % val } } [ ['-l %s', 'label'], ].each do |(format, key)| values = args[key] new_flags = multi_flags.call(values, format) flags.concat(new_flags) end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_service_flags.rb b/spec/helper/get_docker_service_flags.rb index 9ee6e47..0dd7c42 100644 --- a/spec/helper/get_docker_service_flags.rb +++ b/spec/helper/get_docker_service_flags.rb @@ -1,93 +1,95 @@ +# frozen_string_literal: true + require 'shellwords' def get_docker_service_flags(args) flags = [] if args['service_name'] && args['service_name'].to_s != 'undef' flags << "'#{args['service_name']}'" end if args['detach'].to_s != 'false' flags << '--detach' end if args['env'].is_a? Array args['env'].each do |env| flags << "--env #{env}" end end if args['label'].is_a? Array args['label'].each do |label| flags << "--label #{label}" end end if args['mounts'].is_a? Array args['mounts'].each do |mount| flags << "--mount #{mount}" end end if args['networks'].is_a? Array args['networks'].each do |network| flags << "--network #{network}" end end if args['publish'].is_a? Array args['publish'].each do |port| flags << "--publish #{port}" end elsif args['publish'] && args['publish'].to_s != 'undef' flags << "--publish '#{args['publish']}'" end if args['replicas'] && args['replicas'].to_s != 'undef' flags << "--replicas '#{args['replicas']}'" end if args['tty'].to_s != 'false' flags << '--tty' end if args['user'] && args['user'].to_s != 'undef' flags << "--user '#{args['user']}'" end if args['workdir'] && args['workdir'].to_s != 'undef' flags << "--workdir '#{args['workdir']}'" end if args['extra_params'].is_a? Array args['extra_params'].each do |param| flags << param end end if args['host_socket'] && args['host_socket'].to_s != 'undef' flags << "-H '#{args['host_socket']}'" end if args['registry_mirror'].is_a? Array args['registry_mirror'].each do |param| flags << "--registry-mirror='#{param}'" end else if args['registry_mirror'] && args['registry_mirror'].to_s != 'undef' flags << "--registry-mirror='#{args['registry_mirror']}'" end end if args['image'] && args['image'].to_s != 'undef' flags << "'#{args['image']}'" end if args['command'].is_a? Array flags << args['command'].join(' ') elsif args['command'] && args['command'].to_s != 'undef' flags << args['command'].to_s end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_stack_flags.rb b/spec/helper/get_docker_stack_flags.rb index b2769d2..2aa873e 100644 --- a/spec/helper/get_docker_stack_flags.rb +++ b/spec/helper/get_docker_stack_flags.rb @@ -1,27 +1,29 @@ +# frozen_string_literal: true + def get_docker_stack_flags(args) flags = [] if args['bundle_file'] && args['bundle_file'].to_s != 'undef' flags << "--bundle-file '#{args['bundle_file']}'" end if args['compose_files'] && args['compose_files'].to_s != 'undef' args['compose_files'].each do |file| flags << "--compose-file '#{file}'" end end if args['resolve_image'] && args['resolve_image'].to_s != 'undef' flags << "--resolve-image '#{args['resolve_image']}'" end if args['prune'] && args['prune'].to_s != 'undef' flags << '--prune' end if args['with_registry_auth'] && args['with_registry_auth'].to_s != 'undef' flags << '--with-registry-auth' end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_swarm_init_flags.rb b/spec/helper/get_docker_swarm_init_flags.rb index a290fc8..f496e5b 100644 --- a/spec/helper/get_docker_swarm_init_flags.rb +++ b/spec/helper/get_docker_swarm_init_flags.rb @@ -1,55 +1,57 @@ +# frozen_string_literal: true + def get_docker_swarm_init_flags(args) flags = [] if args['init'].to_s != 'false' flags << 'init' end if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' flags << "--advertise-addr '#{args['advertise_addr']}'" end if args['autolock'].to_s != 'false' flags << '--autolock' end if args['cert_expiry'] && args['cert_expiry'].to_s != 'undef' flags << "--cert-expiry '#{args['cert_expiry']}'" end if args['default_addr_pool'].is_a? Array args['default_addr_pool'].each do |default_addr_pool| flags << "--default-addr-pool #{default_addr_pool}" end end if args['default_addr_pool_mask_length'] && args['default_addr_pool_mask_length'].to_s != 'undef' flags << "--default-addr-pool-mask-length '#{args['default_addr_pool_mask_length']}'" end if args['dispatcher_heartbeat'] && args['dispatcher_heartbeat'].to_s != 'undef' flags << "--dispatcher-heartbeat '#{args['dispatcher_heartbeat']}'" end if args['external_ca'] && args['external_ca'].to_s != 'undef' flags << "--external-ca '#{args['external_ca']}'" end if args['force_new_cluster'].to_s != 'false' flags << '--force-new-cluster' end if args['listen_addr'] && args['listen_addr'].to_s != 'undef' flags << "--listen-addr '#{args['listen_addr']}'" end if args['max_snapshots'] && args['max_snapshots'].to_s != 'undef' flags << "--max-snapshots '#{args['max_snapshots']}'" end if args['snapshot_interval'] && args['snapshot_interval'].to_s != 'undef' flags << "--snapshot-interval '#{args['snapshot_interval']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_docker_swarm_join_flags.rb b/spec/helper/get_docker_swarm_join_flags.rb index cbb00fd..4794eaa 100644 --- a/spec/helper/get_docker_swarm_join_flags.rb +++ b/spec/helper/get_docker_swarm_join_flags.rb @@ -1,21 +1,23 @@ +# frozen_string_literal: true + def get_docker_swarm_join_flags(args) flags = [] if args['join'].to_s != 'false' flags << 'join' end if args['advertise_addr'] && args['advertise_addr'].to_s != 'undef' flags << "--advertise-addr '#{args['advertise_addr']}'" end if args['listen_addr'] && args['listen_addr'].to_s != 'undef' flags << "--listen-addr \"#{args['listen_addr']}\"" end if args['token'] && args['token'].to_s != 'undef' flags << "--token '#{args['token']}'" end flags.flatten.join(' ') end diff --git a/spec/helper/get_values_init.rb b/spec/helper/get_values_init.rb index bd2a64c..42e75a0 100644 --- a/spec/helper/get_values_init.rb +++ b/spec/helper/get_values_init.rb @@ -1,75 +1,77 @@ +# frozen_string_literal: true + def get_values_init(_params, _facts) if _params['version'] == :undef || _params['version'] !~ %r{^(17[.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)} if _params['docker_ee'] package_location = _params['docker_ee_source_location'] package_key_source = _params['docker_ee_key_source'] package_key_check_source = true package_key = _params['docker_ee_key_id'] package_repos = _params['docker_ee_repos'] release = _params['docker_ee_release'] docker_start_command = _params['docker_ee_start_command'] docker_package_name = _params['docker_ee_package_name'] else case _facts[:os]['family'] when 'Debian' package_location = _params['docker_ce_source_location'] package_key_source = _params['docker_ce_key_source'] package_key = _params['docker_ce_key_id'] package_repos = _params['docker_ce_channel'] release = _params['docker_ce_release'] when 'RedHat' package_location = _params['docker_ce_source_location'] package_key_source = _params['docker_ce_key_source'] package_key_check_source = true # when 'windows' # fail(translate('This module only work for Docker Enterprise Edition on Windows.')) else package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] end docker_start_command = _params['docker_ce_start_command'] docker_package_name = _params['docker_ce_package_name'] end else case _facts[:os]['family'] when 'Debian' package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] package_key = _params['docker_package_key_id'] package_repos = 'main' release = _params['docker_package_release'] when 'RedHat' package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] else package_location = _params['docker_package_location'] package_key_source = _params['docker_package_key_source'] package_key_check_source = _params['docker_package_key_check_source'] end docker_start_command = _params['docker_engine_start_command'] docker_package_name = _params['docker_engine_package_name'] end root_dir_flag = if _params['version'] != :undef && _params['version'] =~ %r{^(17[.]0[0-4]|1.\d+)} '-g' else '--data-root' end { 'docker_package_name' => docker_package_name, 'docker_start_command' => docker_start_command, 'package_key' => package_key, 'package_key_check_source' => package_key_check_source, 'package_key_source' => package_key_source, 'package_location' => package_location, 'package_repos' => package_repos, 'release' => release, 'root_dir_flag' => root_dir_flag, } end diff --git a/spec/helper/pw_hash.rb b/spec/helper/pw_hash.rb index daed8b1..b4a5c9c 100644 --- a/spec/helper/pw_hash.rb +++ b/spec/helper/pw_hash.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + def pw_hash(_foo, _bar, _asdf) '$6$foobar$v8j5roVj0D8t.Ipwvk0RrMHiZfZRoBMeVQDywxUKFtdRI2EFRi2X6tbOigjpOsa9UDVzgIBtcl2ZEGcM.jnZZ.' end diff --git a/spec/helper/windows_facts.rb b/spec/helper/windows_facts.rb index bff7be0..b32359b 100644 --- a/spec/helper/windows_facts.rb +++ b/spec/helper/windows_facts.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + def windows_facts { 'docker_program_data_path' => 'C:/ProgramData', 'docker_program_files_path' => 'C:/Program Files', 'docker_systemroot' => 'C:/Windows', 'docker_user_temp_path' => 'C:/Users/Administrator/AppData/Local/Temp', } end diff --git a/spec/shared_examples.rb b/spec/shared_examples.rb index 96fb1f3..44e5143 100644 --- a/spec/shared_examples.rb +++ b/spec/shared_examples.rb @@ -1,32 +1,34 @@ +# frozen_string_literal: true + require 'helper/get_defaults' require 'helper/get_docker_exec_flags' require 'helper/get_docker_plugin_enable_flags' require 'helper/get_docker_plugin_install_flags' require 'helper/get_docker_plugin_remove_flags' require 'helper/get_docker_run_flags' require 'helper/get_docker_secrets_flags' require 'helper/get_docker_service_flags' require 'helper/get_docker_stack_flags' require 'helper/get_docker_swarm_init_flags' require 'helper/get_docker_swarm_join_flags' require 'helper/get_values_init' require 'helper/pw_hash' require 'helper/windows_facts' require 'shared_examples/compose' require 'shared_examples/config' require 'shared_examples/exec' require 'shared_examples/image' require 'shared_examples/install' require 'shared_examples/machine' require 'shared_examples/params' require 'shared_examples/plugin' require 'shared_examples/registry' require 'shared_examples/repos' require 'shared_examples/run' require 'shared_examples/secrets' require 'shared_examples/service' require 'shared_examples/services' require 'shared_examples/stack' require 'shared_examples/swarm' require 'shared_examples/system_user' diff --git a/spec/shared_examples/compose.rb b/spec/shared_examples/compose.rb index 299cdd2..bd4c395 100644 --- a/spec/shared_examples/compose.rb +++ b/spec/shared_examples/compose.rb @@ -1,96 +1,98 @@ +# frozen_string_literal: true + shared_examples 'compose' do |_params, _facts| ensure_value = _params['ensure'] version = _params['version'] install_path = _params['install_path'] symlink_name = _params['symlink_name'] proxy = _params['proxy'] base_url = _params['base_url'] raw_url = _params['raw_url'] curl_ensure = _params['curl_ensure'] if _facts[:os]['family'] == 'windows' file_extension = '.exe' file_owner = 'Administrator' else file_extension = '' file_owner = 'root' end docker_compose_location = "#{install_path}/#{symlink_name}#{file_extension}" docker_compose_location_versioned = "#{install_path}/docker-compose-#{version}#{file_extension}" if ensure_value == 'present' docker_compose_url = if raw_url != :undef raw_url else "#{base_url}/#{version}/docker-compose-#{_facts[:kernel]}-x86_64#{file_extension}" end proxy_opt = if proxy != :undef "--proxy #{proxy}" else '' end if _facts[:os]['family'] == 'windows' docker_download_command = "if (Invoke-WebRequest #{docker_compose_url} #{proxy_opt} -UseBasicParsing -OutFile \"#{docker_compose_location_versioned}\") { exit 0 } else { exit 1 }" it { is_expected.to contain_exec("Install Docker Compose #{version}").with( # 'command' => template('docker/windows/download_docker_compose.ps1.erb'), 'provider' => 'powershell', 'creates' => docker_compose_location_versioned, ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'link', 'target' => docker_compose_location_versioned, ).that_requires( "Exec[Install Docker Compose #{version}]", ) } else if curl_ensure it { is_expected.to contain_package('curl') } end it { is_expected.to contain_exec("Install Docker Compose #{version}").with( 'path' => '/usr/bin/', 'cwd' => '/tmp', 'command' => "curl -s -S -L #{proxy_opt} #{docker_compose_url} -o #{docker_compose_location_versioned}", 'creates' => docker_compose_location_versioned, ).that_requires( 'Package[curl]', ) is_expected.to contain_file(docker_compose_location_versioned).with( 'owner' => file_owner, 'mode' => '0755', ).that_requires( "Exec[Install Docker Compose #{version}]", ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'link', 'target' => docker_compose_location_versioned, ).that_requires( "File[#{docker_compose_location_versioned}]", ) } end else it { is_expected.to contain_file(docker_compose_location_versioned).with( 'ensure' => 'absent', ) is_expected.to contain_file(docker_compose_location).with( 'ensure' => 'absent', ) } end end diff --git a/spec/shared_examples/config.rb b/spec/shared_examples/config.rb index 4ac62a5..8bb16bf 100644 --- a/spec/shared_examples/config.rb +++ b/spec/shared_examples/config.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true + shared_examples 'config' do |_params, _facts| docker_users = _params['docker_users'] it { is_expected.to contain_class('docker::config') } unless docker_users.empty? docker_users.each do |user| if _facts[:os]['family'] =~ %r{windows} it { is_expected.to contain_docker__windows_account(user) } else it { is_expected.to contain_docker__system_user(user) } include_examples 'system_user', user, _params['docker_group'] end end end end diff --git a/spec/shared_examples/exec.rb b/spec/shared_examples/exec.rb index 7ada1df..2889d00 100644 --- a/spec/shared_examples/exec.rb +++ b/spec/shared_examples/exec.rb @@ -1,72 +1,74 @@ +# frozen_string_literal: true + shared_examples 'exec' do |_params, _facts, _defaults| command = _params['command'] container = _params['container'] detach = _params['detach'] docker_command = _defaults['docker_command'] env = _params['env'] interactive = _params['interactive'] onlyif = _params['onlyif'] refreshonly = _params['refreshonly'] sanitise_name = _params['sanitise_name'] tty = _params['tty'] unless_value = _params['unless'] if _facts[:os]['family'] == 'windows' exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" exec_timeout = 3000 exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil end docker_exec_flags = get_docker_exec_flags( 'detach' => detach, 'interactive' => interactive, 'tty' => tty, 'env' => env, ) sanitised_container = if sanitise_name container.gsub('[^0-9A-Za-z.\-_]', '-') else container end exec = "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{command}" unless_command = case unless_value when :undef nil when '' nil else "#{docker_command} exec #{docker_exec_flags} #{sanitised_container} #{unless_value}" end onlyif_command = case onlyif when :undef nil when '' nil when 'running' "#{docker_command} ps --no-trunc --format='table {{.Names}}' | grep '^#{sanitised_container}$'" else onlyif end it { is_expected.to contain_exec(exec).with( 'environment' => exec_environment, 'onlyif' => onlyif_command, 'path' => exec_path, 'refreshonly' => refreshonly, 'timeout' => exec_timeout, 'provider' => exec_provider, 'unless' => unless_command, ) } end diff --git a/spec/shared_examples/image.rb b/spec/shared_examples/image.rb index 059eb9a..2e6236d 100644 --- a/spec/shared_examples/image.rb +++ b/spec/shared_examples/image.rb @@ -1,146 +1,148 @@ +# frozen_string_literal: true + shared_examples 'image' do |_params, _facts, _defaults| docker_command = _defaults['docker_command'] docker_dir = _params['docker_dir'] docker_file = _params['docker_file'] docker_tar = _params['docker_tar'] ensure_value = _params['ensure'] force = _params['force'] image = _params['image'] image_digest = _params['image_digest'] image_tag = _params['image_tag'] if _facts[:os]['family'] == 'windows' update_docker_image_template = 'docker/windows/update_docker_image.ps1.erb' update_docker_image_path = "#{_facts['docker_user_temp_path']}/update_docker_image.ps1" exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" exec_timeout = 3000 update_docker_image_owner = nil exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' else update_docker_image_template = 'docker/update_docker_image.sh.erb' update_docker_image_path = '/usr/local/bin/update_docker_image.sh' update_docker_image_owner = 'root' exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil end it { is_expected.to contain_file(update_docker_image_path).with( 'ensure' => 'present', 'owner' => update_docker_image_owner, 'group' => update_docker_image_owner, 'mode' => '0555', # 'content' => template($update_docker_image_template), ) } image_force = if force '-f ' else '' end if image_tag != :undef image_arg = "#{image}:#{image_tag}" image_remove = "#{docker_command} rmi #{image_force}#{image}:#{image_tag}" image_find = "#{docker_command} images -q #{image}:#{image_tag}" elsif image_digest != :undef image_arg = "#{image}@#{image_digest}" image_remove = "#{docker_command} rmi #{image_force}#{image}:#{image_digest}" image_find = "#{docker_command} images -q #{image}@#{image_digest}" else image_arg = image image_remove = "#{docker_command} rmi #{image_force}#{image}" image_find = "#{docker_command} images -q #{image}" end _image_find = if _facts[:os]['family'] == 'windows' "If (-not (#{image_find}) ) { Exit 1 }" else "#{image_find} | grep ." end image_install = if docker_dir != :undef && docker_file != :undef "#{docker_command} build -t #{image_arg} -f #{docker_file} #{docker_dir}" elsif docker_dir != :undef "#{docker_command} build -t #{image_arg} #{docker_dir}" elsif docker_file != :undef if _facts[:os]['family'] == 'windows' "Get-Content #{docker_file} -Raw | #{docker_command} build -t #{image_arg} -" else "#{docker_command} build -t #{image_arg} - < #{docker_file}" end elsif docker_tar != :undef "#{docker_command} load -i #{docker_tar}" else if _facts[:os]['family'] == 'windows' "& #{update_docker_image_path} -DockerImage #{image_arg}" else "#{update_docker_image_path} #{image_arg}" end end if ensure_value == 'absent' it { is_expected.to contain_exec(image_remove).with( 'path' => exec_path, 'environment' => exec_environment, 'onlyif' => _image_find, 'provider' => exec_provider, 'timeout' => exec_timeout, 'logoutput' => true, ) } elsif ensure_value == 'latest' || image_tag == 'latest' it { is_expected.to contain_notify("Check if image #{image_arg} is in-sync").with( 'noop' => false, ).that_notifies( "Exec[#{image_install}]", ) is_expected.to contain_exec(image_install).with( 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'returns' => ['0', '2'], 'provider' => exec_provider, 'logoutput' => true, ).that_requires( "File[#{update_docker_image_path}]", ).that_notifies( "Exec[echo 'Update of #{image_arg} complete']", ) is_expected.to contain_exec("echo 'Update of #{image_arg} complete'").with( 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'logoutput' => true, 'refreshonly' => true, ).that_requires( "File[#{update_docker_image_path}]", ) } elsif ensure_value == 'present' it { is_expected.to contain_exec(image_install).with( 'unless' => _image_find, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'returns' => ['0', '2'], 'provider' => exec_provider, 'logoutput' => true, ).that_requires( "File[#{update_docker_image_path}]", ) } end end diff --git a/spec/shared_examples/install.rb b/spec/shared_examples/install.rb index 2ea4102..a586e46 100644 --- a/spec/shared_examples/install.rb +++ b/spec/shared_examples/install.rb @@ -1,156 +1,158 @@ +# frozen_string_literal: true + shared_examples 'install' do |_params, _facts| values = get_values_init(_params, _facts) ensure_value = if _params['version'] != :undef && _params['ensure'] != 'absent' _params['version'] else _params['ensure'] end if _params['manage_package'] docker_hash = if _params['repo_opt'] == :undef {} else { 'install_options' => _params['repo_opt'] } end if _params['package_source'] != :undef it { is_expected.to contain_class('docker::install') } provider_value = case _facts[:os]['family'] when 'Debian' 'dpkg' when 'RedHat' 'yum' else :undef end case _params['package_source'] when 'docker-engine' it { is_expected.to contain_package('docker').with( { 'ensure' => ensure_value, 'provider' => provider_value, 'source' => _params['package_source'], 'name' => _params['docker_engine_package_name'], }.merge(docker_hash), ) } when 'docker-ce' it { is_expected.to contain_package('docker').with( { 'ensure' => ensure_value, 'provider' => provider_value, 'source' => _params['package_source'], 'name' => _params['docker_ce_package_name'], }.merge(docker_hash), ) } end else if _facts[:os]['family'] != 'windows' it { is_expected.to contain_package('docker').with( 'ensure' => ensure_value, 'name' => values['docker_package_name'], ) } if ensure_value == 'absent' _params['dependent_packages'].each do |dependent_package| it { is_expected.to contain_package(dependent_package).with( 'ensure' => ensure_value, ) } end end else if ensure_value == 'absent' it { if _params['version'] != :undef is_expected.to contain_exec('remove-docker-package').with( 'command' => %r{-RequiredVersion #{_params['version']}}, ) end is_expected.to contain_exec('remove-docker-package').with( 'command' => %r{\$package=Uninstall-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, 'provider' => 'powershell', 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -ErrorAction Ignore}, 'logoutput' => true, ) } else if _params['package_location'] it { is_expected.to contain_exec('install-docker-package').with( 'command' => %r{Invoke-webrequest -UseBasicparsing -Outfile \$dockerLocation "#{_params['docker_download_url']}"}, 'provider' => 'powershell', 'unless' => %r{\$webRequest = \[System.Net.HttpWebRequest\]::Create("#{_params['docker_download_url']}");}, 'logoutput' => true, ).that_notifies( 'Exec[service-restart-on-failure]', ) } else it { if _params['nuget_package_provider_version'] != :undef is_expected. to contain_exec( 'install-docker-package', ).with_command( %r{-RequiredVersion #{_params['nuget_package_provider_version']}}, ).with_unless( %r{\$module.Version.ToString\(\) -ne "#{_params['nuget_package_provider_version']}"}, ) end if _params['docker_msft_provider_version'] != :undef is_expected. to contain_exec( 'install-docker-package', ).with_command( %r{-RequiredVersion #{_params['docker_msft_provider_version']}}, ).with_unless( %r{\$provider.Version.ToString\(\) -ne "#{_params['docker_msft_provider_version']}"}, ) end if _params['version'] != :undef is_expected.to contain_exec( 'install-docker-package', ).with_command( %r{-RequiredVersion #{_params['version']}}, ).with_unless( %r{\$package.Version.ToString\(\) -notmatch "#{_params['version']}"}, ) end is_expected.to contain_exec('install-docker-package').with( 'command' => %r{\$package=Install-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName -Force}, 'provider' => 'powershell', 'unless' => %r{\$package=Get-Package #{_params['docker_ee_package_name']} -ProviderName \$dockerProviderName}, 'logoutput' => true, ).that_notifies( 'Exec[service-restart-on-failure]', ) } end it { is_expected.to contain_exec('service-restart-on-failure').with( 'command' => 'SC.exe failure Docker reset= 432000 actions= restart/30000/restart/60000/restart/60000', 'refreshonly' => true, 'logoutput' => true, 'provider' => 'powershell', ) } end end end end end diff --git a/spec/shared_examples/machine.rb b/spec/shared_examples/machine.rb index 693c5b7..3541d5d 100644 --- a/spec/shared_examples/machine.rb +++ b/spec/shared_examples/machine.rb @@ -1,93 +1,95 @@ +# frozen_string_literal: true + shared_examples 'machine' do |_params, _facts, _defaults| ensure_value = _params['ensure'] version = _params['version'] install_path = _params['install_path'] proxy = _params['proxy'] url = _params['url'] curl_ensure = _params['curl_ensure'] if _facts[:os]['family'] == 'windows' file_extension = '.exe' file_owner = 'Administrator' else file_extension = '' file_owner = 'root' end docker_machine_location = "#{install_path}/docker-machine#{file_extension}" docker_machine_location_versioned = "#{install_path}/docker-machine-#{version}#{file_extension}" if ensure_value == 'present' docker_machine_url = case url when :undef "https://github.com/docker/machine/releases/download/v#{version}/docker-machine-#{_facts[:kernel]}-x86_64#{file_extension}" else url end proxy_opt = case proxy when :undef '' else "--proxy #{proxy}" end if _facts[:os]['family'] == 'windows' docker_download_command = "if (Invoke-WebRequest #{docker_machine_url} #{proxy_opt} -UseBasicParsing -OutFile \"#{docker_machine_location_versioned}\") { exit 0 } else { exit 1 }" it { is_expected.to contain_exec("Install Docker Machine #{version}").with( # 'command' => template('docker/windows/download_docker_machine.ps1.erb'), 'provider' => 'powershell', 'creates' => docker_machine_location_versioned, ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'link', 'target' => docker_machine_location_versioned, ).that_requires( "Exec[Install Docker Machine #{version}]", ) } else if curl_ensure it { is_expected.to contain_package('curl') } end it { is_expected.to contain_exec("Install Docker Machine #{version}").with( 'path' => '/usr/bin/', 'cwd' => '/tmp', 'command' => "curl -s -S -L #{proxy_opt} #{docker_machine_url} -o #{docker_machine_location_versioned}", 'creates' => docker_machine_location_versioned, ).that_requires( 'Package[curl]', ) is_expected.to contain_file(docker_machine_location_versioned).with( 'owner' => file_owner, 'mode' => '0755', ).that_requires( "Exec[Install Docker Machine #{version}]", ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'link', 'target' => docker_machine_location_versioned, ).that_requires( "File[#{docker_machine_location_versioned}]", ) } end else is_expected.to contain_file(docker_machine_location_versioned).with( 'ensure' => 'absent', ) is_expected.to contain_file(docker_machine_location).with( 'ensure' => 'absent', ) end end diff --git a/spec/shared_examples/params.rb b/spec/shared_examples/params.rb index 8156a66..8457124 100644 --- a/spec/shared_examples/params.rb +++ b/spec/shared_examples/params.rb @@ -1,21 +1,23 @@ +# frozen_string_literal: true + shared_examples 'params' do |_facts| case _facts[:os]['family'] when 'Debian' if _facts[:os]['release']['full'] != '14.04' it { is_expected.to contain_class('docker::params') is_expected.to contain_class('docker::systemd_reload') is_expected.to contain_exec('docker-systemd-reload').with( 'path' => [ '/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/', ], 'command' => 'systemctl daemon-reload', 'refreshonly' => 'true', ) } end end end diff --git a/spec/shared_examples/plugin.rb b/spec/shared_examples/plugin.rb index 2bda0a6..793cd3a 100644 --- a/spec/shared_examples/plugin.rb +++ b/spec/shared_examples/plugin.rb @@ -1,88 +1,90 @@ +# frozen_string_literal: true + shared_examples 'plugin' do |_params, _facts, _defaults| ensure_value = _params['ensure'] plugin_name = _params['plugin_name'] enabled = _params['enabled'] timeout = _params['timeout'] plugin_alias = _params['plugin_alias'] disable_on_install = _params['disable_on_install'] disable_content_trust = _params['disable_content_trust'] grant_all_permissions = _params['grant_all_permissions'] force_remove = _params['force_remove'] settings = _params['settings'] docker_command = "#{_defaults['docker_command']} plugin" if ensure_value == 'present' docker_plugin_install_flags = get_docker_plugin_install_flags( 'plugin_name' => plugin_name, 'plugin_alias' => plugin_alias, 'disable_on_install' => disable_on_install, 'disable_content_trust' => disable_content_trust, 'grant_all_permissions' => grant_all_permissions, 'settings' => settings, ) exec_install = "#{docker_command} install #{docker_plugin_install_flags}" unless_install = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin install #{plugin_name}").with( 'command' => exec_install, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'unless' => unless_install, ) } elsif ensure_value == 'absent' docker_plugin_remove_flags = get_docker_plugin_remove_flags( 'plugin_name' => plugin_name, 'force_remove' => force_remove, ) exec_rm = "#{docker_command} rm #{docker_plugin_remove_flags}" onlyif_rm = "#{docker_command} ls --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin remove #{plugin_name}").with( 'command' => exec_rm, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'onlyif' => onlyif_rm, ) } end if enabled docker_plugin_enable_flags = get_docker_plugin_enable_flags( 'plugin_name' => plugin_name, 'plugin_alias' => plugin_alias, 'timeout' => timeout, ) exec_enable = "#{docker_command} enable #{docker_plugin_enable_flags}" onlyif_enable = "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}" it { is_expected.to contain_exec("plugin enable #{plugin_name}").with( 'command' => exec_enable, 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'onlyif' => onlyif_enable, ) } else it { is_expected.to contain_exec("disable #{plugin_name}").with( 'command' => "#{docker_command} disable #{plugin_name}", 'environment' => 'HOME=/root', 'path' => ['/bin', '/usr/bin'], 'timeout' => 0, 'unless' => "#{docker_command} ls -f enabled=false --format='{{.PluginReference}}' | grep -w #{plugin_name}", ) } end end diff --git a/spec/shared_examples/registry.rb b/spec/shared_examples/registry.rb index 9975500..c0ee40b 100644 --- a/spec/shared_examples/registry.rb +++ b/spec/shared_examples/registry.rb @@ -1,121 +1,123 @@ +# frozen_string_literal: true + shared_examples 'registry' do |_title, _params, _facts, _defaults| server = _params['server'] ensure_value = _params['ensure'] username = _params['username'] password = _params['password'] pass_hash = _params['pass_hash'] email = _params['email'] local_user = _params['local_user'] version = _params['version'] receipt = _params['receipt'] docker_command = _defaults['docker_command'] if _facts[:os]['family'] == 'windows' exec_environment = ["PATH=#{_facts['docker_program_files_path']}/Docker/"] exec_timeout = 3000 exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' password_env = '$env:password' exec_user = nil else exec_environment = [] exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil password_env = "\${password}" exec_user = local_user local_user_home = _facts[:docker_home_dirs][local_user] end if ensure_value == 'present' if username != :undef && password != :undef && email != :undef && version != :undef && version =~ %r{1[.][1-9]0?} auth_cmd = "#{docker_command} login -u '#{username}' -p \"#{password_env}\" -e '#{email}' #{server}" auth_environment = "password=#{password}" elsif username != :undef && password != :undef auth_cmd = "#{docker_command} login -u '#{username}' -p \"#{password_env}\" #{server}" auth_environment = "password=#{password}" else auth_cmd = "#{docker_command} login #{server}" auth_environment = '' end else auth_cmd = "#{docker_command} logout #{server}" auth_environment = '' end docker_auth = "#{_title}#{auth_environment}#{auth_cmd}#{local_user}" exec_env = if auth_environment != '' exec_environment << auth_environment << "docker_auth=#{docker_auth}" else exec_environment << "docker_auth=#{docker_auth}" end if receipt if _facts[:os]['family'] != 'windows' server_strip = server.tr('/', '_') local_user_strip = local_user.gsub('[-_]', '') _pass_hash = case pass_hash when :undef pw_hash(docker_auth, 'SHA-512', local_user_strip) else pass_hash end _auth_command = "#{auth_cmd} || rm -f \"/#{local_user_home}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}\"" it { is_expected.to contain_file('/${local_user_home}/registry-auth-puppet_receipt_${server_strip}_${local_user}').with( 'ensure' => ensure_value, 'content' => _pass_hash, 'owner' => local_user, 'group' => local_user, ).that_notifies( "Exec[#{_title} auth]", ) } else server_strip = server.gsub('[/:]', '_') passfile = "#{_facts['docker_user_temp_path']}/registry-auth-puppet_receipt_#{server_strip}_#{local_user}" _auth_command = "if (-not (#{auth_cmd})) { Remove-Item -Path #{passfile} -Force -Recurse -EA SilentlyContinue; exit 0 } else { exit 0 }" if ensure_value == 'absent' it { is_expected.to contain_file(passfile).with( 'ensure' => ensure_value, ).that_notifies( "Exec[#{_title} auth]", ) } elsif ensure_value == 'present' it { is_expected.to contain_exec(compute - hash).with( # 'command' => template('docker/windows/compute_hash.ps1.erb'), 'environment' => exec_env, 'provider' => exec_provider, 'logoutput' => true, # 'unless' => template('docker/windows/check_hash.ps1.erb'), ).that_notifies( "Exec[#{_title} auth]", ) } end end else _auth_command = auth_cmd end it { is_expected.to contain_exec("#{_title} auth").with( 'environment' => exec_env, 'command' => _auth_command, 'user' => exec_user, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'refreshonly' => receipt, ) } end diff --git a/spec/shared_examples/repos.rb b/spec/shared_examples/repos.rb index 099c107..540b29a 100644 --- a/spec/shared_examples/repos.rb +++ b/spec/shared_examples/repos.rb @@ -1,109 +1,111 @@ +# frozen_string_literal: true + shared_examples 'repos' do |_params, _facts| it { is_expected.to contain_class('docker::repos') } values = get_values_init(_params, _facts) location = values['package_location'] key_source = values['package_key_source'] key_check_source = values['package_key_check_source'] architecture = _facts[:os]['architecture'] unless _params['prerequired_packages'].empty? _params['prerequired_packages'].each do |package| it { is_expected.to contain_package(package) } end end case _facts[:os]['family'] when 'Debian' release = values['release'] package_key = values['package_key'] package_repos = values['package_repos'] if _params['use_upstream_package_source'] it { is_expected.to contain_apt__source('docker').with( 'location' => location, 'architecture' => architecture, 'release' => release, 'repos' => package_repos, 'key' => { 'id' => package_key, 'source' => key_source, }, 'include' => { 'src' => false, }, ) } url_split = location.split('/') repo_host = url_split[2] pin_ensure = case _params['pin_upstream_package_source'] when true 'present' else 'absent' end it { is_expected.to contain_apt__pin('docker').with( 'ensure' => pin_ensure, 'origin' => repo_host, 'priority' => _params['apt_source_pin_level'], ) } if _params['manage_package'] it { is_expected.to contain_class('apt') } if _facts[:os]['name'] == 'Debian' && _facts[:os]['distro']['codename'] == 'wheezy' it { is_expected.to contain_class('apt::backports') } end it { _params['prerequired_packages'].each do |package| is_expected.to contain_exec('apt_update').that_comes_before("package[#{package}]") end is_expected.to contain_apt__source('docker').that_comes_before('package[docker]') } end end when 'RedHat' if _params['manage_package'] baseurl = case location when :undef nil else location end gpgkey = case key_source when :undef nil else key_source end gpgkey_check = key_check_source if _params['use_upstream_package_source'] it { is_expected.to contain_yumrepo('docker').with( 'descr' => 'Docker', 'baseurl' => baseurl, 'gpgkey' => gpgkey, 'gpgcheck' => gpgkey_check, ).that_comes_before('package[docker]') } end end end end diff --git a/spec/shared_examples/run.rb b/spec/shared_examples/run.rb index 5e42136..adb358f 100644 --- a/spec/shared_examples/run.rb +++ b/spec/shared_examples/run.rb @@ -1,462 +1,464 @@ +# frozen_string_literal: true + shared_examples 'run' do |_title, _params, _facts, _defaults| after = _params['after'] after_create = _params['after_create'] after_service = _params['after_service'] after_start = _params['after_start'] after_stop = _params['after_stop'] before_start = _params['before_start'] before_stop = _params['before_stop'] command = _params['command'] cpuset = _params['cpuset'] custom_unless = _params['custom_unless'] depend_services = _params['depend_services'] depends = _params['depends'] detach = _params['detach'] disable_network = _params['disable_network'] dns = _params['dns'] dns_search = _params['dns_search'] docker_service = _params['docker_service'] ensure_value = _params['ensure'] env = _params['env'] env_file = _params['env_file'] expose = _params['expose'] extra_parameters = _params['extra_parameters'] extra_systemd_parameters = _params['extra_systemd_parameters'] health_check_cmd = _params['health_check_cmd'] health_check_interval = _params['health_check_interval'] hostentries = _params['hostentries'] hostname = _params['hostname'] image = _params['image'] labels = _params['labels'] links = _params['links'] lxc_conf = _params['lxc_conf'] manage_service = _params['manage_service'] memory_limit = _params['memory_limit'] net = _params['net'] ports = _params['ports'] privileged = _params['privileged'] pull_on_start = _params['pull_on_start'] read_only = _params['read_only'] remain_after_exit = _params['remain_after_exit'] remove_container_on_start = _params['remove_container_on_start'] remove_container_on_stop = _params['remove_container_on_stop'] remove_volume_on_start = _params['remove_volume_on_start'] remove_volume_on_stop = _params['remove_volume_on_stop'] restart = _params['restart'] restart_on_unhealthy = _params['restart_on_unhealthy'] restart_service = _params['restart_service'] restart_service_on_docker_refresh = _params['restart_service_on_docker_refresh'] running = _params['running'] service_prefix = _params['service_prefix'] service_provider = _params['service_provider'] socket_connect = _params['socket_connect'] stop_wait_time = _params['stop_wait_time'] syslog_identifier = _params['syslog_identifier'] systemd_restart = _params['systemd_restart'] tty = _params['tty'] use_name = _params['use_name'] username = _params['username'] volumes = _params['volumes'] volumes_from = _params['volumes_from'] docker_group = _defaults['docker_group'] if socket_connect != [] sockopts = [socket_connect].join(',') docker_command = "#{_defaults['docker_command']} -H #{sockopts}" else docker_command = _defaults['docker_command'] end if use_name it { is_expected.to contain_notify("docker use_name warning: #{_title}").with( 'message' => 'The use_name parameter is no-longer required and will be removed in a future release', 'withpath' => true, ) } end service_provider_real = case service_provider.to_s when 'undef' _defaults['service_provider'] else service_provider end valid_detach = if detach == :undef case service_provider_real when 'systemd' false else _defaults['detach_service_in_init'] end else detach end docker_run_flags = get_docker_run_flags( 'cpuset' => [cpuset], 'disable_network' => disable_network, 'dns_search' => [dns_search], 'dns' => [dns], 'env_file' => [env_file], 'env' => [env], 'expose' => [expose], 'extra_params' => [extra_parameters], 'health_check_cmd' => health_check_cmd, 'health_check_interval' => health_check_interval, 'hostentries' => [hostentries], 'hostname' => hostname, 'labels' => [labels], 'links' => [links], 'lxc_conf' => [lxc_conf], 'memory_limit' => memory_limit, 'net' => net, 'osfamily' => _facts[:os]['family'], 'ports' => [ports], 'privileged' => privileged, 'read_only' => read_only, 'restart_on_unhealthy' => restart_on_unhealthy, 'socket_connect' => [socket_connect], 'tty' => tty, 'username' => username, 'volumes_from' => [volumes_from], 'volumes' => [volumes], ) sanitised_title = _title.gsub('[^0-9A-Za-z.\-_]', '-') if _facts[:os]['family'] == 'windows' exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/;#{_facts['docker_systemroot']}/System32/" exec_timeout = 3000 exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' cidfile = "#{_facts['docker_user_temp_path']}/#{service_prefix}#{sanitised_title}.cid" restart_check = "#{docker_command} inspect #{sanitised_title} -f '{{ if eq \\\"unhealthy\\\" .State.Health.Status }} {{ .Name }}{{ end }}' | findstr #{sanitised_title}" container_running_check = "\$state = #{docker_command} inspect #{sanitised_title} -f \"{{ .State.Running }}\"; if (\$state -ieq \"true\") { Exit 0 } else { Exit 1 }" else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil cidfile = "/var/run/#{service_prefix}#{sanitised_title}.cid" restart_check = "#{docker_command} inspect #{sanitised_title} -f '{{ if eq \"unhealthy\" .State.Health.Status }} {{ .Name }}{{ end }}' | grep #{sanitised_title}" container_running_check = "#{docker_command} inspect #{sanitised_title} -f \"{{ .State.Running }}\" | grep true" end if restart_on_unhealthy it { is_expected.to contain_exec("Restart unhealthy container #{_title} with docker").with( 'command' => "#{docker_command} restart #{sanitised_title}", 'onlyif' => restart_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end if restart.to_s != 'undef' if ensure_value == 'absent' it { is_expected.to contain_exec("stop #{_title} with docker").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) is_expected.to contain_exec("remove #{_title} with docker").with( 'command' => "#{docker_command} rm -v #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) is_expected.to contain_file(cidfile).with( 'ensure' => 'absent', ) } else run_with_docker_command = [ "#{docker_command} run -d #{docker_run_flags}", "--name #{sanitised_title} --cidfile=#{cidfile}", "--restart=\"#{restart}\" #{image} #{command}", ] inspect = [ "#{docker_command} inspect #{sanitised_title}", ] exec_unless = if custom_unless custom_unless << inspect else inspect end it { is_expected.to contain_exec("run #{_title} with docker").with( 'command' => run_with_docker_command.join(' '), ## todo: ## fix the following strange behavior: ## expected that the catalogue would contain Exec[run command with docker] with unless set to [["docker inspect command"]] ## but it is set to [["docker inspect command"], "docker inspect command"] # 'unless' => exec_unless, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } if !running it { is_expected.to contain_exec("stop #{_title} with docker").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => container_running_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } else it { is_expected.to contain_exec("start #{_title} with docker").with( 'command' => "#{docker_command} start #{sanitised_title}", 'unless' => container_running_check, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end end else case service_provider_real when 'systemd' hasstatus = true init_template = 'docker/etc/systemd/system/docker-run.erb' initscript = "/etc/systemd/system/#{service_prefix}#{sanitised_title}.service" mode = '0644' startscript = "/usr/local/bin/docker-run-#{sanitised_title}-start.sh" startstop_template = 'docker/usr/local/bin/docker-run.sh.epp' stopscript = "/usr/local/bin/docker-run-#{sanitised_title}-stop.sh" when 'upstart' hasstatus = true init_template = 'docker/etc/init.d/docker-run.erb' initscript = "/etc/init.d/#{service_prefix}#{sanitised_title}" mode = '0750' startscript = nil startstop_template = nil stopscript = nil else hasstatus = _defaults['service_hasstatus'] end _syslog_identifier = if syslog_identifier syslog_identifier else "#{service_prefix}#{sanitised_title}" end if ensure_value == 'absent' if _facts[:os]['family'] == 'windows' it { is_expected.to contain_exec("stop container #{service_prefix}#{sanitised_title}").with( 'command' => "#{docker_command} stop --time=#{stop_wait_time} #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ).that_notifies( "Exec[remove container #{service_prefix}#{sanitised_title}]", ) } else it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => false, 'enable' => false, 'hasstatus' => hasstatus, 'provider' => service_provider_real, ) } end it { is_expected.to contain_exec("remove container #{service_prefix}#{sanitised_title}").with( 'command' => "#{docker_command} rm -v #{sanitised_title}", 'onlyif' => "#{docker_command} inspect #{sanitised_title}", 'environment' => exec_environment, 'path' => exec_path, 'refreshonly' => true, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } if _facts[:os]['family'] != 'windows' it { is_expected.to contain_file("/etc/systemd/system/#{service_prefix}#{sanitised_title}.service").with( 'ensure' => 'absent', ) } if startscript it { is_expected.to contain_file(startscript).with( 'ensure' => 'absent', ) } end if stopscript it { is_expected.to contain_file(stopscript).with( 'ensure' => 'absent', ) } end else it { is_expected.to contain_file(cidfile).with( 'ensure' => 'absent', ) } end else if startscript it { is_expected.to contain_file(startscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => '0770', ) } end if stopscript it { is_expected.to contain_file(stopscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => '0770', ) } end it { is_expected.to contain_file(initscript).with( 'ensure' => 'file', 'owner' => 'root', 'group' => docker_group, 'mode' => mode, ) } if manage_service if !running it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => running, 'enable' => false, 'hasstatus' => hasstatus, ).that_requires( "File[#{initscript}]", ) } else if initscript == "/etc/init.d/#{service_prefix}#{sanitised_title}" transition_onlyif = [ "/usr/bin/test -f /var/run/docker-#{sanitised_title}.cid &&", "/usr/bin/test -f /etc/init.d/#{service_prefix}#{sanitised_title}", ] it { is_expected.to contain_exec("/bin/sh /etc/init.d/#{service_prefix}#{sanitised_title} stop").with( 'onlyif' => transition_onlyif.join(' '), ).that_comes_before( "File[/var/run/#{service_prefix}#{sanitised_title}.cid]", ) is_expected.to contain_file("/var/run/#{service_prefix}#{sanitised_title}.cid").with( 'ensure' => 'absent', ).that_comes_before( "File[#{initscript}]", ) } end it { is_expected.to contain_service("#{service_prefix}#{sanitised_title}").with( 'ensure' => running, 'enable' => true, 'provider' => service_provider_real, 'hasstatus' => hasstatus, ).that_requires( "File[#{initscript}]", ) } if docker_service if docker_service.to_s == 'true' it { is_expected.to contain_service('docker').that_comes_before("Service[#{service_prefix}#{sanitised_title}]") } if restart_service_on_docker_refresh.to_s == 'true' it { is_expected.to contain_service('docker').that_notifies("Service[#{service_prefix}#{sanitised_title}]") } end else it { is_expected.to contain_service('docker').with('name' => docker_service).that_comes_before("Service[#{service_prefix}#{sanitised_title}]") } if restart_service_on_docker_refresh.to_s == 'true' it { is_expected.to contain_service('docker').with('name' => docker_service).that_notifies("Service[#{service_prefix}#{sanitised_title}]") } end end end end end if service_provider_real == 'systemd' it { is_expected.to contain_exec("docker-#{sanitised_title}-systemd-reload").with( 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], 'command' => 'systemctl daemon-reload', 'refreshonly' => true, ).that_requires( [ "File[#{initscript}]", "File[#{startscript}]", "File[#{stopscript}]", ], ).that_subscribes_to( [ "File[#{initscript}]", "File[#{startscript}]", "File[#{stopscript}]", ], ).that_comes_before( "Service[#{service_prefix}#{sanitised_title}]", ) } end end end end diff --git a/spec/shared_examples/secrets.rb b/spec/shared_examples/secrets.rb index 09669d2..ab0031c 100644 --- a/spec/shared_examples/secrets.rb +++ b/spec/shared_examples/secrets.rb @@ -1,38 +1,40 @@ +# frozen_string_literal: true + shared_examples 'secrets' do |_title, _params, _facts, _defaults| ensure_value = _params['ensure'] label = _params['label'] secret_name = _params['secret_name'] secret_path = _params['secret_path'] docker_command = "#{_defaults['docker_command']} secret" if ensure_value == 'present' docker_secrets_flags = get_docker_secrets_flags( 'ensure' => ensure_value, 'label' => label, 'secret_name' => secret_name, 'secret_path' => secret_path, ) exec_secret = "#{docker_command} #{docker_secrets_flags}" unless_secret = "#{docker_command} inspect #{secret_name}" it { is_expected.to contain_exec("#{_title} docker secret create").with( 'command' => exec_secret, 'unless' => unless_secret, 'path' => ['/bin', '/usr/bin'], ) } end if ensure_value == 'absent' it { is_expected.to contain_exec("#{_title} docker secret rm").with( 'command' => "#{docker_command} rm #{secret_name}", 'onlyif' => "#{docker_command} inspect #{secret_name}", 'path' => ['/bin', '/usr/bin'], ) } end end diff --git a/spec/shared_examples/service.rb b/spec/shared_examples/service.rb index 741d5ea..933e383 100644 --- a/spec/shared_examples/service.rb +++ b/spec/shared_examples/service.rb @@ -1,166 +1,168 @@ +# frozen_string_literal: true + shared_examples 'service' do |_params, _facts| dns_array = [_params['dns']] dns_search_array = [_params['dns_search']] extra_parameters_array = [_params['extra_parameters']] labels_array = [_params['labels']] shell_values_array = [_params['shell_values']] tcp_bind_array = [_params['tcp_bind']] _service_config = if _params['service_config'] != :undef _params['service_config'] else if _facts[:os]['family'] == 'Debian' "/etc/default/#{_params['service_name']}" else nil end end _manage_service = case _params['manage_service'] when true 'Service[docker]' else [] end if _facts[:os]['family'] == 'RedHat' it { is_expected.to contain_file(_params['storage_setup_file']).with( 'ensure' => 'file', 'force' => true, 'before' => _manage_service, 'notify' => _manage_service, ) } end if _facts[:os]['family'] == 'windows' [ "#{_facts['docker_program_data_path']}/docker/", "#{_facts['docker_program_data_path']}/docker/config/", ].each do |dir| it { is_expected.to contain_file(dir).with_ensure('directory') } end end case _params['service_provider'] when 'systemd' it { is_expected.to contain_file('/etc/systemd/system/docker.service.d').with_ensure('directory') } if _params['service_overrides_template'] it { is_expected.to contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with( 'ensure' => 'file', # 'content' => template($service_overrides_template), 'before' => _manage_service, ).that_notifies( 'Exec[docker-systemd-reload-before-service]', ) } end if _params['socket_override'] it { is_expected.to contain_file('/etc/systemd/system/docker.socket.d').with_ensure('directory') } it { is_expected.to contain_file('/etc/systemd/system/docker.socket.d/socket-overrides.conf').with( 'ensure' => 'file', # 'content' => template($socket_overrides_template), ).that_comes_before( _manage_service, ).that_notifies( 'Exec[docker-systemd-reload-before-service]', ) } end it { is_expected.to contain_exec('docker-systemd-reload-before-service').with( 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], 'command' => 'systemctl daemon-reload > /dev/null', 'refreshonly' => true, ).that_notifies( _manage_service, ) } when 'upstart' it { is_expected.to contain_file('/etc/init.d/docker').with( 'ensure' => 'link', 'target' => '/lib/init/upstart-job', 'force' => true, ).that_notifies( _manage_service, ) } end if _params['storage_config'] != :undef it { is_expected.to contain_file(_params['storage_config']).with( 'ensure' => 'file', 'force' => true, ).that_notifies( _manage_service, ) } end if _service_config it { is_expected.to contain_file(_service_config).with( 'ensure' => 'file', 'force' => true, ).that_notifies( _manage_service, ) } end if _params['manage_service'] if _facts[:os]['family'] == 'windows' it { is_expected.to contain_reboot('pending_reboot').with( 'when' => 'pending', 'onlyif' => 'component_based_servicing', 'timeout' => 1, ) } end it { _hasstatus = if _params['service_hasstatus'] == :undef nil else _params['service_hasstatus'] end _hasrestart = if _params['service_hasrestart'] == :undef nil else _params['service_hasrestart'] end _provider = if _params['service_provider'] == :undef nil else _params['service_provider'] end is_expected.to contain_service('docker').with( 'ensure' => _params['service_state'], 'name' => _params['service_name'], 'enable' => _params['service_enable'], 'hasstatus' => _hasstatus, 'hasrestart' => _hasrestart, 'provider' => _provider, ) } end end diff --git a/spec/shared_examples/services.rb b/spec/shared_examples/services.rb index 7b84c8a..efefdeb 100644 --- a/spec/shared_examples/services.rb +++ b/spec/shared_examples/services.rb @@ -1,139 +1,141 @@ +# frozen_string_literal: true + shared_examples 'services' do |_title, _params, _facts, _defaults| command = _params['command'] create = _params['create'] detach = _params['detach'] ensure_value = _params['ensure'] env = _params['env'] extra_params = _params['extra_params'] host_socket = _params['host_socket'] image = _params['image'] label = _params['label'] mounts = _params['mounts'] networks = _params['networks'] publish = _params['publish'] registry_mirror = _params['registry_mirror'] replicas = _params['replicas'] scale = _params['scale'] service_name = _params['service_name'] tty = _params['tty'] update = _params['update'] user = _params['user'] workdir = _params['workdir'] docker_command = "#{_defaults['docker_command']} service" if _facts[:os]['family'] == 'windows' exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/;#{_facts['docker_systemroot']}/System32/" exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_provider = 'powershell' exec_timeout = 3000 else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_provider = nil exec_timeout = 0 end if create docker_service_create_flags = get_docker_service_flags( 'detach' => detach, 'env' => Array(env), 'service_name' => service_name, 'label' => Array(label), 'publish' => publish, 'replicas' => replicas, 'tty' => tty, 'user' => user, 'workdir' => workdir, 'extra_params' => Array(extra_params), 'image' => image, 'host_socket' => host_socket, 'registry_mirror' => registry_mirror, 'mounts' => mounts, 'networks' => networks, 'command' => command, ) _service_name = if service_name == :undef '' else service_name end exec_create = "#{docker_command} create --name #{docker_service_create_flags}" unless_create = "docker service ps #{_service_name}" it { is_expected.to contain_exec("#{_title} docker service create").with( 'command' => exec_create, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, 'unless' => unless_create, ) } end if update docker_service_flags = get_docker_service_flags( 'detach' => detach, 'env' => Array(env), 'service_name' => service_name, 'label' => Array(label), 'publish' => publish, 'replicas' => replicas, 'tty' => tty, 'user' => user, 'workdir' => workdir, 'extra_params' => Array(extra_params), 'image' => image, 'host_socket' => host_socket, 'registry_mirror' => registry_mirror, ) exec_update = "#{docker_command} update #{docker_service_flags}" it { is_expected.to contain_exec("#{_title} docker service update").with( 'command' => exec_update, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end if scale docker_service_flags = get_docker_service_flags( 'service_name' => service_name, 'replicas' => replicas, 'extra_params' => Array(extra_params), ) exec_scale = "#{docker_command} scale #{service_name}=#{replicas}" it { is_expected.to contain_exec("#{_title} docker service scale").with( 'command' => exec_scale, 'environment' => exec_environment, 'path' => exec_path, 'timeout' => exec_timeout, 'provider' => exec_provider, ) } end if ensure_value == 'absent' it { is_expected.to contain_exec("#{_title} docker service remove").with( 'command' => "docker service rm #{service_name}", 'onlyif' => "docker service ps #{service_name}", 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, ) } end end diff --git a/spec/shared_examples/stack.rb b/spec/shared_examples/stack.rb index e7bd949..cad13fb 100644 --- a/spec/shared_examples/stack.rb +++ b/spec/shared_examples/stack.rb @@ -1,57 +1,59 @@ +# frozen_string_literal: true + shared_examples 'stack' do |_title, _params, _facts, _defaults| ensure_value = _params['ensure'] stack_name = _params['stack_name'] bundle_file = _params['bundle_file'] compose_files = _params['compose_files'] prune = _params['prune'] with_registry_auth = _params['with_registry_auth'] resolve_image = _params['resolve_image'] # deprecation('docker::stack','The docker stack define type will be deprecated in a future release. Please migrate to the docker_stack type/provider.') docker_command = "#{_defaults['docker_command']} stack" if _facts[:os]['family'] == 'windows' exec_path = ['C:/Program Files/Docker/'] check_stack = '$info = docker stack ls | select-string -pattern web if ($info -eq $null) { Exit 1 } else { Exit 0 }' provider = 'powershell' else exec_path = ['/bin', '/usr/bin'] check_stack = "#{docker_command} ls | grep #{stack_name}" provider = nil end if ensure_value == 'present' docker_stack_flags = get_docker_stack_flags( 'stack_name' => stack_name, 'bundle_file' => bundle_file, 'compose_files' => compose_files, 'prune' => prune, 'with_registry_auth' => with_registry_auth, 'resolve_image' => resolve_image, ) exec_stack = "#{docker_command} deploy #{docker_stack_flags} #{stack_name}" it { is_expected.to contain_exec("docker stack create #{stack_name}").with( 'command' => exec_stack, 'unless' => check_stack, 'path' => exec_path, 'provider' => provider, ) } end if ensure_value == 'absent' it { is_expected.to contain_exec("docker stack destroy #{stack_name}").with( 'command' => "#{docker_command} rm #{stack_name}", 'onlyif' => check_stack, 'path' => exec_path, 'provider' => provider, ) } end end diff --git a/spec/shared_examples/swarm.rb b/spec/shared_examples/swarm.rb index 37a4cf5..cfbb123 100644 --- a/spec/shared_examples/swarm.rb +++ b/spec/shared_examples/swarm.rb @@ -1,104 +1,106 @@ +# frozen_string_literal: true + shared_examples 'swarm' do |_title, _params, _facts, _defaults| ensure_value = _params['ensure'] init = _params['init'] join = _params['join'] advertise_addr = _params['advertise_addr'] autolock = _params['autolock'] cert_expiry = _params['cert_expiry'] default_addr_pool = _params['default_addr_pool'] default_addr_pool_mask_length = _params['default_addr_pool_mask_length'] dispatcher_heartbeat = _params['dispatcher_heartbeat'] external_ca = _params['external_ca'] force_new_cluster = _params['force_new_cluster'] listen_addr = _params['listen_addr'] max_snapshots = _params['max_snapshots'] snapshot_interval = _params['snapshot_interval'] token = _params['token'] manager_ip = _params['manager_ip'] if _facts[:os]['family'] == 'windows' exec_environment = "PATH=#{_facts['docker_program_files_path']}/Docker/" exec_path = ["#{_facts['docker_program_files_path']}/Docker/"] exec_timeout = 3000 exec_provider = 'powershell' unless_init = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' unless_join = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' onlyif_leave = '$info = docker info | select-string -pattern "Swarm: active" if ($info -eq $null) { Exit 1 } else { Exit 0 }' else exec_environment = 'HOME=/root' exec_path = ['/bin', '/usr/bin'] exec_timeout = 0 exec_provider = nil unless_init = 'docker info | grep -w "Swarm: active"' unless_join = 'docker info | grep -w "Swarm: active"' onlyif_leave = 'docker info | grep -w "Swarm: active"' end docker_command = "#{_defaults['docker_command']} swarm" if init docker_swarm_init_flags = get_docker_swarm_init_flags( 'init' => init, 'advertise_addr' => advertise_addr, 'autolock' => autolock, 'cert_expiry' => cert_expiry, 'dispatcher_heartbeat' => dispatcher_heartbeat, 'default_addr_pool' => default_addr_pool, 'default_addr_pool_mask_length' => default_addr_pool_mask_length, 'external_ca' => external_ca, 'force_new_cluster' => force_new_cluster, 'listen_addr' => listen_addr, 'max_snapshots' => max_snapshots, 'snapshot_interval' => snapshot_interval, ) exec_init = "#{docker_command} #{docker_swarm_init_flags}" it { is_expected.to contain_exec('Swarm init').with( 'command' => exec_init, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, 'unless' => unless_init, ) } end if join docker_swarm_join_flags = get_docker_swarm_join_flags( 'join' => join, 'advertise_addr' => advertise_addr, 'listen_addr' => listen_addr, 'token' => token, ) exec_join = "#{docker_command} #{docker_swarm_join_flags} #{manager_ip}" it { is_expected.to contain_exec('Swarm join').with( 'command' => exec_join, 'environment' => exec_environment, 'path' => exec_path, 'provider' => exec_provider, 'timeout' => exec_timeout, 'unless' => unless_join, ) } end if ensure_value == 'absent' it { is_expected.to contain_exec('Leave swarm').with( 'command' => 'docker swarm leave --force', 'onlyif' => onlyif_leave, 'path' => exec_path, 'provider' => exec_provider, ) } end end diff --git a/spec/shared_examples/system_user.rb b/spec/shared_examples/system_user.rb index ae8bec2..9ea2ca4 100644 --- a/spec/shared_examples/system_user.rb +++ b/spec/shared_examples/system_user.rb @@ -1,20 +1,22 @@ +# frozen_string_literal: true + shared_examples 'system_user' do |user, group| _create_user = true docker_group = group if _create_user it { is_expected.to contain_user(user).with( 'ensure' => 'present', ).that_comes_before("Exec[docker-system-user-#{user}]") } end it { is_expected.to contain_exec("docker-system-user-#{user}").with( 'command' => "/usr/sbin/usermod -aG #{docker_group} #{user}", 'unless' => "/bin/cat /etc/group | grep '^#{docker_group}:' | grep -qw #{user}", ) } end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 373813b..65d59b8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,93 +1,95 @@ +# frozen_string_literal: true + require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' require 'shared_examples' require 'rspec-puppet' require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) include RspecPuppetFacts default_facts = { puppetversion: Puppet.version, facterversion: Facter.version, } default_fact_files = [ File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), ] default_fact_files.each do |f| next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) rescue => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end end RSpec.configure do |c| c.mock_with :rspec c.default_facts = default_facts c.before :each do # set to strictest setting for testing # by default Puppet runs at warning level Puppet.settings[:strict] = :warning end c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] c.after(:suite) do end end # Ensures that a module is defined # @param module_name Name of the module def ensure_module_defined(module_name) module_name.split('::').reduce(Object) do |last_module, next_module| last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) last_module.const_get(next_module, false) end end RSpec::Matchers.define :require_string_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be a String}) end failure_message do |type_class| "#{type_class} should require #{property} to be a String" end end RSpec::Matchers.define :require_hash_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be a Hash}) end failure_message do |type_class| "#{type_class} should require #{property} to be a Hash" end end RSpec::Matchers.define :require_array_for do |property| match do |type_class| config = { name: 'name' } config[property] = 2 expect { type_class.new(config) }.to raise_error(Puppet::Error, %r{#{property} should be an Array}) end failure_message do |type_class| "#{type_class} should require #{property} to be an Array" end end at_exit { RSpec::Puppet::Coverage.report! } # 'spec_overrides' from sync.yml will appear below this line diff --git a/spec/spec_helper_acceptance_local.rb b/spec/spec_helper_acceptance_local.rb index 0a8ea62..c802a0c 100644 --- a/spec/spec_helper_acceptance_local.rb +++ b/spec/spec_helper_acceptance_local.rb @@ -1,193 +1,195 @@ +# frozen_string_literal: true + require 'puppet_litmus' require 'rspec/retry' require 'tempfile' include PuppetLitmus # This method allows a block to be passed in and if an exception is raised # that matches the 'error_matcher' matcher, the block will wait a set number # of seconds before retrying. # Params: # - max_retry_count - Max number of retries # - retry_wait_interval_secs - Number of seconds to wait before retry # - error_matcher - Matcher which the exception raised must match to allow retry # Example Usage: # retry_on_error_matching(3, 5, /OpenGPG Error/) do # apply_manifest(pp, :catch_failures => true) # end def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, error_matcher = nil) try = 0 begin try += 1 yield rescue StandardError => e raise unless try < max_retry_count && (error_matcher.nil? || e.message =~ error_matcher) sleep retry_wait_interval_secs retry end end def create_remote_file(name, full_name, file_content) Tempfile.open name do |tempfile| File.open(tempfile.path, 'w') { |file| file.puts file_content } bolt_upload_file(tempfile.path, full_name) end end RSpec.configure do |c| # Add exclusive filter for Windows untill all the windows functionality is implemented c.filter_run_excluding win_broken: true # Readable test descriptions c.formatter = :documentation # show retry status in spec process c.verbose_retry = true # show exception that triggers a retry if verbose_retry is set to true c.display_try_failure_messages = true # Configure all nodes in nodeset c.before :suite do # Install module and dependencies # Due to RE-6764, running yum update renders the machine unable to install # other software. Thus this workaround. if os[:family] == 'redhat' run_shell('mv /etc/yum.repos.d/redhat.repo /etc/yum.repos.d/internal-mirror.repo', expect_failures: true) run_shell('rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm', expect_failures: true) run_shell('yum update -y -q') # run_shell('yum upgrade -y') end if os[:family] == 'debian' || os[:family] == 'ubuntu' run_shell('apt-get update -y') # run_shell('apt-get upgrade -y') run_shell('apt-get install -y lsb-release') run_shell('apt-get install -y net-tools') end run_shell('puppet module install puppetlabs-stdlib --version 4.24.0', expect_failures: true) run_shell('puppet module install puppetlabs-apt --version 4.4.1', expect_failures: true) run_shell('puppet module install puppetlabs-translate --version 1.0.0', expect_failures: true) run_shell('puppet module install puppetlabs-powershell --version 2.1.5', expect_failures: true) run_shell('puppet module install puppetlabs-reboot --version 2.0.0', expect_failures: true) # net-tools required for netstat utility being used by some tests if os[:family] == 'redhat' && os[:release].to_i == 7 run_shell('yum -y install lvm2 device-mapper device-mapper-persistent-data device-mapper-event device-mapper-libs device-mapper-event-libs') run_shell('yum install -y yum-utils net-tools') run_shell('yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo') run_shell('yum-config-manager --enable docker\*') end docker_compose_content_v3 = <<-EOS version: "3.4" x-images: &default-image alpine:3.8 services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_compose_override_v3 = <<-EOS version: "3.4" x-images: &default-image debian:stable-slim services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_stack_override_v3 = <<-EOS version: "3.4" x-images: &default-image debian:stable-slim services: compose_test: image: *default-image command: /bin/sh -c "while true; do echo hello world; sleep 1; done" EOS docker_compose_content_v3_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_compose_override_v3_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_compose_override_v3_windows2016 = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: external: name: nat EOS docker_stack_content_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle command: cmd.exe /C "ping 8.8.8.8 -t" EOS docker_stack_override_windows = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver EOS docker_stack_override_windows2016 = <<-EOS version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 EOS if os[:family] == 'windows' create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3_windows) create_remote_file(host, '/tmp/docker-stack.yml', docker_stack_content_windows) if os[:release] =~ %r{2019} create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3_windows) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows) else create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3_windows2016) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows2016) end else create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3) create_remote_file(host, '/tmp/docker-stack.yml', docker_compose_content_v3) create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_compose_override_v3) create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_v3) end next unless os[:family] == 'windows' result = run_shell("ipconfig | findstr /i 'ipv4'") raise 'Could not retrieve ip address for Windows box' if result.exit_code != 0 ip = result.stdout.split("\n")[0].split(':')[1].strip retry_on_error_matching(60, 5, %r{connection failure running}) do @windows_ip = ip end apply_manifest("class { 'docker': docker_ee => true, extra_parameters => '\"insecure-registries\": [ \"#{@windows_ip}:5000\" ]' }", catch_failures: true) docker_path = 'C:\\Program Files\\Docker' run_shell("set PATH \"%PATH%;C:\\Users\\Administrator\\AppData\\Local\\Temp;#{docker_path}\"") puts 'Waiting for box to come online' sleep 300 end end diff --git a/spec/unit/lib/facter/docker_spec.rb b/spec/unit/lib/facter/docker_spec.rb index 8088903..715aa5e 100644 --- a/spec/unit/lib/facter/docker_spec.rb +++ b/spec/unit/lib/facter/docker_spec.rb @@ -1,123 +1,125 @@ +# frozen_string_literal: true + require 'spec_helper' require 'json' describe 'Facter::Util::Fact' do before :each do Facter.clear if Facter.value(:kernel) == 'windows' docker_command = 'powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -c docker' Facter::Util::Resolution.stubs(:which).with('docker').returns('C:\Program Files\Docker\docker.exe') else docker_command = 'docker' Facter::Util::Resolution.stubs(:which).with('docker').returns('/usr/bin/docker') end docker_info = File.read(fixtures('facts', 'docker_info')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} info --format '{{json .}}'").returns(docker_info) processors = File.read(fixtures('facts', 'processors')) Facter.fact(:processors).stubs(:value).returns(JSON.parse(processors)) docker_version = File.read(fixtures('facts', 'docker_version')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} version --format '{{json .}}'").returns(docker_version) docker_network_list = File.read(fixtures('facts', 'docker_network_list')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} network ls | tail -n +2").returns(docker_network_list) docker_network_names = [] docker_network_list.each_line { |line| docker_network_names.push line.split[1] } docker_network_names.each do |network| inspect = File.read(fixtures('facts', "docker_network_inspect_#{network}")) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} network inspect #{network}").returns(inspect) end docker_worker_token = File.read(fixtures('facts', 'docker_swarm_worker_token')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} swarm join-token worker -q").returns(docker_worker_token.chomp) docker_manager_token = File.read(fixtures('facts', 'docker_swarm_manager_token')) Facter::Util::Resolution.stubs(:exec).with("#{docker_command} swarm join-token manager -q").returns(docker_manager_token.chomp) end after(:each) { Facter.clear } describe 'docker fact with composer network' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-c5810f1e3113,docker0,eth0,lo') end it do fact = File.read(fixtures('facts', 'facts_with_compose')) fact = JSON.parse(fact.to_json, quirks_mode: true) facts = eval(fact) # rubocop:disable Security/Eval expect(Facter.fact(:docker).value).to include( 'network' => facts['network'], ) end end describe 'docker fact without composer network' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do fact = File.read(fixtures('facts', 'facts_without_compose')).chomp fact_json = fact.to_json facts = JSON.parse(fact_json, quirks_mode: true) facts = eval(facts) # rubocop:disable Security/Eval expect(Facter.fact(:docker).value).to include( 'network' => facts['network'], ) end end describe 'docker client version' do before(:each) do docker_version = File.read(fixtures('facts', 'docker_version')) Facter.fact(:docker_version).stubs(:value).returns(JSON.parse(docker_version)) Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_client_version).value).to eq( '17.03.1-ce-client', ) end end describe 'docker server version' do before(:each) do docker_version = File.read(fixtures('facts', 'docker_version')) Facter.fact(:docker_version).stubs(:value).returns(JSON.parse(docker_version)) Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_server_version).value).to eq( '17.03.1-ce-server', ) end end describe 'docker info' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it 'has valid entries' do expect(Facter.fact(:docker).value).to include( 'Architecture' => 'x86_64', ) end end describe 'docker swarm worker join-token' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_worker_join_token).value).to eq( 'SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-0jh0syqeoj3tlr81p165ydfkm', ) end end describe 'docker swarm manager join-token' do before :each do Facter.fact(:interfaces).stubs(:value).returns('br-19a6ebf6f5a5,docker0,eth0,lo') end it do expect(Facter.fact(:docker_manager_join_token).value).to eq( 'SWMTKN-1-2m7ekt7511j5kgrc6seyrewpdxv47ksz1sdg7iybzhuug6nmws-8gh1ns1lcavgau8k9p6ou7xj3', ) end end end diff --git a/spec/unit/lib/puppet/provider/docker_network_spec.rb b/spec/unit/lib/puppet/provider/docker_network_spec.rb index 804bb27..6800b74 100644 --- a/spec/unit/lib/puppet/provider/docker_network_spec.rb +++ b/spec/unit/lib/puppet/provider/docker_network_spec.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + require 'spec_helper' describe Puppet::Type.type(:docker_network).provider(:ruby) do let(:provider) { resource.provider } let(:instance) { provider.class.instances.first } let(:resource) do Puppet::Type.type(:docker_network).new( ensure: :present, name: 'test-network', driver: 'host', subnet: ['192.168.3.0/24', '10.0.0.0/24'], ) end before :each do # need to reach deep into puppet to unhook the confinement call, so the provider gets properly loaded ['docker', '/usr/local/bin/docker'].each do |docker_path| allow(Puppet::Confine::Exists).to receive(:which).with(docker_path).and_return('/usr/local/bin/docker') end end describe 'create' do it 'creates a docker network' do provider.class.expects(:docker).with(['network', 'create', "--driver=#{resource[:driver]}", "--subnet=#{resource[:subnet][0]}", "--subnet=#{resource[:subnet][1]}", resource[:name]]) expect(provider.create).to be_nil end end end diff --git a/spec/unit/lib/puppet/type/docker_compose_spec.rb b/spec/unit/lib/puppet/type/docker_compose_spec.rb index b3ce01f..9b310ff 100644 --- a/spec/unit/lib/puppet/type/docker_compose_spec.rb +++ b/spec/unit/lib/puppet/type/docker_compose_spec.rb @@ -1,45 +1,47 @@ +# frozen_string_literal: true + require 'spec_helper' compose = Puppet::Type.type(:docker_compose) describe compose do let :params do [ :name, :provider, :scale, :options, :up_args, ] end let :properties do [ :ensure, ] end it 'has expected properties' do properties.each do |property| expect(compose.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(compose.parameters).to be_include(param) end end it 'requires options to be an array' do expect(compose).to require_array_for('options') end it 'requires up_args to be a string' do expect(compose).to require_string_for('up_args') end it 'requires scale to be a hash' do expect(compose).to require_hash_for('scale') end end diff --git a/spec/unit/lib/puppet/type/docker_network_spec.rb b/spec/unit/lib/puppet/type/docker_network_spec.rb index ed99582..bfe8815 100644 --- a/spec/unit/lib/puppet/type/docker_network_spec.rb +++ b/spec/unit/lib/puppet/type/docker_network_spec.rb @@ -1,39 +1,41 @@ +# frozen_string_literal: true + require 'spec_helper' network = Puppet::Type.type(:docker_network) describe network do let :params do [ :name, :provider, :subnet, :gateway, :ip_range, :aux_address, :options, :additional_flags, ] end let :properties do [ :ensure, :driver, :ipam_driver, :id, ] end it 'has expected properties' do properties.each do |property| expect(network.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(network.parameters).to be_include(param) end end end diff --git a/spec/unit/lib/puppet/type/docker_stack_spec.rb b/spec/unit/lib/puppet/type/docker_stack_spec.rb index 4cfb8ec..8cd1dc5 100644 --- a/spec/unit/lib/puppet/type/docker_stack_spec.rb +++ b/spec/unit/lib/puppet/type/docker_stack_spec.rb @@ -1,35 +1,37 @@ +# frozen_string_literal: true + require 'spec_helper' stack = Puppet::Type.type(:docker_stack) describe stack do let :params do [ :name, :provider, :up_args, ] end let :properties do [ :ensure, ] end it 'has expected properties' do properties.each do |property| expect(stack.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(stack.parameters).to be_include(param) end end it 'requires up_args to be a string' do expect(stack).to require_string_for('up_args') end end diff --git a/spec/unit/lib/puppet/type/docker_volume_spec.rb b/spec/unit/lib/puppet/type/docker_volume_spec.rb index c2de5ac..2ff8776 100644 --- a/spec/unit/lib/puppet/type/docker_volume_spec.rb +++ b/spec/unit/lib/puppet/type/docker_volume_spec.rb @@ -1,32 +1,34 @@ +# frozen_string_literal: true + require 'spec_helper' volume = Puppet::Type.type(:docker_volume) describe volume do let :params do [ :name, :provider, :options, ] end let :properties do [ :driver, :mountpoint, ] end it 'has expected properties' do properties.each do |property| expect(volume.properties.map(&:name)).to be_include(property) end end it 'has expected parameters' do params.each do |param| expect(volume.parameters).to be_include(param) end end end