From de3f0005e9e7a2b9ead229dea56339f023edcf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20H=C3=A4feli?= Date: Mon, 18 Feb 2019 10:46:56 +0100 Subject: [PATCH 01/44] Fix frozen string error (#434) --- tasks/swarm_token.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/swarm_token.rb b/tasks/swarm_token.rb index cd083569..35eae179 100755 --- a/tasks/swarm_token.rb +++ b/tasks/swarm_token.rb @@ -7,7 +7,7 @@ def swarm_token(node_role) cmd_string = 'docker swarm join-token -q' - cmd_string << " #{node_role}" unless node_role.nil? + cmd_string += " #{node_role}" unless node_role.nil? stdout, stderr, status = Open3.capture3(cmd_string) raise Puppet::Error, "stderr: '#{stderr}'" if status != 0 From 593d23410333c53649d1cecf8fdb4c1928e573d5 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 18 Feb 2019 20:49:22 +1100 Subject: [PATCH 02/44] Update metadata.json (#429) --- metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metadata.json b/metadata.json index 5f224914..c88335b1 100755 --- a/metadata.json +++ b/metadata.json @@ -18,7 +18,7 @@ }, { "name": "puppetlabs/translate", - "version_requirement": ">= 0.0.1 <=1.1.0" + "version_requirement": ">= 0.0.1 <=1.2.0" }, { "name": "puppetlabs/powershell", @@ -73,4 +73,4 @@ "pdk-version": "1.8.0", "template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git", "template-ref": "1.8.0-0-g0d9da00" -} \ No newline at end of file +} From 686e2ae621f20a255a561fd990bdd29f388af4e4 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 18 Feb 2019 22:42:22 +1100 Subject: [PATCH 03/44] adding in type/provider for docker stack (#433) --- README.md | 18 ++++- lib/puppet/provider/docker_stack/ruby.rb | 90 ++++++++++++++++++++++++ lib/puppet/type/docker_stack.rb | 33 +++++++++ manifests/stack.pp | 3 + spec/acceptance/stack_spec.rb | 22 +++--- spec/unit/docker_stack_spec.rb | 36 ++++++++++ 6 files changed, 188 insertions(+), 14 deletions(-) create mode 100644 lib/puppet/provider/docker_stack/ruby.rb create mode 100644 lib/puppet/type/docker_stack.rb create mode 100644 spec/unit/docker_stack_spec.rb diff --git a/README.md b/README.md index 4d0ef7e6..58649269 100755 --- a/README.md +++ b/README.md @@ -626,6 +626,8 @@ Please note you should supply your master docker-compose file as the first eleme If you are using a v3.2 compose file or above on a Docker Swarm cluster, use the `docker::stack` class. Include the file resource before you run the stack command. +NOTE: this define will be deprecated in a future release in favor of the [docker type](#types) + To deploy the stack, add the following code to the manifest file: ```puppet @@ -927,7 +929,6 @@ docker::plugin {'foo/fooplugin:latest' ensure => 'absent', force_remove => true, } -thub.com ``` ## Reference @@ -974,6 +975,7 @@ thub.com * docker_compose: A type that represents a docker compose file. * docker_network: A type that represents a docker network. * docker_volume: A type that represents a docker volume. +* docker_stack: A type that repsents a docker stack. ### Parameters @@ -1057,6 +1059,20 @@ Additional options for the volume driver. The location that the volume is mounted to. +The following parameters are available in the `docker_stack` type: + +#### 'bundle_file' + +A path to a Distributed Application Bundle file. + +#### 'compose_files' + +An array containing the docker compose file paths. + +#### `up_args` + +Arguments to be passed directly to docker stack deploy. + #### Docker class parameters #### `version` diff --git a/lib/puppet/provider/docker_stack/ruby.rb b/lib/puppet/provider/docker_stack/ruby.rb new file mode 100644 index 00000000..2e99dbd9 --- /dev/null +++ b/lib/puppet/provider/docker_stack/ruby.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +require 'deep_merge' + +Puppet::Type.type(:docker_stack).provide(:ruby) do + desc 'Support for Puppet running Docker Stacks' + + mk_resource_methods + commands docker: 'docker' + + def exists? + Puppet.info("Checking for stack #{name}") + stack_services = {} + stack_containers = [] + resource[:compose_files].each do |file| + compose_file = YAML.safe_load(File.read(file), [], [], true) + # rubocop:disable Style/StringLiterals + containers = docker([ + 'ps', + '--format', + "{{.Label \"com.docker.swarm.service.name\"}}-{{.Image}}", + '--filter', + "label=com.docker.stack.namespace=#{name}", + ]).split("\n").each do |c| + c.slice!("#{name}_") + end + stack_containers.push(*containers) + stack_containers.uniq! + # rubocop:enable Style/StringLiterals + case compose_file['version'] + when %r{^3(\.[0-7])?$} + stack_services.merge!(compose_file['services']) + else + raise(Puppet::Error, "Unsupported docker compose file syntax version \"#{compose_file['version']}\"!") + end + end + + if stack_services.count != stack_containers.count + return false + end + counts = Hash[*stack_services.each.map { |key, array| + image = (array['image']) ? array['image'] : get_image(key, stack_services) + Puppet.info("Checking for compose service #{key} #{image}") + ["#{key}-#{image}", stack_containers.count("#{key}-#{image}")] + }.flatten] + # No containers found for the project + if counts.empty? || + # Containers described in the compose file are not running + counts.any? { |_k, v| v.zero? } + false + else + true + end + end + + def get_image(service_name, stack_services) + image = stack_services[service_name]['image'] + unless image + if stack_services[service_name]['extends'] + image = get_image(stack_services[service_name]['extends'], stack_services) + elsif stack_services[service_name]['build'] + image = "#{name}_#{service_name}" + end + end + image + end + + def create + Puppet.info("Running stack #{name}") + args = ['stack', 'deploy', compose_files, name].insert(1, bundle_file).insert(4, resource[:up_args]).compact + docker(args) + end + + def destroy + Puppet.info("Removing docker stack #{name}") + rm_args = ['stack', 'rm', name] + docker(rm_args) + end + + def bundle_file + return unless resource[:bundle_file].nil? + resource[:bundle_file].map { |x| ['-c', x] }.flatten + end + + def compose_files + resource[:compose_files].map { |x| ['-c', x] }.flatten + end + + private +end diff --git a/lib/puppet/type/docker_stack.rb b/lib/puppet/type/docker_stack.rb new file mode 100644 index 00000000..461907f1 --- /dev/null +++ b/lib/puppet/type/docker_stack.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +Puppet::Type.newtype(:docker_stack) do + @doc = 'A type representing a Docker Stack' + + ensurable + + newparam(:bundle_file) do + desc 'Path to a Distributed Application Bundle file.' + validate do |value| + raise _('bundle files should be a string') unless value.is_a? String + end + end + + newparam(:compose_files, array_matching: :all) do + desc 'An array of Docker Compose Files paths.' + validate do |value| + raise _('compose files should be an array') unless value.is_a? Array + end + end + + newparam(:up_args) do + desc 'Arguments to be passed directly to docker stack deploy.' + validate do |value| + raise _('up_args should be a String') unless value.is_a? String + end + end + + newparam(:name) do + isnamevar + desc 'The name of the stack' + end +end diff --git a/manifests/stack.pp b/manifests/stack.pp index 97388b9d..63844cf3 100644 --- a/manifests/stack.pp +++ b/manifests/stack.pp @@ -47,6 +47,9 @@ include docker::params + 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 = "${docker::params::docker_command} stack" if $::osfamily == 'windows' { diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index 02f2b9bf..c7568bcc 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -5,6 +5,7 @@ tmp_path = 'C:/cygwin64/tmp' test_container = 'nanoserver-sac2016' wait_for_container_seconds = 120 + else docker_args = '' tmp_path = '/tmp' @@ -31,8 +32,7 @@ class { 'docker': #{docker_args} } context 'Creating stack' do let(:install) {" - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml'], ensure => present, }" @@ -60,21 +60,20 @@ class { 'docker': #{docker_args} } context 'Destroying stack' do let(:install) {" - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml'], ensure => present, }" } let(:destroy) {" - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml'], ensure => absent, }" } it 'should run successfully' do apply_manifest(destroy, :catch_failures=>true) + sleep 10 end it 'should be idempotent' do @@ -94,8 +93,7 @@ class { 'docker': #{docker_args} } before(:all) do @install_code = <<-code - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], ensure => present, } @@ -113,8 +111,7 @@ class { 'docker': #{docker_args} } context 'Destroying project with multiple compose files' do before(:all) do @install_code = <<-code - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], ensure => present, } @@ -123,15 +120,14 @@ class { 'docker': #{docker_args} } apply_manifest(@install_code, :catch_failures=>true) @destroy_code = <<-code - docker::stack { 'web': - stack_name => 'web', + docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], ensure => absent, } code apply_manifest(@destroy_code, :catch_failures=>true) - sleep 10 # wait for containers to stop + sleep 10# wait for containers to stop end it 'should be idempotent' do diff --git a/spec/unit/docker_stack_spec.rb b/spec/unit/docker_stack_spec.rb new file mode 100644 index 00000000..2a5958fe --- /dev/null +++ b/spec/unit/docker_stack_spec.rb @@ -0,0 +1,36 @@ +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 'should have expected properties' do + properties.each do |property| + expect(stack.properties.map(&:name)).to be_include(property) + end + end + + it 'should have expected parameters' do + params.each do |param| + expect(stack.parameters).to be_include(param) + end + end + + it 'should require up_args to be a string' do + expect(stack).to require_string_for('up_args') + end +end From ff487877b6ec5f5f23388d10d93849bcf5a924a8 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 18 Feb 2019 22:43:23 +1100 Subject: [PATCH 04/44] updating acceptance tests for cve-2019-5736 (#430) --- spec/acceptance/compose_v3_spec.rb | 2 ++ spec/acceptance/docker_custom_source_spec.rb | 14 +++++++++----- spec/acceptance/docker_full_spec.rb | 2 ++ spec/acceptance/docker_spec.rb | 4 +++- spec/acceptance/network_spec.rb | 6 +++++- spec/acceptance/plugin_spec.rb | 6 +++++- spec/acceptance/stack_spec.rb | 6 +++++- spec/acceptance/volume_spec.rb | 4 ++++ 8 files changed, 35 insertions(+), 9 deletions(-) diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index f00d0312..d83e2289 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -11,6 +11,8 @@ docker_args = "repo_opt => '--enablerepo=localmirror-extras'" elsif fact('os.name') == 'Centos' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index 5128e5c5..7e655ef1 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -6,15 +6,19 @@ 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 = 'microsoft/nanoserver' default_image_tag = '10.0.14393.2189' - #The default args are set because: - #restart => 'always' - there is no service created to manage containers + #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 + skip = false +elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" + skip = true else - skip = true + docker_args = '' + skip = true end describe 'the Puppet Docker module' do @@ -32,7 +36,7 @@ class { 'docker': #{docker_args} } end it 'should be start a docker process' do - if fact('osfamily') == 'windows' + if fact('osfamily') == 'windows' shell('powershell Get-Process -Name dockerd') do |r| expect(r.stdout).to match(/ProcessName/) end diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index dac1d3e3..fc08d03d 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -21,6 +21,8 @@ else if fact('os.family') == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else docker_args = '' end diff --git a/spec/acceptance/docker_spec.rb b/spec/acceptance/docker_spec.rb index 24936a4f..2636c7cc 100644 --- a/spec/acceptance/docker_spec.rb +++ b/spec/acceptance/docker_spec.rb @@ -19,8 +19,10 @@ else if fact('osfamily') == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" else - docker_arg = '' + docker_args = '' end docker_registry_image = 'registry' docker_network = 'bridge' diff --git a/spec/acceptance/network_spec.rb b/spec/acceptance/network_spec.rb index 9152e04f..082e47ff 100644 --- a/spec/acceptance/network_spec.rb +++ b/spec/acceptance/network_spec.rb @@ -6,7 +6,11 @@ puts "Not implemented on Windows" broken = true elsif fact('osfamily') == 'RedHat' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" + docker_args = "repo_opt => '--enablerepo=localmirror-extras'" +elsif fact('os.name') == 'Ubuntu' && fact('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 diff --git a/spec/acceptance/plugin_spec.rb b/spec/acceptance/plugin_spec.rb index 971d3b22..b1b3e0e1 100644 --- a/spec/acceptance/plugin_spec.rb +++ b/spec/acceptance/plugin_spec.rb @@ -6,7 +6,11 @@ puts "Not implemented on Windows" broken = true elsif fact('osfamily') == 'RedHat' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" + docker_args = "repo_opt => '--enablerepo=localmirror-extras'" +elsif fact('os.name') == 'Ubuntu' && fact('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 diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index c7568bcc..ab4c73d4 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -7,7 +7,11 @@ wait_for_container_seconds = 120 else - docker_args = '' + if fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" + else + docker_args = '' + end tmp_path = '/tmp' test_container = 'alpine' wait_for_container_seconds = 10 diff --git a/spec/acceptance/volume_spec.rb b/spec/acceptance/volume_spec.rb index 6970860f..55fde5fd 100644 --- a/spec/acceptance/volume_spec.rb +++ b/spec/acceptance/volume_spec.rb @@ -8,7 +8,11 @@ elsif ('osfamily') == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" command = 'docker' +elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" + command = 'docker' else + docker_args = '' command = 'docker' end From f13f62b1f754c50f43fbfd13ed9196f30315024b Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Tue, 19 Feb 2019 19:50:40 +1100 Subject: [PATCH 05/44] including docker class in all tests of docker::run (#437) --- spec/acceptance/docker_full_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index fc08d03d..8638a9e0 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -800,6 +800,7 @@ class { 'docker': #{docker_args} } it 'should restart a unhealthy container' do pp5=<<-EOS + class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', command => '#{default_run_command}', @@ -810,6 +811,7 @@ class { 'docker': #{docker_args} } EOS pp_delete=<<-EOS + class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', ensure => absent, From d5ec19261e27fce413e7dd611dac003e606e7934 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Tue, 19 Feb 2019 20:10:51 +1100 Subject: [PATCH 06/44] fixing errors with bundle file conditional statement (#436) --- lib/puppet/provider/docker_stack/ruby.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/puppet/provider/docker_stack/ruby.rb b/lib/puppet/provider/docker_stack/ruby.rb index 2e99dbd9..2ea08eff 100644 --- a/lib/puppet/provider/docker_stack/ruby.rb +++ b/lib/puppet/provider/docker_stack/ruby.rb @@ -78,8 +78,7 @@ def destroy end def bundle_file - return unless resource[:bundle_file].nil? - resource[:bundle_file].map { |x| ['-c', x] }.flatten + return resource[:bundle_file].map { |x| ['-c', x] }.flatten unless resource[:bundle_file].nil? end def compose_files From 1cc42964bb98fd2958d86847ac416d408f558be2 Mon Sep 17 00:00:00 2001 From: esalberg Date: Sun, 24 Feb 2019 23:07:43 -0500 Subject: [PATCH 07/44] Add docker socket group overrides for systemd (service and socket) (#441) --- README.md | 15 ++++++++++ manifests/init.pp | 6 ++-- manifests/params.pp | 12 ++++++++ manifests/run.pp | 2 +- manifests/service.pp | 30 ++++++++++++++----- spec/classes/docker_spec.rb | 8 +++++ .../docker.socket.d/socket-overrides.conf.erb | 2 ++ 7 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 templates/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb diff --git a/README.md b/README.md index 58649269..685aabc9 100755 --- a/README.md +++ b/README.md @@ -129,6 +129,21 @@ class { 'docker': } ``` +The default group ownership of the Unix control socket differs based on OS. For example, on RHEL using docker-ce packages >=18.09.1, the socket file used by /usr/lib/systemd/system/docker.socket is owned by the docker group. To override this value in /etc/sysconfig/docker and docker.socket (e.g. to use the 'root' group): + +```puppet +class {'docker': + socket_group => 'root', + socket_override => true, +} +``` + +The socket_group parameter also takes a boolean for legacy cases where setting -G in /etc/sysconfig/docker is not desired: + +```puppet +docker::socket_group: false +``` + For more information about the configuration options for the default docker bridge, see the [Docker documentation](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/). diff --git a/manifests/init.pp b/manifests/init.pp index 78b67c75..0a4f43ef 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -224,7 +224,7 @@ # # [*socket_group*] # Group ownership of the unix control socket. -# Defaults to undefined +# Default is based on OS (docker, dockerroot, undef) # # [*extra_parameters*] # Any extra parameters that should be passed to the docker daemon. @@ -448,7 +448,7 @@ Optional[String] $tmp_dir = $docker::params::tmp_dir, Variant[String,Array,Undef] $dns = $docker::params::dns, Variant[String,Array,Undef] $dns_search = $docker::params::dns_search, - Optional[String] $socket_group = $docker::params::socket_group, + Variant[String,Boolean,Undef] $socket_group = $docker::params::socket_group, Array $labels = $docker::params::labels, Variant[String,Array,Undef] $extra_parameters = undef, Variant[String,Array,Undef] $shell_values = undef, @@ -496,6 +496,8 @@ Variant[String,Boolean,Undef] $service_config = $docker::params::service_config, Optional[String] $service_config_template = $docker::params::service_config_template, Variant[String,Boolean,Undef] $service_overrides_template = $docker::params::service_overrides_template, + Variant[String,Boolean,Undef] $socket_overrides_template = $docker::params::socket_overrides_template, + Optional[Boolean] $socket_override = $docker::params::socket_override, Optional[Boolean] $service_hasstatus = $docker::params::service_hasstatus, Optional[Boolean] $service_hasrestart = $docker::params::service_hasrestart, Optional[String] $registry_mirror = $docker::params::registry_mirror, diff --git a/manifests/params.pp b/manifests/params.pp index 1c34b11d..fe7dd98a 100755 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -118,12 +118,16 @@ $storage_config = '/etc/default/docker-storage' $service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' + $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' + $socket_override = false $service_hasstatus = true $service_hasrestart = true include docker::systemd_reload } else { $service_config_template = 'docker/etc/default/docker.erb' $service_overrides_template = undef + $socket_overrides_template = undef + $socket_override = false $service_provider = 'upstart' $service_hasstatus = true $service_hasrestart = false @@ -136,6 +140,8 @@ $storage_config = '/etc/default/docker-storage' $service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' + $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' + $socket_override = false $service_hasstatus = true $service_hasrestart = true include docker::systemd_reload @@ -184,6 +190,8 @@ $service_provider = 'systemd' $service_config_template = 'docker/etc/sysconfig/docker.systemd.erb' $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb' + $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' + $socket_override = false $use_upstream_package_source = true $package_ce_source_location = "https://download.docker.com/linux/centos/${::operatingsystemmajrelease}/${::architecture}/${docker_ce_channel}" @@ -254,6 +262,8 @@ $storage_setup_file = undef $service_provider = undef $service_overrides_template = undef + $socket_overrides_template = undef + $socket_override = false $service_hasstatus = undef $service_hasrestart = undef $detach_service_in_init = true @@ -280,6 +290,8 @@ $package_ee_package_name = undef $use_upstream_package_source = true $service_overrides_template = undef + $socket_overrides_template = undef + $socket_override = false $service_hasstatus = undef $service_hasrestart = undef $service_provider = undef diff --git a/manifests/run.pp b/manifests/run.pp index f9452a8e..1d3dcb97 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -135,7 +135,7 @@ Optional[String] $health_check_cmd = undef, Optional[Boolean] $restart_on_unhealthy = false, Optional[Integer] $health_check_interval = undef, - Optional[Array] $custom_unless = undef, + Variant[String,Array,Undef] $custom_unless = [], ) { include docker::params if ($socket_connect != []) { diff --git a/manifests/service.pp b/manifests/service.pp index 113652f2..0b57cce2 100755 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -106,6 +106,8 @@ $service_config = $docker::service_config, $service_config_template = $docker::service_config_template, $service_overrides_template = $docker::service_overrides_template, + $socket_overrides_template = $docker::socket_overrides_template, + $socket_override = $docker::socket_override, $service_hasstatus = $docker::service_hasstatus, $service_hasrestart = $docker::service_hasrestart, $daemon_environment_files = $docker::daemon_environment_files, @@ -160,23 +162,37 @@ case $service_provider { 'systemd': { file { '/etc/systemd/system/docker.service.d': - ensure => directory, + ensure => 'directory', } if $service_overrides_template { file { '/etc/systemd/system/docker.service.d/service-overrides.conf': - ensure => present, + ensure => 'present', content => template($service_overrides_template), notify => Exec['docker-systemd-reload-before-service'], before => $_manage_service, } - exec { 'docker-systemd-reload-before-service': - path => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], - command => 'systemctl daemon-reload > /dev/null', - before => $_manage_service, - refreshonly => true, + } + + if $socket_override { + file { '/etc/systemd/system/docker.socket.d': + ensure => 'directory', + } + + file { '/etc/systemd/system/docker.socket.d/socket-overrides.conf': + ensure => 'present', + content => template($socket_overrides_template), + notify => Exec['docker-systemd-reload-before-service'], + before => $_manage_service, } } + + exec { 'docker-systemd-reload-before-service': + path => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], + command => 'systemctl daemon-reload > /dev/null', + notify => $_manage_service, + refreshonly => true, + } } 'upstart': { file { '/etc/init.d/docker': diff --git a/spec/classes/docker_spec.rb b/spec/classes/docker_spec.rb index 3808a164..ecace1c5 100755 --- a/spec/classes/docker_spec.rb +++ b/spec/classes/docker_spec.rb @@ -441,6 +441,14 @@ it { should contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(/docker.io/) } end + context 'with a specific socket group and override' do + let(:params) { { + 'socket_group' => 'root', + 'socket_override' => true, + } } + it { should contain_file('/etc/systemd/system/docker.socket.d/socket-overrides.conf').with_content(/root/) } + end + context 'with a custom package name' do let(:params) { {'docker_ce_package_name' => 'docker-custom-pkg-name' } } it { should contain_package('docker').with_name('docker-custom-pkg-name').with_ensure('present') } diff --git a/templates/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb b/templates/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb new file mode 100644 index 00000000..d6663a3b --- /dev/null +++ b/templates/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb @@ -0,0 +1,2 @@ +[Socket] +SocketGroup=<%= @socket_group %> From 4ba9cfe8398b7951781ae23e7d0047ce4b5cae43 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 25 Feb 2019 18:11:47 +1000 Subject: [PATCH 08/44] changing permissions to remove systemd warning (#440) --- manifests/run.pp | 2 +- spec/defines/run_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/run.pp b/manifests/run.pp index 1d3dcb97..82406f05 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -334,7 +334,7 @@ $stopscript = "/usr/local/bin/docker-run-${sanitised_title}-stop.sh" $startstop_template = 'docker/usr/local/bin/docker-run.sh.epp' $init_template = 'docker/etc/systemd/system/docker-run.erb' - $mode = '0640' + $mode = '0644' } 'upstart': { $initscript = "/etc/init.d/${service_prefix}${sanitised_title}" diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index d3aa4668..1d86c3ad 100755 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -44,7 +44,7 @@ let(:params) { {'command' => 'command', 'image' => 'base'} } it { should compile.with_all_deps } it { should contain_service('docker-sample') } - it { should contain_file(initscript).with_content(/#{Regexp.escape(startscript)}/) } + it { should contain_file(initscript).with_content(/#{Regexp.escape(startscript)}/).with_mode('0644') } it { should contain_file(initscript).with_content(/#{Regexp.escape(stopscript)}/) } it { should contain_file(startscript_or_init).with_content(/docker start/).with_content(/command/).with_content(/base/)} From 16764c381e94cd53e3c14985b4aab02b9a17d44d Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 25 Feb 2019 18:12:46 +1000 Subject: [PATCH 09/44] adding in documentation for use of stack type/provider (#443) --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 685aabc9..af84526d 100755 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ To use the CE packages, add the following code to the manifest file: ```puppet class { 'docker': use_upstream_package_source => false, - repo_opt => '', + repo_opt => '', } ``` @@ -641,7 +641,7 @@ Please note you should supply your master docker-compose file as the first eleme If you are using a v3.2 compose file or above on a Docker Swarm cluster, use the `docker::stack` class. Include the file resource before you run the stack command. -NOTE: this define will be deprecated in a future release in favor of the [docker type](#types) +NOTE: this define will be deprecated in a future release in favor of the [docker stack type](#types) To deploy the stack, add the following code to the manifest file: @@ -669,6 +669,14 @@ docker::stack { 'yourapp': } ``` +To use use the equivalent type and provier, use the following in your manfiest file. For more information on specific parameters see the documentation for [here](#Types) +```puppet +docker_stack { 'test': + compose_files => ['/tmp/docker-compose.yml'], + ensure => present, +} +``` + To remove the stack, set `ensure => absent`. ### Swarm mode From 01932d745a9dd3e792a84b40c818a6301306cf03 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 25 Feb 2019 18:13:11 +1000 Subject: [PATCH 10/44] release for v3.4.0 (#442) --- CHANGELOG.md | 13 +++++++++++++ metadata.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb4be93..80f7b8ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# 3.4.0 + +Introduces docker_stack type and provider + +Fixes frozen string in docker swarm token task + +Acceptance testing updates + +Allow use of newer translate module + +A full list of issues and PRs associated with this release can be found [here](https://github.com/puppetlabs/puppetlabs-docker/milestone/6?closed=1) + + # Version 3.3.0 Pins apt repo to 500 to ensure packages are updated diff --git a/metadata.json b/metadata.json index c88335b1..9cada146 100755 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-docker", - "version": "3.3.0", + "version": "3.4.0", "author": "Puppet Labs", "summary": "Module for installing and managing docker", "license": "Apache-2.0", From a2046798977cdad3035e6f241cb5658274866b94 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 4 Mar 2019 11:11:34 +0100 Subject: [PATCH 11/44] docker::services: Fix using multiple published ports (#447) While the class docker::services already allowed arrays to be specified for `publish` ports, it didn't handle this correctly since this array was simply converted to a string and passed onto Docker, like so: --publish '["80:80", "443:443"]' To correctly publish multiple ports, the `--publish` parameter has to be called specified for each port. --publish '80:80' --publish '443:443' This patch also introduces a new spec test to check this behavior --- README.md | 2 +- .../parser/functions/docker_service_flags.rb | 6 +++++- manifests/services.pp | 3 ++- spec/defines/services_spec.rb | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index af84526d..1a0335a7 100755 --- a/README.md +++ b/README.md @@ -799,7 +799,7 @@ docker::services {'redis': } ``` -To base the service off an image, include the `image` parameter and include the `publish` parameter to expose the service ports. To set the amount of containers running in the service, include the `replicas` parameter. To attach one or multiple filesystems to the service, use the `mounts` parameter. For information regarding the `extra_params` parameter, see `docker service create --help`. +To base the service off an image, include the `image` parameter and include the `publish` parameter to expose the service port (use an array to specify multiple published ports). To set the amount of containers running in the service, include the `replicas` parameter. To attach one or multiple filesystems to the service, use the `mounts` parameter. For information regarding the `extra_params` parameter, see `docker service create --help`. To update the service, add the following code to the manifest file: diff --git a/lib/puppet/parser/functions/docker_service_flags.rb b/lib/puppet/parser/functions/docker_service_flags.rb index 61a8441b..3ca2713b 100644 --- a/lib/puppet/parser/functions/docker_service_flags.rb +++ b/lib/puppet/parser/functions/docker_service_flags.rb @@ -36,7 +36,11 @@ module Puppet::Parser::Functions end end - if opts['publish'] && opts['publish'].to_s != 'undef' + if opts['publish'].is_a? Array + opts['publish'].each do |port| + flags << "--publish #{port}" + end + elsif opts['publish'].to_s != 'undef' flags << "--publish '#{opts['publish']}'" end diff --git a/manifests/services.pp b/manifests/services.pp index 8da17125..937a4a1b 100644 --- a/manifests/services.pp +++ b/manifests/services.pp @@ -26,7 +26,7 @@ # Defaults to [] # # [*publish*] -# Publish a port as a node port. +# Publish port(s) as node ports. # Defaults to undef # # [*replicas*] @@ -66,6 +66,7 @@ # [*registry_mirror*] # This will allow the service to set a registry mirror. # defaults to undef +# # [*mounts*] # Allows attacking filesystem mounts to the service (specified as an array) # defaults to [] diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index 302ac5a8..abbbb343 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -41,6 +41,20 @@ it { should contain_exec('test_service docker service create').with_command(/docker service create/) } it { should contain_exec('test_service_2 docker service create').with_command(/docker service create/) } end + + context 'multiple publish ports' do + let(:pre_condition) { + " + docker::services { 'test_service_3': + service_name => 'foo_3', + image => 'foo:bar', + publish => ['80:8080', '9000:9000' ], + } + " + } + it { should contain_exec('test_service_3 docker service create').with_command(/--publish 80:8080/) } + it { should contain_exec('test_service_3 docker service create').with_command(/--publish 9000:9000/) } + end end context 'with ensure => present and service update' do From 059d8a803535896c727db67a5c5b06f3ea628099 Mon Sep 17 00:00:00 2001 From: esalberg Date: Mon, 4 Mar 2019 10:08:10 -0500 Subject: [PATCH 12/44] Add ability to override After for docker.service (#446) --- README.md | 7 ++++++- manifests/init.pp | 1 + manifests/params.pp | 6 ++++++ manifests/service.pp | 1 + spec/classes/docker_spec.rb | 5 +++++ .../docker.service.d/service-overrides-debian.conf.erb | 5 +++++ .../docker.service.d/service-overrides-rhel.conf.erb | 5 +++++ 7 files changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a0335a7..7fe68d37 100755 --- a/README.md +++ b/README.md @@ -129,6 +129,8 @@ class { 'docker': } ``` +For more information about the configuration options for the default docker bridge, see the [Docker documentation](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/). + The default group ownership of the Unix control socket differs based on OS. For example, on RHEL using docker-ce packages >=18.09.1, the socket file used by /usr/lib/systemd/system/docker.socket is owned by the docker group. To override this value in /etc/sysconfig/docker and docker.socket (e.g. to use the 'root' group): ```puppet @@ -144,8 +146,11 @@ The socket_group parameter also takes a boolean for legacy cases where setting - docker::socket_group: false ``` -For more information about the configuration options for the default docker bridge, see the [Docker documentation](https://docs.docker.com/v17.09/engine/userguide/networking/default_network/custom-docker0/). +To add another service to the After= line in the [Unit] section of the systemd /etc/systemd/system/service-overrides.conf file, use the service_after_override parameter: +```puppet +docker::service_after_override: containerd.service +``` When setting up TLS, upload the related files (CA certificate, server certificate, and key) and include their paths in the manifest file: diff --git a/manifests/init.pp b/manifests/init.pp index 0a4f43ef..c4fa6e5e 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -498,6 +498,7 @@ Variant[String,Boolean,Undef] $service_overrides_template = $docker::params::service_overrides_template, Variant[String,Boolean,Undef] $socket_overrides_template = $docker::params::socket_overrides_template, Optional[Boolean] $socket_override = $docker::params::socket_override, + Optional[String] $service_after_override = $docker::params::service_after_override, Optional[Boolean] $service_hasstatus = $docker::params::service_hasstatus, Optional[Boolean] $service_hasrestart = $docker::params::service_hasrestart, Optional[String] $registry_mirror = $docker::params::registry_mirror, diff --git a/manifests/params.pp b/manifests/params.pp index fe7dd98a..75453c91 100755 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -120,6 +120,7 @@ $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' $socket_override = false + $service_after_override = undef $service_hasstatus = true $service_hasrestart = true include docker::systemd_reload @@ -128,6 +129,7 @@ $service_overrides_template = undef $socket_overrides_template = undef $socket_override = false + $service_after_override = undef $service_provider = 'upstart' $service_hasstatus = true $service_hasrestart = false @@ -142,6 +144,7 @@ $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb' $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' $socket_override = false + $service_after_override = undef $service_hasstatus = true $service_hasrestart = true include docker::systemd_reload @@ -192,6 +195,7 @@ $service_overrides_template = 'docker/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb' $socket_overrides_template = 'docker/etc/systemd/system/docker.socket.d/socket-overrides.conf.erb' $socket_override = false + $service_after_override = undef $use_upstream_package_source = true $package_ce_source_location = "https://download.docker.com/linux/centos/${::operatingsystemmajrelease}/${::architecture}/${docker_ce_channel}" @@ -264,6 +268,7 @@ $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 @@ -292,6 +297,7 @@ $service_overrides_template = undef $socket_overrides_template = undef $socket_override = false + $service_after_override = undef $service_hasstatus = undef $service_hasrestart = undef $service_provider = undef diff --git a/manifests/service.pp b/manifests/service.pp index 0b57cce2..f2d75020 100755 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -108,6 +108,7 @@ $service_overrides_template = $docker::service_overrides_template, $socket_overrides_template = $docker::socket_overrides_template, $socket_override = $docker::socket_override, + $service_after_override = $docker::service_after_override, $service_hasstatus = $docker::service_hasstatus, $service_hasrestart = $docker::service_hasrestart, $daemon_environment_files = $docker::daemon_environment_files, diff --git a/spec/classes/docker_spec.rb b/spec/classes/docker_spec.rb index ecace1c5..ed727974 100755 --- a/spec/classes/docker_spec.rb +++ b/spec/classes/docker_spec.rb @@ -441,6 +441,11 @@ it { should contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(/docker.io/) } end + context 'with an extra After entry' do + let(:params) {{ 'service_after_override' => 'containerd.service' }} + it { should contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(/containerd.service/) } + end + context 'with a specific socket group and override' do let(:params) { { 'socket_group' => 'root', diff --git a/templates/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb b/templates/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb index a60a4778..d7463095 100644 --- a/templates/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb +++ b/templates/etc/systemd/system/docker.service.d/service-overrides-debian.conf.erb @@ -1,3 +1,8 @@ +<% if @service_after_override -%> +[Unit] +After=<%= @service_after_override %> + +<% end -%> [Service] EnvironmentFile=-/etc/default/docker EnvironmentFile=-/etc/default/docker-storage diff --git a/templates/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb b/templates/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb index 071b44a7..2313e93c 100644 --- a/templates/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb +++ b/templates/etc/systemd/system/docker.service.d/service-overrides-rhel.conf.erb @@ -1,3 +1,8 @@ +<% if @service_after_override -%> +[Unit] +After=<%= @service_after_override %> + +<% end -%> [Service] EnvironmentFile=-/etc/sysconfig/docker EnvironmentFile=-/etc/sysconfig/docker-storage From 226be6c1a2b6bf27a52e0a959726a0f15190cdfb Mon Sep 17 00:00:00 2001 From: esalberg Date: Fri, 8 Mar 2019 14:27:46 -0500 Subject: [PATCH 13/44] Add ability to set service_after_override to false (#448) --- manifests/init.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/init.pp b/manifests/init.pp index c4fa6e5e..eb48a626 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -498,7 +498,7 @@ Variant[String,Boolean,Undef] $service_overrides_template = $docker::params::service_overrides_template, Variant[String,Boolean,Undef] $socket_overrides_template = $docker::params::socket_overrides_template, Optional[Boolean] $socket_override = $docker::params::socket_override, - Optional[String] $service_after_override = $docker::params::service_after_override, + Variant[String,Boolean,Undef] $service_after_override = $docker::params::service_after_override, Optional[Boolean] $service_hasstatus = $docker::params::service_hasstatus, Optional[Boolean] $service_hasrestart = $docker::params::service_hasrestart, Optional[String] $registry_mirror = $docker::params::registry_mirror, From 15ee0e43a8eeb487feb0baeabf8bbebddf09d213 Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 8 Mar 2019 20:33:04 +0100 Subject: [PATCH 14/44] Docker::Services: Add networks parameter for swarm services (#450) Allows attaching the service to one or multiple networks --- lib/puppet/parser/functions/docker_service_flags.rb | 6 ++++++ manifests/services.pp | 8 +++++++- spec/defines/services_spec.rb | 7 ++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/puppet/parser/functions/docker_service_flags.rb b/lib/puppet/parser/functions/docker_service_flags.rb index 3ca2713b..bd467ba2 100644 --- a/lib/puppet/parser/functions/docker_service_flags.rb +++ b/lib/puppet/parser/functions/docker_service_flags.rb @@ -36,6 +36,12 @@ module Puppet::Parser::Functions end end + if opts['networks'].is_a? Array + opts['networks'].each do |network| + flags << "--network #{network}" + end + end + if opts['publish'].is_a? Array opts['publish'].each do |port| flags << "--publish #{port}" diff --git a/manifests/services.pp b/manifests/services.pp index 937a4a1b..5ea908fe 100644 --- a/manifests/services.pp +++ b/manifests/services.pp @@ -68,7 +68,11 @@ # defaults to undef # # [*mounts*] -# Allows attacking filesystem mounts to the service (specified as an array) +# Allows attaching filesystem mounts to the service (specified as an array) +# defaults to [] +# +# [*networks*] +# Allows attaching the service to networks (specified as an array) # defaults to [] # # [*command*] @@ -94,6 +98,7 @@ Variant[String,Array,Undef] $host_socket = undef, Variant[String,Array,Undef] $registry_mirror = undef, Variant[String,Array,Undef] $mounts = undef, + Variant[Array,Undef] $networks = undef, Variant[String,Array,Undef] $command = undef, ){ @@ -138,6 +143,7 @@ host_socket => $host_socket, registry_mirror => $registry_mirror, mounts => $mounts, + networks => $networks, command => $command, }) diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index abbbb343..0e257481 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -22,12 +22,14 @@ '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'], } } it { is_expected.to compile.with_all_deps } it { should contain_exec('test_service docker service create').with_command(/docker service create/) } it { should contain_exec('test_service docker service create').with_command(/--env MY_ENV=1/) } it { should contain_exec('test_service docker service create').with_command(/--label bar=baz/) } it { should contain_exec('test_service docker service create').with_command(/--mount type=bind,src=\/tmp\/b,dst=\/tmp\/b,readonly/) } + it { should contain_exec('test_service docker service create').with_command(/--network overlay/) } context 'multiple services declaration' do let(:pre_condition) { @@ -42,18 +44,21 @@ it { should contain_exec('test_service_2 docker service create').with_command(/docker service create/) } end - context 'multiple publish ports' do + context 'multiple publish ports and multiple networks' do let(:pre_condition) { " docker::services { 'test_service_3': service_name => 'foo_3', image => 'foo:bar', publish => ['80:8080', '9000:9000' ], + networks => ['foo_1', 'foo_2'], } " } it { should contain_exec('test_service_3 docker service create').with_command(/--publish 80:8080/) } it { should contain_exec('test_service_3 docker service create').with_command(/--publish 9000:9000/) } + it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_1/) } + it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_2/) } end end From fb2d756fcb582b8aefcca29031dfb7905c952bc3 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 11 Mar 2019 12:16:16 +0100 Subject: [PATCH 15/44] Docker::Services:: fix command parameter used with an array (#452) The module previously allowed specifying the command parameter to docker::services as an array, but did not correctly parse it as such (output with square brackets and quotations marks to docker). This patch fixes this behavior. --- README.md | 3 ++- lib/puppet/parser/functions/docker_service_flags.rb | 4 +++- spec/defines/services_spec.rb | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7fe68d37..8128232a 100755 --- a/README.md +++ b/README.md @@ -801,10 +801,11 @@ docker::services {'redis': replicas => '5', mounts => ['type=bind,source=/etc/my-redis.conf,target=/etc/redis/redis.conf,readonly'], extra_params => ['--update-delay 1m', '--restart-window 30s'], + command => ['redis-server', '--appendonly', 'yes'], } ``` -To base the service off an image, include the `image` parameter and include the `publish` parameter to expose the service port (use an array to specify multiple published ports). To set the amount of containers running in the service, include the `replicas` parameter. To attach one or multiple filesystems to the service, use the `mounts` parameter. For information regarding the `extra_params` parameter, see `docker service create --help`. +To base the service off an image, include the `image` parameter and include the `publish` parameter to expose the service port (use an array to specify multiple published ports). To set the amount of containers running in the service, include the `replicas` parameter. To attach one or multiple filesystems to the service, use the `mounts` parameter. For information regarding the `extra_params` parameter, see `docker service create --help`. The `command` parameter can either be specified as an array or a string. To update the service, add the following code to the manifest file: diff --git a/lib/puppet/parser/functions/docker_service_flags.rb b/lib/puppet/parser/functions/docker_service_flags.rb index bd467ba2..e9148b5e 100644 --- a/lib/puppet/parser/functions/docker_service_flags.rb +++ b/lib/puppet/parser/functions/docker_service_flags.rb @@ -84,7 +84,9 @@ module Puppet::Parser::Functions flags << "'#{opts['image']}'" end - if opts['command'] && opts['command'].to_s != 'undef' + if opts['command'].is_a? Array + flags << opts['command'].join(' ') + elsif opts['command'] && opts['command'].to_s != 'undef' flags << opts['command'].to_s end diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index 0e257481..e35fdff3 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -23,6 +23,7 @@ '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', } } it { is_expected.to compile.with_all_deps } it { should contain_exec('test_service docker service create').with_command(/docker service create/) } @@ -30,6 +31,7 @@ it { should contain_exec('test_service docker service create').with_command(/--label bar=baz/) } it { should contain_exec('test_service docker service create').with_command(/--mount type=bind,src=\/tmp\/b,dst=\/tmp\/b,readonly/) } it { should contain_exec('test_service docker service create').with_command(/--network overlay/) } + it { should contain_exec('test_service docker service create').with_command(/echo hello world/) } context 'multiple services declaration' do let(:pre_condition) { @@ -37,11 +39,13 @@ docker::services { 'test_service_2': service_name => 'foo_2', image => 'foo:bar', + command => ['echo', 'hello', 'world'], } " } it { should contain_exec('test_service docker service create').with_command(/docker service create/) } it { should contain_exec('test_service_2 docker service create').with_command(/docker service create/) } + it { should contain_exec('test_service_2 docker service create').with_command(/echo hello world/) } end context 'multiple publish ports and multiple networks' do @@ -60,6 +64,7 @@ it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_1/) } it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_2/) } end + end context 'with ensure => present and service update' do From 1352bb63d676d30d041d10aede106a2815922b33 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Mon, 11 Mar 2019 08:27:47 -0500 Subject: [PATCH 16/44] making dependency ranges more logical (#453) --- metadata.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/metadata.json b/metadata.json index 9cada146..2f1c2d8d 100755 --- a/metadata.json +++ b/metadata.json @@ -10,23 +10,23 @@ "dependencies": [ { "name": "puppetlabs/stdlib", - "version_requirement": ">= 4.24.0 <= 5.1.0" + "version_requirement": ">= 4.24.0 < 6.0.0" }, { "name": "puppetlabs/apt", - "version_requirement": ">= 4.4.1 <= 6.2.1" + "version_requirement": ">= 4.4.1 < 7.0.0" }, { "name": "puppetlabs/translate", - "version_requirement": ">= 0.0.1 <=1.2.0" + "version_requirement": ">= 0.0.1 < 2.0.0" }, { "name": "puppetlabs/powershell", - "version_requirement": ">= 2.1.4 <= 2.2.0" + "version_requirement": ">= 2.1.4 < 3.0.0" }, { "name": "puppetlabs/reboot", - "version_requirement": ">=2.0.0 <= 2.1.2" + "version_requirement": ">=2.0.0 < 3.0.0" } ], "operatingsystem_support": [ From c8b59023dacf06bbb3f5e692f09f2793cd55b829 Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Tue, 12 Mar 2019 08:07:49 -0500 Subject: [PATCH 17/44] adding in capability to attach multiple networks to container (#451) --- README.md | 2 +- lib/puppet/parser/functions/docker_run_flags.rb | 2 +- manifests/run.pp | 16 +++++++++++----- spec/defines/run_spec.rb | 8 +++++++- templates/docker-run-start.erb | 5 +++++ 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8128232a..aa36fef6 100755 --- a/README.md +++ b/README.md @@ -379,7 +379,7 @@ docker::run { 'helloworld': ports => ['4444', '4555'], expose => ['4666', '4777'], links => ['mysql:db'], - net => 'my-user-def-net', + net => ['my-user-def-net','my-user-def-net-2], disable_network => false, volumes => ['/var/lib/couchdb', '/var/log'], volumes_from => '6446ea52fbc9', diff --git a/lib/puppet/parser/functions/docker_run_flags.rb b/lib/puppet/parser/functions/docker_run_flags.rb index d69812f9..1e457fda 100644 --- a/lib/puppet/parser/functions/docker_run_flags.rb +++ b/lib/puppet/parser/functions/docker_run_flags.rb @@ -22,7 +22,7 @@ module Puppet::Parser::Functions flags << "--restart '#{opts['restart']}'" end - if opts['net'] + if opts['net'].is_a? String flags << "--net #{opts['net']}" end diff --git a/manifests/run.pp b/manifests/run.pp index 82406f05..b5e0056e 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -49,18 +49,24 @@ # Default: false # # [*health_check_cmd*] -# (optional) Specifies the command to execute to check that the container is healthy using the docker health check functionality. +# (optional) Specifies the command to execute to check that the container is healthy using the docker health check functionality. # Default: undef # # [*health_check_interval*] # (optional) Specifies the interval that the health check command will execute in seconds. -# Default: undef +# Default: undef # # [*restart_on_unhealthy*] # (optional) Checks the health status of Docker container and if it is unhealthy the service will be restarted. # The health_check_cmd parameter must be set to true to use this functionality. # Default: undef # +# [*net*] +# +# The docker network to attach to a container. +# Can be a String or Array (if using multiple networks) +# Default: bridge +# # [*extra_parameters*] # An array of additional command line arguments to pass to the `docker run` # command. Useful for adding additional new or experimental options that the @@ -94,7 +100,7 @@ Optional[Boolean] $use_name = false, Optional[Boolean] $running = true, Variant[String,Array,Undef] $volumes_from = [], - Optional[String] $net = 'bridge', + Variant[String,Array] $net = 'bridge', Variant[String,Boolean] $username = false, Variant[String,Boolean] $hostname = false, Variant[String,Array,Undef] $env = [], @@ -305,7 +311,7 @@ if $running == false { exec { "stop ${title} with docker": command => "${docker_command} stop --time=${stop_wait_time} ${sanitised_title}", - unless => "${docker_command} inspect ${sanitised_title} -f \"{{ if (.State.Running) }} {{ nil }}{{ end }}\"", + unless => "${docker_command} inspect ${sanitised_title} -f \"{{ .State.Running }}\" | grep true", environment => $exec_environment, path => $exec_path, provider => $exec_provider, @@ -314,7 +320,7 @@ } else { exec { "start ${title} with docker": command => "${docker_command} start ${sanitised_title}", - onlyif => "${docker_command} inspect ${sanitised_title} -f \"{{ if (.State.Running) }} {{ nil }}{{ end }}\"", + onlyif => "${docker_command} inspect ${sanitised_title} -f \"{{ .State.Running }}\" | grep false", environment => $exec_environment, path => $exec_path, provider => $exec_provider, diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index 1d86c3ad..06119a3a 100755 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -416,11 +416,17 @@ it { should contain_file(startscript_or_init).with_content(/-v \/var\/log/) } end - context 'when using network mode' do + context 'when using network mode with a single network' do let(:params) { {'command' => 'command', 'image' => 'nginx', 'net' => 'host'} } it { should contain_file(startscript_or_init).with_content(/--net host/) } end + context 'when using network mode with multiple networks' do + let(:params) { {'command' => 'command', 'image' => 'nginx', 'net' => ['host','foo']} } + it { should contain_file(startscript_or_init).with_content(/docker network connect host sample/) } + it { should contain_file(startscript_or_init).with_content(/docker network connect foo sample/) } + end + context 'when `pull_on_start` is true' do let(:params) { {'command' => 'command', 'image' => 'base', 'pull_on_start' => true } } it { should contain_file(startscript_or_init).with_content(/docker pull base/) } diff --git a/templates/docker-run-start.erb b/templates/docker-run-start.erb index 2c19198c..4ae99e8d 100644 --- a/templates/docker-run-start.erb +++ b/templates/docker-run-start.erb @@ -16,5 +16,10 @@ <% if @command %> <%= @command %><% end %> <% if @after_create %><%= @after_create %><% end %> +<% if @net.is_a? Array%> + <% @net.each do |n| %> +/usr/bin/<%= @docker_command %> network connect <%= n %> <%= @sanitised_title %> + <% end %> +<% end %> /usr/bin/<%= @docker_command %> start <% if ! @valid_detach %>-a<% end %> <%= @sanitised_title %> From 84e8edc3f660fe97b170ee6d6c2e3a9b7a422be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= Date: Wed, 13 Mar 2019 12:28:00 +0100 Subject: [PATCH 18/44] fix(syntax): Remove duplicate parenthesis (#454) --- manifests/plugin.pp | 2 +- manifests/run.pp | 8 ++++---- manifests/services.pp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifests/plugin.pp b/manifests/plugin.pp index f3b64571..0eef3636 100644 --- a/manifests/plugin.pp +++ b/manifests/plugin.pp @@ -65,7 +65,7 @@ $docker_command = "${docker::params::docker_command} plugin" if ($::osfamily == 'windows') { - fail(translate(('Feature not implemented on windows.'))) + fail(translate('Feature not implemented on windows.')) } if $ensure == 'present' { diff --git a/manifests/run.pp b/manifests/run.pp index b5e0056e..db87c09a 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -158,11 +158,11 @@ } if ($remove_volume_on_start and !$remove_container_on_start) { - fail translate(("In order to remove the volume on start for ${title} you need to also remove the container")) + fail(translate("In order to remove the volume on start for ${title} you need to also remove the container")) } if ($remove_volume_on_stop and !$remove_container_on_stop) { - fail translate(("In order to remove the volume on stop for ${title} you need to also remove the container")) + fail(translate("In order to remove the volume on stop for ${title} you need to also remove the container")) } if $use_name { @@ -352,10 +352,10 @@ } default: { if $::osfamily != 'windows' { - fail translate(('Docker needs a Debian or RedHat based system.')) + fail(translate('Docker needs a Debian or RedHat based system.')) } elsif $ensure == 'present' { - fail translate(('Restart parameter is required for Windows')) + fail(translate('Restart parameter is required for Windows')) } } } diff --git a/manifests/services.pp b/manifests/services.pp index 5ea908fe..b6ea3c3c 100644 --- a/manifests/services.pp +++ b/manifests/services.pp @@ -108,10 +108,10 @@ if $ensure == 'absent' { if $update { - fail translate(('When removing a service you can not update it.')) + fail(translate('When removing a service you can not update it.')) } if $scale { - fail translate(('When removing a service you can not update it.')) + fail(translate('When removing a service you can not update it.')) } } From e59ec60b6ff686732764d52cd51216fe3fe971eb Mon Sep 17 00:00:00 2001 From: davejrt <2067825+davejrt@users.noreply.github.com> Date: Thu, 14 Mar 2019 07:17:08 -0500 Subject: [PATCH 19/44] release 3.5.0 (#458) --- CHANGELOG.md | 12 ++++++++++++ metadata.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80f7b8ff..62ad54b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 3.5.0 + +Changes range for dependent modules + +Use multiple networks in docker::run and docker::services + +Fixes quotes with docker::services command + +Publish multiple ports to docker::services + +A full list of issues and PRs associated with this release can be found [here](https://github.com/puppetlabs/puppetlabs-docker/milestone/7?closed=1) + # 3.4.0 Introduces docker_stack type and provider diff --git a/metadata.json b/metadata.json index 2f1c2d8d..f3904ccc 100755 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-docker", - "version": "3.4.0", + "version": "3.5.0", "author": "Puppet Labs", "summary": "Module for installing and managing docker", "license": "Apache-2.0", From ddd99ac4439e867010356b5274fdc94c004719c0 Mon Sep 17 00:00:00 2001 From: acurus-puppetmaster Date: Tue, 19 Mar 2019 09:51:18 +1100 Subject: [PATCH 20/44] Update readme for aws logging options (#459) * wip: updated README to include aws logging option details added in pull request #354 * wip: corrected formatting * wip: corrected formatting --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aa36fef6..d990e3e1 100755 --- a/README.md +++ b/README.md @@ -1271,6 +1271,7 @@ Valid values: * `gelf`: Graylog Extended Log Format (GELF) logging driver that writes log messages to a GELF endpoint: Graylog or Logstash. * `fluentd`: fluentd logging driver that writes log messages to fluentd (forward input). * `splunk`: Splunk logging driver that writes log messages to Splunk (HTTP Event Collector). +* `awslogs`: AWS Cloudwatch logging driver that writes log messages to a AWS Cloudwatch LogStream #### `log_opt` @@ -1287,6 +1288,7 @@ Valid values: * `gelf`: gelf-address=udp://host:port, gelf-tag="some_tag" * `fluentd`: fluentd-address=host:port, fluentd-tag={{.ID}} - short container id (12 characters), {{.FullID}} - full container id, {{.Name}} - container name * `splunk`: splunk-token=, splunk-url=https://your_splunk_instance:8088| +* `awslogs`: awslogs-group=, awslogs-stream=, awslogs-create-group=true|false, awslogs-datetime-format=, awslog-multiline-pattern=, tag={{.ID}} - short container id (12 characters), {{.FullID}} - full container id, {{.Name}} - container name #### `selinux_enabled` From e01a33fbfded519f543a2863b53e2b8e6b1c3919 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Tue, 2 Apr 2019 12:54:53 +0100 Subject: [PATCH 21/44] Allow images tagged latest to update on each run Restore the code to update images tagged with 'latest' on each run, moving this to be guarded by a refreshonly meta-parameter that is triggered by a notify resource that is disabled for 'noop'. Because the original code to update images was run via 'onlyif' to indicate if the image was in sync by performing a pull and testing the new digest against the old, this meant that simply applying 'noop' to this exec resource would not work. 'noop' does not affect running the components of a resource to validate if it is in-sync, which is the purpose of the 'onlyif' & 'unless' settings for an exec. To support 'noop' mode, previously the code to update the image on each run was dropped to prevent it accidentally refreshing the local image and then skipping an image restart because there was no update event on a subsequent real run. To resolve, it is necessary to have a prior resource that is used as a proxy, and only when it notifies the image update resource, will the 'onlyif' action be tested to determine if in sync. This prior resource can be disabled from a noop run, and subsequently although puppet records that it would send a refresh event in 'noop' mode, none are actually sent during a 'noop' run thus preventing the image from being updated by a side effect of checking if the notified exec was in-sync. Fixes #316 --- manifests/image.pp | 16 +++++++++++++++- spec/defines/image_spec.rb | 6 +++--- spec/defines/image_windows_spec.rb | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/manifests/image.pp b/manifests/image.pp index c19f1d69..b3364313 100644 --- a/manifests/image.pp +++ b/manifests/image.pp @@ -140,7 +140,21 @@ timeout => $exec_timeout, logoutput => true, } - } elsif $ensure == 'latest' or $image_tag == 'latest' or $ensure == 'present' { + } elsif $ensure == 'latest' or $image_tag == 'latest' { + notify { "Check if image ${image_arg} is in-sync": + noop => false, + } + ~> exec { "echo 'Update of ${image_arg} complete'": + environment => $exec_environment, + path => $exec_path, + timeout => $exec_timeout, + onlyif => $image_install, + require => File[$update_docker_image_path], + provider => $exec_provider, + logoutput => true, + refreshonly => true, + } + } elsif $ensure == 'present' { exec { $image_install: unless => $_image_find, environment => $exec_environment, diff --git a/spec/defines/image_spec.rb b/spec/defines/image_spec.rb index 6bc22bf1..0d029817 100644 --- a/spec/defines/image_spec.rb +++ b/spec/defines/image_spec.rb @@ -134,17 +134,17 @@ context 'with ensure => latest' do let(:params) { { 'ensure' => 'latest' } } - it { should contain_exec("/usr/local/bin/update_docker_image.sh base") } + it { should contain_exec("echo 'Update of base complete'").with_onlyif('/usr/local/bin/update_docker_image.sh base') } end context 'with ensure => latest and image_tag => precise' do let(:params) { { 'ensure' => 'latest', 'image_tag' => 'precise' } } - it { should contain_exec("/usr/local/bin/update_docker_image.sh base:precise") } + it { should contain_exec("echo 'Update of base:precise complete'") } end context 'with ensure => latest and image_digest => sha256:deadbeef' do let(:params) { { 'ensure' => 'latest', 'image_digest' => 'sha256:deadbeef' } } - it { should contain_exec("/usr/local/bin/update_docker_image.sh base@sha256:deadbeef") } + it { should contain_exec("echo 'Update of base@sha256:deadbeef complete'") } end context 'with an invalid image name' do diff --git a/spec/defines/image_windows_spec.rb b/spec/defines/image_windows_spec.rb index c3f55666..7bd33762 100644 --- a/spec/defines/image_windows_spec.rb +++ b/spec/defines/image_windows_spec.rb @@ -48,7 +48,7 @@ context 'with ensure => latest' do let(:params) { { 'ensure' => 'latest' } } - it { should contain_exec("& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base") } + it { should contain_exec("echo 'Update of base complete'").with_onlyif('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base') } end end \ No newline at end of file From d4dac109b72c4d487cb4b24b1d941533686bf378 Mon Sep 17 00:00:00 2001 From: hugotanure Date: Wed, 3 Apr 2019 15:24:44 -0300 Subject: [PATCH 22/44] Fix docker::image to not run images (#465) --- manifests/image.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/image.pp b/manifests/image.pp index c19f1d69..282097fe 100644 --- a/manifests/image.pp +++ b/manifests/image.pp @@ -153,5 +153,5 @@ } } - Docker::Image <| title == $title |> -> Docker::Run <| image == $image_arg |> + Docker::Image <| title == $title |> } From 043395e267e4c3b4545eff7298b579d5338abbba Mon Sep 17 00:00:00 2001 From: acurus-puppetmaster Date: Mon, 8 Apr 2019 19:05:06 +1000 Subject: [PATCH 23/44] Introduced docker machine support (#466) Fix test cases, class and readme Removed travis customisation --- README.md | 21 ++++ manifests/machine.pp | 100 ++++++++++++++++++ manifests/params.pp | 3 + spec/classes/compose_spec.rb | 4 +- spec/classes/machine_spec.rb | 88 +++++++++++++++ .../windows/download_docker_machine.ps1.erb | 23 ++++ 6 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 manifests/machine.pp create mode 100644 spec/classes/machine_spec.rb create mode 100644 templates/windows/download_docker_machine.ps1.erb diff --git a/README.md b/README.md index d990e3e1..2c8320f0 100755 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ * [Networks](#networks) * [Volumes](#volumes) * [Compose](#compose) + * [Machine](#machine) * [Swarm mode](#swarm-mode) * [Tasks](#tasks) * [Docker services](#docker-services) @@ -684,6 +685,25 @@ docker_stack { 'test': To remove the stack, set `ensure => absent`. +### Machine + +Docker Machine is a tool that lets you install Docker Engine on virtual hosts, and manage the hosts with docker-machine commands. You can use Machine to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or Digital Ocean. + +For more information on machines see the [Docker Machines](https://docs.docker.com/machine/) documentation. + +This module only takes responsability for installing the Docker Machine utility. + +To install Docker Machine, add the following code to the manifest file: + +```puppet +class {'docker::machine': + ensure => present, + version => '1.16.1', +} +``` + +Set the `version` parameter to any version you need to install. + ### Swarm mode To natively manage a cluster of Docker Engines known as a swarm, Docker Engine 1.12 includes a swarm mode. @@ -969,6 +989,7 @@ docker::plugin {'foo/fooplugin:latest' * docker * docker::compose * docker::images +* docker::machine * docker::networks * docker::params * docker::plugins diff --git a/manifests/machine.pp b/manifests/machine.pp new file mode 100644 index 00000000..795e874c --- /dev/null +++ b/manifests/machine.pp @@ -0,0 +1,100 @@ +# == Class: docker::machine +# +# Class to install Docker Machine using the recommended curl command. +# +# === Parameters +# +# [*ensure*] +# Whether to install or remove Docker Machine +# Valid values are absent present +# Defaults to present +# +# [*version*] +# The version of Docker Machine to install. +# Defaults to the value set in $docker::params::machine_version +# +# [*install_path*] +# The path where to install Docker Machine. +# Defaults to the value set in $docker::params::machine_install_path +# +# [*proxy*] +# Proxy to use for downloading Docker Machine. +# +class docker::machine( + Optional[Pattern[/^present$|^absent$/]] $ensure = 'present', + Optional[String] $version = $docker::params::machine_version, + Optional[String] $install_path = $docker::params::machine_install_path, + Optional[String] $proxy = undef +) inherits docker::params { + + if $proxy != undef { + validate_re($proxy, '^((http[s]?)?:\/\/)?([^:^@]+:[^:^@]+@|)([\da-z\.-]+)\.([\da-z\.]{2,6})(:[\d])?([\/\w \.-]*)*\/?$') + } + + if $::osfamily == 'windows' { + $file_extension = '.exe' + $file_owner = 'Administrator' + } else { + $file_extension = '' + $file_owner = 'root' + } + + $docker_machine_location = "${install_path}/docker-machine${file_extension}" + $docker_machine_location_versioned = "${install_path}/docker-machine-${version}${file_extension}" + + if $ensure == 'present' { + $docker_machine_url = "https://github.com/docker/machine/releases/download/v${version}/docker-machine-${::kernel}-x86_64${file_extension}" + + if $proxy != undef { + $proxy_opt = "--proxy ${proxy}" + } else { + $proxy_opt = '' + } + + if $::osfamily == 'windows' { +# lint:ignore:140chars + $docker_download_command = "if (Invoke-WebRequest ${docker_machine_url} ${proxy_opt} -UseBasicParsing -OutFile \"${docker_machine_location_versioned}\") { exit 0 } else { exit 1}" +# lint:endignore + + exec { "Install Docker Machine ${version}": + command => template('docker/windows/download_docker_machine.ps1.erb'), + provider => powershell, + creates => $docker_machine_location_versioned, + } + + file { $docker_machine_location: + ensure => 'link', + target => $docker_machine_location_versioned, + require => Exec["Install Docker Machine ${version}"] + } + } else { + ensure_packages(['curl']) + exec { "Install Docker Machine ${version}": + 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, + require => Package['curl'], + } + + file { $docker_machine_location_versioned: + owner => $file_owner, + mode => '0755', + require => Exec["Install Docker Machine ${version}"] + } + + file { $docker_machine_location: + ensure => 'link', + target => $docker_machine_location_versioned, + require => File[$docker_machine_location_versioned] + } + } + } else { + file { [ + $docker_machine_location_versioned, + $docker_machine_location + ]: + ensure => absent, + } + } +} diff --git a/manifests/params.pp b/manifests/params.pp index 75453c91..b8df7279 100755 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -30,13 +30,16 @@ $tls_key = "${::docker_program_data_path}/docker/certs.d/server-key.pem" $compose_version = '1.21.2' $compose_install_path = "${::docker_program_files_path}/Docker" + $machine_install_path = "${::docker_program_files_path}/Docker" } else { $tls_cacert = '/etc/docker/tls/ca.pem' $tls_cert = '/etc/docker/tls/cert.pem' $tls_key = '/etc/docker/tls/key.pem' $compose_version = '1.9.0' $compose_install_path = '/usr/local/bin' + $machine_install_path = '/usr/local/bin' } + $machine_version = '0.16.1' $ip_forward = true $iptables = true $ipv6 = false diff --git a/spec/classes/compose_spec.rb b/spec/classes/compose_spec.rb index d241d2fe..100359ad 100644 --- a/spec/classes/compose_spec.rb +++ b/spec/classes/compose_spec.rb @@ -69,8 +69,8 @@ end context 'when proxy contains username and password' do - let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', - :version => '1.7.0'} } + let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', + :version => '1.7.0'} } it { is_expected.to compile } it { is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0') diff --git a/spec/classes/machine_spec.rb b/spec/classes/machine_spec.rb new file mode 100644 index 00000000..6c4a35d4 --- /dev/null +++ b/spec/classes/machine_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' + +describe 'docker::machine', :type => :class do + let(:facts) do + { + :kernel => 'Linux', + :osfamily => 'Debian', + :operatingsystem => 'Ubuntu', + :lsbdistid => 'Ubuntu', + :lsbdistcodename => 'maverick', + :kernelrelease => '3.8.0-29-generic', + :operatingsystemrelease => '10.04', + :operatingsystemmajrelease => '10', + } + end + + it { is_expected.to compile } + + context 'with defaults for all parameters' do + it { should compile.with_all_deps } + it { should contain_exec('Install Docker Machine 0.16.1').with( + 'path' => '/usr/bin/', + 'cwd' => '/tmp', + 'command' => 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.1/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.1', + 'creates' => '/usr/local/bin/docker-machine-0.16.1', + 'require' => 'Package[curl]' + )} + it { should contain_file('/usr/local/bin/docker-machine-0.16.1').with( + 'owner' => 'root', + 'mode' => '0755', + 'require' => 'Exec[Install Docker Machine 0.16.1]' + )} + it { should contain_file('/usr/local/bin/docker-machine').with( + 'ensure' => 'link', + 'target' => '/usr/local/bin/docker-machine-0.16.1', + 'require' => 'File[/usr/local/bin/docker-machine-0.16.1]' + )} + end + + context 'with ensure => absent' do + let (:params) { { :ensure => 'absent' } } + it { should contain_file('/usr/local/bin/docker-machine-0.16.1').with_ensure('absent') } + it { should contain_file('/usr/local/bin/docker-machine').with_ensure('absent') } + end + + context 'when no proxy is provided' do + let(:params) { {:version => '0.16.0'} } + it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + } + end + + context 'when proxy is provided' do + let(:params) { {:proxy => 'http://proxy.example.org:3128/', + :version => '0.16.0'} } + it { is_expected.to compile } + it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://proxy.example.org:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + } + end + + context 'when proxy is not a http proxy' do + let(:params) { {:proxy => 'this is not a URL'} } + it do + expect { + is_expected.to compile + }.to raise_error(/does not match/) + end + end + + context 'when proxy contains username and password' do + let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', + :version => '0.16.0'} } + it { is_expected.to compile } + it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + } + end + + context 'when proxy IP is provided' do + let(:params) { {:proxy => 'http://10.10.10.10:3128/', + :version => '0.16.0'} } + it { is_expected.to compile } + it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://10.10.10.10:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + } + end +end diff --git a/templates/windows/download_docker_machine.ps1.erb b/templates/windows/download_docker_machine.ps1.erb new file mode 100644 index 00000000..229dd6b9 --- /dev/null +++ b/templates/windows/download_docker_machine.ps1.erb @@ -0,0 +1,23 @@ +try { +$WebClient = New-Object System.Net.WebClient +<%if @proxy %> +$uri = New-Object Uri("<%= @proxy %>") +if ($uri.UserInfo -eq $null) { + $WebProxy = New-Object System.Net.WebProxy("<%= @proxy %>",$true) + $WebClient.Proxy = $WebProxy +} +else { + $user,$password = $uri.UserInfo -split (':') + $proxyAddress = $uri.Scheme + "://" + $uri.Host + ":" + $uri.Port + $uri.PathAndQuery + $WebProxy = New-Object System.Net.WebProxy($uri,$true) + $WebClient.Proxy = $WebProxy + $WebClient.Proxy.Credentials = New-Object System.Net.NetworkCredential($user, $password) +} +<% end %> + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + $WebClient.DownloadFile("<%= @docker_machine_url %>","<%= @docker_machine_location_versioned %>") +} +catch { + exit 1 +} +exit 0 \ No newline at end of file From e9f906cb7cbd114e28a67be2ec0e985f4c53c9b6 Mon Sep 17 00:00:00 2001 From: Seth Hayward <37913900+twistedduck@users.noreply.github.com> Date: Tue, 9 Apr 2019 07:51:48 +0000 Subject: [PATCH 24/44] Fix publish flag being erroneously added to docker service commands (#471) --- lib/puppet/parser/functions/docker_service_flags.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/parser/functions/docker_service_flags.rb b/lib/puppet/parser/functions/docker_service_flags.rb index e9148b5e..9d0f3147 100644 --- a/lib/puppet/parser/functions/docker_service_flags.rb +++ b/lib/puppet/parser/functions/docker_service_flags.rb @@ -46,7 +46,7 @@ module Puppet::Parser::Functions opts['publish'].each do |port| flags << "--publish #{port}" end - elsif opts['publish'].to_s != 'undef' + elsif opts['publish'] && opts['publish'].to_s != 'undef' flags << "--publish '#{opts['publish']}'" end From 0506ec8bd7deb988705a2e10f177a3486f4777b4 Mon Sep 17 00:00:00 2001 From: Florin Dragos Date: Mon, 8 Apr 2019 17:58:29 +0300 Subject: [PATCH 25/44] Fix container running check to work for windows hosts --- manifests/run.pp | 6 ++++-- spec/defines/run_windows_spec.rb | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/manifests/run.pp b/manifests/run.pp index db87c09a..1f01f65a 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -240,6 +240,7 @@ $cidfile = "${::docker_user_temp_path}/${service_prefix}${sanitised_title}.cid" # lint:ignore:140chars $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 }" # lint:endignore } else { $exec_environment = 'HOME=/root' @@ -249,6 +250,7 @@ $cidfile = "/var/run/${service_prefix}${sanitised_title}.cid" # lint:ignore:140chars $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" # lint:endignore } @@ -311,7 +313,7 @@ if $running == false { exec { "stop ${title} with docker": command => "${docker_command} stop --time=${stop_wait_time} ${sanitised_title}", - unless => "${docker_command} inspect ${sanitised_title} -f \"{{ .State.Running }}\" | grep true", + onlyif => $container_running_check, environment => $exec_environment, path => $exec_path, provider => $exec_provider, @@ -320,7 +322,7 @@ } else { exec { "start ${title} with docker": command => "${docker_command} start ${sanitised_title}", - onlyif => "${docker_command} inspect ${sanitised_title} -f \"{{ .State.Running }}\" | grep false", + unless => $container_running_check, environment => $exec_environment, path => $exec_path, provider => $exec_provider, diff --git a/spec/defines/run_windows_spec.rb b/spec/defines/run_windows_spec.rb index 5f368653..03afa375 100755 --- a/spec/defines/run_windows_spec.rb +++ b/spec/defines/run_windows_spec.rb @@ -40,6 +40,7 @@ it { should contain_exec('run sample with docker').with_command(/--restart="always"/) } it { should contain_exec('run sample with docker').with_command(/base command/) } it { should contain_exec('run sample with docker').with_timeout(3000) } + it { should contain_exec('start sample with docker').with_command(/docker start sample/) } end context 'with restart policy set to on-failure' do @@ -82,6 +83,12 @@ it { should_not contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"')} end + context 'with ensure present and running false' do + let(:params) { {'ensure' => 'present', 'image' => 'base', 'restart' => 'always', 'running' => false} } + it { should compile.with_all_deps } + it { should contain_exec("stop sample with docker").with_command('docker stop --time=0 sample') } + end + context 'with ensure present and no restart policy' do let(:params) { {'ensure' => 'present', 'image' => 'base'} } it do From f9e4c88250ba5fcce6f9eee44a543f9261af171a Mon Sep 17 00:00:00 2001 From: Tobias Wolter Date: Tue, 16 Apr 2019 14:21:40 +0200 Subject: [PATCH 26/44] Add missing apostrophe in array. (#473) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c8320f0..c2b37545 100755 --- a/README.md +++ b/README.md @@ -380,7 +380,7 @@ docker::run { 'helloworld': ports => ['4444', '4555'], expose => ['4666', '4777'], links => ['mysql:db'], - net => ['my-user-def-net','my-user-def-net-2], + net => ['my-user-def-net','my-user-def-net-2'], disable_network => false, volumes => ['/var/lib/couchdb', '/var/log'], volumes_from => '6446ea52fbc9', From c36e36b74dbbddf65aae315e3f8928d733182f09 Mon Sep 17 00:00:00 2001 From: Florin Dragos Date: Tue, 16 Apr 2019 17:52:15 +0300 Subject: [PATCH 27/44] Fix supported operating systems in the readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c8320f0..8c17df04 100755 --- a/README.md +++ b/README.md @@ -1607,12 +1607,14 @@ Sanitises string or array of strings for safe usage as container name inside scr This module supports: +* Centos 7.0 * Debian 8.0 * Debian 9.0 +* RedHat 7.0 * Ubuntu 14.04 * Ubuntu 16.04 * Ubuntu 18.04 -* Centos 7.0 +* Windows Server 2016 (Docker Enterprise Edition only) ## Development From 4b57d04dc54397845e98134a66e874474630d23f Mon Sep 17 00:00:00 2001 From: "James T. Lee" Date: Wed, 20 Dec 2017 14:38:29 -0500 Subject: [PATCH 28/44] Add service_provider parameter to docker::run This module already has the code to support all systemd-based distributions, yet it is artificially locked to just Red Hat and Ubuntu/Debian. By exposing the `service_provider` parameter in the `docker::run` defined type (a parameter that is also exposed in the main `docker` class), this module becomes usable on most other distributions. Other minor fixes have been added to set missing variables when running under a non-Debian or non-RedHat operating system. --- manifests/init.pp | 15 ++- manifests/install.pp | 2 +- manifests/run.pp | 30 +++-- manifests/service.pp | 4 +- spec/defines/run_spec.rb | 229 +++++++++++++++++++-------------------- 5 files changed, 152 insertions(+), 128 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index eb48a626..1ccbbc0c 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -502,13 +502,14 @@ Optional[Boolean] $service_hasstatus = $docker::params::service_hasstatus, Optional[Boolean] $service_hasrestart = $docker::params::service_hasrestart, Optional[String] $registry_mirror = $docker::params::registry_mirror, + Boolean $acknowledge_unsupported_os = false, # Windows specific parameters Optional[String] $docker_msft_provider_version = $docker::params::docker_msft_provider_version, Optional[String] $nuget_package_provider_version = $docker::params::nuget_package_provider_version, ) inherits docker::params { - if $::osfamily { + if $::osfamily and !$acknowledge_unsupported_os { assert_type(Pattern[/^(Debian|RedHat|windows)$/], $::osfamily) |$a, $b| { fail(translate('This module only works on Debian, Red Hat or Windows based systems.')) } @@ -620,7 +621,11 @@ 'windows': { fail(translate('This module only work for Docker Enterprise Edition on Windows.')) } - default: {} + default: { + $package_location = $docker_package_location + $package_key_source = $docker_package_key_source + $package_key_check_source = $docker_package_key_check_source + } } $docker_start_command = $docker_ce_start_command $docker_package_name = $docker_ce_package_name @@ -640,7 +645,11 @@ $package_key_source = $docker_package_key_source $package_key_check_source = $docker_package_key_check_source } - default : {} + default : { + $package_location = $docker_package_location + $package_key_source = $docker_package_key_source + $package_key_check_source = $docker_package_key_check_source + } } $docker_start_command = $docker_engine_start_command $docker_package_name = $docker_engine_package_name diff --git a/manifests/install.pp b/manifests/install.pp index 542320e7..eb26b86b 100755 --- a/manifests/install.pp +++ b/manifests/install.pp @@ -30,7 +30,7 @@ ) { $docker_start_command = $docker::docker_start_command - if $::osfamily { + if $::osfamily and !::docker::acknowledge_unsupported_os { assert_type(Pattern[/^(Debian|RedHat|windows)$/], $::osfamily) |$a, $b| { fail(translate('This module only works on Debian, RedHat or Windows.')) } diff --git a/manifests/run.pp b/manifests/run.pp index 1f01f65a..d5f339fc 100755 --- a/manifests/run.pp +++ b/manifests/run.pp @@ -109,6 +109,7 @@ Variant[String,Array,Undef] $dns_search = [], Variant[String,Array,Undef] $lxc_conf = [], Optional[String] $service_prefix = 'docker-', + Optional[String] $service_provider = undef, Optional[Boolean] $restart_service = true, Optional[Boolean] $restart_service_on_docker_refresh = true, Optional[Boolean] $manage_service = true, @@ -176,8 +177,16 @@ assert_type(Pattern[/^(no|always|on-success|on-failure|on-abnormal|on-abort|on-watchdog)$/], $systemd_restart) } + $service_provider_real = $service_provider ? { + undef => $docker::params::service_provider, + default => $service_provider, + } + if $detach == undef { - $valid_detach = $docker::params::detach_service_in_init + $valid_detach = $service_provider_real ? { + 'systemd' => false, + default => $docker::params::detach_service_in_init, + } } else { $valid_detach = $detach } @@ -335,7 +344,7 @@ $docker_run_inline_start = template('docker/docker-run-start.erb') $docker_run_inline_stop = template('docker/docker-run-stop.erb') - case $docker::params::service_provider { + case $service_provider_real { 'systemd': { $initscript = "/etc/systemd/system/${service_prefix}${sanitised_title}.service" $startscript = "/usr/local/bin/docker-run-${sanitised_title}-start.sh" @@ -343,6 +352,7 @@ $startstop_template = 'docker/usr/local/bin/docker-run.sh.epp' $init_template = 'docker/etc/systemd/system/docker-run.erb' $mode = '0644' + $hasstatus = true } 'upstart': { $initscript = "/etc/init.d/${service_prefix}${sanitised_title}" @@ -350,7 +360,8 @@ $mode = '0750' $startscript = undef $stopscript = undef - $starstop_template = undef + $startstop_template = undef + $hasstatus = true } default: { if $::osfamily != 'windows' { @@ -359,6 +370,8 @@ elsif $ensure == 'present' { fail(translate('Restart parameter is required for Windows')) } + + $hasstatus = $::docker::params::service_hasstatus } } @@ -385,7 +398,8 @@ service { "${service_prefix}${sanitised_title}": ensure => false, enable => false, - hasstatus => $docker::params::service_hasstatus, + hasstatus => $hasstatus, + provider => $service_provider_real, } } exec { @@ -453,7 +467,7 @@ service { "${service_prefix}${sanitised_title}": ensure => $running, enable => false, - hasstatus => $docker::params::service_hasstatus, + hasstatus => $hasstatus, require => File[$initscript], } } @@ -482,8 +496,8 @@ service { "${service_prefix}${sanitised_title}": ensure => $running, enable => true, - provider => $docker::params::service_provider, - hasstatus => $docker::params::service_hasstatus, + provider => $service_provider_real, + hasstatus => $hasstatus, require => File[$initscript], } } @@ -502,7 +516,7 @@ } } } - if $docker::params::service_provider == 'systemd' { + if $service_provider_real == 'systemd' { exec { "docker-${sanitised_title}-systemd-reload": path => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], command => 'systemctl daemon-reload', diff --git a/manifests/service.pp b/manifests/service.pp index f2d75020..0e2f4467 100755 --- a/manifests/service.pp +++ b/manifests/service.pp @@ -121,7 +121,7 @@ $root_dir_flag = $docker::root_dir_flag, ) { - unless $::osfamily =~ /(Debian|RedHat|windows)/ { + unless $::osfamily =~ /(Debian|RedHat|windows)/ or $::docker::acknowledge_unsupported_os { fail(translate('The docker::service class needs a Debian, Redhat or Windows based system.')) } @@ -137,6 +137,8 @@ } else { if $::osfamily == 'Debian' { $_service_config = "/etc/default/${service_name}" + } else { + $_service_config = undef } } diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index 06119a3a..e2398bfb 100755 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -1,9 +1,11 @@ require 'spec_helper' -['Debian', 'RedHat'].each do |osfamily| +['Debian', 'RedHat', 'generic systemd'].each do |osfamily| describe 'docker::run', :type => :define do let(:title) { 'sample' } - let(:pre_condition) { "class { 'docker': docker_group => 'docker', service_name => 'docker' }" } + + params = {'command' => 'command', 'image' => 'base'} + context "on #{osfamily}" do initscript = '/etc/systemd/system/docker-sample.service' @@ -11,6 +13,8 @@ stopscript = "/usr/local/bin/docker-run-sample-stop.sh" if osfamily == 'Debian' + pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker' }" + let(:pre_condition) { pre_condition } let(:facts) { { :architecture => 'amd64', :osfamily => 'Debian', @@ -20,10 +24,12 @@ :kernelrelease => '4.4.0-21-generic', :operatingsystemrelease => '16.04', :operatingsystemmajrelease => '16.04', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } + :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } } } systemd = true elsif osfamily == 'RedHat' + pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker' }" + let(:pre_condition) { pre_condition } let(:facts) { { :architecture => 'x86_64', :osfamily => osfamily, @@ -35,13 +41,22 @@ :os => { :distro => { :codename => 'wheezy' }, :family => osfamily, :name => osfamily, :release => { :major => '7', :full => '7.0' } } } } systemd = true + elsif osfamily == 'generic systemd' + pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker', service_provider => systemd, acknowledge_unsupported_os => true }" + let(:pre_condition) { pre_condition } + let(:facts) { { + :osfamily => 'Gentoo', + :operatingsystem => 'Generic', + } } + params.merge!({'service_provider' => 'systemd'}) + systemd = true end - + startscript_or_init = systemd ? startscript : initscript stopscript_or_init = systemd ? stopscript : initscript context 'passing the required params' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } it { should compile.with_all_deps } it { should contain_service('docker-sample') } it { should contain_file(initscript).with_content(/#{Regexp.escape(startscript)}/).with_mode('0644') } @@ -55,7 +70,7 @@ end context 'when passing `after` containers' do - let(:params) { {'command' => 'command', 'image' => 'base', 'after' => ['foo', 'bar', 'foo_bar/baz']} } + let(:params) { params.merge({'after' => ['foo', 'bar', 'foo_bar/baz']}) } if (systemd) it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo.service/) } it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-bar.service/) } @@ -71,7 +86,7 @@ end context 'when passing `depends` containers' do - let(:params) { {'command' => 'command', 'image' => 'base', 'depends' => ['foo', 'bar', 'foo_bar/baz']} } + let(:params) { params.merge({'depends' => ['foo', 'bar', 'foo_bar/baz']}) } if (systemd) it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo.service/) } it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-bar.service/) } @@ -90,7 +105,7 @@ end context 'when passing `depend_services`' do - let(:params) { {'command' => 'command', 'image' => 'base', 'depend_services' => ['foo', 'bar']} } + let(:params) { params.merge({'depend_services' => ['foo', 'bar']}) } if (systemd) it { should contain_file(initscript).with_content(/After=(.*\s+)?foo.service/) } it { should contain_file(initscript).with_content(/After=(.*\s+)?bar.service/) } @@ -98,7 +113,7 @@ it { should contain_file(initscript).with_content(/Requires=(.*\s+)?bar.service/) } context 'with full systemd unit names' do - let(:params) { {'command' => 'command', 'image' => 'base', 'depend_services' => ['foo', 'bar.service', 'baz.target']} } + let(:params) { params.merge({'depend_services' => ['foo', 'bar.service', 'baz.target']}) } it { should contain_file(initscript).with_content(/After=(.*\s+)?foo.service(\s+|$)/) } it { should contain_file(initscript).with_content(/After=(.*\s+)?bar.service(\s+|$)/) } it { should contain_file(initscript).with_content(/After=(.*\s+)?baz.target(\s+|$)/) } @@ -116,12 +131,10 @@ context 'removing containers and volumes' do context 'when trying to remove the volume and not the container on stop' do - let(:params) {{ - 'command' => 'command', - 'image' => 'base', + let(:params) { params.merge({ 'remove_container_on_stop' => false, 'remove_volume_on_stop' => true, - }} + }) } it do expect { should contain_service('docker-sample') @@ -130,12 +143,10 @@ end context 'when trying to remove the volume and not the container on start' do - let(:params) {{ - 'command' => 'command', - 'image' => 'base', + let(:params) { params.merge({ 'remove_container_on_start' => false, 'remove_volume_on_start' => true, - }} + }) } it do expect { should contain_service('docker-sample') @@ -144,235 +155,231 @@ end context 'When restarting an unhealthy container' do - let(:params) {{ - 'command' => 'command', - 'image' => 'base', + let(:params) { params.merge({ 'health_check_cmd' => 'pwd', 'restart_on_unhealthy' => true, 'health_check_interval' => 60, - }} + }) } if (systemd) - it { should contain_file(stopscript).with_content(/\/usr\/bin\/docker stop --time=0 /).with_content(/\/usr\/bin\/docker rm/) } + it { should contain_file(stopscript).with_content(/\/usr\/bin\/docker stop --time=0 /).with_content(/\/usr\/bin\/docker rm/) } it { should contain_file(startscript).with_content(/--health-cmd/) } end end context 'when not removing containers on container start and stop' do - let(:params) {{ - 'command' => 'command', - 'image' => 'base', + let(:params) { params.merge({ 'remove_container_on_start' => false, 'remove_container_on_stop' => false, - }} + }) } it { should_not contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } end context 'when removing containers on container start' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_container_on_start' => true} } + let(:params) { params.merge({'remove_container_on_start' => true}) } it { should contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } end context 'when removing containers on container stop' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_container_on_stop' => true} } + let(:params) { params.merge({'remove_container_on_stop' => true}) } it { should contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } end context 'when not removing volumes on container start' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_volume_on_start' => false} } + let(:params) { params.merge({'remove_volume_on_start' => false}) } it { should_not contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm -v sample/) } end context 'when removing volumes on container start' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_volume_on_start' => true} } + let(:params) { params.merge({'remove_volume_on_start' => true}) } it { should contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm -v/) } end context 'when not removing volumes on container stop' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_volume_on_stop' => false} } + let(:params) { params.merge({'remove_volume_on_stop' => false}) } it { should_not contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm -v sample/) } end context 'when removing volumes on container stop' do - let(:params) { {'command' => 'command', 'image' => 'base', 'remove_volume_on_stop' => true} } + let(:params) { params.merge({'remove_volume_on_stop' => true}) } it { should contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm -v/) } end end context 'with autorestart functionality' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } if (systemd) it { should contain_file(initscript).with_content(/Restart=on-failure/) } end end context 'when lxc_conf disables swap' do - let(:params) { {'command' => 'command', 'image' => 'base', 'lxc_conf' => 'lxc.cgroup.memory.memsw.limit_in_bytes=536870912'} } + let(:params) { params.merge({'lxc_conf' => 'lxc.cgroup.memory.memsw.limit_in_bytes=536870912'}) } it { should contain_file(startscript_or_init).with_content(/-lxc-conf=\"lxc.cgroup.memory.memsw.limit_in_bytes=536870912\"/) } end context 'when `use_name` is true' do - let(:params) { {'command' => 'command', 'image' => 'base', 'use_name' => true } } + let(:params) { params.merge({'use_name' => true }) } it { should contain_file(startscript_or_init).with_content(/--name sample /) } end context 'when stopping the service' do - let(:params) { {'command' => 'command', 'image' => 'base', 'running' => false} } + let(:params) { params.merge({'running' => false}) } it { should contain_service('docker-sample').with_ensure(false) } end context 'when passing a memory limit in bytes' do - let(:params) { {'command' => 'command', 'image' => 'base', 'memory_limit' => '1000b'} } + let(:params) { params.merge({'memory_limit' => '1000b'}) } it { should contain_file(startscript_or_init).with_content(/-m 1000b/) } end context 'when passing a cpuset' do - let(:params) { {'command' => 'command', 'image' => 'base', 'cpuset' => '3'} } + let(:params) { params.merge({'cpuset' => '3'}) } it { should contain_file(startscript_or_init).with_content(/--cpuset-cpus=3/) } end context 'when passing a multiple cpu cpuset' do - let(:params) { {'command' => 'command', 'image' => 'base', 'cpuset' => ['0', '3']} } + let(:params) { params.merge({'cpuset' => ['0', '3']}) } it { should contain_file(startscript_or_init).with_content(/--cpuset-cpus=0,3/) } end context 'when not passing a cpuset' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } it { should contain_file(startscript_or_init).without_content(/--cpuset-cpus=/) } end context 'when passing a links option' do - let(:params) { {'command' => 'command', 'image' => 'base', 'links' => ['example:one', 'example:two']} } + let(:params) { params.merge({'links' => ['example:one', 'example:two']}) } it { should contain_file(startscript_or_init).with_content(/--link example:one/).with_content(/--link example:two/) } end context 'when passing a hostname' do - let(:params) { {'command' => 'command', 'image' => 'base', 'hostname' => 'example.com'} } + let(:params) { params.merge({'hostname' => 'example.com'}) } it { should contain_file(startscript_or_init).with_content(/-h 'example.com'/) } end context 'when not passing a hostname' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } it { should contain_file(startscript_or_init).without_content(/-h ''/) } end context 'when passing a username' do - let(:params) { {'command' => 'command', 'image' => 'base', 'username' => 'bob'} } + let(:params) { params.merge({'username' => 'bob'}) } it { should contain_file(startscript_or_init).with_content(/-u 'bob'/) } end context 'when not passing a username' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } it { should contain_file(startscript_or_init).without_content(/-u ''/) } end context 'when passing a port number' do - let(:params) { {'command' => 'command', 'image' => 'base', 'ports' => '4444'} } + let(:params) { params.merge({'ports' => '4444'}) } it { should contain_file(startscript_or_init).with_content(/-p 4444/) } end context 'when passing a port to expose' do - let(:params) { {'command' => 'command', 'image' => 'base', 'expose' => '4666'} } + let(:params) { params.merge({'expose' => '4666'}) } it { should contain_file(startscript_or_init).with_content(/--expose=4666/) } end context 'when passing a label' do - let(:params) { {'command' => 'command', 'image' => 'base', 'labels' => 'key=value'} } + let(:params) { params.merge({'labels' => 'key=value'}) } it { should contain_file(startscript_or_init).with_content(/-l key=value/) } end context 'when passing a hostentry' do - let(:params) { {'command' => 'command', 'image' => 'base', 'hostentries' => 'dummyhost:127.0.0.2'} } + let(:params) { params.merge({'hostentries' => 'dummyhost:127.0.0.2'}) } it { should contain_file(startscript_or_init).with_content(/--add-host dummyhost:127.0.0.2/) } end context 'when connecting to shared data volumes' do - let(:params) { {'command' => 'command', 'image' => 'base', 'volumes_from' => '6446ea52fbc9'} } + let(:params) { params.merge({'volumes_from' => '6446ea52fbc9'}) } it { should contain_file(startscript_or_init).with_content(/--volumes-from 6446ea52fbc9/) } end context 'when connecting to several shared data volumes' do - let(:params) { {'command' => 'command', 'image' => 'base', 'volumes_from' => ['sample-linked-container-1', 'sample-linked-container-2']} } + let(:params) { params.merge({'volumes_from' => ['sample-linked-container-1', 'sample-linked-container-2']}) } it { should contain_file(startscript_or_init).with_content(/--volumes-from sample-linked-container-1/) } it { should contain_file(startscript_or_init).with_content(/--volumes-from sample-linked-container-2/) } end context 'when passing several port numbers' do - let(:params) { {'command' => 'command', 'image' => 'base', 'ports' => ['4444', '4555']} } + let(:params) { params.merge({'ports' => ['4444', '4555']}) } it { should contain_file(startscript_or_init).with_content(/-p 4444/).with_content(/-p 4555/) } end context 'when passing several labels' do - let(:params) { {'command' => 'command', 'image' => 'base', 'labels' => ['key1=value1', 'key2=value2']} } + let(:params) { params.merge({'labels' => ['key1=value1', 'key2=value2']}) } it { should contain_file(startscript_or_init).with_content(/-l key1=value1/).with_content(/-l key2=value2/) } end context 'when passing several ports to expose' do - let(:params) { {'command' => 'command', 'image' => 'base', 'expose' => ['4666', '4777']} } + let(:params) { params.merge({'expose' => ['4666', '4777']}) } it { should contain_file(startscript_or_init).with_content(/--expose=4666/).with_content(/--expose=4777/) } end context 'when passing serveral environment variables' do - let(:params) { {'command' => 'command', 'image' => 'base', 'env' => ['FOO=BAR', 'FOO2=BAR2']} } + let(:params) { params.merge({'env' => ['FOO=BAR', 'FOO2=BAR2']}) } it { should contain_file(startscript_or_init).with_content(/-e "FOO=BAR"/).with_content(/-e "FOO2=BAR2"/) } end context 'when passing an environment variable' do - let(:params) { {'command' => 'command', 'image' => 'base', 'env' => 'FOO=BAR'} } + let(:params) { params.merge({'env' => 'FOO=BAR'}) } it { should contain_file(startscript_or_init).with_content(/-e "FOO=BAR"/) } end context 'when passing serveral environment files' do - let(:params) { {'command' => 'command', 'image' => 'base', 'env_file' => ['/etc/foo.env', '/etc/bar.env']} } + let(:params) { params.merge({'env_file' => ['/etc/foo.env', '/etc/bar.env']}) } it { should contain_file(startscript_or_init).with_content(/--env-file \/etc\/foo.env/).with_content(/--env-file \/etc\/bar.env/) } end context 'when passing an environment file' do - let(:params) { {'command' => 'command', 'image' => 'base', 'env_file' => '/etc/foo.env'} } + let(:params) { params.merge({'env_file' => '/etc/foo.env'}) } it { should contain_file(startscript_or_init).with_content(/--env-file \/etc\/foo.env/) } end context 'when passing serveral dns addresses' do - let(:params) { {'command' => 'command', 'image' => 'base', 'dns' => ['8.8.8.8', '8.8.4.4']} } + let(:params) { params.merge({'dns' => ['8.8.8.8', '8.8.4.4']}) } it { should contain_file(startscript_or_init).with_content(/--dns 8.8.8.8/).with_content(/--dns 8.8.4.4/) } end context 'when passing a dns address' do - let(:params) { {'command' => 'command', 'image' => 'base', 'dns' => '8.8.8.8'} } + let(:params) { params.merge({'dns' => '8.8.8.8'}) } it { should contain_file(startscript_or_init).with_content(/--dns 8.8.8.8/) } end context 'when passing serveral sockets to connect to' do - let(:params) { {'command' => 'command', 'image' => 'base', 'socket_connect' => ['tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567']} } + let(:params) { params.merge({'socket_connect' => ['tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567']}) } it { should contain_file(startscript_or_init).with_content(/-H tcp:\/\/127.0.0.1:4567/) } end context 'when passing a socket to connect to' do - let(:params) { {'command' => 'command', 'image' => 'base', 'socket_connect' => 'tcp://127.0.0.1:4567'} } + let(:params) { params.merge({'socket_connect' => 'tcp://127.0.0.1:4567'}) } it { should contain_file(startscript_or_init).with_content(/-H tcp:\/\/127.0.0.1:4567/) } end context 'when passing serveral dns search domains' do - let(:params) { {'command' => 'command', 'image' => 'base', 'dns_search' => ['my.domain.local', 'other-domain.de']} } + let(:params) { params.merge({'dns_search' => ['my.domain.local', 'other-domain.de']}) } it { should contain_file(startscript_or_init).with_content(/--dns-search my.domain.local/).with_content(/--dns-search other-domain.de/) } end context 'when passing a dns search domain' do - let(:params) { {'command' => 'command', 'image' => 'base', 'dns_search' => 'my.domain.local'} } + let(:params) { params.merge({'dns_search' => 'my.domain.local'}) } it { should contain_file(startscript_or_init).with_content(/--dns-search my.domain.local/) } end context 'when disabling network' do - let(:params) { {'command' => 'command', 'image' => 'base', 'disable_network' => true} } + let(:params) { params.merge({'disable_network' => true}) } it { should contain_file(startscript_or_init).with_content(/-n false/) } end context 'when running privileged' do - let(:params) { {'command' => 'command', 'image' => 'base', 'privileged' => true} } + let(:params) { params.merge({'privileged' => true}) } it { should contain_file(startscript_or_init).with_content(/--privileged/) } end context 'should run with correct detached value' do - let(:params) { {'command' => 'command', 'image' => 'base'} } + let(:params) { params } if (systemd) it { should_not contain_file(startscript).with_content(/--detach=true/) } else @@ -381,90 +388,90 @@ end context 'should be able to override detached' do - let(:params) { {'command' => 'command', 'image' => 'base', 'detach' => false} } + let(:params) { params.merge({'detach' => false}) } it { should contain_file(startscript_or_init).without_content(/--detach=true/) } end context 'when running with a tty' do - let(:params) { {'command' => 'command', 'image' => 'base', 'tty' => true} } + let(:params) { params.merge({'tty' => true}) } it { should contain_file(startscript_or_init).with_content(/-t/) } end context 'when running with read-only image' do - let(:params) { {'command' => 'command', 'image' => 'base', 'read_only' => true} } + let(:params) { params.merge({'read_only' => true}) } it { should contain_file(startscript_or_init).with_content(/--read-only=true/) } end context 'when passing serveral extra parameters' do - let(:params) { {'command' => 'command', 'image' => 'base', 'extra_parameters' => ['--rm', '-w /tmp']} } + let(:params) { params.merge({'extra_parameters' => ['--rm', '-w /tmp']}) } it { should contain_file(startscript_or_init).with_content(/--rm/).with_content(/-w \/tmp/) } end context 'when passing an extra parameter' do - let(:params) { {'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } + let(:params) { params.merge({'extra_parameters' => '-c 4'}) } it { should contain_file(startscript_or_init).with_content(/-c 4/) } end context 'when passing a data volume' do - let(:params) { {'command' => 'command', 'image' => 'base', 'volumes' => '/var/log'} } + let(:params) { params.merge({'volumes' => '/var/log'}) } it { should contain_file(startscript_or_init).with_content(/-v \/var\/log/) } end context 'when passing serveral data volume' do - let(:params) { {'command' => 'command', 'image' => 'base', 'volumes' => ['/var/lib/couchdb', '/var/log']} } + let(:params) { params.merge({'volumes' => ['/var/lib/couchdb', '/var/log']}) } it { should contain_file(startscript_or_init).with_content(/-v \/var\/lib\/couchdb/) } it { should contain_file(startscript_or_init).with_content(/-v \/var\/log/) } end context 'when using network mode with a single network' do - let(:params) { {'command' => 'command', 'image' => 'nginx', 'net' => 'host'} } + let(:params) { params.merge({'net' => 'host'}) } it { should contain_file(startscript_or_init).with_content(/--net host/) } end context 'when using network mode with multiple networks' do - let(:params) { {'command' => 'command', 'image' => 'nginx', 'net' => ['host','foo']} } + let(:params) { params.merge({'net' => ['host','foo']}) } it { should contain_file(startscript_or_init).with_content(/docker network connect host sample/) } it { should contain_file(startscript_or_init).with_content(/docker network connect foo sample/) } end context 'when `pull_on_start` is true' do - let(:params) { {'command' => 'command', 'image' => 'base', 'pull_on_start' => true } } + let(:params) { params.merge({'pull_on_start' => true}) } it { should contain_file(startscript_or_init).with_content(/docker pull base/) } end context 'when `pull_on_start` is false' do - let(:params) { {'command' => 'command', 'image' => 'base', 'pull_on_start' => false } } + let(:params) { params.merge({'pull_on_start' => false}) } it { should_not contain_file(startscript_or_init).with_content(/docker pull base/) } end context 'when `before_start` is set' do - let(:params) { {'command' => 'command', 'image' => 'base', 'before_start' => "echo before_start" } } + let(:params) { params.merge({'before_start' => "echo before_start"}) } it { should contain_file(startscript_or_init).with_content(/before_start/) } end context 'when `before_start` is not set' do - let(:params) { {'command' => 'command', 'image' => 'base', 'before_start' => false } } + let(:params) { params.merge({'before_start' => false}) } it { should_not contain_file(startscript_or_init).with_content(/before_start/) } end context 'when `before_stop` is set' do - let(:params) { {'command' => 'command', 'image' => 'base', 'before_stop' => "echo before_stop" } } + let(:params) { params.merge({'before_stop' => "echo before_stop"}) } it { should contain_file(stopscript_or_init).with_content(/before_stop/) } end context 'when `before_stop` is not set' do - let(:params) { {'command' => 'command', 'image' => 'base', 'before_stop' => false } } + let(:params) { params.merge({'before_stop' => false}) } it { should_not contain_file(stopscript_or_init).with_content(/before_stop/) } end context 'when `after_create` is set' do - let(:params) { {'command' => 'command', 'image' => 'base', 'after_create' => "echo after_create" } } + let(:params) { params.merge({'after_create' => "echo after_create"}) } it { should contain_file(startscript_or_init).with_content(/after_create/) } end context 'with an title that will not format into a path' do let(:title) { 'this/that' } - let(:params) { {'image' => 'base'} } + let(:params) { params } new_initscript = '/etc/systemd/system/docker-this-that.service' new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' @@ -478,7 +485,7 @@ context 'with manage_service turned off' do let(:title) { 'this/that' } - let(:params) { {'image' => 'base', 'manage_service' => false} } + let(:params) { params.merge({'manage_service' => false}) } new_initscript = '/etc/systemd/system/docker-this-that.service' new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' @@ -492,7 +499,7 @@ context 'with service_prefix set to empty string' do let(:title) { 'this/that' } - let(:params) { {'image' => 'base', 'service_prefix' => ''} } + let(:params) { params.merge({'service_prefix' => ''}) } new_initscript = '/etc/systemd/system/this-that.service' new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' @@ -515,7 +522,7 @@ context 'with title that need sanitisation' do let(:title) { 'this/that_other' } - let(:params) { {'image' => 'base' } } + let(:params) { params } new_initscript = '/etc/systemd/system/docker-this-that_other.service' new_startscript = '/usr/local/bin/docker-run-this-that_other-start.sh' @@ -528,7 +535,7 @@ end context 'with an invalid image name' do - let(:params) { {'command' => 'command', 'image' => 'with spaces', 'running' => 'not a boolean'} } + let(:params) { params.merge({'image' => 'with spaces', 'running' => 'not a boolean'}) } it do expect { should contain_service('docker-sample') @@ -538,7 +545,7 @@ context 'with an invalid running value' do let(:title) { 'with spaces' } - let(:params) { {'command' => 'command', 'image' => 'base', 'running' => 'not a boolean'} } + let(:params) { params.merge({'running' => 'not a boolean'}) } it do expect { should contain_service('docker-sample') @@ -548,7 +555,7 @@ context 'with an invalid memory value' do let(:title) { 'with spaces' } - let(:params) { {'command' => 'command', 'image' => 'base', 'memory' => 'not a number'} } + let(:params) { params.merge({'memory' => 'not a number'}) } it do expect { should contain_service('docker-sample') @@ -558,7 +565,7 @@ context 'with a missing memory unit' do let(:title) { 'with spaces' } - let(:params) { {'command' => 'command', 'image' => 'base', 'memory' => '10240'} } + let(:params) { params.merge({'memory' => '10240'}) } it do expect { should contain_service('docker-sample') @@ -567,7 +574,7 @@ end context 'with restart policy set to no' do - let(:params) { {'restart' => 'no', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } + let(:params) { params.merge({'restart' => 'no', 'extra_parameters' => '-c 4'}) } it { should contain_exec('run sample with docker') } it { should contain_exec('run sample with docker').with_unless(/sample/) } it { should contain_exec('run sample with docker').with_unless(/inspect/) } @@ -579,7 +586,7 @@ end context 'with restart policy set to always' do - let(:params) { {'restart' => 'always', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } + let(:params) { params.merge({'restart' => 'always', 'extra_parameters' => '-c 4'}) } it { should contain_exec('run sample with docker') } it { should contain_exec('run sample with docker').with_unless(/sample/) } it { should contain_exec('run sample with docker').with_unless(/inspect/) } @@ -591,7 +598,7 @@ end context 'with restart policy set to on-failure' do - let(:params) { {'restart' => 'on-failure', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } + let(:params) { params.merge({'restart' => 'on-failure', 'extra_parameters' => '-c 4'}) } it { should contain_exec('run sample with docker') } it { should contain_exec('run sample with docker').with_unless(/sample/) } it { should contain_exec('run sample with docker').with_unless(/inspect/) } @@ -603,7 +610,7 @@ end context 'with restart policy set to on-failure:3' do - let(:params) { {'restart' => 'on-failure:3', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } + let(:params) { params.merge({'restart' => 'on-failure:3', 'extra_parameters' => '-c 4'}) } it { should contain_exec('run sample with docker') } it { should contain_exec('run sample with docker').with_unless(/sample/) } it { should contain_exec('run sample with docker').with_unless(/inspect/) } @@ -615,65 +622,57 @@ end context 'when `docker_service` is false' do - let(:params) { {'command' => 'command', 'image' => 'base', 'docker_service' => false} } + let(:params) { params.merge({'docker_service' => false}) } it { should compile.with_all_deps } it { should contain_service('docker-sample') } end context 'when `docker_service` is true' do - let(:params) { {'command' => 'command', 'image' => 'base', 'docker_service' => true} } - let(:pre_condition) { - [ "service { 'docker': }", - "class { 'docker': docker_group => 'docker', service_name => 'docker' }" ] } + let(:params) { params.merge({'docker_service' => true}) } + let(:pre_condition) { ["service { 'docker': provider => systemd }", pre_condition] } it { should compile.with_all_deps } it { should contain_service('docker').that_comes_before('Service[docker-sample]') } it { should contain_service('docker').that_notifies('Service[docker-sample]') } end context 'when `docker_service` is true and `restart_service_on_docker_refresh` is false' do - let(:params) { {'command' => 'command', 'image' => 'base', 'docker_service' => true, 'restart_service_on_docker_refresh' => false} } - let(:pre_condition) { - [ "service { 'docker': }", - "class { 'docker': docker_group => 'docker', service_name => 'docker' }" ] } + let(:params) { params.merge({'docker_service' => true, 'restart_service_on_docker_refresh' => false}) } + let(:pre_condition) { ["service { 'docker': provider => systemd }", pre_condition] } it { should compile.with_all_deps } it { should contain_service('docker').that_comes_before('Service[docker-sample]') } end context 'when `docker_service` is `my-docker`' do - let(:params) { {'command' => 'command', 'image' => 'base', 'docker_service' => 'my-docker'} } - let(:pre_condition) { - [ "service { 'my-docker': }", - "class { 'docker': docker_group => 'docker', service_name => 'docker' }" ] } + let(:params) { params.merge({'docker_service' => 'my-docker'}) } + let(:pre_condition) { ["service { 'my-docker': provider => systemd }", pre_condition] } it { should compile.with_all_deps } it { should contain_service('my-docker').that_comes_before('Service[docker-sample]') } it { should contain_service('my-docker').that_notifies('Service[docker-sample]') } end context 'when `docker_service` is `my-docker` and `restart_service_on_docker_refresh` is false' do - let(:params) { {'command' => 'command', 'image' => 'base', 'docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false} } - let(:pre_condition) { - [ "service { 'my-docker': }", - "class { 'docker': docker_group => 'docker', service_name => 'docker' }" ] } + let(:params) { params.merge({'docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false}) } + let(:pre_condition) { ["service { 'my-docker': provider => systemd }", pre_condition] } it { should compile.with_all_deps } it { should contain_service('my-docker').that_comes_before('Service[docker-sample]') } end context 'with syslog_identifier' do - let(:params) { {'command' => 'command', 'image' => 'base', 'syslog_identifier' => 'docker-universe' } } + let(:params) { params.merge({'syslog_identifier' => 'docker-universe' }) } if systemd it { should contain_file(initscript).with_content(/^SyslogIdentifier=docker-universe$/) } end end context 'with extra_systemd_parameters' do - let(:params) { {'command' => 'command', 'image' => 'base', 'extra_systemd_parameters' => {'RestartSec' => 5}} } + let(:params) { params.merge({'extra_systemd_parameters' => {'RestartSec' => 5}}) } if (systemd) it { should contain_file(initscript).with_content(/^RestartSec=5$/) } end end context 'with ensure absent' do - let(:params) { {'ensure' => 'absent', 'command' => 'command', 'image' => 'base'} } + let(:params) { params.merge({'ensure' => 'absent'}) } it { should compile.with_all_deps } it { should contain_service('docker-sample').with_ensure(false) } it { should contain_exec("remove container docker-sample").with_command('docker rm -v sample') } From 2a0f381e01aaf60f490dfc3ea30a7a9c12333a84 Mon Sep 17 00:00:00 2001 From: David Schmitt Date: Wed, 1 May 2019 13:44:55 +0100 Subject: [PATCH 29/44] Add missing single quote (#478) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 84eae345..a7a8ca8e 100755 --- a/README.md +++ b/README.md @@ -639,7 +639,7 @@ To supply multiple overide compose files add the following to the manifest file: ```puppet docker_compose {'test': - compose_files => ['master-docker-compose.yml', 'override-compose.yml], + compose_files => ['master-docker-compose.yml', 'override-compose.yml'], } ``` From d7473ebfbd83b23fab0ee17e7045ba2c04a1d2cb Mon Sep 17 00:00:00 2001 From: Markus Benning Date: Mon, 6 May 2019 15:47:24 +0200 Subject: [PATCH 30/44] Update docker volume documentation The documentation of * docker_volume type * docker::volumes puppet class in README.md seems to be outdated and incorrect. This tries to fix the docs and adds an example for using an NFS volume. --- README.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a7a8ca8e..411cb3d3 100755 --- a/README.md +++ b/README.md @@ -540,6 +540,20 @@ docker_volume { 'my-volume': } ``` +Additional mount options can be passed to the `local` driver. For mounting a NFS export use: + +```puppet +docker_volume { 'nfs-volume': + ensure => present, + driver => 'local', + options => { + type => 'nfs4', + o => 'addr=10.10.10.10,rw', + device => ':/exports/data' + }, +} +``` + The name value and the `ensure` parameter are required. If you do not include the `driver` value, the default `local` is used. If using Hiera, configure the `docker::volumes` class in the manifest file: @@ -547,17 +561,20 @@ If using Hiera, configure the `docker::volumes` class in the manifest file: ```yaml --- classes: - - docker::volumes::volumes + - docker::volumes -docker::volumes::volumes: +docker::volumes: blueocean: ensure: present driver: local options: - - ['type=nfs','o=addr=%{custom_manager},rw','device=:/srv/blueocean'] + type: "nfs" + o: "addr=%{custom_manager},rw", + device: ":/srv/blueocean" ``` -Any extra options should be passed in as an array +Available parameters for `options` depend on the used volume driver. For details read +[Using volumes](https://docs.docker.com/storage/volumes/) from the Docker manual. Some of the key advantages for using `volumes` over `bind mounts` are: @@ -582,8 +599,6 @@ docker::run { 'helloworld': } ``` -For more information on volumes see the [Docker Volumes](https://docs.docker.com/engine/admin/volumes/volumes) documentation. - ### Compose Docker Compose describes a set of containers in YAML format and runs a command to build and run those containers. Included in the docker module is the `docker_compose` type. This enables Puppet to run Compose and remediate any issues to ensure reality matches the model in your Compose file. From 978117902a61ff217affb8cd541f4f05e7a79f06 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Tue, 7 May 2019 17:47:48 +0100 Subject: [PATCH 31/44] (MODULES-9034) Fix Ubuntu and Debian tests --- spec/acceptance/docker_spec.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/acceptance/docker_spec.rb b/spec/acceptance/docker_spec.rb index 2636c7cc..3b377924 100644 --- a/spec/acceptance/docker_spec.rb +++ b/spec/acceptance/docker_spec.rb @@ -131,9 +131,6 @@ class { 'docker': it 'should apply with no errors' do apply_manifest(pp, :catch_failures=>true) end - it 'should be idempotent' do - apply_manifest(pp, :catch_changes=>true) - end end context "When registry_mirror is set", :win_broken => broken do From b95529d7b3352d5bc282f0ce79f4e79a78c91f06 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Wed, 8 May 2019 14:48:19 +0100 Subject: [PATCH 32/44] (MODULES-9035) Fix RedHat acceptance tests --- spec/acceptance/stack_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index ab4c73d4..e968c484 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -81,8 +81,9 @@ class { 'docker': #{docker_args} } end it 'should be idempotent' do - apply_manifest(destroy, :catch_changes=>true) - sleep 5 + retry_on_error_matching(10, 3, /Removing network web_default/) do + apply_manifest(destroy, :catch_changes=>true) + end end it 'should not find a docker stack' do @@ -135,8 +136,9 @@ class { 'docker': #{docker_args} } end it 'should be idempotent' do - apply_manifest(@destroy_code, :catch_changes=>true) - sleep 5 + retry_on_error_matching(10, 3, /Removing network web_default/) do + apply_manifest(@destroy_code, :catch_changes=>true) + end end it 'should not find a docker stack' do From 1808b9528931030835f9e383f7f3826a724220b5 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Mon, 13 May 2019 13:53:35 +0100 Subject: [PATCH 33/44] (MODULES-9036) Fix Windows acceptance tests While fixing the tests I uncovered that the docker_stack provider does not check for the existence of stacks properly on Windows. This appears to be due to it looking for containers tagged with latest, as not having any tag. As a result, the stack is created on every run and also cannot be destroyed. The changes here help rectify this however there is probably a better solution needed. --- lib/puppet/provider/docker_stack/ruby.rb | 1 + spec/acceptance/docker_custom_source_spec.rb | 4 ++-- spec/acceptance/docker_full_spec.rb | 8 +++---- spec/acceptance/stack_spec.rb | 23 +++++++++++--------- spec/spec_helper_acceptance.rb | 8 +++---- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/puppet/provider/docker_stack/ruby.rb b/lib/puppet/provider/docker_stack/ruby.rb index 2ea08eff..e45297ae 100644 --- a/lib/puppet/provider/docker_stack/ruby.rb +++ b/lib/puppet/provider/docker_stack/ruby.rb @@ -40,6 +40,7 @@ def exists? end counts = Hash[*stack_services.each.map { |key, array| image = (array['image']) ? array['image'] : get_image(key, stack_services) + image = "#{image}:latest" unless image.include?(':') Puppet.info("Checking for compose service #{key} #{image}") ["#{key}-#{image}", stack_containers.count("#{key}-#{image}")] }.flatten] diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index 7e655ef1..6229ae8c 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -4,8 +4,8 @@ if fact('osfamily') == '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 = 'microsoft/nanoserver' - default_image_tag = '10.0.14393.2189' + default_image = 'winamd64/hello-world' + default_image_tag = 'nanoserver-sac2016' #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. diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 8638a9e0..79f2e7b9 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -2,10 +2,10 @@ if fact('kernel') == 'windows' docker_args = 'docker_ee => true' - default_image = 'microsoft/nanoserver' - default_image_tag = '10.0.14393.2189' - second_image = 'hello-world' - default_digest = 'sha256:204c41542c0927ac0296802e44c56b886b47e99cf8220fb49d46951bd5fc1742' + default_image = 'winamd64/hello-world' + default_image_tag = 'nanoserver-sac2016' + default_digest = 'sha256:88f6207b9281e60dc4a91008e68b542cc7350d06985c7fc3c5132e6f6b9b3ebe' + 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: diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index e968c484..10ccda16 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -57,9 +57,9 @@ class { 'docker': #{docker_args} } end end - it 'should find a docker container' do - shell("docker ps | grep web_compose_test", :acceptable_exit_codes => [0]) - end + it 'should not find a docker container' do + shell("docker ps -a -q -f \"name=web_compose_test\"", :acceptable_exit_codes => [0]) + end end context 'Destroying stack' do @@ -87,10 +87,9 @@ class { 'docker': #{docker_args} } end it 'should not find a docker stack' do - sleep 5 - shell('docker stack ls') do |r| - expect(r.stdout).to_not match(/web/) - end + shell('docker stack ls') do |r| + expect(r.stdout).to_not match(/web/) + end end end @@ -131,8 +130,10 @@ class { 'docker': #{docker_args} } } code - apply_manifest(@destroy_code, :catch_failures=>true) - sleep 10# wait for containers to stop + retry_on_error_matching(10, 3, /Removing network web_default/) do + apply_manifest(@destroy_code, :catch_failures=>true) + end + sleep 15 # Wait for containers to stop and be destroyed end it 'should be idempotent' do @@ -148,7 +149,9 @@ class { 'docker': #{docker_args} } end it 'should not find a docker container' do - shell("docker ps | grep web_compose_test", :acceptable_exit_codes => [1]) + shell("docker ps", :acceptable_exit_codes => [0]) do |r| + expect(r.stdout).not_to match(/web_compose_test/) + end end end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 075dc681..b98127ce 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -112,7 +112,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: hello-world:nanoserver + image: winamd64/hello-world command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: @@ -123,7 +123,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: hello-world:nanoserver-sac2016 + image: winamd64/hello-world:nanoserver-sac2016 command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: @@ -134,14 +134,14 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: hello-world:nanoserver + image: winamd64/hello-world command: cmd.exe /C "ping 8.8.8.8 -t" EOS docker_stack_override_windows = <<-EOS version: "3" services: compose_test: - image: hello-world:nanoserver-sac2016 + image: winamd64/hello-world:nanoserver-sac2016 EOS if fact_on(host, 'osfamily') == 'windows' create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3_windows) From d4f1cfb73a5f3f2729de623a4db929d2d211450b Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Wed, 15 May 2019 10:55:54 +0100 Subject: [PATCH 34/44] (MODULES-9029) Update pdk template to 46a1deb --- .gitignore | 3 ++ .pdkignore | 18 ++++++++++ .rubocop.yml | 18 ++++------ .sync.yml | 87 ++++++++++++++++----------------------------- .travis.yml | 65 ++++++++++++++++++++++----------- Gemfile | 29 ++++++++------- Rakefile | 13 ++----- metadata.json | 6 ++-- spec/spec_helper.rb | 35 ++++-------------- 9 files changed, 129 insertions(+), 145 deletions(-) diff --git a/.gitignore b/.gitignore index 650022e5..2767022c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ /convert_report.txt /update_report.txt .DS_Store +.project +.envrc +/inventory.yaml diff --git a/.pdkignore b/.pdkignore index 650022e5..e6215cd0 100644 --- a/.pdkignore +++ b/.pdkignore @@ -22,3 +22,21 @@ /convert_report.txt /update_report.txt .DS_Store +.project +.envrc +/inventory.yaml +/appveyor.yml +/.fixtures.yml +/Gemfile +/.gitattributes +/.gitignore +/.gitlab-ci.yml +/.pdkignore +/Rakefile +/rakelib/ +/.rspec +/.rubocop.yml +/.travis.yml +/.yardopts +/spec/ +/.vscode/ diff --git a/.rubocop.yml b/.rubocop.yml index 6c527904..413a6442 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,10 @@ --- -require: rubocop-rspec +require: +- rubocop-rspec +- rubocop-i18n AllCops: DisplayCopNames: true - TargetRubyVersion: '2.3' + TargetRubyVersion: '2.1' Include: - "./**/*.rb" Exclude: @@ -12,11 +14,6 @@ AllCops: - "**/Rakefile" - pkg/**/* - spec/fixtures/**/* - - spec/classes/**/* - - spec/acceptance/**/* - - spec/acceptance_swarm/**/* - - spec/defines/**/* - - spec/unit/**/* - vendor/**/* - "**/Puppetfile" - "**/Vagrantfile" @@ -24,6 +21,8 @@ AllCops: Metrics/LineLength: Description: People have wide screens, use them. Max: 200 +GetText: + Enabled: false GetText/DecorateString: Description: We don't want to decorate test output. Exclude: @@ -75,6 +74,7 @@ Style/TrailingCommaInLiteral: Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets +inherit_from: ".rubocop_todo.yml" RSpec/MessageSpies: EnforcedStyle: receive Style/Documentation: @@ -125,7 +125,3 @@ Style/IfUnlessModifier: Enabled: false Style/SymbolProc: Enabled: false -Style/SafeNavigation: - Description: Does not work with all ruby versions - Exclude: - - lib/puppet/parser/functions/docker_exec_flags.rb \ No newline at end of file diff --git a/.sync.yml b/.sync.yml index 266c8dab..41f35438 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,65 +1,40 @@ --- +.gitlab-ci.yml: + delete: true + +.rubocop.yml: + default_configs: + inherit_from: .rubocop_todo.yml + require: + - rubocop-rspec + .travis.yml: - bundler_args: ' ' + docker_sets: + - set: docker/debian-8 + - set: docker/ubuntu-14.04 + docker_defaults: + bundler_args: "" + secure: "" branches: - release - remove_includes: - - - env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec - rvm: 2.1.9 - includes: - - - env: PUPPET_GEM_VERSION="~> 4.0" CHECK=parallel_spec - rvm: 2.3.3 + +appveyor.yml: + delete: true Gemfile: - required: + optional: ':development': - - gem: 'facter' - version: '>= 1.7.0' - - gem: "rspec-retry" - - gem: 'thor' - - gem: 'semantic_puppet' - - gem: 'beaker-rspec' - from_env: BEAKER_RSPEC_VERSION - - gem: "beaker" - version: '~> 2.0' - from_env: BEAKER_VERSION + - gem: 'github_changelog_generator' + git: 'https://github.com/skywinder/github-changelog-generator' + ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' + condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2')" + required: + ':system_tests': - gem: 'puppet-module-posix-system-r#{minor_version}' platforms: ruby - - gem: 'rspec' - version: '~> 2.0' - condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('1.8.7') && Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('1.9')" - - gem: 'rake' - version: '~> 10.0' - condition: "Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('1.8.7') && Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('1.9')" - -Rakefile: - requires: - - puppet-lint/tasks/puppet-lint - - puppetlabs_spec_helper/rake_tasks - - metadata-json-lint/rake_task - - rspec_junit_formatter - - puppet_pot_generator/rake_tasks - -.rubocop.yml: - include_todos: - inherit_from: '.rubocop_todo.yml' - profiles: - strict: - configs: - AllCops: - TargetRubyVersion: '2.2' - Exclude: - - spec/defines/* - - spec/classes/* - - spec/* - - spec/acceptance/* - - rakelib/* - - -.gitlab-ci.yml: - delete: true - -appveyor.yml: - delete: true \ No newline at end of file + - gem: 'puppet-module-win-system-r#{minor_version}' + platforms: + - mswin + - mingw + - x64_mingw + - gem: 'rspec-retry' \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index cb92e189..1877a175 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,38 +1,63 @@ --- -sudo: false -dist: trusty language: ruby cache: bundler before_install: - bundle -v - rm -f Gemfile.lock - - gem update --system + - gem update --system $RUBYGEMS_VERSION - gem --version - bundle -v script: - - 'bundle exec rake syntax lint metadata_lint check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop' - - 'bundle exec rake parallel_spec' -bundler_args: + - 'bundle exec rake $CHECK' +bundler_args: --without system_tests rvm: - - 2.4.4 -env: - - PUPPET_GEM_VERSION="~> 4.0" - - PUPPET_GEM_VERSION="~> 5.0" - - PUPPET_GEM_VERSION="~> 6.0" + - 2.5.3 +stages: + - static + - spec + - acceptance + - + if: tag =~ ^v\d + name: deploy matrix: fast_finish: true + include: + - + bundler_args: + dist: trusty + env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=docker/debian-8 BEAKER_TESTMODE=apply + rvm: 2.5.3 + script: bundle exec rake beaker + services: docker + stage: acceptance + sudo: required + - + bundler_args: + dist: trusty + env: PUPPET_INSTALL_TYPE=agent BEAKER_debug=true BEAKER_PUPPET_COLLECTION=puppet6 BEAKER_set=docker/ubuntu-14.04 BEAKER_TESTMODE=apply + rvm: 2.5.3 + script: bundle exec rake beaker + services: docker + stage: acceptance + sudo: required + - + env: CHECK="check:symlinks check:git_ignore check:dot_underscore check:test_file rubocop syntax lint metadata_lint" + stage: static + - + env: PUPPET_GEM_VERSION="~> 5.0" CHECK=parallel_spec + rvm: 2.4.5 + stage: spec + - + env: PUPPET_GEM_VERSION="~> 6.0" CHECK=parallel_spec + rvm: 2.5.3 + stage: spec + - + env: DEPLOY_TO_FORGE=yes + stage: deploy branches: only: - master - /^v\d/ + - release notifications: email: false -deploy: - provider: puppetforge - user: puppet - password: - secure: "" - on: - tags: true - all_branches: true - condition: "$DEPLOY_TO_FORGE = yes" diff --git a/Gemfile b/Gemfile index 9234ae8d..3fa946fd 100755 --- a/Gemfile +++ b/Gemfile @@ -17,23 +17,22 @@ ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments minor_version = ruby_version_segments[0..1].join('.') group :development do - gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') - gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') - gem "json", '<= 2.0.4', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.4.4') - gem "puppet-module-posix-default-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-posix-dev-r#{minor_version}", require: false, platforms: [:ruby] - gem "puppet-module-win-default-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] - gem "puppet-module-win-dev-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "fast_gettext", '1.1.0', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') + gem "fast_gettext", require: false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') + gem "json_pure", '<= 2.0.1', require: false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') + gem "json", '= 1.8.1', require: false if Gem::Version.new(RUBY_VERSION.dup) == Gem::Version.new('2.1.9') + gem "json", '= 2.0.4', require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) + gem "puppet-module-posix-default-r#{minor_version}", '~> 0.3', require: false, platforms: [:ruby] + gem "puppet-module-posix-dev-r#{minor_version}", '~> 0.3', require: false, platforms: [:ruby] + gem "puppet-module-win-default-r#{minor_version}", '~> 0.3', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "puppet-module-win-dev-r#{minor_version}", '~> 0.3', require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "github_changelog_generator", require: false, git: 'https://github.com/skywinder/github-changelog-generator', ref: '20ee04ba1234e9e83eb2ffb5056e23d641c7a018' if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.2.2') end - group :system_tests do - gem "beaker-puppet_install_helper", :require => false - gem "beaker-rspec" - gem "beaker", "~> 3.13" - gem "rspec" - gem "rspec-retry" + gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby] + gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw] + gem "rspec-retry", require: false end puppet_version = ENV['PUPPET_GEM_VERSION'] diff --git a/Rakefile b/Rakefile index 7b487ef1..597f494c 100644 --- a/Rakefile +++ b/Rakefile @@ -14,7 +14,7 @@ end def changelog_project return unless Rake.application.top_level_tasks.include? "changelog" - returnVal = nil || JSON.load(File.read('metadata.json'))['name'] + returnVal = nil || JSON.load(File.read('metadata.json'))['source'].match(%r{.*/([^/]*)})[1] raise "unable to find the changelog_project in .sync.yml or the name in metadata.json" if returnVal.nil? puts "GitHubChangelogGenerator project:#{returnVal}" returnVal @@ -22,7 +22,7 @@ end def changelog_future_release return unless Rake.application.top_level_tasks.include? "changelog" - returnVal = JSON.load(File.read('metadata.json'))['version'] + returnVal = "v%s" % JSON.load(File.read('metadata.json'))['version'] raise "unable to find the future_release (version) in metadata.json" if returnVal.nil? puts "GitHubChangelogGenerator future_release:#{returnVal}" returnVal @@ -74,12 +74,3 @@ EOM end end -desc 'Run syntax, lint and metadata tests' -task :test => [ - :syntax, - :lint, - :metadata_lint, - :spec, -] - - diff --git a/metadata.json b/metadata.json index f3904ccc..90535490 100755 --- a/metadata.json +++ b/metadata.json @@ -70,7 +70,7 @@ "version_requirement": ">= 4.2.1 < 7.0.0" } ], - "pdk-version": "1.8.0", - "template-url": "file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git", - "template-ref": "1.8.0-0-g0d9da00" + "pdk-version": "1.10.0", + "template-url": "https://github.com/puppetlabs/pdk-templates.git#master", + "template-ref": "heads/master-0-g46a1deb" } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 951cae60..3ac4f0da 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' @@ -21,7 +19,7 @@ next unless File.exist?(f) && File.readable?(f) && File.size?(f) begin - default_facts.merge!(YAML.safe_load(File.read(f))) + default_facts.merge!(YAML.safe_load(File.read(f), [], [], true)) rescue => e RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" end @@ -34,8 +32,13 @@ # 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) @@ -43,30 +46,4 @@ def ensure_module_defined(module_name) 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 - # 'spec_overrides' from sync.yml will appear below this line From a2fa90991fbb872aa64d842d422798da646fefba Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Thu, 16 May 2019 11:00:48 +0100 Subject: [PATCH 35/44] (MODULES-9029) Fix rubocop offenses --- .puppet-lint.rc | 1 + .sync.yml | 5 +- spec/acceptance/compose_v3_spec.rb | 164 +-- spec/acceptance/docker_custom_source_spec.rb | 97 +- spec/acceptance/docker_full_spec.rb | 540 ++++---- spec/acceptance/docker_spec.rb | 190 +-- spec/acceptance/network_spec.rb | 41 +- spec/acceptance/plugin_spec.rb | 35 +- spec/acceptance/stack_spec.rb | 233 ++-- spec/acceptance/volume_spec.rb | 38 +- spec/acceptance_swarm/swarm_spec.rb | 159 +-- spec/classes/compose_spec.rb | 124 +- spec/classes/compose_windows_spec.rb | 76 +- spec/classes/docker_spec.rb | 1081 ++++++++++------- spec/classes/docker_windows_spec.rb | 665 +++++----- spec/classes/machine_spec.rb | 122 +- spec/classes/system_reload_spec.rb | 37 +- spec/defines/exec_spec.rb | 70 +- spec/defines/exec_windows_spec.rb | 75 +- spec/defines/image_spec.rb | 113 +- spec/defines/image_windows_spec.rb | 103 +- spec/defines/plugin_spec.rb | 32 +- spec/defines/registry_spec.rb | 55 +- spec/defines/run_spec.rb | 710 ++++++----- spec/defines/run_windows_spec.rb | 143 ++- spec/defines/secrets_spec.rb | 58 +- spec/defines/services_spec.rb | 142 ++- spec/defines/stack_spec.rb | 116 +- spec/defines/swarm_spec.rb | 119 +- spec/defines/system_user_spec.rb | 39 +- spec/spec_helper.rb | 26 + spec/spec_helper_acceptance.rb | 14 + spec/unit/docker_network_spec.rb | 63 - .../facter/docker_spec.rb} | 37 +- .../puppet/provider/docker_network_spec.rb | 25 + .../puppet/type}/docker_compose_spec.rb | 17 +- .../lib/puppet/type/docker_network_spec.rb | 38 + .../puppet/type}/docker_stack_spec.rb | 9 +- .../puppet/type}/docker_volume_spec.rb | 6 +- 39 files changed, 3108 insertions(+), 2510 deletions(-) create mode 100644 .puppet-lint.rc delete mode 100644 spec/unit/docker_network_spec.rb rename spec/unit/{docker_facts_spec.rb => lib/facter/docker_spec.rb} (80%) create mode 100644 spec/unit/lib/puppet/provider/docker_network_spec.rb rename spec/unit/{ => lib/puppet/type}/docker_compose_spec.rb (57%) create mode 100644 spec/unit/lib/puppet/type/docker_network_spec.rb rename spec/unit/{ => lib/puppet/type}/docker_stack_spec.rb (70%) rename spec/unit/{ => lib/puppet/type}/docker_volume_spec.rb (83%) diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 00000000..cc96ece0 --- /dev/null +++ b/.puppet-lint.rc @@ -0,0 +1 @@ +--relative diff --git a/.sync.yml b/.sync.yml index 41f35438..3a8fe94a 100644 --- a/.sync.yml +++ b/.sync.yml @@ -37,4 +37,7 @@ Gemfile: - mswin - mingw - x64_mingw - - gem: 'rspec-retry' \ No newline at end of file + - gem: 'rspec-retry' + +spec/spec_helper.rb: + unmanaged: true \ No newline at end of file diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index d83e2289..a7324c73 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -7,15 +7,15 @@ tmp_path = 'C:/cygwin64/tmp' test_container = 'nanoserver-sac2016' else - if fact('os.name') == 'RedHat' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" - elsif fact('os.name') == 'Centos' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" - elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' - docker_args = "version => '18.06.1~ce~3-0~ubuntu'" - else - docker_args = '' - end + docker_args = if fact('os.name') == 'RedHat' + "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Centos' + "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('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' @@ -24,134 +24,134 @@ describe 'docker compose' do before(:all) do - retry_on_error_matching(60, 5, /connection failure running/) 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) + apply_manifest(install_code, catch_failures: true) end end context 'Creating compose v3 projects' do - it 'should have docker compose installed' do - shell('docker-compose --help', :acceptable_exit_codes => [0]) + let(:install_pp) do + <<-MANIFEST + docker_compose { 'web': + compose_files => ['#{tmp_path}/docker-compose-v3.yml'], + ensure => present, + } + MANIFEST end - before(:all) do - @install = <<-code -docker_compose { 'web': - compose_files => ['#{tmp_path}/docker-compose-v3.yml'], - ensure => present, -} - code - apply_manifest(@install, :catch_failures=>true) + + it 'is idempotent' do + idempotent_apply(default, install_pp, {}) end - it 'should be idempotent' do - apply_manifest(@install, :catch_changes=>true) + it 'has docker compose installed' do + shell('docker-compose --help', acceptable_exit_codes: [0]) end - it 'should find a docker container' do - shell('docker inspect web_compose_test_1', :acceptable_exit_codes => [0]) + it 'finds a docker container' do + shell('docker inspect web_compose_test_1', acceptable_exit_codes: [0]) end end context 'creating compose projects with multi compose files' do before(:all) do - @install = <<-pp1 -docker_compose { 'web1': - compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], - ensure => present, -} - pp1 + 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, :catch_failures=>true) + apply_manifest(install_pp, catch_failures: true) end it "should find container with #{test_container} tag" do - shell("docker inspect web1_compose_test_1 | grep #{test_container}", :acceptable_exit_codes => [0]) + shell("docker inspect web1_compose_test_1 | grep #{test_container}", acceptable_exit_codes: [0]) end end context 'Destroying project with multiple compose files' 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 = <<-pp1 -docker_compose { 'web1': - compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], - ensure => present, -} - pp1 + install_pp = <<-MANIFEST + docker_compose { 'web1': + compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], + ensure => present, + } + MANIFEST - @destroy = <<-pp2 -docker_compose { 'web1': - compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'], - ensure => absent, -} - pp2 - apply_manifest(@install, :catch_failures=>true) - apply_manifest(@destroy, :catch_failures=>true) + apply_manifest(install_pp, catch_failures: true) end - it 'should be idempotent' do - apply_manifest(@destroy, :catch_changes=>true) + it 'is idempotent' do + idempotent_apply(default, destroy_pp, {}) end - it 'should not find a docker container' do - shell('docker inspect web1_compose_test_1', :acceptable_exit_codes => [1]) + it 'does not find a docker container' do + shell('docker inspect web1_compose_test_1', acceptable_exit_codes: [1]) end end context 'Requesting a specific version of compose' do - before(:all) do - @version = '1.21.2' - @pp = <<-code -class { 'docker::compose': - version => '#{@version}', -} - code - apply_manifest(@pp, :catch_failures=>true) + let(:version) do + '1.21.2' end - it 'should be idempotent' do - apply_manifest(@pp, :catch_changes=>true) + it 'is idempotent' do + pp = <<-MANIFEST + class { 'docker::compose': + version => '#{version}', + } + MANIFEST + idempotent_apply(default, pp, {}) end - it 'should have installed the requested version' do - shell('docker-compose --version', :acceptable_exit_codes => [0]) do |r| - expect(r.stdout).to match(/#{@version}/) + it 'has installed the requested version' do + shell('docker-compose --version', acceptable_exit_codes: [0]) do |r| + expect(r.stdout).to match(%r{#{version}}) end end end context 'Removing docker compose' do - before(:all) do - @version = '1.21.2' - @pp = <<-code -class { 'docker::compose': - ensure => absent, - version => '#{@version}', -} - code - apply_manifest(@pp, :catch_failures=>true) + let(:version) do + '1.21.2' end - it 'should be idempotent' do - apply_manifest(@pp, :catch_changes=>true) + it 'is idempotent' do + pp = <<-MANIFEST + class { 'docker::compose': + ensure => absent, + version => '#{version}', + } + MANIFEST + idempotent_apply(default, pp, {}) end - it 'should have removed the relevant files' do - shell("test -e \"#{install_dir}/docker-compose#{file_extension}\"", :acceptable_exit_codes => [1]) - shell("test -e \"#{install_dir}/docker-compose-#{@version}#{file_extension}\"", :acceptable_exit_codes => [1]) + it 'has removed the relevant files' do + shell("test -e \"#{install_dir}/docker-compose#{file_extension}\"", acceptable_exit_codes: [1]) + shell("test -e \"#{install_dir}/docker-compose-#{version}#{file_extension}\"", acceptable_exit_codes: [1]) end after(:all) do - install_code = <<-code + install_pp = <<-MANIFEST class { 'docker': #{docker_args}} class { 'docker::compose': } - code - apply_manifest(install_code, :catch_failures=>true) + MANIFEST + apply_manifest(install_pp, catch_failures: true) end end - end +end diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index 6229ae8c..a5675e43 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -3,56 +3,57 @@ skip = false if fact('osfamily') == '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-world' - default_image_tag = 'nanoserver-sac2016' - #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 + 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-world' + # 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 fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' - docker_args = "version => '18.06.1~ce~3-0~ubuntu'" - skip = true + docker_args = "version => '18.06.1~ce~3-0~ubuntu'" + skip = true else - docker_args = '' - skip = true + docker_args = '' + skip = true end describe 'the Puppet Docker module' do - context 'with download location', :skip => skip do - let(:pp) {" - class { 'docker': #{docker_args} } - "} + context 'with download location', skip: skip do + let(:pp) do + " + class { 'docker': #{docker_args} } + " + end - it 'should run successfully' do - apply_manifest(pp, :catch_failures => true) + it 'runs successfully' do + apply_manifest(pp, catch_failures: true) end - it 'should run idempotently' do - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + it 'runs idempotently' do + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' end - it 'should be start a docker process' do - if fact('osfamily') == 'windows' + it 'is start a docker process' do + if fact('osfamily') == 'windows' shell('powershell Get-Process -Name dockerd') do |r| - expect(r.stdout).to match(/ProcessName/) + expect(r.stdout).to match(%r{ProcessName}) end - else + else shell('ps aux | grep docker') do |r| - expect(r.stdout).to match(/dockerd -H unix:\/\/\/var\/run\/docker.sock/) - end + expect(r.stdout).to match %r{dockerd -H unix:\/\/\/var\/run\/docker.sock} end + end end - it 'should install a working docker client' do - shell("#{docker_command} ps", :acceptable_exit_codes => [0] ) + it 'installs a working docker client' do + shell("#{docker_command} ps", acceptable_exit_codes: [0]) end - it 'should stop a running container and remove container' do - pp=<<-EOS + it 'stops a running container and remove container' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -67,7 +68,7 @@ class { 'docker': #{docker_args} } } EOS - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -81,26 +82,26 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 15 + # A sleep to give docker time to execute properly + sleep 15 - shell("#{docker_command} ps", :acceptable_exit_codes => [0]) + shell("#{docker_command} ps", acceptable_exit_codes: [0]) - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 15 + # A sleep to give docker time to execute properly + sleep 15 - shell("#{docker_command} inspect container-3-6", :acceptable_exit_codes => [1]) - if fact('osfamily') == 'windows' - shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', :acceptable_exit_codes => [1]) - else - shell('test -f /etc/systemd/system/container-3-6.service', :acceptable_exit_codes => [1]) + shell("#{docker_command} inspect container-3-6", acceptable_exit_codes: [1]) + if fact('osfamily') == 'windows' + shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', acceptable_exit_codes: [1]) + else + shell('test -f /etc/systemd/system/container-3-6.service', acceptable_exit_codes: [1]) + end end end end -end \ No newline at end of file diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 79f2e7b9..5f3ee2ab 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -8,50 +8,50 @@ 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. + # 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_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:\windows\temp\test_file.txt"' default_docker_exec_command = 'cmd /c "echo test > c:\windows\temp\test_file.txt"' docker_mount_path = 'C:/Users/Administrator/AppData/Local/Temp' - storage_driver = "windowsfilter" + storage_driver = 'windowsfilter' else - if fact('os.family') == 'RedHat' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" - elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' - docker_args = "version => '18.06.1~ce~3-0~ubuntu'" - else - docker_args = '' - end + docker_args = if fact('os.family') == 'RedHat' + "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('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_dockerfile = '/root/Dockerfile' dockerfile_test = "#{default_dockerfile}_test.txt" - docker_command = "docker" + docker_command = 'docker' default_docker_run_arg = '' - default_run_command = "init" + 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" - if fact('os.family') == 'Debian' && fact('os.release.major') =~ (/14.04|^8$/) - storage_driver = "aufs" - elsif fact('os.family') == 'RedHat' - storage_driver = "devicemapper" - else - storage_driver = "overlay2" - end + docker_mount_path = '/root' + storage_driver = 'devicemapper' + storage_driver = if fact('os.family') == 'Debian' && fact('os.release.major') =~ %r{14.04|^8$} + 'aufs' + elsif fact('os.family') == 'RedHat' + 'devicemapper' + else + 'overlay2' + end end describe 'the Puppet Docker module' do context 'clean up before each test' do before(:each) do - retry_on_error_matching(60, 5, /connection failure running/) do + retry_on_error_matching(60, 5, %r{connection failure running}) do # Stop all container using systemd 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 @@ -60,48 +60,45 @@ shell("#{docker_command} rmi -f $(#{docker_command} images -q) || true") # Check to make sure no images are present shell("#{docker_command} images | wc -l") do |r| - expect(r.stdout).to match(/^0|1$/) + expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: end # Check to make sure no running containers are present shell("#{docker_command} ps | wc -l") do |r| - expect(r.stdout).to match(/^0|1$/) + expect(r.stdout).to match(%r{^0|1$}) # rubocop:disable RSpec/ExpectInHook: end end end - describe 'docker class' do context 'without any parameters' do - let(:pp) {" - class { 'docker': #{docker_args} } - "} + let(:pp) { "class { 'docker': #{docker_args} }" } - it 'should run successfully' do - apply_manifest(pp, :catch_failures => true) + it 'runs successfully' do + apply_manifest(pp, catch_failures: true) end - it 'should run idempotently' do - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + it 'runs idempotently' do + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' end - it 'should be start a docker process' do + it 'is start a docker process' do if fact('osfamily') == 'windows' shell('powershell Get-Process -Name dockerd') do |r| - expect(r.stdout).to match(/ProcessName/) + expect(r.stdout).to match(%r{ProcessName}) end else shell('ps aux | grep docker') do |r| - expect(r.stdout).to match(/dockerd -H unix:\/\/\/var\/run\/docker.sock/) + expect(r.stdout).to match(%r{dockerd -H unix:\/\/\/var\/run\/docker.sock}) end end end - it 'should install a working docker client' do - shell("#{docker_command} ps", :acceptable_exit_codes => [0] ) + it 'installs a working docker client' do + shell("#{docker_command} ps", acceptable_exit_codes: [0]) end - it 'should stop a running container and remove container' do - pp=<<-EOS + it 'stops a running container and remove container' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -116,7 +113,7 @@ class { 'docker': #{docker_args} } } EOS - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -130,100 +127,98 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 15 + # A sleep to give docker time to execute properly + sleep 15 - shell("#{docker_command} ps", :acceptable_exit_codes => [0]) + shell("#{docker_command} ps", acceptable_exit_codes: [0]) - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 15 + # A sleep to give docker time to execute properly + sleep 15 - shell("#{docker_command} inspect container-3-6", :acceptable_exit_codes => [1]) - if fact('osfamily') == 'windows' - shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', :acceptable_exit_codes => [1]) - else - shell('test -f /etc/systemd/system/container-3-6.service', :acceptable_exit_codes => [1]) + shell("#{docker_command} inspect container-3-6", acceptable_exit_codes: [1]) + if fact('osfamily') == 'windows' + shell('test -f /cygdrive/c/Users/Administrator/AppData/Local/Temp/container-3-6.service', acceptable_exit_codes: [1]) + else + shell('test -f /etc/systemd/system/container-3-6.service', acceptable_exit_codes: [1]) + end end end - end context 'passing a storage driver' do - before(:all) do - @pp=<<-EOS + let(:pp) do + <<-MANIFEST class {'docker': - #{docker_args}, - storage_driver => "#{storage_driver}", + #{docker_args}, + storage_driver => "#{storage_driver}", } - EOS + MANIFEST + end - apply_manifest(@pp, :catch_failures => true) + it 'applies manifest' do + apply_manifest(pp, catch_failures: true) sleep 15 - end + end - it 'should result in the docker daemon being configured with the specified storage driver' do - shell("#{docker_command} info -f \"{{ .Driver}}\"") do |r| - expect(r.stdout).to match (/#{storage_driver}/) - end + it 'results in the docker daemon being configured with the specified storage driver' do + 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 - before(:all) do - @pp =<<-EOS + let(:pp) do + <<-MANIFEST class { 'docker': tcp_bind => 'tcp://127.0.0.1:4444', #{docker_args} } - EOS - apply_manifest(@pp, :catch_failures => true) - # A sleep to give docker time to execute properly - sleep 4 + MANIFEST end - it 'should run idempotently' do - apply_manifest(@pp, :catch_changes => true) unless fact('selinux') == 'true' + it 'runs idempotently' do + idempotent_apply(default, pp, {}) unless fact('selinux') == 'true' + sleep 4 end - it 'should result in docker listening on the specified address' do + it 'results in docker listening on the specified address' do if fact('osfamily') == 'windows' shell('netstat -a -b') do |r| - expect(r.stdout).to match(/127.0.0.1:4444/) + expect(r.stdout).to match(%r{127.0.0.1:4444}) end else shell('netstat -tulpn | grep docker') do |r| - expect(r.stdout).to match(/tcp\s+0\s+0\s+127.0.0.1:4444\s+0.0.0.0\:\*\s+LISTEN\s+\d+\/docker/) + 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 - before(:each) do - @pp =<<-EOS + let(:pp) do + <<-MANIFEST class { 'docker': socket_bind => 'unix:///var/run/docker.sock', #{docker_args} } - EOS - apply_manifest(@pp, :catch_failures => true) - # A sleep to give docker time to execute properly - sleep 4 + MANIFEST end - it 'should run idempotently' do - apply_manifest(@pp, :catch_changes => true) unless fact('selinux') == 'true' + it 'runs idempotently' do + idempotent_apply(default, pp, {}) unless fact('selinux') == 'true' + sleep 4 end - it 'should show docker listening on the specified unix socket' do + it 'shows docker listening on the specified unix socket' do if fact('osfamily') != 'windows' shell('ps aux | grep docker') do |r| - expect(r.stdout).to match(/unix:\/\/\/var\/run\/docker.sock/) + expect(r.stdout).to match(%r{unix:\/\/\/var\/run\/docker.sock}) end end end @@ -231,53 +226,52 @@ class { 'docker': context 'uninstall docker' do after(:all) do - @pp =<<-EOS + pp = <<-EOS class {'docker': #{docker_args}, ensure => 'present' } EOS - apply_manifest(@pp, :catch_failures => true) + apply_manifest(pp, catch_failures: true) # Wait for reboot if windows sleep 300 if fact('osfamily') == 'windows' end - it 'should uninstall successfully' do - @pp =<<-EOS + it 'uninstalls successfully' do + pp = <<-EOS class {'docker': #{docker_args}, ensure => 'absent' } EOS - apply_manifest(@pp, :catch_failures => true) + apply_manifest(pp, catch_failures: true) sleep 4 - shell('docker ps', :acceptable_exit_codes => [1, 127]) + shell('docker ps', acceptable_exit_codes: [1, 127]) end end end describe 'docker::image' do - - it 'should successfully download an image from the Docker Hub' do - pp=<<-EOS + 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 fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} images") do |r| - expect(r.stdout).to match(/#{default_image}/) + expect(r.stdout).to match(%r{#{default_image}}) end end - it 'should successfully download an image based on a tag from the Docker Hub' do - pp=<<-EOS + 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, @@ -286,19 +280,19 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} images") do |r| - expect(r.stdout).to match(/#{default_image}\s+#{default_image_tag}/) + expect(r.stdout).to match(%r{#{default_image}\s+#{default_image_tag}}) end end - it 'should successfully download an image based on a digest from the Docker Hub' do - pp=<<-EOS + 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, @@ -306,26 +300,25 @@ class { 'docker': #{docker_args} } require => Class['docker'], } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} images --digests") do |r| - expect(r.stdout).to match(/#{default_image}.*#{default_digest}/) + expect(r.stdout).to match(%r{#{default_image}.*#{default_digest}}) end end - it 'should create a new image based on a Dockerfile' do + it 'creates a new image based on a Dockerfile' do + run_cmd = if fact('osfamily') == 'windows' + 'RUN echo test > C:\\Windows\\Temp\\Dockerfile_test.txt' + else + "RUN echo test > #{dockerfile_test}" + end - if fact('osfamily') == 'windows' - run_cmd = 'RUN echo test > C:\\Windows\\Temp\\Dockerfile_test.txt' - else - run_cmd = "RUN echo test > #{dockerfile_test}" - end - - pp=<<-EOS + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { 'alpine_with_file': @@ -340,24 +333,24 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 if fact('osfamily') == 'windows' shell("#{docker_command} run alpine_with_file cmd /c dir Windows\\\\Temp") do |r| - expect(r.stdout).to match(/_test.txt/) + expect(r.stdout).to match(%r{_test.txt}) end else shell("#{docker_command} run alpine_with_file ls #{dockerfile_test}") do |r| - expect(r.stdout).to match(/#{dockerfile_test}/) + expect(r.stdout).to match(%r{#{dockerfile_test}}) end end end - it 'should create a new image based on a tar', :win_broken => true do - pp=<<-EOS + 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'], @@ -371,15 +364,15 @@ class { 'docker': #{docker_args} } } EOS - pp2=<<-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 fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 @@ -396,7 +389,7 @@ class { 'docker': #{docker_args} } # Make sure no other containers are running shell("#{docker_command} ps | wc -l") do |r| - expect(r.stdout).to match(/^1$/) + expect(r.stdout).to match(%r{^1$}) end # Export new to a tar file @@ -407,50 +400,50 @@ class { 'docker': #{docker_args} } # Make sure no other images are present shell("#{docker_command} images | wc -l") do |r| - expect(r.stdout).to match(/^1$/) + expect(r.stdout).to match(%r{^1$}) end - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} run alpine_from_commit ls /root") do |r| - expect(r.stdout).to match(/test_file_for_tar_test.txt/) + expect(r.stdout).to match(%r{test_file_for_tar_test.txt}) end end - it 'should successfully delete the image' do - pp1=<<-EOS + 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 + 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 fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} images") do |r| - expect(r.stdout).to_not match(/#{default_image}/) + expect(r.stdout).not_to match(%r{#{default_image}}) end end end - describe "docker::run" do - it 'should start a container with a configurable command' do - pp=<<-EOS + describe 'docker::run' do + it 'starts a container with a configurable command' do + pp = <<-EOS class { 'docker': #{docker_args} } @@ -466,8 +459,8 @@ class { 'docker': #{docker_args} } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 @@ -475,20 +468,20 @@ class { 'docker': #{docker_args} container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if fact('osfamily') == 'windows' shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Windows\\\\Temp") do |r| - expect(r.stdout).to match(/test_file.txt/) + expect(r.stdout).to match(%r{test_file.txt}) end else shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| - expect(r.stdout).to match(/test_file.txt/) + expect(r.stdout).to match(%r{test_file.txt}) end end container_name = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") - expect("#{container_name.stdout.strip}").to match(/(container-3-1|container_3_1)/) + expect(container_name.stdout.strip.to_s).to match(%r{(container-3-1|container_3_1)}) end - it 'should start a container with port configuration' do - pp=<<-EOS + it 'starts a container with port configuration' do + pp = <<-EOS class { 'docker': #{docker_args}} docker::image { '#{default_image}': @@ -505,19 +498,19 @@ class { 'docker': #{docker_args}} } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} ps") do |r| - expect(r.stdout).to match(/"#{default_run_command}".+5555\/tcp\, 0\.0\.0.0\:\d+\-\>4444\/tcp/) + expect(r.stdout).to match(%r{#{default_run_command}.+5555\/tcp\, 0\.0\.0.0\:\d+\-\>4444\/tcp}) end end - it 'should start a container with the hostname set' do - pp=<<-EOS + it 'starts a container with the hostname set' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -533,8 +526,8 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 @@ -542,12 +535,12 @@ class { 'docker': #{docker_args} } container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") shell("#{docker_command} exec #{container_id.stdout.strip} hostname") do |r| - expect(r.stdout).to match(/testdomain.com/) + expect(r.stdout).to match(%r{testdomain.com}) end end - it 'should start a container while mounting local volumes' do - pp=<<-EOS + it 'starts a container while mounting local volumes' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -568,27 +561,27 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if fact('osfamily') == 'windows' shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Administrator\\\\AppData\\\\Local\\\\Temp\\\\mnt") do |r| - expect(r.stdout).to match(/test_mount.txt/) + expect(r.stdout).to match(%r{test_mount.txt}) end else shell("#{docker_command} exec #{container_id.stdout.strip} ls /root/mnt") do |r| - expect(r.stdout).to match(/test_mount.txt/) + 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 'should start a container with cpuset paramater set', :win_broken => true do - pp=<<-EOS + # 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}': @@ -604,20 +597,20 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell('#{docker_command} inspect container_3_5_5') do |r| - expect(r.stdout).to match(/"CpusetCpus"\: "0"/) + 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 'should start multiple linked containers', :win_broken => true do - pp=<<-EOS + # 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}': @@ -632,15 +625,15 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 - container_1 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") + container1 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -650,29 +643,29 @@ class { 'docker': #{docker_args} } docker::run { 'container_3_5_2': image => '#{default_image}', command => '#{default_run_command}', - depends => ['#{container_1.stdout.strip}'], - links => "#{container_1.stdout.strip}:the_link", + 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 fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 - container_2 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") + container2 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") shell("#{docker_command} inspect -f \"{{ .HostConfig.Links }}\" #{container_id.stdout.strip}") do |r| - expect(r.stdout).to match("/#{container_1.stdout.strip}:/#{container_2.stdout.strip}/the_link") + expect(r.stdout).to match("/#{container1.stdout.strip}:/#{container2.stdout.strip}/the_link") end end - it 'should stop a running container' do - pp=<<-EOS + it 'stops a running container' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -687,7 +680,7 @@ class { 'docker': #{docker_args} } } EOS - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -702,29 +695,29 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} ps | wc -l") do |r| - expect(r.stdout).to match(/^2$/) + expect(r.stdout).to match(%r{^2$}) end - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 4 shell("#{docker_command} ps | wc -l") do |r| - expect(r.stdout).to match(/^1$/) + expect(r.stdout).to match(%r{^1$}) end end - it 'should stop a running container and remove container' do - pp=<<-EOS + it 'stops a running container and remove container' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -739,7 +732,7 @@ class { 'docker': #{docker_args} } } EOS - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -753,25 +746,25 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 15 - shell("#{docker_command} inspect container_3_6_1", :acceptable_exit_codes => [0]) + shell("#{docker_command} inspect container_3_6_1", acceptable_exit_codes: [0]) - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' # A sleep to give docker time to execute properly sleep 15 - shell("#{docker_command} inspect container_3_6_1", :acceptable_exit_codes => [1]) + shell("#{docker_command} inspect container_3_6_1", acceptable_exit_codes: [1]) end - it 'should allow dependency for ordering of independent run and image' do - pp=<<-EOS + it 'allows dependency for ordering of independent run and image' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } @@ -793,13 +786,12 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' - + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' end - it 'should restart a unhealthy container' do - pp5=<<-EOS + it 'restarts a unhealthy container' do + pp5 = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', @@ -810,7 +802,7 @@ class { 'docker': #{docker_args} } } EOS - pp_delete=<<-EOS + pp_delete = <<-EOS class { 'docker': #{docker_args} } docker::run { 'container_3_7_3': image => '#{default_image}', @@ -819,24 +811,24 @@ class { 'docker': #{docker_args} } EOS if fact('osfamily') == 'windows' - apply_manifest(pp5, :catch_failures => true) - elsif fact('os.release.major') =~ (/14.04|8/) - apply_manifest(pp5, :catch_failures => true) do |r| - expect(r.stdout).to match(/container_3_7_3/) + apply_manifest(pp5, catch_failures: true) + elsif fact('os.release.major') =~ %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(/docker-container_3_7_3-systemd-reload/) + 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 + apply_manifest(pp_delete, catch_failures: true) end end + end - describe "docker::exec" do - it 'should run a command inside an already running container' do - pp=<<-EOS + describe 'docker::exec' do + it 'runs a command inside an already running container' do + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': @@ -851,51 +843,51 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 15 + # A sleep to give docker time to execute properly + sleep 15 - container_1 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") + container1 = shell("#{docker_command} ps | awk 'FNR == 2 {print $NF}'") - pp2=<<-EOS + pp2 = <<-EOS class { 'docker': #{docker_args} } docker::exec { 'test_command': - container => '#{container_1.stdout.strip}', + container => '#{container1.stdout.strip}', command => '#{default_docker_exec_command}', tty => true, } EOS - pp_delete=<<-EOS + pp_delete = <<-EOS docker::run { 'container_4_1': image => '#{default_image}', ensure => absent, } EOS - apply_manifest(pp2, :catch_failures => true) + apply_manifest(pp2, catch_failures: true) - # A sleep to give docker time to execute properly - sleep 4 + # A sleep to give docker time to execute properly + sleep 4 - container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") - if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Windows\\\\Temp") do |r| - expect(r.stdout).to match(/test_file.txt/) - end - else - shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| - expect(r.stdout).to match(/test_file.txt/) - end + container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") + if fact('osfamily') == 'windows' + shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Windows\\\\Temp") do |r| + expect(r.stdout).to match(%r{test_file.txt}) + end + else + shell("#{docker_command} exec #{container_id.stdout.strip} ls /root") do |r| + expect(r.stdout).to match(%r{test_file.txt}) end - apply_manifest(pp_delete, :catch_failures => true) end + apply_manifest(pp_delete, catch_failures: true) + end - it 'should only run if notified when refreshonly is true' do - container_name = 'container_4_2' - pp=<<-EOS + it 'onlies run if notified when refreshonly is true' do + container_name = 'container_4_2' + pp = <<-EOS class { 'docker': #{docker_args} } docker::image { '#{default_image}': } @@ -913,54 +905,54 @@ class { 'docker': #{docker_args} } } EOS - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 4 + # A sleep to give docker time to execute properly + sleep 4 - if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| - expect(r.stdout).to_not match(/test_file.txt/) - end - else - shell("#{docker_command} exec #{container_name} ls /root") do |r| - expect(r.stdout).to_not match(/test_file.txt/) - end + if fact('osfamily') == 'windows' + shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| + expect(r.stdout).not_to match(%r{test_file.txt}) end + else + 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 + pp_extra = <<-EOS file { '#{default_dockerfile}_dummy_file': ensure => 'present', notify => Docker::Exec['test_command'], } EOS - pp_delete=<<-EOS + pp_delete = <<-EOS docker::run { '#{container_name}': image => '#{default_image}', ensure => absent, } EOS - pp2 = pp + pp_extra + pp2 = pp + pp_extra - apply_manifest(pp2, :catch_failures => true) - apply_manifest(pp2, :catch_changes => true) unless fact('selinux') == 'true' + apply_manifest(pp2, catch_failures: true) + apply_manifest(pp2, catch_changes: true) unless fact('selinux') == 'true' - # A sleep to give docker time to execute properly - sleep 4 + # A sleep to give docker time to execute properly + sleep 4 - if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| - expect(r.stdout).to match(/test_file.txt/) - end - else - shell("#{docker_command} exec #{container_name} ls /root") do |r| - expect(r.stdout).to match(/test_file.txt/) - end + if fact('osfamily') == 'windows' + shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| + expect(r.stdout).to match(%r{test_file.txt}) + end + else + shell("#{docker_command} exec #{container_name} ls /root") do |r| + expect(r.stdout).to match(%r{test_file.txt}) end - apply_manifest(pp_delete, :catch_failures => true) end + apply_manifest(pp_delete, catch_failures: true) end end +end diff --git a/spec/acceptance/docker_spec.rb b/spec/acceptance/docker_spec.rb index 3b377924..ae8be3f5 100644 --- a/spec/acceptance/docker_spec.rb +++ b/spec/acceptance/docker_spec.rb @@ -12,25 +12,25 @@ docker_network = 'nat' registry_host = @windows_ip config_file = '/cygdrive/c/Users/Administrator/.docker/config.json' - root_dir = "C:/Users/Administrator/AppData/Local/Temp" + root_dir = 'C:/Users/Administrator/AppData/Local/Temp' server_strip = "#{registry_host}_#{registry_port}" bad_server_strip = "#{registry_host}_5001" broken = true else - if fact('osfamily') == 'RedHat' - docker_args = "repo_opt => '--enablerepo=localmirror-extras'" - elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' - docker_args = "version => '18.06.1~ce~3-0~ubuntu'" - else - docker_args = '' - end + docker_args = if fact('osfamily') == 'RedHat' + "repo_opt => '--enablerepo=localmirror-extras'" + elsif fact('os.name') == 'Ubuntu' && fact('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" + root_dir = '/root' end describe 'docker' do @@ -38,22 +38,25 @@ service_name = 'docker' command = 'docker' - context 'When adding system user', :win_broken => broken do - let(:pp) {" - class { 'docker': #{docker_arg} - docker_users => ['user1'] - } - "} - - it 'the docker daemon' do - apply_manifest(pp, :catch_failures=>true) do |r| - expect(r.stdout).to_not match(/docker-systemd-reload-before-service/) - end - end - end - - context 'with default parameters', :win_broken => broken do - let(:pp) {" + context 'When adding system user', win_broken: broken do + let(:pp) do + " + class { 'docker': #{docker_arg} + 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 'with default parameters', win_broken: broken do + let(:pp) do + " class { 'docker': docker_users => [ 'testuser' ], #{docker_args} @@ -69,14 +72,15 @@ class { 'docker': restart => 'always', require => Docker::Image['nginx'], } - "} + " + end - it 'should apply with no errors' do - apply_manifest(pp, :catch_failures=>true) + it 'applies with no errors' do + apply_manifest(pp, catch_failures: true) end - it 'should be idempotent' do - apply_manifest(pp, :catch_changes=>true) + it 'is idempotent' do + apply_manifest(pp, catch_changes: true) end describe package(package_name) do @@ -89,73 +93,84 @@ class { 'docker': end describe command("#{command} version") do - its(:exit_status) { should eq 0 } + its(:exit_status) { is_expected.to eq 0 } end - describe command("#{command} images"), :sudo => true do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /nginx/ } + describe command("#{command} images"), sudo: true do + its(:exit_status) { is_expected.to eq 0 } + its(:stdout) { is_expected.to match %r{nginx} } end - describe command("#{command} inspect nginx"), :sudo => true do - its(:exit_status) { should eq 0 } + describe command("#{command} inspect nginx"), sudo: true do + its(:exit_status) { is_expected.to eq 0 } end - describe command("#{command} inspect nginx2"), :sudo => true do - its(:exit_status) { should eq 0 } + describe command("#{command} inspect nginx2"), sudo: true do + its(:exit_status) { is_expected.to eq 0 } end - describe command("#{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`"), :sudo => true do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /nginx -g 'daemon off;'/ } + describe command("#{command} ps --no-trunc | grep `cat /var/run/docker-nginx2.cid`"), sudo: true do + its(:exit_status) { is_expected.to eq 0 } + its(:stdout) { is_expected.to match %r{nginx -g 'daemon off;'} } end describe command('netstat -tlndp') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /0\.0\.0\.0\:80/ } + its(:exit_status) { is_expected.to eq 0 } + its(:stdout) { is_expected.to match %r{0\.0\.0\.0\:80} } end describe command('id testuser | grep docker') do - its(:exit_status) { should eq 0 } - its(:stdout) { should match /docker/ } + its(:exit_status) { is_expected.to eq 0 } + its(:stdout) { is_expected.to match %r{docker} } end end - context "When asked to have the latest image of something", :win_broken => broken do - let(:pp) {" + 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 } - "} - it 'should apply with no errors' do - apply_manifest(pp, :catch_failures=>true) + " + 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) {" + context 'When registry_mirror is set', win_broken: broken do + let(:pp) do + " class { 'docker': registry_mirror => 'http://testmirror.io' } - "} - it 'should apply with no errors' do - apply_manifest(pp, :catch_failures=>true) - end + " + end + + it 'applies with no errors' do + apply_manifest(pp, catch_failures: true) + end - it 'should have a registry mirror set' do + it 'has a registry mirror set' do shell('ps -aux | grep docker') do |r| - expect(r.stdout).to match(/--registry-mirror=http:\/\/testmirror.io/) + expect(r.stdout).to match(%r{--registry-mirror=http:\/\/testmirror.io}) end end end context 'registry' do - before(:all) do - @registry_address = "#{registry_host}:#{registry_port}" - @registry_bad_address = "#{registry_host}:5001" - # @registry_email = 'user@example.com' - @manifest = <<-EOS + 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_arg}} docker::run { 'registry': image => '#{docker_registry_image}', @@ -164,50 +179,47 @@ class { 'docker': #{docker_arg}} net => '#{docker_network}', ports => '#{registry_port}:#{registry_port}', } - EOS - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest(@manifest, :catch_failures=>true) + 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 'should be able to login to the registry', :retry => 3, :retry_wait => 10 do - manifest = <<-EOS - docker::registry { '#{@registry_address}': + it 'is able to login to the registry', retry: 3, retry_wait: 10 do + pp = <<-MANIFEST + docker::registry { '#{registry_address}': username => 'username', password => 'password', } - EOS - apply_manifest(manifest, :catch_failures=>true) - shell("grep #{@registry_address} #{config_file}", :acceptable_exit_codes => [0]) - shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{server_strip}_root\"", :acceptable_exit_codes => [0]) + MANIFEST + apply_manifest(pp, catch_failures: true) + shell("grep #{registry_address} #{config_file}", acceptable_exit_codes: [0]) + shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{server_strip}_root\"", acceptable_exit_codes: [0]) end - it 'should be able to logout from the registry' do - manifest = <<-EOS - docker::registry { '#{@registry_address}': + it 'is able to logout from the registry' do + pp = <<-MANIFEST + docker::registry { '#{registry_address}': ensure=> absent, } - EOS - apply_manifest(manifest, :catch_failures=>true) - shell("grep #{@registry_address} #{config_file}", :acceptable_exit_codes => [1,2]) - # shell("grep #{@registry_email} #{@config_file}", :acceptable_exit_codes => [1,2]) + MANIFEST + apply_manifest(pp, catch_failures: true) + shell("grep #{registry_address} #{config_file}", acceptable_exit_codes: [1, 2]) end - it 'should not create receipt if registry login fails' do - manifest = <<-EOS - docker::registry { '#{@registry_bad_address}': + it 'does not create receipt if registry login fails' do + pp = <<-MANIFEST + docker::registry { '#{registry_bad_address}': username => 'username', password => 'password', } - EOS - apply_manifest(manifest, :catch_failures=>true) - shell("grep #{@registry_bad_address} #{config_file}", :acceptable_exit_codes => [1,2]) - shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{bad_server_strip}_root\"", :acceptable_exit_codes => [1]) + MANIFEST + apply_manifest(pp, catch_failures: true) + shell("grep #{registry_bad_address} #{config_file}", acceptable_exit_codes: [1, 2]) + shell("test -e \"#{root_dir}/registry-auth-puppet_receipt_#{bad_server_strip}_root\"", acceptable_exit_codes: [1]) end - end - end diff --git a/spec/acceptance/network_spec.rb b/spec/acceptance/network_spec.rb index 082e47ff..bf748945 100644 --- a/spec/acceptance/network_spec.rb +++ b/spec/acceptance/network_spec.rb @@ -1,9 +1,11 @@ require 'spec_helper_acceptance' broken = false +command = 'docker' +network_name = 'test-network' if fact('osfamily') == 'windows' - puts "Not implemented on Windows" + puts 'Not implemented on Windows' broken = true elsif fact('osfamily') == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" @@ -13,39 +15,32 @@ docker_args = '' end -describe 'docker network', :win_broken => broken do - command = 'docker' - +describe 'docker network', win_broken: broken do before(:all) do - install_code = "class { 'docker': #{docker_args}}" - apply_manifest(install_code, :catch_failures=>true) + install_pp = "class { 'docker': #{docker_args}}" + apply_manifest(install_pp, catch_failures: true) end describe command("#{command} network --help") do - its(:exit_status) { should eq 0 } + its(:exit_status) { is_expected.to eq 0 } end context 'with a local bridge network described in Puppet' do - before(:all) do - @name = 'test-network' - @pp = <<-code - docker_network { '#{@name}': - ensure => present, - } - code - apply_manifest(@pp, :catch_failures=>true) - end - - it 'should be idempotent' do - apply_manifest(@pp, :catch_changes=>true) + after(:all) do + shell("#{command} network rm #{network_name}") end - it 'should have created a network' do - shell("#{command} network inspect #{@name}", :acceptable_exit_codes => [0]) + it 'is idempotent' do + pp = <<-MANIFEST + docker_network { '#{network_name}': + ensure => present, + } + MANIFEST + idempotent_apply(default, pp, {}) end - after(:all) do - shell("#{command} network rm #{@name}") + it 'has created a network' do + shell("#{command} network inspect #{network_name}", acceptable_exit_codes: [0]) end end end diff --git a/spec/acceptance/plugin_spec.rb b/spec/acceptance/plugin_spec.rb index b1b3e0e1..ea48a213 100644 --- a/spec/acceptance/plugin_spec.rb +++ b/spec/acceptance/plugin_spec.rb @@ -1,9 +1,11 @@ require 'spec_helper_acceptance' broken = false +command = 'docker' +plugin_name = 'vieux/sshfs' if fact('osfamily') == 'windows' - puts "Not implemented on Windows" + puts 'Not implemented on Windows' broken = true elsif fact('osfamily') == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" @@ -13,37 +15,30 @@ docker_args = '' end -describe 'docker plugin', :win_broken => broken do - command = 'docker' - +describe 'docker plugin', win_broken: broken do before(:all) do install_code = "class { 'docker': #{docker_args}}" - apply_manifest(install_code, :catch_failures => true) + apply_manifest(install_code, catch_failures: true) end describe command("#{command} plugin --help") do - its(:exit_status) { should eq 0 } + its(:exit_status) { is_expected.to eq 0 } end context 'manage a plugin' do - before(:all) do - @name = 'vieux/sshfs' - @pp = <<-code - docker::plugin { '#{@name}':} - code - apply_manifest(@pp, :catch_failures => true) - end - - it 'should be idempotent' do - apply_manifest(@pp, :catch_changes => true) + after(:all) do + shell("#{command} plugin rm -f #{plugin_name}") end - it 'should have installed a plugin' do - shell("#{command} plugin inspect #{@name}", :acceptable_exit_codes => [0]) + it 'is idempotent' do + pp = <<-MANIFEST + docker::plugin { '#{plugin_name}':} + MANIFEST + idempotent_apply(default, pp, {}) end - after(:all) do - shell("#{command} plugin rm -f #{@name}") + it 'has installed a plugin' do + shell("#{command} plugin inspect #{plugin_name}", acceptable_exit_codes: [0]) end end end diff --git a/spec/acceptance/stack_spec.rb b/spec/acceptance/stack_spec.rb index 10ccda16..c44403aa 100644 --- a/spec/acceptance/stack_spec.rb +++ b/spec/acceptance/stack_spec.rb @@ -3,24 +3,22 @@ if fact('osfamily') == 'windows' docker_args = 'docker_ee => true' tmp_path = 'C:/cygwin64/tmp' - test_container = 'nanoserver-sac2016' wait_for_container_seconds = 120 else - if fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' - docker_args = "version => '18.06.1~ce~3-0~ubuntu'" - else - docker_args = '' - end + docker_args = if fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' + "version => '18.06.1~ce~3-0~ubuntu'" + else + '' + end tmp_path = '/tmp' - test_container = 'alpine' wait_for_container_seconds = 10 end describe 'docker stack' do before(:all) do - retry_on_error_matching(60, 5, /connection failure running/) do - @install_code = <<-code + retry_on_error_matching(60, 5, %r{connection failure running}) do + install_pp = <<-MANIFEST class { 'docker': #{docker_args} } docker::swarm {'cluster_manager': init => true, @@ -29,130 +27,143 @@ class { 'docker': #{docker_args} } listen_addr => $facts['networking']['ip'], require => Class['docker'], } - code - apply_manifest(@install_code, :catch_failures=>true) + MANIFEST + apply_manifest(install_pp, catch_failures: true) end end context 'Creating stack' do - let(:install) {" - docker_stack { 'web': - compose_files => ['#{tmp_path}/docker-stack.yml'], - ensure => present, - }" - } - - it 'should deploy stack' do - apply_manifest(install, :catch_failures=>true) + 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 'should be idempotent' do - apply_manifest(install, :catch_changes=>true) + it 'is idempotent' do + apply_manifest(install_pp, catch_changes: true) end - it 'should find a stack' do - shell('docker stack ls') do |r| - expect(r.stdout).to match(/web/) - end + it 'finds a stack' do + shell('docker stack ls') do |r| + expect(r.stdout).to match(%r{web}) + end end - it 'should not find a docker container' do - shell("docker ps -a -q -f \"name=web_compose_test\"", :acceptable_exit_codes => [0]) + it 'does not find a docker container' do + shell('docker ps -a -q -f "name=web_compose_test"', acceptable_exit_codes: [0]) end end context 'Destroying stack' do - let(:install) {" + let(:install) do + <<-MANIFEST docker_stack { 'web': compose_files => ['#{tmp_path}/docker-stack.yml'], ensure => present, - }" } - let(:destroy) {" - docker_stack { 'web': - compose_files => ['#{tmp_path}/docker-stack.yml'], - ensure => absent, - }" + MANIFEST + end + + let(:destroy) do + <<-MANIFEST + docker_stack { 'web': + compose_files => ['#{tmp_path}/docker-stack.yml'], + ensure => absent, } - it 'should run successfully' do - apply_manifest(destroy, :catch_failures=>true) - sleep 10 - end - - it 'should be idempotent' do - retry_on_error_matching(10, 3, /Removing network web_default/) do - apply_manifest(destroy, :catch_changes=>true) - end - end - - it 'should not find a docker stack' do - shell('docker stack ls') do |r| - expect(r.stdout).to_not match(/web/) - end - end - end - - context 'creating stack with multi compose files' do - - before(:all) do - @install_code = <<-code - docker_stack { 'web': - compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], - ensure => present, - } - code - - apply_manifest(@install_code, :catch_failures=>true) - end - - it "should find container with web_compose_test tag" do - sleep wait_for_container_seconds - shell("docker ps | grep web_compose_test", :acceptable_exit_codes => [0]) - end + 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 - context 'Destroying project with multiple compose files' do - before(:all) do - @install_code = <<-code - docker_stack { 'web': - compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], - ensure => present, - } - code - - apply_manifest(@install_code, :catch_failures=>true) - - @destroy_code = <<-code - docker_stack { 'web': - compose_files => ['#{tmp_path}/docker-stack.yml', '#{tmp_path}/docker-stack-override.yml'], - ensure => absent, - } - code - - retry_on_error_matching(10, 3, /Removing network web_default/) do - apply_manifest(@destroy_code, :catch_failures=>true) - end - sleep 15 # Wait for containers to stop and be destroyed - end - - it 'should be idempotent' do - retry_on_error_matching(10, 3, /Removing network web_default/) do - apply_manifest(@destroy_code, :catch_changes=>true) - end - end - - it 'should not find a docker stack' do - shell('docker stack ls') do |r| - expect(r.stdout).to_not match(/web/) - end - end - - it 'should not find a docker container' do - shell("docker ps", :acceptable_exit_codes => [0]) do |r| - expect(r.stdout).not_to match(/web_compose_test/) - end - end + it 'does not find a docker stack' do + 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 + shell('docker ps | grep web_compose_test', acceptable_exit_codes: [0]) + 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 + shell('docker stack ls') do |r| + expect(r.stdout).not_to match(%r{web}) + end + end + + it 'does not find a docker container' do + shell('docker ps', acceptable_exit_codes: [0]) 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 55fde5fd..98f31e0f 100644 --- a/spec/acceptance/volume_spec.rb +++ b/spec/acceptance/volume_spec.rb @@ -1,11 +1,11 @@ require 'spec_helper_acceptance' -broken = false +volume_name = 'test-volume' if fact('osfamily') == 'windows' docker_args = 'docker_ee => true' - command = "\"/cygdrive/c/Program Files/Docker/docker\"" -elsif ('osfamily') == 'RedHat' + command = '"/cygdrive/c/Program Files/Docker/docker"' +elsif 'osfamily' == 'RedHat' docker_args = "repo_opt => '--enablerepo=localmirror-extras'" command = 'docker' elsif fact('os.name') == 'Ubuntu' && fact('os.release.full') == '14.04' @@ -18,37 +18,33 @@ describe 'docker volume' do before(:all) do - retry_on_error_matching(60, 5, /connection failure running/) do - install_code = "class { 'docker': #{docker_args} }" - apply_manifest(install_code, :catch_failures => true) + 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 'should expose volume subcommand' do - shell("#{command} volume --help", :acceptable_exit_codes => [0]) + it 'exposes volume subcommand' do + shell("#{command} volume --help", acceptable_exit_codes: [0]) end context 'with a local volume described in Puppet' do - before(:all) do - @name = 'test-volume' - @pp = <<-code - docker_volume { '#{@name}': + it 'applies idempotently' do + pp = <<-MANIFEST + docker_volume { '#{volume_name}': ensure => present, } - code - apply_manifest(@pp, :catch_failures => true) - end + MANIFEST - it 'should be idempotent' do - apply_manifest(@pp, :catch_changes => true) + idempotent_apply(default, pp, {}) end - it 'should have created a volume' do - shell("#{command} volume inspect #{@name}", :acceptable_exit_codes => [0]) + it 'has created a volume' do + shell("#{command} volume inspect #{volume_name}", acceptable_exit_codes: [0]) end after(:all) do - shell("#{command} volume rm #{@name}") + shell("#{command} volume rm #{volume_name}") end end -end \ No newline at end of file +end diff --git a/spec/acceptance_swarm/swarm_spec.rb b/spec/acceptance_swarm/swarm_spec.rb index ad94f820..7cffe174 100644 --- a/spec/acceptance_swarm/swarm_spec.rb +++ b/spec/acceptance_swarm/swarm_spec.rb @@ -1,17 +1,11 @@ require 'spec_helper_acceptance' if fact('osfamily') == 'windows' - install_dir = '/cygdrive/c/Program Files/Docker' - file_extension = '.exe' docker_args = 'docker_ee => true' - tmp_path = 'C:/cygwin64/tmp' test_docker_image = 'hello-world:nanoserver' test_docker_command = 'cmd.exe /C "ping /t 8.8.8.8"' else - install_dir = '/usr/local/bin' - file_extension = '' docker_args = '' - tmp_path = '/tmp' test_docker_image = 'ubuntu:16.04' test_docker_command = '/bin/sh -c "while true; do echo hello world; sleep 1; done"' end @@ -26,83 +20,111 @@ skip_tests = true end -describe 'docker swarm', :skip => skip_tests do - before(:all) do - retry_on_error_matching(60, 5, /connection failure running/) do - @install_code = <<-code +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) + apply_manifest_on(swarm_manager, install_code, catch_failures: true) end - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest_on(swarm_worker, @install_code, :catch_failures=>true) + retry_on_error_matching(60, 5, %r{connection failure running}) do + apply_manifest_on(swarm_worker, install_code, catch_failures: true) end - end - context 'Creating a swarm master' do - before(:all) do - @setup_manager = <<-code + setup_manager_pp = <<-MANIFEST docker::swarm {'cluster_manager': init => true, advertise_addr => '#{manager_ip}', listen_addr => '#{manager_ip}', - ensure => 'present', + ensure => 'present', } - code + MANIFEST - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest_on(swarm_manager, @setup_manager, :catch_failures=>true) - end + 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 + 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 - it 'should be idempotent' do - apply_manifest_on(swarm_manager, @setup_manager, :catch_failures=>true) + 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 master' 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 - it 'should display nodes' do - on swarm_manager, 'docker node ls', :acceptable_exit_codes => [0] do |result| - expect(result.stdout).to match(/Leader/) + 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 'should join a node' do - token = shell('docker swarm join-token -q worker').stdout.strip - @setup_slave = <<-code - docker::swarm {'cluster_worker': - join => true, - advertise_addr => '#{swarm_worker.ip}', - listen_addr => '#{swarm_worker.ip}', - manager_ip => '#{manager_ip}', - token => '#{token}', + 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}', } - code - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest_on(swarm_worker, @setup_slave, :catch_failures=>true) + 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, /connection failure running/) do + retry_on_error_matching(60, 5, %r{connection failure running}) do on swarm_worker, 'docker info' do |result| - expect(result.stdout).to match(/Swarm: active/) + 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] + 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 'should start a container' do - @start_service = <<-code + it 'starts a container' do + start_service = <<-MANIFEST docker::services {'helloworld': create => true, service_name => 'helloworld', @@ -111,33 +133,14 @@ class { 'docker': #{docker_args} } command => '#{test_docker_command}', replicas => '2', } - code + 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(/Running/) - end - end + apply_manifest_on(swarm_manager, start_service, catch_failures: true) - after(:all) do - remove_worker = <<-code - docker::swarm {'cluster_worker': - ensure => 'absent', - } - code - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest_on(swarm_worker, remove_worker, :catch_failures=>true) - end - remove_mgr = <<-code - docker::swarm {'cluster_manager': - ensure => 'absent', - } - code - retry_on_error_matching(60, 5, /connection failure running/) do - apply_manifest_on(swarm_manager, remove_mgr, :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 \ No newline at end of file +end diff --git a/spec/classes/compose_spec.rb b/spec/classes/compose_spec.rb index 100359ad..de01abb6 100644 --- a/spec/classes/compose_spec.rb +++ b/spec/classes/compose_spec.rb @@ -1,88 +1,118 @@ require 'spec_helper' -describe 'docker::compose', :type => :class do +describe 'docker::compose', type: :class do let(:facts) do { - :kernel => 'Linux', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :lsbdistid => 'Ubuntu', - :lsbdistcodename => 'maverick', - :kernelrelease => '3.8.0-29-generic', - :operatingsystemrelease => '10.04', - :operatingsystemmajrelease => '10', + kernel: 'Linux', + osfamily: 'Debian', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + lsbdistcodename: 'maverick', + kernelrelease: '3.8.0-29-generic', + operatingsystemrelease: '10.04', + operatingsystemmajrelease: '10', } end it { is_expected.to compile } context 'with defaults for all parameters' do - it { should compile.with_all_deps } - it { should contain_exec('Install Docker Compose 1.9.0').with( - 'path' => '/usr/bin/', - 'cwd' => '/tmp', - 'command' => 'curl -s -S -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.9.0', - 'creates' => '/usr/local/bin/docker-compose-1.9.0', - 'require' => 'Package[curl]' - )} - it { should contain_file('/usr/local/bin/docker-compose-1.9.0').with( - 'owner' => 'root', - 'mode' => '0755', - 'require' => 'Exec[Install Docker Compose 1.9.0]' - )} - it { should contain_file('/usr/local/bin/docker-compose').with( - 'ensure' => 'link', - 'target' => '/usr/local/bin/docker-compose-1.9.0', - 'require' => 'File[/usr/local/bin/docker-compose-1.9.0]' - )} + it { is_expected.to compile.with_all_deps } + it { + is_expected.to contain_exec('Install Docker Compose 1.9.0').with( + 'path' => '/usr/bin/', + 'cwd' => '/tmp', + 'command' => 'curl -s -S -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.9.0', + 'creates' => '/usr/local/bin/docker-compose-1.9.0', + 'require' => 'Package[curl]', + ) + } + it { + is_expected.to contain_file('/usr/local/bin/docker-compose-1.9.0').with( + 'owner' => 'root', + 'mode' => '0755', + 'require' => 'Exec[Install Docker Compose 1.9.0]', + ) + } + it { + is_expected.to contain_file('/usr/local/bin/docker-compose').with( + 'ensure' => 'link', + 'target' => '/usr/local/bin/docker-compose-1.9.0', + 'require' => 'File[/usr/local/bin/docker-compose-1.9.0]', + ) + } end context 'with ensure => absent' do - let (:params) { { :ensure => 'absent' } } - it { should contain_file('/usr/local/bin/docker-compose-1.9.0').with_ensure('absent') } - it { should contain_file('/usr/local/bin/docker-compose').with_ensure('absent') } + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_file('/usr/local/bin/docker-compose-1.9.0').with_ensure('absent') } + it { is_expected.to contain_file('/usr/local/bin/docker-compose').with_ensure('absent') } end context 'when no proxy is provided' do - let(:params) { {:version => '1.7.0'} } - it { is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( - 'curl -s -S -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0') + let(:params) { { version: '1.7.0' } } + + it { + is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( + 'curl -s -S -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0', + ) } end context 'when proxy is provided' do - let(:params) { {:proxy => 'http://proxy.example.org:3128/', - :version => '1.7.0'} } + let(:params) do + { proxy: 'http://proxy.example.org:3128/', + version: '1.7.0' } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( - 'curl -s -S -L --proxy http://proxy.example.org:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0') + it { + is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( + 'curl -s -S -L --proxy http://proxy.example.org:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0', + ) } end context 'when proxy is not a http proxy' do - let(:params) { {:proxy => 'this is not a URL'} } + let(:params) { { proxy: 'this is not a URL' } } + it do expect { is_expected.to compile - }.to raise_error(/does not match/) + }.to raise_error(%r{does not match}) end end context 'when proxy contains username and password' do - let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', - :version => '1.7.0'} } + let(:params) do + { + proxy: 'http://user:password@proxy.example.org:3128/', + version: '1.7.0', + } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( - 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0') + it { + is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( + 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/'\ + ' https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64'\ + ' -o /usr/local/bin/docker-compose-1.7.0', + ) } end context 'when proxy IP is provided' do - let(:params) { {:proxy => 'http://10.10.10.10:3128/', - :version => '1.7.0'} } + let(:params) do + { proxy: 'http://10.10.10.10:3128/', + version: '1.7.0' } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( - 'curl -s -S -L --proxy http://10.10.10.10:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0') + it { + is_expected.to contain_exec('Install Docker Compose 1.7.0').with_command( + 'curl -s -S -L --proxy http://10.10.10.10:3128/ https://github.com/docker/compose/releases/download/1.7.0/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose-1.7.0', + ) } end end diff --git a/spec/classes/compose_windows_spec.rb b/spec/classes/compose_windows_spec.rb index 9c681b9c..209c7652 100644 --- a/spec/classes/compose_windows_spec.rb +++ b/spec/classes/compose_windows_spec.rb @@ -1,72 +1,86 @@ require 'spec_helper' -describe 'docker::compose', :type => :class do +describe 'docker::compose', type: :class do let(:facts) do { - :architecture => 'amd64', - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernel => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemrelease => '2016', - :operatingsystemmajrelease => '2016', - :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', - :os => { :family => 'windows', :name => 'windows', :release => { :major => '2016', :full => '2016' } } + architecture: 'amd64', + osfamily: 'windows', + operatingsystem: 'windows', + kernel: 'windows', + kernelrelease: '10.0.14393', + operatingsystemrelease: '2016', + operatingsystemmajrelease: '2016', + 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', + os: { family: 'windows', name: 'windows', release: { major: '2016', full: '2016' } }, } end it { is_expected.to compile } context 'with defaults for all parameters' do - it { should compile.with_all_deps } + it { is_expected.to compile.with_all_deps } - it { should contain_file('C:/Program Files/Docker/docker-compose.exe').with( - 'ensure' => 'link', - 'target' => 'C:/Program Files/Docker/docker-compose-1.21.2.exe', - 'require' => 'Exec[Install Docker Compose 1.21.2]' - )} + it { + is_expected.to contain_file('C:/Program Files/Docker/docker-compose.exe').with( + 'ensure' => 'link', + 'target' => 'C:/Program Files/Docker/docker-compose-1.21.2.exe', + 'require' => 'Exec[Install Docker Compose 1.21.2]', + ) + } end context 'with ensure => absent' do - let (:params) { { :ensure => 'absent' } } - it { should contain_file('C:/Program Files/Docker/docker-compose-1.21.2.exe').with_ensure('absent') } - it { should contain_file('C:/Program Files/Docker/docker-compose.exe').with_ensure('absent') } + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_file('C:/Program Files/Docker/docker-compose-1.21.2.exe').with_ensure('absent') } + it { is_expected.to contain_file('C:/Program Files/Docker/docker-compose.exe').with_ensure('absent') } end context 'when no proxy is provided' do - let(:params) { {:version => '1.7.0'} } + let(:params) { { version: '1.7.0' } } + it { is_expected.to contain_exec('Install Docker Compose 1.7.0') } end context 'when proxy is provided' do - let(:params) { {:proxy => 'http://proxy.example.org:3128/', - :version => '1.7.0'} } + let(:params) do + { proxy: 'http://proxy.example.org:3128/', + version: '1.7.0' } + end + it { is_expected.to compile } it { is_expected.to contain_exec('Install Docker Compose 1.7.0') } end context 'when proxy is not a http proxy' do - let(:params) { {:proxy => 'this is not a URL'} } + let(:params) { { proxy: 'this is not a URL' } } + it do expect { is_expected.to compile - }.to raise_error(/does not match/) + }.to raise_error(%r{does not match}) end end context 'when proxy contains username and password' do - let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', - :version => '1.7.0'} } + let(:params) do + { proxy: 'http://user:password@proxy.example.org:3128/', + version: '1.7.0' } + end + it { is_expected.to compile } it { is_expected.to contain_exec('Install Docker Compose 1.7.0') } end context 'when proxy IP is provided' do - let(:params) { {:proxy => 'http://10.10.10.10:3128/', - :version => '1.7.0'} } + let(:params) do + { proxy: 'http://10.10.10.10:3128/', + version: '1.7.0' } + end + it { is_expected.to compile } it { is_expected.to contain_exec('Install Docker Compose 1.7.0') } end diff --git a/spec/classes/docker_spec.rb b/spec/classes/docker_spec.rb index ed727974..09558d1a 100755 --- a/spec/classes/docker_spec.rb +++ b/spec/classes/docker_spec.rb @@ -1,930 +1,1075 @@ require 'spec_helper' -describe 'docker', :type => :class do - +describe 'docker', type: :class do ['Debian', 'Ubuntu', 'RedHat'].each do |osfamily| context "on #{osfamily}" do - if osfamily == 'Debian' - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'stretch', - :kernelrelease => '4.9.0-3-amd64', - :operatingsystemrelease => '9.0', - :operatingsystemmajrelease => '9', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'stretch', + kernelrelease: '4.9.0-3-amd64', + operatingsystemrelease: '9.0', + operatingsystemmajrelease: '9', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + service_config_file = '/etc/default/docker' storage_config_file = '/etc/default/docker-storage' context 'It should include default prerequired_packages' do - it { should contain_package('cgroupfs-mount').with_ensure('present') } + it { is_expected.to contain_package('cgroupfs-mount').with_ensure('present') } end end if osfamily == 'Ubuntu' - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :lsbdistid => 'Ubuntu', - :lsbdistcodename => 'xenial', - :kernelrelease => '4.4.0-21-generic', - :operatingsystemrelease => '16.04', - :operatingsystemmajrelease => '16.04', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + lsbdistcodename: 'xenial', + kernelrelease: '4.4.0-21-generic', + operatingsystemrelease: '16.04', + operatingsystemmajrelease: '16.04', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + service_config_file = '/etc/default/docker' storage_config_file = '/etc/default/docker-storage' - it { should contain_service('docker').with_hasrestart('true') } + it { is_expected.to contain_service('docker').with_hasrestart('true') } context 'It should include default prerequired_packages' do - it { should contain_package('cgroup-lite').with_ensure('present') } - it { should contain_package('apparmor').with_ensure('present') } + it { is_expected.to contain_package('cgroup-lite').with_ensure('present') } + it { is_expected.to contain_package('apparmor').with_ensure('present') } end end - if osfamily == 'Ubuntu' - - it { should contain_class('apt') } - it { should contain_package('docker').with_name('docker-ce').with_ensure('present') } - it { should contain_apt__source('docker').with_location('https://download.docker.com/linux/ubuntu') } - it { should contain_apt__pin('docker') - .with_ensure('present') - .with_origin('download.docker.com') - .with_priority(500) + if ['Debian', 'Ubuntu'].include?(osfamily) + it { is_expected.to contain_class('apt') } + it { is_expected.to contain_package('docker').with_name('docker-ce').with_ensure('present') } + it { + is_expected.to contain_apt__pin('docker') + .with_ensure('present') + .with_origin('download.docker.com') + .with_priority(500) } - it { should contain_package('docker').with_install_options(nil) } + it { is_expected.to contain_package('docker').with_install_options(nil) } + it { is_expected.to contain_file('/etc/default/docker').without_content(%r{icc=}) } + end - it { should contain_file('/etc/default/docker').without_content(/icc=/) } + if osfamily == 'Ubuntu' + it { is_expected.to contain_apt__source('docker').with_location('https://download.docker.com/linux/ubuntu') } end if osfamily == 'Debian' - - it { should contain_class('apt') } - it { should contain_package('docker').with_name('docker-ce').with_ensure('present') } - it { should contain_apt__source('docker').with_location('https://download.docker.com/linux/debian') } - it { should contain_apt__pin('docker') - .with_ensure('present') - .with_origin('download.docker.com') - .with_priority(500) - } - it { should contain_package('docker').with_install_options(nil) } - - it { should contain_file('/etc/default/docker').without_content(/icc=/) } + it { is_expected.to contain_apt__source('docker').with_location('https://download.docker.com/linux/debian') } end - if osfamily == 'Debian' or osfamily == 'Ubuntu' + if ['Debian', 'Ubuntu'].include?(osfamily) context 'with a custom version' do - let(:params) { {'version' => '1.7.0' } } - it { should contain_package('docker').with_ensure('1.7.0').with_name('docker-engine') } + let(:params) { { 'version' => '1.7.0' } } + + it { is_expected.to contain_package('docker').with_ensure('1.7.0').with_name('docker-engine') } end context 'with no upstream package source' do - let(:params) { {'use_upstream_package_source' => false } } - it { should_not contain_apt__source('docker') } - it { should_not contain_apt__pin('docker') } - it { should contain_package('docker').with_name('docker-ce') } + let(:params) { { 'use_upstream_package_source' => false } } + + it { is_expected.not_to contain_apt__source('docker') } + it { is_expected.not_to contain_apt__pin('docker') } + it { is_expected.to contain_package('docker').with_name('docker-ce') } end context 'with no upstream package source' do - let(:params) { {'use_upstream_package_source' => false } } - it { should_not contain_apt__source('docker') } - it { should_not contain_apt__pin('docker') } - it { should contain_package('docker') } + let(:params) { { 'use_upstream_package_source' => false } } + + it { is_expected.not_to contain_apt__source('docker') } + it { is_expected.not_to contain_apt__pin('docker') } + it { is_expected.to contain_package('docker') } end context 'with no package pinning' do - let(:params) { {'pin_upstream_package_source' => false } } - it { should contain_apt__pin('docker').with_ensure('absent') } + let(:params) { { 'pin_upstream_package_source' => false } } + + it { is_expected.to contain_apt__pin('docker').with_ensure('absent') } end context 'with different package pinning priority' do - let(:params) { { - 'pin_upstream_package_source' => true, - 'apt_source_pin_level' => 900, - } } - it { should contain_apt__pin('docker').with_priority(900) } + let(:params) do + { + 'pin_upstream_package_source' => true, + 'apt_source_pin_level' => 900, + } + end + + it { is_expected.to contain_apt__pin('docker').with_priority(900) } end context 'when given a specific tmp_dir' do - let(:params) {{ 'tmp_dir' => '/bigtmp' }} - it { should contain_file('/etc/default/docker').with_content(/TMPDIR="\/bigtmp"/) } + let(:params) { { 'tmp_dir' => '/bigtmp' } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{TMPDIR="\/bigtmp"}) } end context 'with ip_forwaring param set to false' do - let(:params) {{ 'ip_forward' => false }} - it { should contain_file('/etc/default/docker').with_content(/ip-forward=false/) } + let(:params) { { 'ip_forward' => false } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{ip-forward=false}) } end context 'with ip_masq param set to false' do - let(:params) {{ 'ip_masq' => false }} - it { should contain_file('/etc/default/docker').with_content(/ip-masq=false/) } + let(:params) { { 'ip_masq' => false } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{ip-masq=false}) } end context 'with iptables param set to false' do - let(:params) {{ 'iptables' => false }} - it { should contain_file('/etc/default/docker').with_content(/iptables=false/) } + let(:params) { { 'iptables' => false } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{iptables=false}) } end context 'with icc param set to false' do - let(:params) {{ 'icc' => false }} - it { should contain_file('/etc/default/docker').with_content(/icc=false/) } + let(:params) { { 'icc' => false } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{icc=false}) } end context 'with tcp_bind array param' do - let(:params) {{ 'tcp_bind' => ['tcp://127.0.0.1:2375', 'tcp://10.0.0.1:2375'] }} + let(:params) { { 'tcp_bind' => ['tcp://127.0.0.1:2375', 'tcp://10.0.0.1:2375'] } } + it do - should contain_file('/etc/default/docker').with_content( - /tcp:\/\/127.0.0.1:2375 -H tcp:\/\/10.0.0.1:2375/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375 -H tcp:\/\/10.0.0.1:2375}, ) end end context 'with tcp_bind string param' do - let(:params) {{ 'tcp_bind' => 'tcp://127.0.0.1:2375' }} + let(:params) { { 'tcp_bind' => 'tcp://127.0.0.1:2375' } } + it do - should contain_file('/etc/default/docker').with_content( - /tcp:\/\/127.0.0.1:2375/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, ) end end context 'with tls param' do - let(:params) {{ + let(:params) do + { 'tcp_bind' => 'tcp://127.0.0.1:2375', 'tls_enable' => true, - }} + } + end + it do - should contain_file('/etc/default/docker').with_content( - /tcp:\/\/127.0.0.1:2375/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, ) - should contain_file('/etc/default/docker').with_content( - /--tls --tlsverify --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{--tls --tlsverify --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem}, ) end end context 'with tls param and without tlsverify' do - let(:params) {{ + let(:params) do + { 'tcp_bind' => 'tcp://127.0.0.1:2375', 'tls_enable' => true, 'tls_verify' => false, - }} + } + end + it do - should contain_file('/etc/default/docker').with_content( - /tcp:\/\/127.0.0.1:2375/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, ) - should contain_file('/etc/default/docker').with_content( - /--tls --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem/ + is_expected.to contain_file('/etc/default/docker').with_content( + %r{--tls --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem}, ) end end context 'with fixed_cidr and bridge params' do - let(:params) {{ 'fixed_cidr' => '10.0.0.0/24' }} - let(:params) {{ - 'fixed_cidr' => '10.0.0.0/24', - 'bridge' => 'br0', - }} - it { should contain_file('/etc/default/docker').with_content(/fixed-cidr 10.0.0.0\/24/) } + let(:params) do + { + 'fixed_cidr' => '10.0.0.0/24', + 'bridge' => 'br0', + } + end + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{fixed-cidr 10.0.0.0\/24}) } end context 'with ipv6 params' do - let(:params) {{ - 'ipv6' => true, - 'ipv6_cidr' => '2001:db8:1::/64', - 'default_gateway_ipv6' => 'fe80::2d4:12ff:fef6:67a2/16' - }} - it { should contain_file('/etc/default/docker').with_content(/--ipv6/) } - it { should contain_file('/etc/default/docker').with_content(/--fixed-cidr-v6 2001:db8:1::\/64/) } - it { should contain_file('/etc/default/docker').with_content(/--default-gateway-v6 fe80::2d4:12ff:fef6:67a2\/16/) } + let(:params) do + { + 'ipv6' => true, + 'ipv6_cidr' => '2001:db8:1::/64', + 'default_gateway_ipv6' => 'fe80::2d4:12ff:fef6:67a2/16', + } + end + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{--ipv6}) } + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{--fixed-cidr-v6 2001:db8:1::\/64}) } + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{--default-gateway-v6 fe80::2d4:12ff:fef6:67a2\/16}) } end context 'with default_gateway and bridge params' do - let(:params) {{ - 'default_gateway' => '10.0.0.1', - 'bridge' => 'br0', - }} - it { should contain_file('/etc/default/docker').with_content(/default-gateway 10.0.0.1/) } + let(:params) do + { + 'default_gateway' => '10.0.0.1', + 'bridge' => 'br0', + } + end + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{default-gateway 10.0.0.1}) } end context 'with bridge param' do - let(:params) {{ 'bridge' => 'br0' }} - it { should contain_file('/etc/default/docker').with_content(/bridge br0/) } + let(:params) { { 'bridge' => 'br0' } } + + it { is_expected.to contain_file('/etc/default/docker').with_content(%r{bridge br0}) } end context 'with custom service_name' do - let(:params) {{ 'service_name' => 'docker.io' }} - it { should contain_file('/etc/default/docker.io') } - end + let(:params) { { 'service_name' => 'docker.io' } } + + it { is_expected.to contain_file('/etc/default/docker.io') } + end end if osfamily == 'RedHat' - let(:facts) { { - :architecture => 'x86_64', - :osfamily => osfamily, - :operatingsystem => 'RedHat', - :operatingsystemrelease => '7.2', - :operatingsystemmajrelease => '7', - :kernelversion => '3.10.0', - } } + let(:facts) do + { + architecture: 'x86_64', + osfamily: osfamily, + operatingsystem: 'RedHat', + operatingsystemrelease: '7.2', + operatingsystemmajrelease: '7', + kernelversion: '3.10.0', + } + end + service_config_file = '/etc/sysconfig/docker' storage_config_file = '/etc/sysconfig/docker-storage' - it { should contain_file('/etc/sysconfig/docker').without_content(/icc=/) } + it { is_expected.to contain_file('/etc/sysconfig/docker').without_content(%r{icc=}) } context 'with proxy param' do - let(:params) { {'proxy' => 'http://127.0.0.1:3128' } } - it { should contain_file(service_config_file).with_content(/http_proxy='http:\/\/127.0.0.1:3128'/) } - it { should contain_file(service_config_file).with_content(/https_proxy='http:\/\/127.0.0.1:3128'/) } + let(:params) { { 'proxy' => 'http://127.0.0.1:3128' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{http_proxy='http:\/\/127.0.0.1:3128'}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{https_proxy='http:\/\/127.0.0.1:3128'}) } end context 'with no_proxy param' do - let(:params) { {'no_proxy' => '.github.com' } } - it { should contain_file(service_config_file).with_content(/no_proxy='.github.com'/) } + let(:params) { { 'no_proxy' => '.github.com' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{no_proxy='.github.com'}) } end context 'with registry_mirror param set to mirror value' do - let(:params) {{ 'registry_mirror' => 'https://mirror.gcr.io' }} - it { should contain_file('/etc/sysconfig/docker').with_content(/registry-mirror/) } + let(:params) { { 'registry_mirror' => 'https://mirror.gcr.io' } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{registry-mirror}) } end context 'when given a specific tmp_dir' do - let(:params) {{ 'tmp_dir' => '/bigtmp' }} - it { should contain_file('/etc/sysconfig/docker').with_content(/TMPDIR="\/bigtmp"/) } + let(:params) { { 'tmp_dir' => '/bigtmp' } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{TMPDIR="\/bigtmp"}) } end context 'with ip_forwaring param set to false' do - let(:params) {{ 'ip_forward' => false }} - it { should contain_file('/etc/sysconfig/docker').with_content(/ip-forward=false/) } + let(:params) { { 'ip_forward' => false } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{ip-forward=false}) } end context 'with ip_masq param set to false' do - let(:params) {{ 'ip_masq' => false }} - it { should contain_file('/etc/sysconfig/docker').with_content(/ip-masq=false/) } + let(:params) { { 'ip_masq' => false } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{ip-masq=false}) } end context 'with iptables param set to false' do - let(:params) {{ 'iptables' => false }} - it { should contain_file('/etc/sysconfig/docker').with_content(/iptables=false/) } + let(:params) { { 'iptables' => false } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{iptables=false}) } end context 'with icc param set to false' do - let(:params) {{ 'icc' => false }} - it { should contain_file('/etc/sysconfig/docker').with_content(/icc=false/) } + let(:params) { { 'icc' => false } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{icc=false}) } end context 'with tcp_bind array param' do - let(:params) {{ 'tcp_bind' => ['tcp://127.0.0.1:2375', 'tcp://10.0.0.1:2375'] }} + let(:params) { { 'tcp_bind' => ['tcp://127.0.0.1:2375', 'tcp://10.0.0.1:2375'] } } + it do - should contain_file('/etc/sysconfig/docker').with_content( - /tcp:\/\/127.0.0.1:2375 -H tcp:\/\/10.0.0.1:2375/) + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375 -H tcp:\/\/10.0.0.1:2375}, + ) end end context 'with tcp_bind string param' do - let(:params) {{ 'tcp_bind' => 'tcp://127.0.0.1:2375' }} + let(:params) { { 'tcp_bind' => 'tcp://127.0.0.1:2375' } } + it do - should contain_file('/etc/sysconfig/docker').with_content( - /tcp:\/\/127.0.0.1:2375/) + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, + ) end end context 'with tls param' do - let(:params) {{ + let(:params) do + { 'tcp_bind' => 'tcp://127.0.0.1:2375', 'tls_enable' => true, - }} + } + end + it do - should contain_file('/etc/sysconfig/docker').with_content( - /tcp:\/\/127.0.0.1:2375/ + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, ) - should contain_file('/etc/sysconfig/docker').with_content( - /--tls --tlsverify --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem/ + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{--tls --tlsverify --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem}, ) end end context 'with tls param and without tlsverify' do - let(:params) {{ + let(:params) do + { 'tcp_bind' => 'tcp://127.0.0.1:2375', 'tls_enable' => true, 'tls_verify' => false, - }} + } + end + it do - should contain_file('/etc/sysconfig/docker').with_content( - /tcp:\/\/127.0.0.1:2375/ + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{tcp:\/\/127.0.0.1:2375}, ) - should contain_file('/etc/sysconfig/docker').with_content( - /--tls --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem/ + is_expected.to contain_file('/etc/sysconfig/docker').with_content( + %r{--tls --tlscacert=\/etc\/docker\/tls\/ca.pem --tlscert=\/etc\/docker\/tls\/cert.pem --tlskey=\/etc\/docker\/tls\/key.pem}, ) end end context 'with fixed_cidr and bridge params' do - let(:params) {{ 'fixed_cidr' => '10.0.0.0/24' }} - let(:params) {{ - 'fixed_cidr' => '10.0.0.0/24', - 'bridge' => 'br0', - }} - it { should contain_file('/etc/sysconfig/docker').with_content(/fixed-cidr 10.0.0.0\/24/) } + let(:params) do + { + 'fixed_cidr' => '10.0.0.0/24', + 'bridge' => 'br0', + } + end + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{fixed-cidr 10.0.0.0\/24}) } end context 'with default_gateway and bridge params' do - let(:params) {{ - 'default_gateway' => '10.0.0.1', - 'bridge' => 'br0', - }} - it { should contain_file('/etc/sysconfig/docker').with_content(/default-gateway 10.0.0.1/) } + let(:params) do + { + 'default_gateway' => '10.0.0.1', + 'bridge' => 'br0', + } + end + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{default-gateway 10.0.0.1}) } end context 'with bridge param' do - let(:params) {{ 'bridge' => 'br0' }} - it { should contain_file('/etc/sysconfig/docker').with_content(/bridge br0/) } + let(:params) { { 'bridge' => 'br0' } } + + it { is_expected.to contain_file('/etc/sysconfig/docker').with_content(%r{bridge br0}) } end context 'when given specific storage options' do - let(:params) {{ - 'storage_driver' => 'devicemapper', - 'dm_basesize' => '3G' - }} - it { should contain_file('/etc/sysconfig/docker-storage').with_content(/^(DOCKER_STORAGE_OPTIONS=" --storage-driver devicemapper --storage-opt dm.basesize=3G)/) } + let(:params) do + { + 'storage_driver' => 'devicemapper', + 'dm_basesize' => '3G', + } + end + + it { is_expected.to contain_file('/etc/sysconfig/docker-storage').with_content(%r{^(DOCKER_STORAGE_OPTIONS=" --storage-driver devicemapper --storage-opt dm.basesize=3G)}) } end context 'It should include default prerequired_packages' do - it { should contain_package('device-mapper').with_ensure('present') } + it { is_expected.to contain_package('device-mapper').with_ensure('present') } end context 'It should install from rpm package' do - let(:params) { { - 'manage_package' => true, - 'use_upstream_package_source' => false, - 'docker_engine_package_name' => 'docker-engine', - 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm' - } } + let(:params) do + { + 'manage_package' => true, + 'use_upstream_package_source' => false, + 'docker_engine_package_name' => 'docker-engine', + 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', + } + end + it do - should contain_package('docker').with( + is_expected.to contain_package('docker').with( 'ensure' => 'present', 'source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', - 'name' => 'docker-engine' + 'name' => 'docker-engine', ) end end context 'It should install from rpm package with docker::repo_opt set' do - let(:params) { { - 'manage_package' => true, - 'use_upstream_package_source' => false, - 'docker_engine_package_name' => 'docker-engine', - 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', - 'repo_opt' => '--enablerepo=rhel7-extras' - } } + let(:params) do + { + 'manage_package' => true, + 'use_upstream_package_source' => false, + 'docker_engine_package_name' => 'docker-engine', + 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', + 'repo_opt' => '--enablerepo=rhel7-extras', + } + end + it do - should contain_package('docker').with( + is_expected.to contain_package('docker').with( 'ensure' => 'present', 'source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', 'name' => 'docker-engine', - 'install_options' => '--enablerepo=rhel7-extras' + 'install_options' => '--enablerepo=rhel7-extras', ) end end context 'It uses default docker::repo_opt' do - let(:params) { { - 'manage_package' => true, - 'use_upstream_package_source' => false, - 'docker_engine_package_name' => 'docker-engine', - 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm' - } } + let(:params) do + { + 'manage_package' => true, + 'use_upstream_package_source' => false, + 'docker_engine_package_name' => 'docker-engine', + 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', + } + end + it do - should contain_package('docker').with( + is_expected.to contain_package('docker').with( 'ensure' => 'present', 'source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', 'name' => 'docker-engine', - 'install_options' => '--enablerepo=rhel-7-server-extras-rpms' + 'install_options' => '--enablerepo=rhel-7-server-extras-rpms', ) - end end context 'It allows overwriting docker::repo_opt with empty string' do - let(:params) { { - 'manage_package' => true, - 'use_upstream_package_source' => false, - 'docker_engine_package_name' => 'docker-engine', - 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', - 'repo_opt' => '' - } } + let(:params) do + { + 'manage_package' => true, + 'use_upstream_package_source' => false, + 'docker_engine_package_name' => 'docker-engine', + 'package_source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', + 'repo_opt' => '', + } + end + it do - should contain_package('docker').with( + is_expected.to contain_package('docker').with( 'ensure' => 'present', 'source' => 'https://get.docker.com/rpm/1.7.0/centos-7/RPMS/x86_64/docker-engine-1.7.0-1.el7.x86_64.rpm', 'name' => 'docker-engine', - 'install_options' => nil + 'install_options' => nil, ) end end end - it { should compile.with_all_deps } - it { should contain_class('docker::repos').that_comes_before('Class[docker::install]') } - it { should contain_class('docker::install').that_comes_before('Class[docker::config]') } - it { should contain_class('docker::config').that_comes_before('Class[docker::service]') } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') } + it { is_expected.to contain_class('docker::install').that_comes_before('Class[docker::config]') } + it { is_expected.to contain_class('docker::config').that_comes_before('Class[docker::service]') } - it { should contain_file(service_config_file).without_content(/icc=/) } + it { is_expected.to contain_file(service_config_file).without_content(%r{icc=}) } # storage_config_file = '/etc/default/docker-storage' context 'with a specific docker command' do - let(:params) {{ 'docker_ce_start_command' => 'docker.io' }} - it { should contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(/docker.io/) } + let(:params) { { 'docker_ce_start_command' => 'docker.io' } } + + it { is_expected.to contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(%r{docker.io}) } end context 'with an extra After entry' do - let(:params) {{ 'service_after_override' => 'containerd.service' }} - it { should contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(/containerd.service/) } + let(:params) { { 'service_after_override' => 'containerd.service' } } + + it { is_expected.to contain_file('/etc/systemd/system/docker.service.d/service-overrides.conf').with_content(%r{containerd.service}) } end context 'with a specific socket group and override' do - let(:params) { { - 'socket_group' => 'root', - 'socket_override' => true, - } } - it { should contain_file('/etc/systemd/system/docker.socket.d/socket-overrides.conf').with_content(/root/) } + let(:params) do + { + 'socket_group' => 'root', + 'socket_override' => true, + } + end + + it { is_expected.to contain_file('/etc/systemd/system/docker.socket.d/socket-overrides.conf').with_content(%r{root}) } end context 'with a custom package name' do - let(:params) { {'docker_ce_package_name' => 'docker-custom-pkg-name' } } - it { should contain_package('docker').with_name('docker-custom-pkg-name').with_ensure('present') } + let(:params) { { 'docker_ce_package_name' => 'docker-custom-pkg-name' } } + + it { is_expected.to contain_package('docker').with_name('docker-custom-pkg-name').with_ensure('present') } end context 'with a custom package name and version' do - let(:params) { { - 'version' => '17.06.2~ce-0~debian', - 'docker_ce_package_name' => 'docker-custom-pkg-name', - } } - it { should contain_package('docker').with_name('docker-custom-pkg-name').with_ensure('17.06.2~ce-0~debian') } + let(:params) do + { + 'version' => '17.06.2~ce-0~debian', + 'docker_ce_package_name' => 'docker-custom-pkg-name', + } + end + + it { is_expected.to contain_package('docker').with_name('docker-custom-pkg-name').with_ensure('17.06.2~ce-0~debian') } end context 'when not managing the package' do let(:params) { { 'manage_package' => false } } + skip 'the APT module at v2.1 does not support STRICT_VARIABLES' do - it { should_not contain_package('docker') } + it { is_expected.not_to contain_package('docker') } end end context 'It should accept custom prerequired_packages' do - let(:params) { {'prerequired_packages' => [ 'test_package' ], - 'manage_package' => false, } } + let(:params) do + { 'prerequired_packages' => ['test_package'], + 'manage_package' => false } + end + skip 'the APT module at v2.1 does not support STRICT_VARIABLES' do - it { should contain_package('test_package').with_ensure('present') } + it { is_expected.to contain_package('test_package').with_ensure('present') } end end context 'with proxy param' do - let(:params) { {'proxy' => 'http://127.0.0.1:3128' } } - it { should contain_file(service_config_file).with_content(/http_proxy='http:\/\/127.0.0.1:3128'/) } - it { should contain_file(service_config_file).with_content(/https_proxy='http:\/\/127.0.0.1:3128'/) } + let(:params) { { 'proxy' => 'http://127.0.0.1:3128' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{http_proxy='http:\/\/127.0.0.1:3128'}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{https_proxy='http:\/\/127.0.0.1:3128'}) } end context 'with no_proxy param' do - let(:params) { {'no_proxy' => '.github.com' } } - it { should contain_file(service_config_file).with_content(/no_proxy='.github.com'/) } + let(:params) { { 'no_proxy' => '.github.com' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{no_proxy='.github.com'}) } end context 'with execdriver param lxc' do - let(:params) { { 'execdriver' => 'lxc' }} - it { should contain_file(service_config_file).with_content(/-e lxc/) } + let(:params) { { 'execdriver' => 'lxc' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{-e lxc}) } end context 'with execdriver param native' do - let(:params) { { 'execdriver' => 'native' }} - it { should contain_file(service_config_file).with_content(/-e native/) } + let(:params) { { 'execdriver' => 'native' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{-e native}) } end ['aufs', 'devicemapper', 'btrfs', 'overlay', 'overlay2', 'vfs', 'zfs'].each do |driver| context "with #{driver} storage driver" do - let(:params) { { 'storage_driver' => driver }} - it { should contain_file(storage_config_file).with_content(/ --storage-driver #{driver}/) } + let(:params) { { 'storage_driver' => driver } } + + it { is_expected.to contain_file(storage_config_file).with_content(%r{ --storage-driver #{driver}}) } end end context 'with thinpool device param' do - let(:params) { + let(:params) do { 'storage_driver' => 'devicemapper', - 'dm_thinpooldev' => '/dev/mapper/vg_test-docker--pool' - } - } - it { should contain_file(storage_config_file).with_content(/--storage-opt dm\.thinpooldev=\/dev\/mapper\/vg_test-docker--pool/) } + 'dm_thinpooldev' => '/dev/mapper/vg_test-docker--pool' } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{--storage-opt dm\.thinpooldev=\/dev\/mapper\/vg_test-docker--pool}) } end context 'with use deferred removal param' do - let(:params) { + let(:params) do { 'storage_driver' => 'devicemapper', - 'dm_use_deferred_removal' => true - } - } - it { should contain_file(storage_config_file).with_content(/--storage-opt dm\.use_deferred_removal=true/) } + 'dm_use_deferred_removal' => true } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{--storage-opt dm\.use_deferred_removal=true}) } end context 'with use deferred deletion param' do - let(:params) { + let(:params) do { 'storage_driver' => 'devicemapper', - 'dm_use_deferred_deletion' => true - } - } - it { should contain_file(storage_config_file).with_content(/--storage-opt dm\.use_deferred_deletion=true/) } + 'dm_use_deferred_deletion' => true } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{--storage-opt dm\.use_deferred_deletion=true}) } end context 'with block discard param' do - let(:params) { + let(:params) do { 'storage_driver' => 'devicemapper', - 'dm_blkdiscard' => true - } - } - it { should contain_file(storage_config_file).with_content(/--storage-opt dm\.blkdiscard=true/) } + 'dm_blkdiscard' => true } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{--storage-opt dm\.blkdiscard=true}) } end context 'with override udev sync check param' do - let(:params) { + let(:params) do { 'storage_driver' => 'devicemapper', - 'dm_override_udev_sync_check' => true - } - } - it { should contain_file(storage_config_file).with_content(/--storage-opt dm\.override_udev_sync_check=true/) } + 'dm_override_udev_sync_check' => true } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{--storage-opt dm\.override_udev_sync_check=true}) } end context 'without execdriver param' do - it { should_not contain_file(service_config_file).with_content(/-e lxc/) } - it { should_not contain_file(service_config_file).with_content(/-e native/) } + it { is_expected.not_to contain_file(service_config_file).with_content(%r{-e lxc}) } + it { is_expected.not_to contain_file(service_config_file).with_content(%r{-e native}) } end context 'with multi dns param' do - let(:params) { {'dns' => ['8.8.8.8', '8.8.4.4']} } - it { should contain_file(service_config_file).with_content(/--dns 8.8.8.8/).with_content(/--dns 8.8.4.4/) } + let(:params) { { 'dns' => ['8.8.8.8', '8.8.4.4'] } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--dns 8.8.8.8}).with_content(%r{--dns 8.8.4.4}) } end context 'with dns param' do - let(:params) { {'dns' => '8.8.8.8'} } - it { should contain_file(service_config_file).with_content(/--dns 8.8.8.8/) } + let(:params) { { 'dns' => '8.8.8.8' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--dns 8.8.8.8}) } end context 'with multi dns_search param' do - let(:params) { {'dns_search' => ['my.domain.local', 'other-domain.de']} } - it { should contain_file(service_config_file).with_content(/--dns-search my.domain.local/).with_content(/--dns-search other-domain.de/) } + let(:params) { { 'dns_search' => ['my.domain.local', 'other-domain.de'] } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--dns-search my.domain.local}).with_content(%r{--dns-search other-domain.de}) } end context 'with dns_search param' do - let(:params) { {'dns_search' => 'my.domain.local'} } - it { should contain_file(service_config_file).with_content(/--dns-search my.domain.local/) } + let(:params) { { 'dns_search' => 'my.domain.local' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--dns-search my.domain.local}) } end context 'with multi extra parameters' do - let(:params) { {'extra_parameters' => ['--this this', '--that that'] } } - it { should contain_file(service_config_file).with_content(/--this this/) } - it { should contain_file(service_config_file).with_content(/--that that/) } + let(:params) { { 'extra_parameters' => ['--this this', '--that that'] } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--this this}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{--that that}) } end context 'with a string extra parameters' do - let(:params) { {'extra_parameters' => '--this this' } } - it { should contain_file(service_config_file).with_content(/--this this/) } + let(:params) { { 'extra_parameters' => '--this this' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--this this}) } end context 'with multi shell values' do - let(:params) { {'shell_values' => ['--this this', '--that that'] } } - it { should contain_file(service_config_file).with_content(/--this this/) } - it { should contain_file(service_config_file).with_content(/--that that/) } + let(:params) { { 'shell_values' => ['--this this', '--that that'] } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--this this}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{--that that}) } end context 'with a string shell values' do - let(:params) { {'shell_values' => '--this this' } } - it { should contain_file(service_config_file).with_content(/--this this/) } + let(:params) { { 'shell_values' => '--this this' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--this this}) } end context 'with socket group set' do - let(:params) { { 'socket_group' => 'notdocker' }} - it { should contain_file(service_config_file).with_content(/-G notdocker/) } + let(:params) { { 'socket_group' => 'notdocker' } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{-G notdocker}) } end context 'with labels set' do - let(:params) { { 'labels' => ['storage=ssd','stage=production'] }} - it { should contain_file(service_config_file).with_content(/--label storage=ssd/) } - it { should contain_file(service_config_file).with_content(/--label stage=production/) } + let(:params) { { 'labels' => ['storage=ssd', 'stage=production'] } } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--label storage=ssd}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{--label stage=production}) } end context 'with service_state set to stopped' do - let(:params) { {'service_state' => 'stopped'} } - it { should contain_service('docker').with_ensure('stopped') } + let(:params) { { 'service_state' => 'stopped' } } + + it { is_expected.to contain_service('docker').with_ensure('stopped') } end context 'with a custom service name' do - let(:params) { {'service_name' => 'docker.io'} } - it { should contain_service('docker').with_name('docker.io') } + let(:params) { { 'service_name' => 'docker.io' } } + + it { is_expected.to contain_service('docker').with_name('docker.io') } end context 'with service_enable set to false' do - let(:params) { {'service_enable' => false} } - it { should contain_service('docker').with_enable('false') } + let(:params) { { 'service_enable' => false } } + + it { is_expected.to contain_service('docker').with_enable('false') } end context 'with service_enable set to true' do - let(:params) { {'service_enable' => true} } - it { should contain_service('docker').with_enable('true') } + let(:params) { { 'service_enable' => true } } + + it { is_expected.to contain_service('docker').with_enable('true') } end context 'with service_manage set to false' do - let(:params) { {'manage_service' => false} } - it { should_not contain_service('docker') } + let(:params) { { 'manage_service' => false } } + + it { is_expected.not_to contain_service('docker') } end context 'with specific log_level' do let(:params) { { 'log_level' => 'debug' } } - it { should contain_file(service_config_file).with_content(/-l debug/) } + + it { is_expected.to contain_file(service_config_file).with_content(%r{-l debug}) } end context 'with an invalid log_level' do - let(:params) { { 'log_level' => 'verbose'} } + let(:params) { { 'log_level' => 'verbose' } } + it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /log_level must be one of debug, info, warn, error or fatal/) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{log_level must be one of debug, info, warn, error or fatal}) end end context 'with specific log_driver' do let(:params) { { 'log_driver' => 'json-file' } } - it { should contain_file(service_config_file).with_content(/--log-driver json-file/) } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--log-driver json-file}) } end context 'with an invalid log_driver' do - let(:params) { { 'log_driver' => 'etwlogs'} } + let(:params) { { 'log_driver' => 'etwlogs' } } + it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /log_driver must be one of none, json-file, syslog, journald, gelf, fluentd, splunk or awslogs/) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{log_driver must be one of none, json-file, syslog, journald, gelf, fluentd, splunk or awslogs}) end end context 'with specific log_driver and log_opt' do - let(:params) { + let(:params) do { 'log_driver' => 'json-file', - 'log_opt' => [ 'max-size=1m','max-file=3' ] - } - } - it { should contain_file(service_config_file).with_content(/--log-driver json-file/) } - it { should contain_file(service_config_file).with_content(/--log-opt max-size=1m/) } - it { should contain_file(service_config_file).with_content(/--log-opt max-file=3/) } + 'log_opt' => ['max-size=1m', 'max-file=3'] } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{--log-driver json-file}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{--log-opt max-size=1m}) } + it { is_expected.to contain_file(service_config_file).with_content(%r{--log-opt max-file=3}) } end context 'without log_driver no log_opt' do - let(:params) { { 'log_opt' => [ 'max-size=1m' ] } } - it { should_not contain_file(service_config_file).with_content(/--log-opt max-size=1m/) } + let(:params) { { 'log_opt' => ['max-size=1m'] } } + + it { is_expected.not_to contain_file(service_config_file).with_content(%r{--log-opt max-size=1m}) } end context 'with storage_driver set to devicemapper and dm_* options set' do - let(:params) { {'storage_driver' => 'devicemapper', - 'dm_datadev' => '/dev/sda', - 'dm_metadatadev' => '/dev/sdb', } } - it { should contain_file(storage_config_file).with_content(/dm.datadev=\/dev\/sda/) } + let(:params) do + { 'storage_driver' => 'devicemapper', + 'dm_datadev' => '/dev/sda', + 'dm_metadatadev' => '/dev/sdb' } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{dm.datadev=\/dev\/sda}) } end context 'with storage_driver unset and dm_ options set' do - let(:params) { {'dm_datadev' => '/dev/sda', - 'dm_metadatadev' => '/dev/sdb', } } - it { should raise_error(Puppet::Error, /Values for dm_ variables will be ignored unless storage_driver is set to devicemapper./) } + let(:params) do + { 'dm_datadev' => '/dev/sda', + 'dm_metadatadev' => '/dev/sdb' } + end + + it { is_expected.to raise_error(Puppet::Error, %r{Values for dm_ variables will be ignored unless storage_driver is set to devicemapper.}) } end context 'with storage_driver and dm_basesize set' do - let(:params) { {'storage_driver' => 'devicemapper', - 'dm_basesize' => '20G', }} - it { should contain_file(storage_config_file).with_content(/dm.basesize=20G/) } + let(:params) do + { 'storage_driver' => 'devicemapper', + 'dm_basesize' => '20G' } + end + + it { is_expected.to contain_file(storage_config_file).with_content(%r{dm.basesize=20G}) } end context 'with storage_driver unset and dm_basesize set' do - let(:params) { {'dm_basesize' => '20G' }} - it { should raise_error(Puppet::Error, /Values for dm_ variables will be ignored unless storage_driver is set to devicemapper./) } + let(:params) { { 'dm_basesize' => '20G' } } + + it { is_expected.to raise_error(Puppet::Error, %r{Values for dm_ variables will be ignored unless storage_driver is set to devicemapper.}) } end context 'with specific selinux_enabled parameter' do let(:params) { { 'selinux_enabled' => true } } - it { should contain_file(service_config_file).with_content(/--selinux-enabled=true/) } + + it { is_expected.to contain_file(service_config_file).with_content(%r{--selinux-enabled=true}) } end context 'with an invalid selinux_enabled parameter' do - let(:params) { { 'selinux_enabled' => 'yes'} } + let(:params) { { 'selinux_enabled' => 'yes' } } + it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /got String/) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{got String}) end end context 'with custom root dir && Docker version < 17.06' do - let(:params) { { - 'root_dir' => '/mnt/docker', - 'version' => '17.03', - } } - it { should contain_file(service_config_file).with_content(/-g \/mnt\/docker/) } + let(:params) do + { + 'root_dir' => '/mnt/docker', + 'version' => '17.03', + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{-g \/mnt\/docker}) } end context 'with custom root dir && Docker version > 17.05' do - let(:params) { { - 'root_dir' => '/mnt/docker', - 'version' => '18.03', - } } - it { should contain_file(service_config_file).with_content(/--data-root \/mnt\/docker/) } - end + let(:params) do + { + 'root_dir' => '/mnt/docker', + 'version' => '18.03', + } + end + it { is_expected.to contain_file(service_config_file).with_content(%r{--data-root \/mnt\/docker}) } + end context 'with ensure absent' do - let(:params) { {'ensure' => 'absent' } } - it { should contain_package('docker').with_ensure('absent') } + let(:params) { { 'ensure' => 'absent' } } + + it { is_expected.to contain_package('docker').with_ensure('absent') } end context 'with ensure absent and ' do - let(:params) { {'ensure' => 'absent' } } - it { should contain_package('docker').with_ensure('absent') } - it { should contain_package('docker-ce-cli').with_ensure('absent') } - it { should contain_package('containerd.io').with_ensure('absent') } + let(:params) { { 'ensure' => 'absent' } } + + it { is_expected.to contain_package('docker').with_ensure('absent') } + it { is_expected.to contain_package('docker-ce-cli').with_ensure('absent') } + it { is_expected.to contain_package('containerd.io').with_ensure('absent') } end context 'with an invalid combination of devicemapper options' do - let(:params) { + let(:params) do { 'dm_datadev' => '/dev/mapper/vg_test-docker--pool_tdata', 'dm_metadatadev' => '/dev/mapper/vg_test-docker--pool_tmeta', - 'dm_thinpooldev' => '/dev/mapper/vg_test-docker--pool' - } - } + 'dm_thinpooldev' => '/dev/mapper/vg_test-docker--pool' } + end + it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /You can use the \$dm_thinpooldev parameter, or the \$dm_datadev and \$dm_metadatadev parameter pair, but you cannot use both./) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{You can use the \$dm_thinpooldev parameter, or the \$dm_datadev and \$dm_metadatadev parameter pair, but you cannot use both.}) end end - end - end ['RedHat', 'CentOS'].each do |operatingsystem| context "on #{operatingsystem}" do - let(:facts) { { - :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystem => operatingsystem, - :operatingsystemrelease => '7.0', - :operatingsystemmajrelease => '7', - :kernelversion => '3.10.0', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } + let(:facts) do + { + architecture: 'x86_64', + osfamily: 'RedHat', + operatingsystem: operatingsystem, + operatingsystemrelease: '7.0', + operatingsystemmajrelease: '7', + kernelversion: '3.10.0', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end storage_setup_file = '/etc/sysconfig/docker-storage-setup' context 'with storage driver' do - let(:params) { { 'storage_driver' => 'devicemapper' }} - it { should contain_file(storage_setup_file).with_content(/^STORAGE_DRIVER=devicemapper/) } + let(:params) { { 'storage_driver' => 'devicemapper' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^STORAGE_DRIVER=devicemapper}) } end context 'with storage devices' do - let(:params) { { 'storage_devs' => '/dev/sda,/dev/sdb' }} - it { should contain_file(storage_setup_file).with_content(/^DEVS="\/dev\/sda,\/dev\/sdb"/) } + let(:params) { { 'storage_devs' => '/dev/sda,/dev/sdb' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^DEVS="\/dev\/sda,\/dev\/sdb"}) } end context 'with storage volume group' do - let(:params) { { 'storage_vg' => 'vg_test' }} - it { should contain_file(storage_setup_file).with_content(/^VG=vg_test/) } + let(:params) { { 'storage_vg' => 'vg_test' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^VG=vg_test}) } end context 'with storage root size' do - let(:params) { { 'storage_root_size' => '10G' }} - it { should contain_file(storage_setup_file).with_content(/^ROOT_SIZE=10G/) } + let(:params) { { 'storage_root_size' => '10G' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^ROOT_SIZE=10G}) } end context 'with storage data size' do - let(:params) { { 'storage_data_size' => '10G' }} - it { should contain_file(storage_setup_file).with_content(/^DATA_SIZE=10G/) } + let(:params) { { 'storage_data_size' => '10G' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^DATA_SIZE=10G}) } end context 'with storage min data size' do - let(:params) { { 'storage_min_data_size' => '2G' }} - it { should contain_file(storage_setup_file).with_content(/^MIN_DATA_SIZE=2G/) } + let(:params) { { 'storage_min_data_size' => '2G' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^MIN_DATA_SIZE=2G}) } end context 'with storage chunk size' do - let(:params) { { 'storage_chunk_size' => '10G' }} - it { should contain_file(storage_setup_file).with_content(/^CHUNK_SIZE=10G/) } + let(:params) { { 'storage_chunk_size' => '10G' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^CHUNK_SIZE=10G}) } end context 'with storage grow partition' do - let(:params) { { 'storage_growpart' => true }} - it { should contain_file(storage_setup_file).with_content(/^GROWPART=true/) } + let(:params) { { 'storage_growpart' => true } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^GROWPART=true}) } end context 'with storage auto extend pool' do - let(:params) { { 'storage_auto_extend_pool' => '1' }} - it { should contain_file(storage_setup_file).with_content(/^AUTO_EXTEND_POOL=1/) } + let(:params) { { 'storage_auto_extend_pool' => '1' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^AUTO_EXTEND_POOL=1}) } end context 'with storage auto extend threshold' do - let(:params) { { 'storage_pool_autoextend_threshold' => '1' }} - it { should contain_file(storage_setup_file).with_content(/^POOL_AUTOEXTEND_THRESHOLD=1/) } + let(:params) { { 'storage_pool_autoextend_threshold' => '1' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^POOL_AUTOEXTEND_THRESHOLD=1}) } end context 'with storage auto extend percent' do - let(:params) { { 'storage_pool_autoextend_percent' => '10' }} - it { should contain_file(storage_setup_file).with_content(/^POOL_AUTOEXTEND_PERCENT=10/) } + let(:params) { { 'storage_pool_autoextend_percent' => '10' } } + + it { is_expected.to contain_file(storage_setup_file).with_content(%r{^POOL_AUTOEXTEND_PERCENT=10}) } end context 'with custom storage_setup_file' do - let(:params) { { 'storage_setup_file' => '/etc/sysconfig/docker-latest-storage-setup' }} - it { should contain_file('/etc/sysconfig/docker-latest-storage-setup').with_content(/managed by Puppet/) } - end + let(:params) { { 'storage_setup_file' => '/etc/sysconfig/docker-latest-storage-setup' } } + it { is_expected.to contain_file('/etc/sysconfig/docker-latest-storage-setup').with_content(%r{managed by Puppet}) } + end end end context 'specific to Ubuntu Trusty' do - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :lsbdistid => 'Ubuntu', - :operatingsystem => 'Ubuntu', - :lsbdistcodename => 'trusty', - :operatingsystemrelease => '14.04', - :kernelrelease => '3.8.0-29-generic', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } - it { should contain_service('docker').with_provider('upstart') } - it { should contain_package('docker').with_name('docker-ce').with_ensure('present') } - it { should contain_package('apparmor') } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + operatingsystem: 'Ubuntu', + lsbdistcodename: 'trusty', + operatingsystemrelease: '14.04', + kernelrelease: '3.8.0-29-generic', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + + it { is_expected.to contain_service('docker').with_provider('upstart') } + it { is_expected.to contain_package('docker').with_name('docker-ce').with_ensure('present') } + it { is_expected.to contain_package('apparmor') } end context 'newer versions of Debian and Ubuntu' do context 'Ubuntu >= 15.04' do - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :lsbdistid => 'Ubuntu', - :operatingsystem => 'Ubuntu', - :lsbdistcodename => 'trusty', - :operatingsystemrelease => '15.04', - :kernelrelease => '3.8.0-29-generic', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } - - it { should contain_service('docker').with_provider('systemd').with_hasstatus(true).with_hasrestart(true) } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + lsbdistid: 'Ubuntu', + operatingsystem: 'Ubuntu', + lsbdistcodename: 'trusty', + operatingsystemrelease: '15.04', + kernelrelease: '3.8.0-29-generic', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + + it { is_expected.to contain_service('docker').with_provider('systemd').with_hasstatus(true).with_hasrestart(true) } end context 'Debian >= 8' do - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } - - it { should contain_service('docker').with_provider('systemd').with_hasstatus(true).with_hasrestart(true) } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + + it { is_expected.to contain_service('docker').with_provider('systemd').with_hasstatus(true).with_hasrestart(true) } end end context 'with an invalid distro name' do - let(:facts) { { - :architecture => 'Whatever', - :osfamily => 'Whatever', - :operatingsystem => 'Whatever', - :lsbdistid => 'Whatever', - :lsbdistcodename => 'Whatever', - :kernelrelease => 'Whatever', - :operatingsystemmajrelease => 'Whatever', - :os => { :distro => { :codename => 'Whatever' }, :family => 'Whatever', :name => 'Whatever', :release => { :major => 'Whatever', :full => 'Whatever' } } - } } + let(:facts) do + { + architecture: 'Whatever', + osfamily: 'Whatever', + operatingsystem: 'Whatever', + lsbdistid: 'Whatever', + lsbdistcodename: 'Whatever', + kernelrelease: 'Whatever', + operatingsystemmajrelease: 'Whatever', + os: { distro: { codename: 'Whatever' }, family: 'Whatever', name: 'Whatever', release: { major: 'Whatever', full: 'Whatever' } }, + } + end + it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /This module only works on Debian, Red Hat or Windows based systems./) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{This module only works on Debian, Red Hat or Windows based systems.}) end end context 'CentOS < 7' do - let(:facts) { { - :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystem => 'CentOS', - :kernelversion => '3.10.0', - :operatingsystemmajrelease => '6', - :os => { :family => 'RedHat', :name => 'CentOS', :release => { :major => '6', :full => '6.0' } } - } } + let(:facts) do + { + architecture: 'x86_64', + osfamily: 'RedHat', + operatingsystem: 'CentOS', + kernelversion: '3.10.0', + operatingsystemmajrelease: '6', + os: { family: 'RedHat', name: 'CentOS', release: { major: '6', full: '6.0' } }, + } + end it do expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /This module only works on CentOS version 7 and higher based systems./) + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{This module only works on CentOS version 7 and higher based systems.}) end end - end diff --git a/spec/classes/docker_windows_spec.rb b/spec/classes/docker_windows_spec.rb index 9c3e629b..6d5b226b 100644 --- a/spec/classes/docker_windows_spec.rb +++ b/spec/classes/docker_windows_spec.rb @@ -1,291 +1,384 @@ require 'spec_helper' -describe 'docker', :type => :class do - osfamily = "windows" - context "on #{osfamily}" do - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemrelease => '2016', - :operatingsystemmajrelease => '2016', - :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', - :os => { :family => 'windows', :name => 'windows', :release => { :major => '2016', :full => '2016' } } - } } - service_config_file = 'C:/ProgramData/docker/config/daemon.json' - let(:params) {{ 'docker_ee' => true }} - - it { should compile.with_all_deps } - it { should contain_file('C:/ProgramData/docker/').with({ - 'ensure' => 'directory' - } ) } - it { should contain_file('C:/ProgramData/docker/config/')} - it { should contain_exec('service-restart-on-failure') } - it { should contain_exec('install-docker-package').with_command(/Install-PackageProvider NuGet -Force/) } - it { should contain_exec('install-docker-package').with_command(/Install-Module \$dockerProviderName -Force/) } - it { should contain_class('docker::repos').that_comes_before('Class[docker::install]') } - it { should contain_class('docker::install').that_comes_before('Class[docker::config]') } - it { should contain_class('docker::config').that_comes_before('Class[docker::service]') } - - it { should contain_file(service_config_file).without_content(/icc=/) } - - context 'with dns' do - let(:params) { { - 'dns' => '8.8.8.8', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"dns": \["8.8.8.8"\],/) } - end - - context 'with multi dns' do - let(:params) { { - 'dns' => ['8.8.8.8', '8.8.4.4'], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"dns": \["8.8.8.8","8.8.4.4"\],/) } - end - - context 'with dns search' do - let(:params) { { - 'dns_search' => ['my.domain.local'], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"dns-search": \["my.domain.local"\],/) } - end - - context 'with multi dns search' do - let(:params) { { - 'dns_search' => ['my.domain.local', 'other-domain.de'], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"dns-search": \["my.domain.local","other-domain.de"\],/) } - end - - context 'with log_driver' do - let(:params) { { - 'log_driver' => 'etwlogs', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"log-driver": "etwlogs"/) } - end - - context 'with invalid log_driver' do - let(:params) { { - 'log_driver' => 'invalid', - 'docker_ee' => true - } } - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /log_driver must be one of none, json-file, syslog, gelf, fluentd, splunk, awslogs or etwlogs/) - end - end - - context 'with invalid journald log_driver' do - let(:params) { { - 'log_driver' => 'journald', - 'docker_ee' => true - } } - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /log_driver must be one of none, json-file, syslog, gelf, fluentd, splunk, awslogs or etwlogs/) - end - end - - context 'with mtu' do - let(:params) { { - 'mtu' => '1450', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"mtu": 1450/) } - end - - context 'with log_level' do - let(:params) { { - 'log_level' => 'debug', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"log-level": "debug"/) } - end - - context 'with invalid log_level' do - let(:params) { { - 'log_level' => 'verbose', - 'docker_ee' => true - } } - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /log_level must be one of debug, info, warn, error or fatal/) - end - end - - context 'with storage_driver' do - let(:params) { { - 'storage_driver' => 'windowsfilter', - 'docker_ee' => true - } } - it { should compile.with_all_deps } - end - - context 'with an invalid storage_driver' do - let(:params) { { - 'storage_driver' => 'invalid', - 'docker_ee' => true - } } - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /Valid values for storage_driver on windows are windowsfilter/) - end - end - - context 'with tcp_bind' do - let(:params) { { - 'tcp_bind' => "tcp://0.0.0.0:2376", - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"hosts": \["tcp:\/\/0.0.0.0:2376"\]/) } - end - - context 'with multiple tcp_bind' do - let(:params) { { - 'tcp_bind' => ["tcp://0.0.0.0:2376", "npipe://"], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"hosts": \["tcp:\/\/0.0.0.0:2376","npipe:\/\/"\]/) } - end - - context 'with tls_enable, tcp_bind and tls configuration' do - let(:params) { { - 'tls_enable' => true, - 'tcp_bind' => ["tcp://0.0.0.0:2376"], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content( - /"hosts": \["tcp:\/\/0.0.0.0:2376"]/).with_content( - /"tlsverify": true/).with_content( - /"tlscacert": "C:\/ProgramData\/docker\/certs.d\/ca.pem"/).with_content( - /"tlscert": "C:\/ProgramData\/docker\/certs.d\/server-cert.pem"/).with_content( - /"tlskey": "C:\/ProgramData\/docker\/certs.d\/server-key.pem"/) - } - end - - context 'with tls_enable, tcp_bind and custom tls cacert' do - let(:params) { { - 'tls_enable' => true, - 'tcp_bind' => ["tcp://0.0.0.0:2376"], - 'tls_cacert' => 'C:/certs/ca.pem', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content( - /"tlscacert": "C:\/certs\/ca.pem"/) - } - end - - context 'with tls_enable, tcp_bind and custom tls cert' do - let(:params) { { - 'tls_enable' => true, - 'tcp_bind' => ["tcp://0.0.0.0:2376"], - 'tls_cert' => 'C:/certs/server-cert.pem', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content( - /"tlscert": "C:\/certs\/server-cert.pem"/) - } - end - - context 'with tls_enable, tcp_bind and custom tls key' do - let(:params) { { - 'tls_enable' => true, - 'tcp_bind' => ["tcp://0.0.0.0:2376"], - 'tls_key' => 'C:/certs/server-key.pem', - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content( - /"tlskey": "C:\/certs\/server-key.pem"/) - } - end - - context 'with custom socket group' do - let(:params) { { - 'socket_group' => "custom", - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"group": "custom"/)} - end - - context 'with custom bridge' do - let(:params) { { - 'bridge' => "l2bridge", - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"bridge": "l2bridge"/)} - end - - context 'with invalid bridge' do - let(:params) { { - 'bridge' => "invalid", - 'docker_ee' => true - } } - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /bridge must be one of none, nat, transparent, overlay, l2bridge or l2tunnel on Windows./) - end - end - - context 'with custom fixed cidr' do - let(:params) { { - 'fixed_cidr'=> "10.0.0.0/24", - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"fixed-cidr": "10.0.0.0\/24"/)} - end - - context 'with custom registry mirror' do - let(:params) { { - 'registry_mirror'=> "https://mirror.gcr.io", - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"registry-mirrors": \["https:\/\/mirror.gcr.io"\]/)} - end - - context 'with custom label' do - let(:params) { { - 'labels'=> ["mylabel"], - 'docker_ee' => true - } } - it { should contain_file(service_config_file).with_content(/"labels": \["mylabel"\]/)} - end - - context 'with default package name' do - let(:params) { { - 'docker_ee' => true - } } - it { should contain_exec('install-docker-package').with_command(/ Docker /) } - end - - context 'with custom package name' do - let(:params) { { - 'docker_ee_package_name'=> "mydockerpackage", - 'docker_ee' => true - } } - it { should contain_exec('install-docker-package').with_command(/ mydockerpackage /) } - end - - context 'without docker_ee' do - let(:params) {{ 'docker_ee' => false }} - it do - expect { - should contain_package('docker') - }.to raise_error(Puppet::Error, /This module only work for Docker Enterprise Edition on Windows./) - end +describe 'docker', type: :class do + osfamily = 'windows' + context "on #{osfamily}" do + let(:facts) do + { + architecture: 'amd64', + osfamily: 'windows', + operatingsystem: 'windows', + kernelrelease: '10.0.14393', + operatingsystemrelease: '2016', + operatingsystemmajrelease: '2016', + 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', + os: { family: 'windows', name: 'windows', release: { major: '2016', full: '2016' } }, + } + end + let(:params) { { 'docker_ee' => true } } + let(:service_config_file) { 'C:/ProgramData/docker/config/daemon.json' } + + it { is_expected.to compile.with_all_deps } + it { + is_expected.to contain_file('C:/ProgramData/docker/').with('ensure' => 'directory') + } + it { is_expected.to contain_file('C:/ProgramData/docker/config/') } + it { is_expected.to contain_exec('service-restart-on-failure') } + it { is_expected.to contain_exec('install-docker-package').with_command(%r{Install-PackageProvider NuGet -Force}) } + it { is_expected.to contain_exec('install-docker-package').with_command(%r{Install-Module \$dockerProviderName -Force}) } + it { is_expected.to contain_class('docker::repos').that_comes_before('Class[docker::install]') } + it { is_expected.to contain_class('docker::install').that_comes_before('Class[docker::config]') } + it { is_expected.to contain_class('docker::config').that_comes_before('Class[docker::service]') } + + it { is_expected.to contain_file(service_config_file).without_content(%r{icc=}) } + + context 'with dns' do + let(:params) do + { + 'dns' => '8.8.8.8', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"dns": \["8.8.8.8"\],}) } + end + + context 'with multi dns' do + let(:params) do + { + 'dns' => ['8.8.8.8', '8.8.4.4'], + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"dns": \["8.8.8.8","8.8.4.4"\],}) } + end + + context 'with dns search' do + let(:params) do + { + 'dns_search' => ['my.domain.local'], + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"dns-search": \["my.domain.local"\],}) } + end + + context 'with multi dns search' do + let(:params) do + { + 'dns_search' => ['my.domain.local', 'other-domain.de'], + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"dns-search": \["my.domain.local","other-domain.de"\],}) } + end + + context 'with log_driver' do + let(:params) do + { + 'log_driver' => 'etwlogs', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"log-driver": "etwlogs"}) } + end + + context 'with invalid log_driver' do + let(:params) do + { + 'log_driver' => 'invalid', + 'docker_ee' => true, + } + end + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{log_driver must be one of none, json-file, syslog, gelf, fluentd, splunk, awslogs or etwlogs}) + end + end + + context 'with invalid journald log_driver' do + let(:params) do + { + 'log_driver' => 'journald', + 'docker_ee' => true, + } + end + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{log_driver must be one of none, json-file, syslog, gelf, fluentd, splunk, awslogs or etwlogs}) + end + end + + context 'with mtu' do + let(:params) do + { + 'mtu' => '1450', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"mtu": 1450}) } + end + + context 'with log_level' do + let(:params) do + { + 'log_level' => 'debug', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"log-level": "debug"}) } + end + + context 'with invalid log_level' do + let(:params) do + { + 'log_level' => 'verbose', + 'docker_ee' => true, + } + end + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{log_level must be one of debug, info, warn, error or fatal}) + end + end + + context 'with storage_driver' do + let(:params) do + { + 'storage_driver' => 'windowsfilter', + 'docker_ee' => true, + } + end + + it { is_expected.to compile.with_all_deps } + end + + context 'with an invalid storage_driver' do + let(:params) do + { + 'storage_driver' => 'invalid', + 'docker_ee' => true, + } + end + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{Valid values for storage_driver on windows are windowsfilter}) + end + end + + context 'with tcp_bind' do + let(:params) do + { + 'tcp_bind' => 'tcp://0.0.0.0:2376', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"hosts": \["tcp:\/\/0.0.0.0:2376"\]}) } + end + + context 'with multiple tcp_bind' do + let(:params) do + { + 'tcp_bind' => ['tcp://0.0.0.0:2376', 'npipe://'], + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"hosts": \["tcp:\/\/0.0.0.0:2376","npipe:\/\/"\]}) } + end + + context 'with tls_enable, tcp_bind and tls configuration' do + let(:params) do + { + 'tls_enable' => true, + 'tcp_bind' => ['tcp://0.0.0.0:2376'], + 'docker_ee' => true, + } + end + + it { + is_expected.to contain_file(service_config_file).with_content( + %r{"hosts": \["tcp:\/\/0.0.0.0:2376"]}, + ).with_content( + %r{"tlsverify": true}, + ).with_content( + %r{"tlscacert": "C:\/ProgramData\/docker\/certs.d\/ca.pem"}, + ).with_content( + %r{"tlscert": "C:\/ProgramData\/docker\/certs.d\/server-cert.pem"}, + ).with_content( + %r{"tlskey": "C:\/ProgramData\/docker\/certs.d\/server-key.pem"}, + ) + } + end + + context 'with tls_enable, tcp_bind and custom tls cacert' do + let(:params) do + { + 'tls_enable' => true, + 'tcp_bind' => ['tcp://0.0.0.0:2376'], + 'tls_cacert' => 'C:/certs/ca.pem', + 'docker_ee' => true, + } + end + + it { + is_expected.to contain_file(service_config_file).with_content( + %r{"tlscacert": "C:\/certs\/ca.pem"}, + ) + } + end + + context 'with tls_enable, tcp_bind and custom tls cert' do + let(:params) do + { + 'tls_enable' => true, + 'tcp_bind' => ['tcp://0.0.0.0:2376'], + 'tls_cert' => 'C:/certs/server-cert.pem', + 'docker_ee' => true, + } + end + + it { + is_expected.to contain_file(service_config_file).with_content( + %r{"tlscert": "C:\/certs\/server-cert.pem"}, + ) + } + end + + context 'with tls_enable, tcp_bind and custom tls key' do + let(:params) do + { + 'tls_enable' => true, + 'tcp_bind' => ['tcp://0.0.0.0:2376'], + 'tls_key' => 'C:/certs/server-key.pem', + 'docker_ee' => true, + } + end + + it { + is_expected.to contain_file(service_config_file).with_content( + %r{"tlskey": "C:\/certs\/server-key.pem"}, + ) + } + end + + context 'with custom socket group' do + let(:params) do + { + 'socket_group' => 'custom', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"group": "custom"}) } + end + + context 'with custom bridge' do + let(:params) do + { + 'bridge' => 'l2bridge', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"bridge": "l2bridge"}) } + end + + context 'with invalid bridge' do + let(:params) do + { + 'bridge' => 'invalid', + 'docker_ee' => true, + } + end + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{bridge must be one of none, nat, transparent, overlay, l2bridge or l2tunnel on Windows.}) + end + end + + context 'with custom fixed cidr' do + let(:params) do + { + 'fixed_cidr' => '10.0.0.0/24', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"fixed-cidr": "10.0.0.0\/24"}) } + end + + context 'with custom registry mirror' do + let(:params) do + { + 'registry_mirror' => 'https://mirror.gcr.io', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"registry-mirrors": \["https:\/\/mirror.gcr.io"\]}) } + end + + context 'with custom label' do + let(:params) do + { + 'labels' => ['mylabel'], + 'docker_ee' => true, + } + end + + it { is_expected.to contain_file(service_config_file).with_content(%r{"labels": \["mylabel"\]}) } + end + + context 'with default package name' do + let(:params) do + { + 'docker_ee' => true, + } + end + + it { is_expected.to contain_exec('install-docker-package').with_command(%r{ Docker }) } + end + + context 'with custom package name' do + let(:params) do + { + 'docker_ee_package_name' => 'mydockerpackage', + 'docker_ee' => true, + } + end + + it { is_expected.to contain_exec('install-docker-package').with_command(%r{ mydockerpackage }) } + end + + context 'without docker_ee' do + let(:params) { { 'docker_ee' => false } } + + it do + expect { + is_expected.to contain_package('docker') + }.to raise_error(Puppet::Error, %r{This module only work for Docker Enterprise Edition on Windows.}) end end + end end diff --git a/spec/classes/machine_spec.rb b/spec/classes/machine_spec.rb index 6c4a35d4..ca5cfab3 100644 --- a/spec/classes/machine_spec.rb +++ b/spec/classes/machine_spec.rb @@ -1,88 +1,116 @@ require 'spec_helper' -describe 'docker::machine', :type => :class do +describe 'docker::machine', type: :class do let(:facts) do { - :kernel => 'Linux', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :lsbdistid => 'Ubuntu', - :lsbdistcodename => 'maverick', - :kernelrelease => '3.8.0-29-generic', - :operatingsystemrelease => '10.04', - :operatingsystemmajrelease => '10', + kernel: 'Linux', + osfamily: 'Debian', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + lsbdistcodename: 'maverick', + kernelrelease: '3.8.0-29-generic', + operatingsystemrelease: '10.04', + operatingsystemmajrelease: '10', } end it { is_expected.to compile } context 'with defaults for all parameters' do - it { should compile.with_all_deps } - it { should contain_exec('Install Docker Machine 0.16.1').with( - 'path' => '/usr/bin/', - 'cwd' => '/tmp', - 'command' => 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.1/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.1', - 'creates' => '/usr/local/bin/docker-machine-0.16.1', - 'require' => 'Package[curl]' - )} - it { should contain_file('/usr/local/bin/docker-machine-0.16.1').with( - 'owner' => 'root', - 'mode' => '0755', - 'require' => 'Exec[Install Docker Machine 0.16.1]' - )} - it { should contain_file('/usr/local/bin/docker-machine').with( - 'ensure' => 'link', - 'target' => '/usr/local/bin/docker-machine-0.16.1', - 'require' => 'File[/usr/local/bin/docker-machine-0.16.1]' - )} + it { is_expected.to compile.with_all_deps } + it { + is_expected.to contain_exec('Install Docker Machine 0.16.1').with( + 'path' => '/usr/bin/', + 'cwd' => '/tmp', + 'command' => 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.1/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.1', + 'creates' => '/usr/local/bin/docker-machine-0.16.1', + 'require' => 'Package[curl]', + ) + } + it { + is_expected.to contain_file('/usr/local/bin/docker-machine-0.16.1').with( + 'owner' => 'root', + 'mode' => '0755', + 'require' => 'Exec[Install Docker Machine 0.16.1]', + ) + } + it { + is_expected.to contain_file('/usr/local/bin/docker-machine').with( + 'ensure' => 'link', + 'target' => '/usr/local/bin/docker-machine-0.16.1', + 'require' => 'File[/usr/local/bin/docker-machine-0.16.1]', + ) + } end context 'with ensure => absent' do - let (:params) { { :ensure => 'absent' } } - it { should contain_file('/usr/local/bin/docker-machine-0.16.1').with_ensure('absent') } - it { should contain_file('/usr/local/bin/docker-machine').with_ensure('absent') } + let(:params) { { ensure: 'absent' } } + + it { is_expected.to contain_file('/usr/local/bin/docker-machine-0.16.1').with_ensure('absent') } + it { is_expected.to contain_file('/usr/local/bin/docker-machine').with_ensure('absent') } end context 'when no proxy is provided' do - let(:params) { {:version => '0.16.0'} } - it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( - 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + let(:params) { { version: '0.16.0' } } + + it { + is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0', + ) } end context 'when proxy is provided' do - let(:params) { {:proxy => 'http://proxy.example.org:3128/', - :version => '0.16.0'} } + let(:params) do + { proxy: 'http://proxy.example.org:3128/', + version: '0.16.0' } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( - 'curl -s -S -L --proxy http://proxy.example.org:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + it { + is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://proxy.example.org:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0', + ) } end context 'when proxy is not a http proxy' do - let(:params) { {:proxy => 'this is not a URL'} } + let(:params) { { proxy: 'this is not a URL' } } + it do expect { is_expected.to compile - }.to raise_error(/does not match/) + }.to raise_error(%r{does not match}) end end context 'when proxy contains username and password' do - let(:params) { {:proxy => 'http://user:password@proxy.example.org:3128/', - :version => '0.16.0'} } + let(:params) do + { proxy: 'http://user:password@proxy.example.org:3128/', + version: '0.16.0' } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( - 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + it { + is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://user:password@proxy.example.org:3128/'\ + ' https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64'\ + ' -o /usr/local/bin/docker-machine-0.16.0', + ) } end context 'when proxy IP is provided' do - let(:params) { {:proxy => 'http://10.10.10.10:3128/', - :version => '0.16.0'} } + let(:params) do + { proxy: 'http://10.10.10.10:3128/', + version: '0.16.0' } + end + it { is_expected.to compile } - it { is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( - 'curl -s -S -L --proxy http://10.10.10.10:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0') + it { + is_expected.to contain_exec('Install Docker Machine 0.16.0').with_command( + 'curl -s -S -L --proxy http://10.10.10.10:3128/ https://github.com/docker/machine/releases/download/v0.16.0/docker-machine-Linux-x86_64 -o /usr/local/bin/docker-machine-0.16.0', + ) } end end diff --git a/spec/classes/system_reload_spec.rb b/spec/classes/system_reload_spec.rb index 983e7d73..a17620b0 100644 --- a/spec/classes/system_reload_spec.rb +++ b/spec/classes/system_reload_spec.rb @@ -1,22 +1,25 @@ require 'spec_helper' -describe 'docker::systemd_reload', :type => :class do - - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'stretch', - :kernelrelease => '9.3.0-amd64', - :operatingsystemrelease => '9.3', - :operatingsystemmajrelease => '9', - } } +describe 'docker::systemd_reload', type: :class do + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'stretch', + kernelrelease: '9.3.0-amd64', + operatingsystemrelease: '9.3', + operatingsystemmajrelease: '9', + } + end context 'with systems that have systemd' do - it { should contain_exec('docker-systemd-reload').with( - 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], - 'command' => 'systemctl daemon-reload', - 'refreshonly' => 'true' - ) } + it { + is_expected.to contain_exec('docker-systemd-reload').with( + 'path' => ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'], + 'command' => 'systemctl daemon-reload', + 'refreshonly' => 'true', + ) + } end -end \ No newline at end of file +end diff --git a/spec/defines/exec_spec.rb b/spec/defines/exec_spec.rb index bb472108..56bf54b2 100644 --- a/spec/defines/exec_spec.rb +++ b/spec/defines/exec_spec.rb @@ -1,63 +1,75 @@ require 'spec_helper' -describe 'docker::exec', :type => :define do +describe 'docker::exec', type: :define do let(:title) { 'sample' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end context 'when running detached' do - let(:params) { {'command' => 'command', 'container' => 'container', 'detach' => true} } - it { should contain_exec('docker exec --detach=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'detach' => true } } + + it { is_expected.to contain_exec('docker exec --detach=true container command') } end context 'when running with tty' do - let(:params) { {'command' => 'command', 'container' => 'container', 'tty' => true} } - it { should contain_exec('docker exec --tty=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'tty' => true } } + + it { is_expected.to contain_exec('docker exec --tty=true container command') } end context 'when running with interactive' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true} } - it { should contain_exec('docker exec --interactive=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command') } end context 'when running with onlyif "running"' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'running'} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif ('docker ps --no-trunc --format=\'table {{.Names}}\' | grep \'^container$\'') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'running' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif 'docker ps --no-trunc --format=\'table {{.Names}}\' | grep \'^container$\'' } end context 'when running without onlyif custom command' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'custom'} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif ('custom') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'custom' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif 'custom' } end context 'when running without onlyif' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif (nil) } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif nil } end context 'when running with unless' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'unless' => 'some_command arg1'} } - it { should contain_exec('docker exec --interactive=true container command').with_unless ('docker exec --interactive=true container some_command arg1') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'unless' => 'some_command arg1' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_unless 'docker exec --interactive=true container some_command arg1' } end context 'when running without unless' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true,} } - it { should contain_exec('docker exec --interactive=true container command').with_unless (nil) } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_unless nil } end context 'with title that need sanitisation' do - let(:params) { {'command' => 'command', 'container' => 'container_sample/1', 'detach' => true, 'sanitise_name' => true} } - it { should contain_exec('docker exec --detach=true container_sample-1 command') } + let(:params) { { 'command' => 'command', 'container' => 'container_sample/1', 'detach' => true, 'sanitise_name' => true } } + + it { is_expected.to contain_exec('docker exec --detach=true container_sample-1 command') } end context 'with environment variables passed to exec' do - let(:params) { {'command' => 'command', 'container' => 'container', 'env' => ['FOO=BAR','FOO2=BAR2']} } - it { should contain_exec('docker exec --env FOO=BAR --env FOO2=BAR2 container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'env' => ['FOO=BAR', 'FOO2=BAR2'] } } + + it { is_expected.to contain_exec('docker exec --env FOO=BAR --env FOO2=BAR2 container command') } end end diff --git a/spec/defines/exec_windows_spec.rb b/spec/defines/exec_windows_spec.rb index 1cdb68c4..bfcd2810 100644 --- a/spec/defines/exec_windows_spec.rb +++ b/spec/defines/exec_windows_spec.rb @@ -1,63 +1,74 @@ require 'spec_helper' -describe 'docker::exec', :type => :define do +describe 'docker::exec', type: :define do let(:title) { 'sample' } - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemrelease => '2016', - :operatingsystemmajrelease => '2016', - :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', - :os => { :family => 'windows', :name => 'windows', :release => { :major => '2016', :full => '2016' } } - } } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'windows', + operatingsystem: 'windows', + kernelrelease: '10.0.14393', + operatingsystemrelease: '2016', + operatingsystemmajrelease: '2016', + 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', + os: { family: 'windows', name: 'windows', release: { major: '2016', full: '2016' } }, + } + end context 'when running detached' do - let(:params) { {'command' => 'command', 'container' => 'container', 'detach' => true} } - it { should contain_exec('docker exec --detach=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'detach' => true } } + + it { is_expected.to contain_exec('docker exec --detach=true container command') } end context 'when running with tty' do - let(:params) { {'command' => 'command', 'container' => 'container', 'tty' => true} } - it { should contain_exec('docker exec --tty=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'tty' => true } } + + it { is_expected.to contain_exec('docker exec --tty=true container command') } end context 'when running with interactive' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true} } - it { should contain_exec('docker exec --interactive=true container command') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command') } end context 'when running with onlyif "running"' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'running'} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif ('docker ps --no-trunc --format=\'table {{.Names}}\' | grep \'^container$\'') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'running' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif 'docker ps --no-trunc --format=\'table {{.Names}}\' | grep \'^container$\'' } end context 'when running without onlyif custom command' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'custom'} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif ('custom') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'onlyif' => 'custom' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif 'custom' } end context 'when running without onlyif' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true} } - it { should contain_exec('docker exec --interactive=true container command').with_onlyif (nil) } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_onlyif nil } end context 'when running with unless' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true, 'unless' => 'some_command arg1'} } - it { should contain_exec('docker exec --interactive=true container command').with_unless ('docker exec --interactive=true container some_command arg1') } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true, 'unless' => 'some_command arg1' } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_unless 'docker exec --interactive=true container some_command arg1' } end context 'when running without unless' do - let(:params) { {'command' => 'command', 'container' => 'container', 'interactive' => true,} } - it { should contain_exec('docker exec --interactive=true container command').with_unless (nil) } + let(:params) { { 'command' => 'command', 'container' => 'container', 'interactive' => true } } + + it { is_expected.to contain_exec('docker exec --interactive=true container command').with_unless nil } end context 'with title that need sanitisation' do - let(:params) { {'command' => 'command', 'container' => 'container_sample/1', 'detach' => true, 'sanitise_name' => true} } - it { should contain_exec('docker exec --detach=true container_sample-1 command') } + let(:params) { { 'command' => 'command', 'container' => 'container_sample/1', 'detach' => true, 'sanitise_name' => true } } + + it { is_expected.to contain_exec('docker exec --detach=true container_sample-1 command') } end end diff --git a/spec/defines/image_spec.rb b/spec/defines/image_spec.rb index 0d029817..68d63163 100644 --- a/spec/defines/image_spec.rb +++ b/spec/defines/image_spec.rb @@ -1,166 +1,193 @@ require 'spec_helper' -describe 'docker::image', :type => :define do +describe 'docker::image', type: :define do let(:title) { 'base' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end context 'with ensure => absent' do let(:params) { { 'ensure' => 'absent' } } - it { should contain_exec('docker rmi base') } + + it { is_expected.to contain_exec('docker rmi base') } end context 'with ensure => absent and force => true' do let(:params) { { 'ensure' => 'absent', 'force' => true } } - it { should contain_exec('docker rmi -f base') } + + it { is_expected.to contain_exec('docker rmi -f base') } end context 'with ensure => absent and image_tag => precise' do let(:params) { { 'ensure' => 'absent', 'image_tag' => 'precise' } } - it { should contain_exec('docker rmi base:precise') } + + it { is_expected.to contain_exec('docker rmi base:precise') } end context 'with ensure => present' do let(:params) { { 'ensure' => 'present' } } - it { should contain_file('/usr/local/bin/update_docker_image.sh') } - it { should contain_exec('/usr/local/bin/update_docker_image.sh base') } + + it { is_expected.to contain_file('/usr/local/bin/update_docker_image.sh') } + it { is_expected.to contain_exec('/usr/local/bin/update_docker_image.sh base') } end context 'with docker_file => Dockerfile' do - let(:params) { { 'docker_file' => 'Dockerfile' }} - it { should contain_exec('docker build -t base - < Dockerfile') } + let(:params) { { 'docker_file' => 'Dockerfile' } } + + it { is_expected.to contain_exec('docker build -t base - < Dockerfile') } end context 'with ensure => present and docker_file => Dockerfile' do let(:params) { { 'ensure' => 'present', 'docker_file' => 'Dockerfile' } } - it { should contain_exec('docker build -t base - < Dockerfile') } + + it { is_expected.to contain_exec('docker build -t base - < Dockerfile') } end context 'with docker_dir => /tmp/docker_images/test1 and docker_file => /tmp/docker_images/test1/Dockerfile_altbuild' do - let(:params) { { 'docker_dir' => '/tmp/docker_images/test1', 'docker_file' => '/tmp/docker_images/test1/Dockerfile_altbuild' }} - it { should contain_exec('docker build -t base -f /tmp/docker_images/test1/Dockerfile_altbuild /tmp/docker_images/test1') } + let(:params) { { 'docker_dir' => '/tmp/docker_images/test1', 'docker_file' => '/tmp/docker_images/test1/Dockerfile_altbuild' } } + + it { is_expected.to contain_exec('docker build -t base -f /tmp/docker_images/test1/Dockerfile_altbuild /tmp/docker_images/test1') } end context 'with docker_dir => /tmp/docker_images/test1' do - let(:params) { { 'docker_dir' => '/tmp/docker_images/test1' }} - it { should contain_exec('docker build -t base /tmp/docker_images/test1') } + let(:params) { { 'docker_dir' => '/tmp/docker_images/test1' } } + + it { is_expected.to contain_exec('docker build -t base /tmp/docker_images/test1') } end context 'with ensure => present and docker_dir => /tmp/docker_images/test1' do let(:params) { { 'ensure' => 'present', 'docker_dir' => '/tmp/docker_images/test1' } } - it { should contain_exec('docker build -t base /tmp/docker_images/test1') } + + it { is_expected.to contain_exec('docker build -t base /tmp/docker_images/test1') } end context 'with ensure => present and image_tag => precise' do let(:params) { { 'ensure' => 'present', 'image_tag' => 'precise' } } - it { should contain_exec('/usr/local/bin/update_docker_image.sh base:precise') } + + it { is_expected.to contain_exec('/usr/local/bin/update_docker_image.sh base:precise') } end context 'with ensure => present and image_digest => sha256:deadbeef' do let(:params) { { 'ensure' => 'present', 'image_digest' => 'sha256:deadbeef' } } - it { should contain_exec('/usr/local/bin/update_docker_image.sh base@sha256:deadbeef') } + + it { is_expected.to contain_exec('/usr/local/bin/update_docker_image.sh base@sha256:deadbeef') } end context 'with ensure => present and image_tag => precise and docker_file => Dockerfile' do let(:params) { { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_file' => 'Dockerfile' } } - it { should contain_exec('docker build -t base:precise - < Dockerfile') } + + it { is_expected.to contain_exec('docker build -t base:precise - < Dockerfile') } end context 'with ensure => present and image_tag => precise and docker_dir => /tmp/docker_images/test1' do let(:params) { { 'ensure' => 'present', 'image_tag' => 'precise', 'docker_dir' => '/tmp/docker_images/test1' } } - it { should contain_exec('docker build -t base:precise /tmp/docker_images/test1') } + + it { is_expected.to contain_exec('docker build -t base:precise /tmp/docker_images/test1') } end context 'with docker_tar => /tmp/docker_tars/test1.tar' do let(:params) { { 'docker_tar' => '/tmp/docker_tars/test1.tar' } } - it { should contain_exec('docker load -i /tmp/docker_tars/test1.tar') } + + it { is_expected.to contain_exec('docker load -i /tmp/docker_tars/test1.tar') } end context 'with ensure => present and docker_tar => /tmp/docker_tars/test1.tar' do let(:params) { { 'ensure' => 'present', 'docker_tar' => '/tmp/docker_tars/test1.tar' } } - it { should contain_exec('docker load -i /tmp/docker_tars/test1.tar') } + + it { is_expected.to contain_exec('docker load -i /tmp/docker_tars/test1.tar') } end context 'with docker_file => Dockerfile and docker_tar => /tmp/docker_tars/test1.tar' do - let(:params) { { 'docker_file' => 'Dockerfile', 'docker_tar' => '/tmp/docker_tars/test1.tar' }} + let(:params) { { 'docker_file' => 'Dockerfile', 'docker_tar' => '/tmp/docker_tars/test1.tar' } } + it do expect { - should have_exec_resource_count(1) + is_expected.to have_exec_resource_count(1) }.to raise_error(Puppet::Error) end end context 'with docker_tar => /tmp/docker_tars/test1.tar and docker_dir => /tmp/docker_images/test1' do - let(:params) { { 'docker_tar' => '/tmp/docker_tars/test1.tar', 'docker_dir' => '/tmp/docker_images/test1' }} + let(:params) { { 'docker_tar' => '/tmp/docker_tars/test1.tar', 'docker_dir' => '/tmp/docker_images/test1' } } + it do expect { - should have_exec_resource_count(1) + is_expected.to have_exec_resource_count(1) }.to raise_error(Puppet::Error) end end context 'with image_digest => sha256:deadbeef and docker_file => Dockerfile' do - let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_file' => 'Dockerfile' }} + let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_file' => 'Dockerfile' } } + it do expect { - should have_exec_resource_count(1) + is_expected.to have_exec_resource_count(1) }.to raise_error(Puppet::Error) end end context 'with image_digest => sha256:deadbeef and docker_dir => /tmp/docker_images/test1' do - let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_dir' => '/tmp/docker_images/test1' }} + let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_dir' => '/tmp/docker_images/test1' } } + it do expect { - should have_exec_resource_count(1) + is_expected.to have_exec_resource_count(1) }.to raise_error(Puppet::Error) end end context 'with image_digest => sha256:deadbeef and docker_tar => /tmp/docker_tars/test1.tar' do - let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_tar' => '/tmp/docker_tars/test1.tar' }} + let(:params) { { 'image_digest' => 'sha256:deadbeef', 'docker_tar' => '/tmp/docker_tars/test1.tar' } } + it do expect { - should have_exec_resource_count(1) + is_expected.to have_exec_resource_count(1) }.to raise_error(Puppet::Error) end end context 'with ensure => latest' do let(:params) { { 'ensure' => 'latest' } } - it { should contain_exec("echo 'Update of base complete'").with_onlyif('/usr/local/bin/update_docker_image.sh base') } + + it { is_expected.to contain_exec("echo 'Update of base complete'").with_onlyif('/usr/local/bin/update_docker_image.sh base') } end context 'with ensure => latest and image_tag => precise' do let(:params) { { 'ensure' => 'latest', 'image_tag' => 'precise' } } - it { should contain_exec("echo 'Update of base:precise complete'") } + + it { is_expected.to contain_exec("echo 'Update of base:precise complete'") } end context 'with ensure => latest and image_digest => sha256:deadbeef' do let(:params) { { 'ensure' => 'latest', 'image_digest' => 'sha256:deadbeef' } } - it { should contain_exec("echo 'Update of base@sha256:deadbeef complete'") } + + it { is_expected.to contain_exec("echo 'Update of base@sha256:deadbeef complete'") } end context 'with an invalid image name' do let(:title) { 'with spaces' } + it do expect { - should contain_exec('/usr/local/bin/update_docker_image.sh with spaces') + is_expected.to contain_exec('/usr/local/bin/update_docker_image.sh with spaces') }.to raise_error(Puppet::Error) end end context 'with an invalid ensure value' do let(:params) { { 'ensure' => 'not present or absent' } } + it do expect { - should contain_exec('docker rmi base') + is_expected.to contain_exec('docker rmi base') }.to raise_error(Puppet::Error) end end diff --git a/spec/defines/image_windows_spec.rb b/spec/defines/image_windows_spec.rb index 7bd33762..860fd0c8 100644 --- a/spec/defines/image_windows_spec.rb +++ b/spec/defines/image_windows_spec.rb @@ -1,54 +1,63 @@ require 'spec_helper' -describe 'docker::image', :type => :define do +describe 'docker::image', type: :define do let(:title) { 'base' } - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemrelease => '2016', - :operatingsystemmajrelease => '2016', - :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', - :os => { :family => 'windows', :name => 'windows', :release => { :major => '2016', :full => '2016' } } - } } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'windows', + operatingsystem: 'windows', + kernelrelease: '10.0.14393', + operatingsystemrelease: '2016', + operatingsystemmajrelease: '2016', + 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', + os: { family: 'windows', name: 'windows', release: { major: '2016', full: '2016' } }, + } + end + context 'with ensure => present' do - let(:params) { { 'ensure' => 'present' } } - it { should contain_file('C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1') } - it { should contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base') } + let(:params) { { 'ensure' => 'present' } } + + it { is_expected.to contain_file('C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1') } + it { is_expected.to contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base') } end context 'with docker_file => Dockerfile' do - let(:params) { { 'docker_file' => 'Dockerfile' }} - it { should contain_exec('Get-Content Dockerfile -Raw | docker build -t base -') } - end - - context 'with ensure => present and docker_file => Dockerfile' do - let(:params) { { 'ensure' => 'present', 'docker_file' => 'Dockerfile' } } - it { should contain_exec('Get-Content Dockerfile -Raw | docker build -t base -') } - end - - context 'with ensure => present and image_tag => nanoserver' do - let(:params) { { 'ensure' => 'present', 'image_tag' => 'nanoserver' } } - it { should contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base:nanoserver') } - end - - context 'with ensure => present and image_digest => sha256:deadbeef' do - let(:params) { { 'ensure' => 'present', 'image_digest' => 'sha256:deadbeef' } } - it { should contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base@sha256:deadbeef') } - end - - context 'with ensure => present and image_tag => nanoserver and docker_file => Dockerfile' do - let(:params) { { 'ensure' => 'present', 'image_tag' => 'nanoserver', 'docker_file' => 'Dockerfile' } } - it { should contain_exec('Get-Content Dockerfile -Raw | docker build -t base:nanoserver -') } - end - - context 'with ensure => latest' do - let(:params) { { 'ensure' => 'latest' } } - it { should contain_exec("echo 'Update of base complete'").with_onlyif('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base') } - end - -end \ No newline at end of file + let(:params) { { 'docker_file' => 'Dockerfile' } } + + it { is_expected.to contain_exec('Get-Content Dockerfile -Raw | docker build -t base -') } + end + + context 'with ensure => present and docker_file => Dockerfile' do + let(:params) { { 'ensure' => 'present', 'docker_file' => 'Dockerfile' } } + + it { is_expected.to contain_exec('Get-Content Dockerfile -Raw | docker build -t base -') } + end + + context 'with ensure => present and image_tag => nanoserver' do + let(:params) { { 'ensure' => 'present', 'image_tag' => 'nanoserver' } } + + it { is_expected.to contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base:nanoserver') } + end + + context 'with ensure => present and image_digest => sha256:deadbeef' do + let(:params) { { 'ensure' => 'present', 'image_digest' => 'sha256:deadbeef' } } + + it { is_expected.to contain_exec('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base@sha256:deadbeef') } + end + + context 'with ensure => present and image_tag => nanoserver and docker_file => Dockerfile' do + let(:params) { { 'ensure' => 'present', 'image_tag' => 'nanoserver', 'docker_file' => 'Dockerfile' } } + + it { is_expected.to contain_exec('Get-Content Dockerfile -Raw | docker build -t base:nanoserver -') } + end + + context 'with ensure => latest' do + let(:params) { { 'ensure' => 'latest' } } + + it { is_expected.to contain_exec("echo 'Update of base complete'").with_onlyif('& C:/Users/Administrator/AppData/Local/Temp/update_docker_image.ps1 -DockerImage base') } + end +end diff --git a/spec/defines/plugin_spec.rb b/spec/defines/plugin_spec.rb index c887cc6f..a5b673be 100644 --- a/spec/defines/plugin_spec.rb +++ b/spec/defines/plugin_spec.rb @@ -1,30 +1,34 @@ require 'spec_helper' -describe 'docker::plugin', :type => :define do +describe 'docker::plugin', type: :define do let(:title) { 'foo/plugin:latest' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end context 'with defaults for all parameters' do it { is_expected.to compile.with_all_deps } - it { should contain_exec('plugin install foo/plugin:latest').with_command(/docker plugin install/) } + it { is_expected.to contain_exec('plugin install foo/plugin:latest').with_command(%r{docker plugin install}) } end context 'with enabled => false' do - let(:params) { { 'enabled' => false, } } + let(:params) { { 'enabled' => false } } + it { is_expected.to compile.with_all_deps } - it { should contain_exec("disable foo/plugin:latest").with_command(/docker plugin disable/) } + it { is_expected.to contain_exec('disable foo/plugin:latest').with_command(%r{docker plugin disable}) } end context 'with ensure => absent' do - let(:params) { { 'ensure' => 'absent'} } + let(:params) { { 'ensure' => 'absent' } } + it { is_expected.to compile.with_all_deps } - it { should contain_exec('plugin remove foo/plugin:latest').with_command(/docker plugin rm/) } + it { is_expected.to contain_exec('plugin remove foo/plugin:latest').with_command(%r{docker plugin rm}) } end end diff --git a/spec/defines/registry_spec.rb b/spec/defines/registry_spec.rb index 35bd5435..420702d9 100644 --- a/spec/defines/registry_spec.rb +++ b/spec/defines/registry_spec.rb @@ -1,68 +1,81 @@ require 'spec_helper' -describe 'docker::registry', :type => :define do +describe 'docker::registry', type: :define do let(:title) { 'localhost:5000' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end let(:params) { { 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth') } + + it { is_expected.to contain_exec('localhost:5000 auth') } context 'with ensure => present' do let(:params) { { 'ensure' => 'absent', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command('docker logout localhost:5000') } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command('docker logout localhost:5000') } end context 'with ensure => present' do let(:params) { { 'ensure' => 'present', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } end context 'with ensure => present and username => user1' do let(:params) { { 'ensure' => 'present', 'username' => 'user1', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } end context 'with ensure => present and password => secret' do let(:params) { { 'ensure' => 'present', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } end context 'with ensure => present and email => user1@example.io' do let(:params) { { 'ensure' => 'present', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command('docker login localhost:5000') } end context 'with ensure => present and username => user1, and password => secret and email => user1@example.io' do let(:params) { { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_environment(/password=secret/) } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_environment(%r{password=secret}) } end - context 'with ensure => present and username => user1, and password => secret and email => user1@example.io and version < 1.11.0' do + context 'with ensure => present and username => user1, and password => secret and email => user1@example.io and version < 1.11.0' do let(:params) { { 'ensure' => 'present', 'username' => 'user1', 'password' => 'secret', 'email' => 'user1@example.io', 'version' => '1.9.0', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" -e 'user1@example.io' localhost:5000").with_environment(/password=secret/) } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" -e 'user1@example.io' localhost:5000").with_environment(%r{password=secret}) } end context 'with username => user1, and password => secret' do let(:params) { { 'username' => 'user1', 'password' => 'secret', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_environment(/password=secret/) } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_environment(%r{password=secret}) } end context 'with username => user1, and password => secret and local_user => testuser' do let(:params) { { 'username' => 'user1', 'password' => 'secret', 'local_user' => 'testuser', 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } } - it { should contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_user('testuser').with_environment(/password=secret/) } + + it { is_expected.to contain_exec('localhost:5000 auth').with_command("docker login -u 'user1' -p \"${password}\" localhost:5000").with_user('testuser').with_environment(%r{password=secret}) } end context 'with an invalid ensure value' do let(:params) { { 'ensure' => 'not present or absent' } } + it do expect { - should contain_exec('docker logout localhost:5000') + is_expected.to contain_exec('docker logout localhost:5000') }.to raise_error(Puppet::Error) end end diff --git a/spec/defines/run_spec.rb b/spec/defines/run_spec.rb index e2398bfb..6572640a 100755 --- a/spec/defines/run_spec.rb +++ b/spec/defines/run_spec.rb @@ -1,54 +1,62 @@ require 'spec_helper' ['Debian', 'RedHat', 'generic systemd'].each do |osfamily| - describe 'docker::run', :type => :define do + describe 'docker::run', type: :define do let(:title) { 'sample' } - params = {'command' => 'command', 'image' => 'base'} + params = { 'command' => 'command', 'image' => 'base' } context "on #{osfamily}" do - initscript = '/etc/systemd/system/docker-sample.service' - startscript = "/usr/local/bin/docker-run-sample-start.sh" - stopscript = "/usr/local/bin/docker-run-sample-stop.sh" + startscript = '/usr/local/bin/docker-run-sample-start.sh' + stopscript = '/usr/local/bin/docker-run-sample-stop.sh' if osfamily == 'Debian' pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker' }" let(:pre_condition) { pre_condition } - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :lsbdistid => 'Ubuntu', - :lsbdistcodename => 'xenial', - :kernelrelease => '4.4.0-21-generic', - :operatingsystemrelease => '16.04', - :operatingsystemmajrelease => '16.04', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } + let(:facts) do + { + architecture: 'amd64', + osfamily: 'Debian', + operatingsystem: 'Ubuntu', + lsbdistid: 'Ubuntu', + lsbdistcodename: 'xenial', + kernelrelease: '4.4.0-21-generic', + operatingsystemrelease: '16.04', + operatingsystemmajrelease: '16.04', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + systemd = true elsif osfamily == 'RedHat' pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker' }" let(:pre_condition) { pre_condition } - let(:facts) { { - :architecture => 'x86_64', - :osfamily => osfamily, - :operatingsystem => 'RedHat', - :lsbdistcodename => 'xenial', - :operatingsystemrelease => '7.2', - :operatingsystemmajrelease => '7', - :kernelversion => '3.10.0', - :os => { :distro => { :codename => 'wheezy' }, :family => osfamily, :name => osfamily, :release => { :major => '7', :full => '7.0' } } - } } + let(:facts) do + { + architecture: 'x86_64', + osfamily: osfamily, + operatingsystem: 'RedHat', + lsbdistcodename: 'xenial', + operatingsystemrelease: '7.2', + operatingsystemmajrelease: '7', + kernelversion: '3.10.0', + os: { distro: { codename: 'wheezy' }, family: osfamily, name: osfamily, release: { major: '7', full: '7.0' } }, + } + end + systemd = true elsif osfamily == 'generic systemd' pre_condition = "class { 'docker': docker_group => 'docker', service_name => 'docker', service_provider => systemd, acknowledge_unsupported_os => true }" let(:pre_condition) { pre_condition } - let(:facts) { { - :osfamily => 'Gentoo', - :operatingsystem => 'Generic', - } } - params.merge!({'service_provider' => 'systemd'}) + let(:facts) do + { + osfamily: 'Gentoo', + operatingsystem: 'Generic', + } + end + + params['service_provider'] = 'systemd' systemd = true end @@ -57,416 +65,481 @@ context 'passing the required params' do let(:params) { params } - it { should compile.with_all_deps } - it { should contain_service('docker-sample') } - it { should contain_file(initscript).with_content(/#{Regexp.escape(startscript)}/).with_mode('0644') } - it { should contain_file(initscript).with_content(/#{Regexp.escape(stopscript)}/) } - it { should contain_file(startscript_or_init).with_content(/docker start/).with_content(/command/).with_content(/base/)} + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('docker-sample') } + it { is_expected.to contain_file(initscript).with_content(%r{#{Regexp.escape(startscript)}}).with_mode('0644') } + it { is_expected.to contain_file(initscript).with_content(%r{#{Regexp.escape(stopscript)}}) } + it { is_expected.to contain_file(startscript_or_init).with_content(%r{docker start}).with_content(%r{command}).with_content(%r{base}) } if systemd - it { should contain_file(initscript).with_content(/^SyslogIdentifier=docker-sample$/) } + it { is_expected.to contain_file(initscript).with_content(%r{^SyslogIdentifier=docker-sample$}) } end - end context 'when passing `after` containers' do - let(:params) { params.merge({'after' => ['foo', 'bar', 'foo_bar/baz']}) } - if (systemd) - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo.service/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-bar.service/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo_bar-baz.service/) } - it { should contain_file(initscript).with_content(/Wants=(.*\s+)?docker-foo.service/) } - it { should contain_file(initscript).with_content(/Wants=(.*\s+)?docker-bar.service/) } - it { should contain_file(initscript).with_content(/Wants=(.*\s+)?docker-foo_bar-baz.service/) } + let(:params) { params.merge('after' => ['foo', 'bar', 'foo_bar/baz']) } + + if systemd + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-bar.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-foo_bar-baz.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Wants=(.*\s+)?docker-foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Wants=(.*\s+)?docker-bar.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Wants=(.*\s+)?docker-foo_bar-baz.service}) } else - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-foo/) } - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-bar/) } - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-foo_bar-baz/) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-foo}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-bar}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-foo_bar-baz}) } end end context 'when passing `depends` containers' do - let(:params) { params.merge({'depends' => ['foo', 'bar', 'foo_bar/baz']}) } - if (systemd) - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo.service/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-bar.service/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?docker-foo_bar-baz.service/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?docker-foo.service/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?docker-bar.service/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?docker-foo_bar-baz.service/) } + let(:params) { params.merge('depends' => ['foo', 'bar', 'foo_bar/baz']) } + + if systemd + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-bar.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?docker-foo_bar-baz.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?docker-foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?docker-bar.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?docker-foo_bar-baz.service}) } else - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-foo/) } - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-bar/) } - it { should contain_file(initscript).with_content(/Required-Start:.*\s+docker-foo_bar-baz/) } - it { should contain_file(initscript).with_content(/Required-Stop:.*\s+docker-foo/) } - it { should contain_file(initscript).with_content(/Required-Stop:.*\s+docker-bar/) } - it { should contain_file(initscript).with_content(/Required-Stop:.*\s+docker-foo_bar-baz/) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-foo}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-bar}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+docker-foo_bar-baz}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Stop:.*\s+docker-foo}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Stop:.*\s+docker-bar}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Stop:.*\s+docker-foo_bar-baz}) } end end context 'when passing `depend_services`' do - let(:params) { params.merge({'depend_services' => ['foo', 'bar']}) } - if (systemd) - it { should contain_file(initscript).with_content(/After=(.*\s+)?foo.service/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?bar.service/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?foo.service/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?bar.service/) } + let(:params) { params.merge('depend_services' => ['foo', 'bar']) } + + if systemd + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?bar.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?foo.service}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?bar.service}) } context 'with full systemd unit names' do - let(:params) { params.merge({'depend_services' => ['foo', 'bar.service', 'baz.target']}) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?foo.service(\s+|$)/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?bar.service(\s+|$)/) } - it { should contain_file(initscript).with_content(/After=(.*\s+)?baz.target(\s+|$)/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?foo.service(\s+|$)/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?bar.service(\s+|$)/) } - it { should contain_file(initscript).with_content(/Requires=(.*\s+)?baz.target(\s+|$)/) } + let(:params) { params.merge('depend_services' => ['foo', 'bar.service', 'baz.target']) } + + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?foo.service(\s+|$)}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?bar.service(\s+|$)}) } + it { is_expected.to contain_file(initscript).with_content(%r{After=(.*\s+)?baz.target(\s+|$)}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?foo.service(\s+|$)}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?bar.service(\s+|$)}) } + it { is_expected.to contain_file(initscript).with_content(%r{Requires=(.*\s+)?baz.target(\s+|$)}) } end else - it { should contain_file(initscript).with_content(/Required-Start:.*\s+foo/) } - it { should contain_file(initscript).with_content(/Required-Start:.*\s+bar/) } - it { should contain_file(initscript).with_content(/Required-Stop:.*\s+foo/) } - it { should contain_file(initscript).with_content(/Required-Stop:.*\s+bar/) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+foo}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Start:.*\s+bar}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Stop:.*\s+foo}) } + it { is_expected.to contain_file(initscript).with_content(%r{Required-Stop:.*\s+bar}) } end end context 'removing containers and volumes' do context 'when trying to remove the volume and not the container on stop' do - let(:params) { params.merge({ - 'remove_container_on_stop' => false, - 'remove_volume_on_stop' => true, - }) } + let(:params) do + params.merge('remove_container_on_stop' => false, + 'remove_volume_on_stop' => true) + end + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'when trying to remove the volume and not the container on start' do - let(:params) { params.merge({ - 'remove_container_on_start' => false, - 'remove_volume_on_start' => true, - }) } + let(:params) do + params.merge('remove_container_on_start' => false, + 'remove_volume_on_start' => true) + end + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'When restarting an unhealthy container' do - let(:params) { params.merge({ - 'health_check_cmd' => 'pwd', - 'restart_on_unhealthy' => true, - 'health_check_interval' => 60, - }) } - if (systemd) - it { should contain_file(stopscript).with_content(/\/usr\/bin\/docker stop --time=0 /).with_content(/\/usr\/bin\/docker rm/) } - it { should contain_file(startscript).with_content(/--health-cmd/) } - end + let(:params) do + params.merge('health_check_cmd' => 'pwd', + 'restart_on_unhealthy' => true, + 'health_check_interval' => 60) + end + + if systemd + it { is_expected.to contain_file(stopscript).with_content(%r{\/usr\/bin\/docker stop --time=0 }).with_content(%r{\/usr\/bin\/docker rm}) } + it { is_expected.to contain_file(startscript).with_content(%r{--health-cmd}) } + end end context 'when not removing containers on container start and stop' do - let(:params) { params.merge({ - 'remove_container_on_start' => false, - 'remove_container_on_stop' => false, - }) } - it { should_not contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } + let(:params) do + params.merge('remove_container_on_start' => false, + 'remove_container_on_stop' => false) + end + + it { is_expected.not_to contain_file(startscript_or_init).with_content(%r{\/usr\/bin\/docker rm sample}) } end context 'when removing containers on container start' do - let(:params) { params.merge({'remove_container_on_start' => true}) } - it { should contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } + let(:params) { params.merge('remove_container_on_start' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{\/usr\/bin\/docker rm sample}) } end context 'when removing containers on container stop' do - let(:params) { params.merge({'remove_container_on_stop' => true}) } - it { should contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm sample/) } + let(:params) { params.merge('remove_container_on_stop' => true) } + + it { is_expected.to contain_file(stopscript_or_init).with_content(%r{\/usr\/bin\/docker rm sample}) } end context 'when not removing volumes on container start' do - let(:params) { params.merge({'remove_volume_on_start' => false}) } - it { should_not contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm -v sample/) } + let(:params) { params.merge('remove_volume_on_start' => false) } + + it { is_expected.not_to contain_file(startscript_or_init).with_content(%r{\/usr\/bin\/docker rm -v sample}) } end context 'when removing volumes on container start' do - let(:params) { params.merge({'remove_volume_on_start' => true}) } - it { should contain_file(startscript_or_init).with_content(/\/usr\/bin\/docker rm -v/) } + let(:params) { params.merge('remove_volume_on_start' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{\/usr\/bin\/docker rm -v}) } end context 'when not removing volumes on container stop' do - let(:params) { params.merge({'remove_volume_on_stop' => false}) } - it { should_not contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm -v sample/) } + let(:params) { params.merge('remove_volume_on_stop' => false) } + + it { is_expected.not_to contain_file(stopscript_or_init).with_content(%r{\/usr\/bin\/docker rm -v sample}) } end context 'when removing volumes on container stop' do - let(:params) { params.merge({'remove_volume_on_stop' => true}) } - it { should contain_file(stopscript_or_init).with_content(/\/usr\/bin\/docker rm -v/) } + let(:params) { params.merge('remove_volume_on_stop' => true) } + + it { is_expected.to contain_file(stopscript_or_init).with_content(%r{\/usr\/bin\/docker rm -v}) } end end context 'with autorestart functionality' do let(:params) { params } - if (systemd) - it { should contain_file(initscript).with_content(/Restart=on-failure/) } + + if systemd + it { is_expected.to contain_file(initscript).with_content(%r{Restart=on-failure}) } end end context 'when lxc_conf disables swap' do - let(:params) { params.merge({'lxc_conf' => 'lxc.cgroup.memory.memsw.limit_in_bytes=536870912'}) } - it { should contain_file(startscript_or_init).with_content(/-lxc-conf=\"lxc.cgroup.memory.memsw.limit_in_bytes=536870912\"/) } + let(:params) { params.merge('lxc_conf' => 'lxc.cgroup.memory.memsw.limit_in_bytes=536870912') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-lxc-conf=\"lxc.cgroup.memory.memsw.limit_in_bytes=536870912\"}) } end context 'when `use_name` is true' do - let(:params) { params.merge({'use_name' => true }) } - it { should contain_file(startscript_or_init).with_content(/--name sample /) } + let(:params) { params.merge('use_name' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--name sample }) } end context 'when stopping the service' do - let(:params) { params.merge({'running' => false}) } - it { should contain_service('docker-sample').with_ensure(false) } + let(:params) { params.merge('running' => false) } + + it { is_expected.to contain_service('docker-sample').with_ensure(false) } end context 'when passing a memory limit in bytes' do - let(:params) { params.merge({'memory_limit' => '1000b'}) } - it { should contain_file(startscript_or_init).with_content(/-m 1000b/) } + let(:params) { params.merge('memory_limit' => '1000b') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-m 1000b}) } end context 'when passing a cpuset' do - let(:params) { params.merge({'cpuset' => '3'}) } - it { should contain_file(startscript_or_init).with_content(/--cpuset-cpus=3/) } + let(:params) { params.merge('cpuset' => '3') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--cpuset-cpus=3}) } end context 'when passing a multiple cpu cpuset' do - let(:params) { params.merge({'cpuset' => ['0', '3']}) } - it { should contain_file(startscript_or_init).with_content(/--cpuset-cpus=0,3/) } + let(:params) { params.merge('cpuset' => ['0', '3']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--cpuset-cpus=0,3}) } end context 'when not passing a cpuset' do let(:params) { params } - it { should contain_file(startscript_or_init).without_content(/--cpuset-cpus=/) } + + it { is_expected.to contain_file(startscript_or_init).without_content(%r{--cpuset-cpus=}) } end context 'when passing a links option' do - let(:params) { params.merge({'links' => ['example:one', 'example:two']}) } - it { should contain_file(startscript_or_init).with_content(/--link example:one/).with_content(/--link example:two/) } + let(:params) { params.merge('links' => ['example:one', 'example:two']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--link example:one}).with_content(%r{--link example:two}) } end context 'when passing a hostname' do - let(:params) { params.merge({'hostname' => 'example.com'}) } - it { should contain_file(startscript_or_init).with_content(/-h 'example.com'/) } + let(:params) { params.merge('hostname' => 'example.com') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-h 'example.com'}) } end context 'when not passing a hostname' do let(:params) { params } - it { should contain_file(startscript_or_init).without_content(/-h ''/) } + + it { is_expected.to contain_file(startscript_or_init).without_content(%r{-h ''}) } end context 'when passing a username' do - let(:params) { params.merge({'username' => 'bob'}) } - it { should contain_file(startscript_or_init).with_content(/-u 'bob'/) } + let(:params) { params.merge('username' => 'bob') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-u 'bob'}) } end context 'when not passing a username' do let(:params) { params } - it { should contain_file(startscript_or_init).without_content(/-u ''/) } + + it { is_expected.to contain_file(startscript_or_init).without_content(%r{-u ''}) } end context 'when passing a port number' do - let(:params) { params.merge({'ports' => '4444'}) } - it { should contain_file(startscript_or_init).with_content(/-p 4444/) } + let(:params) { params.merge('ports' => '4444') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-p 4444}) } end context 'when passing a port to expose' do - let(:params) { params.merge({'expose' => '4666'}) } - it { should contain_file(startscript_or_init).with_content(/--expose=4666/) } + let(:params) { params.merge('expose' => '4666') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--expose=4666}) } end context 'when passing a label' do - let(:params) { params.merge({'labels' => 'key=value'}) } - it { should contain_file(startscript_or_init).with_content(/-l key=value/) } + let(:params) { params.merge('labels' => 'key=value') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-l key=value}) } end context 'when passing a hostentry' do - let(:params) { params.merge({'hostentries' => 'dummyhost:127.0.0.2'}) } - it { should contain_file(startscript_or_init).with_content(/--add-host dummyhost:127.0.0.2/) } + let(:params) { params.merge('hostentries' => 'dummyhost:127.0.0.2') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--add-host dummyhost:127.0.0.2}) } end context 'when connecting to shared data volumes' do - let(:params) { params.merge({'volumes_from' => '6446ea52fbc9'}) } - it { should contain_file(startscript_or_init).with_content(/--volumes-from 6446ea52fbc9/) } + let(:params) { params.merge('volumes_from' => '6446ea52fbc9') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--volumes-from 6446ea52fbc9}) } end context 'when connecting to several shared data volumes' do - let(:params) { params.merge({'volumes_from' => ['sample-linked-container-1', 'sample-linked-container-2']}) } - it { should contain_file(startscript_or_init).with_content(/--volumes-from sample-linked-container-1/) } - it { should contain_file(startscript_or_init).with_content(/--volumes-from sample-linked-container-2/) } + let(:params) { params.merge('volumes_from' => ['sample-linked-container-1', 'sample-linked-container-2']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--volumes-from sample-linked-container-1}) } + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--volumes-from sample-linked-container-2}) } end context 'when passing several port numbers' do - let(:params) { params.merge({'ports' => ['4444', '4555']}) } - it { should contain_file(startscript_or_init).with_content(/-p 4444/).with_content(/-p 4555/) } + let(:params) { params.merge('ports' => ['4444', '4555']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-p 4444}).with_content(%r{-p 4555}) } end context 'when passing several labels' do - let(:params) { params.merge({'labels' => ['key1=value1', 'key2=value2']}) } - it { should contain_file(startscript_or_init).with_content(/-l key1=value1/).with_content(/-l key2=value2/) } + let(:params) { params.merge('labels' => ['key1=value1', 'key2=value2']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-l key1=value1}).with_content(%r{-l key2=value2}) } end context 'when passing several ports to expose' do - let(:params) { params.merge({'expose' => ['4666', '4777']}) } - it { should contain_file(startscript_or_init).with_content(/--expose=4666/).with_content(/--expose=4777/) } + let(:params) { params.merge('expose' => ['4666', '4777']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--expose=4666}).with_content(%r{--expose=4777}) } end context 'when passing serveral environment variables' do - let(:params) { params.merge({'env' => ['FOO=BAR', 'FOO2=BAR2']}) } - it { should contain_file(startscript_or_init).with_content(/-e "FOO=BAR"/).with_content(/-e "FOO2=BAR2"/) } + let(:params) { params.merge('env' => ['FOO=BAR', 'FOO2=BAR2']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-e "FOO=BAR"}).with_content(%r{-e "FOO2=BAR2"}) } end context 'when passing an environment variable' do - let(:params) { params.merge({'env' => 'FOO=BAR'}) } - it { should contain_file(startscript_or_init).with_content(/-e "FOO=BAR"/) } + let(:params) { params.merge('env' => 'FOO=BAR') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-e "FOO=BAR"}) } end context 'when passing serveral environment files' do - let(:params) { params.merge({'env_file' => ['/etc/foo.env', '/etc/bar.env']}) } - it { should contain_file(startscript_or_init).with_content(/--env-file \/etc\/foo.env/).with_content(/--env-file \/etc\/bar.env/) } + let(:params) { params.merge('env_file' => ['/etc/foo.env', '/etc/bar.env']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--env-file \/etc\/foo.env}).with_content(%r{--env-file \/etc\/bar.env}) } end context 'when passing an environment file' do - let(:params) { params.merge({'env_file' => '/etc/foo.env'}) } - it { should contain_file(startscript_or_init).with_content(/--env-file \/etc\/foo.env/) } + let(:params) { params.merge('env_file' => '/etc/foo.env') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--env-file \/etc\/foo.env}) } end context 'when passing serveral dns addresses' do - let(:params) { params.merge({'dns' => ['8.8.8.8', '8.8.4.4']}) } - it { should contain_file(startscript_or_init).with_content(/--dns 8.8.8.8/).with_content(/--dns 8.8.4.4/) } + let(:params) { params.merge('dns' => ['8.8.8.8', '8.8.4.4']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--dns 8.8.8.8}).with_content(%r{--dns 8.8.4.4}) } end context 'when passing a dns address' do - let(:params) { params.merge({'dns' => '8.8.8.8'}) } - it { should contain_file(startscript_or_init).with_content(/--dns 8.8.8.8/) } + let(:params) { params.merge('dns' => '8.8.8.8') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--dns 8.8.8.8}) } end context 'when passing serveral sockets to connect to' do - let(:params) { params.merge({'socket_connect' => ['tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567']}) } - it { should contain_file(startscript_or_init).with_content(/-H tcp:\/\/127.0.0.1:4567/) } + let(:params) { params.merge('socket_connect' => ['tcp://127.0.0.1:4567', 'tcp://127.0.0.2:4567']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-H tcp:\/\/127.0.0.1:4567}) } end context 'when passing a socket to connect to' do - let(:params) { params.merge({'socket_connect' => 'tcp://127.0.0.1:4567'}) } - it { should contain_file(startscript_or_init).with_content(/-H tcp:\/\/127.0.0.1:4567/) } + let(:params) { params.merge('socket_connect' => 'tcp://127.0.0.1:4567') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-H tcp:\/\/127.0.0.1:4567}) } end context 'when passing serveral dns search domains' do - let(:params) { params.merge({'dns_search' => ['my.domain.local', 'other-domain.de']}) } - it { should contain_file(startscript_or_init).with_content(/--dns-search my.domain.local/).with_content(/--dns-search other-domain.de/) } + let(:params) { params.merge('dns_search' => ['my.domain.local', 'other-domain.de']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--dns-search my.domain.local}).with_content(%r{--dns-search other-domain.de}) } end context 'when passing a dns search domain' do - let(:params) { params.merge({'dns_search' => 'my.domain.local'}) } - it { should contain_file(startscript_or_init).with_content(/--dns-search my.domain.local/) } + let(:params) { params.merge('dns_search' => 'my.domain.local') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--dns-search my.domain.local}) } end context 'when disabling network' do - let(:params) { params.merge({'disable_network' => true}) } - it { should contain_file(startscript_or_init).with_content(/-n false/) } + let(:params) { params.merge('disable_network' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-n false}) } end context 'when running privileged' do - let(:params) { params.merge({'privileged' => true}) } - it { should contain_file(startscript_or_init).with_content(/--privileged/) } + let(:params) { params.merge('privileged' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--privileged}) } end context 'should run with correct detached value' do let(:params) { params } - if (systemd) - it { should_not contain_file(startscript).with_content(/--detach=true/) } + + if systemd + it { is_expected.not_to contain_file(startscript).with_content(%r{--detach=true}) } else - it { should contain_file(initscript).with_content(/--detach=true/) } + it { is_expected.to contain_file(initscript).with_content(%r{--detach=true}) } end end context 'should be able to override detached' do - let(:params) { params.merge({'detach' => false}) } - it { should contain_file(startscript_or_init).without_content(/--detach=true/) } + let(:params) { params.merge('detach' => false) } + + it { is_expected.to contain_file(startscript_or_init).without_content(%r{--detach=true}) } end context 'when running with a tty' do - let(:params) { params.merge({'tty' => true}) } - it { should contain_file(startscript_or_init).with_content(/-t/) } + let(:params) { params.merge('tty' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-t}) } end context 'when running with read-only image' do - let(:params) { params.merge({'read_only' => true}) } - it { should contain_file(startscript_or_init).with_content(/--read-only=true/) } + let(:params) { params.merge('read_only' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--read-only=true}) } end context 'when passing serveral extra parameters' do - let(:params) { params.merge({'extra_parameters' => ['--rm', '-w /tmp']}) } - it { should contain_file(startscript_or_init).with_content(/--rm/).with_content(/-w \/tmp/) } + let(:params) { params.merge('extra_parameters' => ['--rm', '-w /tmp']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--rm}).with_content(%r{-w \/tmp}) } end context 'when passing an extra parameter' do - let(:params) { params.merge({'extra_parameters' => '-c 4'}) } - it { should contain_file(startscript_or_init).with_content(/-c 4/) } + let(:params) { params.merge('extra_parameters' => '-c 4') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-c 4}) } end context 'when passing a data volume' do - let(:params) { params.merge({'volumes' => '/var/log'}) } - it { should contain_file(startscript_or_init).with_content(/-v \/var\/log/) } + let(:params) { params.merge('volumes' => '/var/log') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-v \/var\/log}) } end context 'when passing serveral data volume' do - let(:params) { params.merge({'volumes' => ['/var/lib/couchdb', '/var/log']}) } - it { should contain_file(startscript_or_init).with_content(/-v \/var\/lib\/couchdb/) } - it { should contain_file(startscript_or_init).with_content(/-v \/var\/log/) } + let(:params) { params.merge('volumes' => ['/var/lib/couchdb', '/var/log']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-v \/var\/lib\/couchdb}) } + it { is_expected.to contain_file(startscript_or_init).with_content(%r{-v \/var\/log}) } end context 'when using network mode with a single network' do - let(:params) { params.merge({'net' => 'host'}) } - it { should contain_file(startscript_or_init).with_content(/--net host/) } + let(:params) { params.merge('net' => 'host') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{--net host}) } end context 'when using network mode with multiple networks' do - let(:params) { params.merge({'net' => ['host','foo']}) } - it { should contain_file(startscript_or_init).with_content(/docker network connect host sample/) } - it { should contain_file(startscript_or_init).with_content(/docker network connect foo sample/) } + let(:params) { params.merge('net' => ['host', 'foo']) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{docker network connect host sample}) } + it { is_expected.to contain_file(startscript_or_init).with_content(%r{docker network connect foo sample}) } end context 'when `pull_on_start` is true' do - let(:params) { params.merge({'pull_on_start' => true}) } - it { should contain_file(startscript_or_init).with_content(/docker pull base/) } + let(:params) { params.merge('pull_on_start' => true) } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{docker pull base}) } end context 'when `pull_on_start` is false' do - let(:params) { params.merge({'pull_on_start' => false}) } - it { should_not contain_file(startscript_or_init).with_content(/docker pull base/) } + let(:params) { params.merge('pull_on_start' => false) } + + it { is_expected.not_to contain_file(startscript_or_init).with_content(%r{docker pull base}) } end context 'when `before_start` is set' do - let(:params) { params.merge({'before_start' => "echo before_start"}) } - it { should contain_file(startscript_or_init).with_content(/before_start/) } + let(:params) { params.merge('before_start' => 'echo before_start') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{before_start}) } end context 'when `before_start` is not set' do - let(:params) { params.merge({'before_start' => false}) } - it { should_not contain_file(startscript_or_init).with_content(/before_start/) } + let(:params) { params.merge('before_start' => false) } + + it { is_expected.not_to contain_file(startscript_or_init).with_content(%r{before_start}) } end context 'when `before_stop` is set' do - let(:params) { params.merge({'before_stop' => "echo before_stop"}) } - it { should contain_file(stopscript_or_init).with_content(/before_stop/) } + let(:params) { params.merge('before_stop' => 'echo before_stop') } + + it { is_expected.to contain_file(stopscript_or_init).with_content(%r{before_stop}) } end context 'when `before_stop` is not set' do - let(:params) { params.merge({'before_stop' => false}) } - it { should_not contain_file(stopscript_or_init).with_content(/before_stop/) } + let(:params) { params.merge('before_stop' => false) } + + it { is_expected.not_to contain_file(stopscript_or_init).with_content(%r{before_stop}) } end context 'when `after_create` is set' do - let(:params) { params.merge({'after_create' => "echo after_create"}) } - it { should contain_file(startscript_or_init).with_content(/after_create/) } + let(:params) { params.merge('after_create' => 'echo after_create') } + + it { is_expected.to contain_file(startscript_or_init).with_content(%r{after_create}) } end context 'with an title that will not format into a path' do @@ -477,45 +550,46 @@ new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' new_stopscript = '/usr/local/bin/docker-run-this-that-stop.sh' - it { should contain_service('docker-this-that') } - it { should contain_file(new_initscript) } - it { should contain_file(new_startscript) } - it { should contain_file(new_stopscript) } + it { is_expected.to contain_service('docker-this-that') } + it { is_expected.to contain_file(new_initscript) } + it { is_expected.to contain_file(new_startscript) } + it { is_expected.to contain_file(new_stopscript) } end context 'with manage_service turned off' do let(:title) { 'this/that' } - let(:params) { params.merge({'manage_service' => false}) } + let(:params) { params.merge('manage_service' => false) } new_initscript = '/etc/systemd/system/docker-this-that.service' new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' new_stopscript = '/usr/local/bin/docker-run-this-that-stop.sh' - it { should_not contain_service('docker-this-that') } - it { should contain_file(new_initscript) } - it { should contain_file(new_startscript) } - it { should contain_file(new_stopscript) } + it { is_expected.not_to contain_service('docker-this-that') } + it { is_expected.to contain_file(new_initscript) } + it { is_expected.to contain_file(new_startscript) } + it { is_expected.to contain_file(new_stopscript) } end context 'with service_prefix set to empty string' do let(:title) { 'this/that' } - let(:params) { params.merge({'service_prefix' => ''}) } + let(:params) { params.merge('service_prefix' => '') } new_initscript = '/etc/systemd/system/this-that.service' new_startscript = '/usr/local/bin/docker-run-this-that-start.sh' new_stopscript = '/usr/local/bin/docker-run-this-that-stop.sh' - it { should contain_service('this-that') } - it { should contain_file(new_initscript) } - it { should contain_file(new_startscript) } - it { should contain_file(new_stopscript) } + it { is_expected.to contain_service('this-that') } + it { is_expected.to contain_file(new_initscript) } + it { is_expected.to contain_file(new_startscript) } + it { is_expected.to contain_file(new_stopscript) } end context 'with an invalid title' do let(:title) { 'with spaces' } + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end @@ -528,158 +602,172 @@ new_startscript = '/usr/local/bin/docker-run-this-that_other-start.sh' new_stopscript = '/usr/local/bin/docker-run-this-that_other-stop.sh' - it { should contain_service('docker-this-that_other') } - it { should contain_file(new_initscript) } - it { should contain_file(new_startscript) } - it { should contain_file(new_stopscript) } + it { is_expected.to contain_service('docker-this-that_other') } + it { is_expected.to contain_file(new_initscript) } + it { is_expected.to contain_file(new_startscript) } + it { is_expected.to contain_file(new_stopscript) } end context 'with an invalid image name' do - let(:params) { params.merge({'image' => 'with spaces', 'running' => 'not a boolean'}) } + let(:params) { params.merge('image' => 'with spaces', 'running' => 'not a boolean') } + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'with an invalid running value' do let(:title) { 'with spaces' } - let(:params) { params.merge({'running' => 'not a boolean'}) } + let(:params) { params.merge('running' => 'not a boolean') } + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'with an invalid memory value' do let(:title) { 'with spaces' } - let(:params) { params.merge({'memory' => 'not a number'}) } + let(:params) { params.merge('memory' => 'not a number') } + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'with a missing memory unit' do let(:title) { 'with spaces' } - let(:params) { params.merge({'memory' => '10240'}) } + let(:params) { params.merge('memory' => '10240') } + it do expect { - should contain_service('docker-sample') + is_expected.to contain_service('docker-sample') }.to raise_error(Puppet::Error) end end context 'with restart policy set to no' do - let(:params) { params.merge({'restart' => 'no', 'extra_parameters' => '-c 4'}) } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=\/var\/run\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="no"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(0) } + let(:params) { params.merge('restart' => 'no', 'extra_parameters' => '-c 4') } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=\/var\/run\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="no"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(0) } end context 'with restart policy set to always' do - let(:params) { params.merge({'restart' => 'always', 'extra_parameters' => '-c 4'}) } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=\/var\/run\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="always"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(0) } + let(:params) { params.merge('restart' => 'always', 'extra_parameters' => '-c 4') } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=\/var\/run\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="always"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(0) } end context 'with restart policy set to on-failure' do - let(:params) { params.merge({'restart' => 'on-failure', 'extra_parameters' => '-c 4'}) } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=\/var\/run\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="on-failure"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(0) } + let(:params) { params.merge('restart' => 'on-failure', 'extra_parameters' => '-c 4') } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=\/var\/run\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="on-failure"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(0) } end context 'with restart policy set to on-failure:3' do - let(:params) { params.merge({'restart' => 'on-failure:3', 'extra_parameters' => '-c 4'}) } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=\/var\/run\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="on-failure:3"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(0) } + let(:params) { params.merge('restart' => 'on-failure:3', 'extra_parameters' => '-c 4') } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=\/var\/run\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="on-failure:3"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(0) } end context 'when `docker_service` is false' do - let(:params) { params.merge({'docker_service' => false}) } - it { should compile.with_all_deps } - it { should contain_service('docker-sample') } + let(:params) { params.merge('docker_service' => false) } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('docker-sample') } end context 'when `docker_service` is true' do - let(:params) { params.merge({'docker_service' => true}) } + let(:params) { params.merge('docker_service' => true) } let(:pre_condition) { ["service { 'docker': provider => systemd }", pre_condition] } - it { should compile.with_all_deps } - it { should contain_service('docker').that_comes_before('Service[docker-sample]') } - it { should contain_service('docker').that_notifies('Service[docker-sample]') } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('docker').that_comes_before('Service[docker-sample]') } + it { is_expected.to contain_service('docker').that_notifies('Service[docker-sample]') } end context 'when `docker_service` is true and `restart_service_on_docker_refresh` is false' do - let(:params) { params.merge({'docker_service' => true, 'restart_service_on_docker_refresh' => false}) } + let(:params) { params.merge('docker_service' => true, 'restart_service_on_docker_refresh' => false) } let(:pre_condition) { ["service { 'docker': provider => systemd }", pre_condition] } - it { should compile.with_all_deps } - it { should contain_service('docker').that_comes_before('Service[docker-sample]') } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('docker').that_comes_before('Service[docker-sample]') } end context 'when `docker_service` is `my-docker`' do - let(:params) { params.merge({'docker_service' => 'my-docker'}) } + let(:params) { params.merge('docker_service' => 'my-docker') } let(:pre_condition) { ["service { 'my-docker': provider => systemd }", pre_condition] } - it { should compile.with_all_deps } - it { should contain_service('my-docker').that_comes_before('Service[docker-sample]') } - it { should contain_service('my-docker').that_notifies('Service[docker-sample]') } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('my-docker').that_comes_before('Service[docker-sample]') } + it { is_expected.to contain_service('my-docker').that_notifies('Service[docker-sample]') } end context 'when `docker_service` is `my-docker` and `restart_service_on_docker_refresh` is false' do - let(:params) { params.merge({'docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false}) } + let(:params) { params.merge('docker_service' => 'my-docker', 'restart_service_on_docker_refresh' => false) } let(:pre_condition) { ["service { 'my-docker': provider => systemd }", pre_condition] } - it { should compile.with_all_deps } - it { should contain_service('my-docker').that_comes_before('Service[docker-sample]') } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('my-docker').that_comes_before('Service[docker-sample]') } end context 'with syslog_identifier' do - let(:params) { params.merge({'syslog_identifier' => 'docker-universe' }) } + let(:params) { params.merge('syslog_identifier' => 'docker-universe') } + if systemd - it { should contain_file(initscript).with_content(/^SyslogIdentifier=docker-universe$/) } + it { is_expected.to contain_file(initscript).with_content(%r{^SyslogIdentifier=docker-universe$}) } end end context 'with extra_systemd_parameters' do - let(:params) { params.merge({'extra_systemd_parameters' => {'RestartSec' => 5}}) } - if (systemd) - it { should contain_file(initscript).with_content(/^RestartSec=5$/) } + let(:params) { params.merge('extra_systemd_parameters' => { 'RestartSec' => 5 }) } + + if systemd + it { is_expected.to contain_file(initscript).with_content(%r{^RestartSec=5$}) } end end context 'with ensure absent' do - let(:params) { params.merge({'ensure' => 'absent'}) } - it { should compile.with_all_deps } - it { should contain_service('docker-sample').with_ensure(false) } - it { should contain_exec("remove container docker-sample").with_command('docker rm -v sample') } - it { should_not contain_file('docker-sample.service')} - end + let(:params) { params.merge('ensure' => 'absent') } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_service('docker-sample').with_ensure(false) } + it { is_expected.to contain_exec('remove container docker-sample').with_command('docker rm -v sample') } + it { is_expected.not_to contain_file('docker-sample.service') } + end end end - end diff --git a/spec/defines/run_windows_spec.rb b/spec/defines/run_windows_spec.rb index 03afa375..86356843 100755 --- a/spec/defines/run_windows_spec.rb +++ b/spec/defines/run_windows_spec.rb @@ -1,99 +1,108 @@ require 'spec_helper' -describe 'docker::run', :type => :define do +describe 'docker::run', type: :define do let(:title) { 'sample' } let(:pre_condition) { 'class { \'docker\': docker_ee => true }' } - let(:facts) { { - :architecture => 'amd64', - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemrelease => '2016', - :operatingsystemmajrelease => '2016', - :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', - :os => { :family => 'windows', :name => 'windows', :release => { :major => '2016', :full => '2016' } } - } } - command = 'docker' + let(:facts) do + { + architecture: 'amd64', + osfamily: 'windows', + operatingsystem: 'windows', + kernelrelease: '10.0.14393', + operatingsystemrelease: '2016', + operatingsystemmajrelease: '2016', + 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', + os: { family: 'windows', name: 'windows', release: { major: '2016', full: '2016' } }, + } + end context 'with restart policy set to no' do - let(:params) { {'restart' => 'no', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="no"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(3000) } + let(:params) { { 'restart' => 'no', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4' } } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="no"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(3000) } end context 'with restart policy set to always' do - let(:params) { {'restart' => 'always', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="always"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(3000) } - it { should contain_exec('start sample with docker').with_command(/docker start sample/) } + let(:params) { { 'restart' => 'always', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4' } } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="always"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(3000) } + it { is_expected.to contain_exec('start sample with docker').with_command(%r{docker start sample}) } end context 'with restart policy set to on-failure' do - let(:params) { {'restart' => 'on-failure', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="on-failure"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(3000) } + let(:params) { { 'restart' => 'on-failure', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4' } } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="on-failure"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(3000) } end context 'with restart policy set to on-failure:3' do - let(:params) { {'restart' => 'on-failure:3', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4'} } - it { should contain_exec('run sample with docker') } - it { should contain_exec('run sample with docker').with_unless(/sample/) } - it { should contain_exec('run sample with docker').with_unless(/inspect/) } - it { should contain_exec('run sample with docker').with_command(/--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid/) } - it { should contain_exec('run sample with docker').with_command(/-c 4/) } - it { should contain_exec('run sample with docker').with_command(/--restart="on-failure:3"/) } - it { should contain_exec('run sample with docker').with_command(/base command/) } - it { should contain_exec('run sample with docker').with_timeout(3000) } + let(:params) { { 'restart' => 'on-failure:3', 'command' => 'command', 'image' => 'base', 'extra_parameters' => '-c 4' } } + + it { is_expected.to contain_exec('run sample with docker') } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{sample}) } + it { is_expected.to contain_exec('run sample with docker').with_unless(%r{inspect}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--cidfile=C:\/Users\/Administrator\/AppData\/Local\/Temp\/docker-sample.cid}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{-c 4}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{--restart="on-failure:3"}) } + it { is_expected.to contain_exec('run sample with docker').with_command(%r{base command}) } + it { is_expected.to contain_exec('run sample with docker').with_timeout(3000) } end context 'with ensure absent' do - let(:params) { {'ensure' => 'absent', 'command' => 'command', 'image' => 'base'} } - it { should compile.with_all_deps } - it { should contain_exec("stop container docker-sample").with_command('docker stop --time=0 sample') } - it { should contain_exec("remove container docker-sample").with_command('docker rm -v sample') } - it { should_not contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"')} + let(:params) { { 'ensure' => 'absent', 'command' => 'command', 'image' => 'base' } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_exec('stop container docker-sample').with_command('docker stop --time=0 sample') } + it { is_expected.to contain_exec('remove container docker-sample').with_command('docker rm -v sample') } + it { is_expected.not_to contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"') } end context 'with ensure absent and restart policy' do - let(:params) { {'ensure' => 'absent', 'command' => 'command', 'image' => 'base', 'restart' => 'always'} } - it { should compile.with_all_deps } - it { should contain_exec("stop sample with docker").with_command('docker stop --time=0 sample') } - it { should contain_exec("remove sample with docker").with_command('docker rm -v sample') } - it { should_not contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"')} + let(:params) { { 'ensure' => 'absent', 'command' => 'command', 'image' => 'base', 'restart' => 'always' } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_exec('stop sample with docker').with_command('docker stop --time=0 sample') } + it { is_expected.to contain_exec('remove sample with docker').with_command('docker rm -v sample') } + it { is_expected.not_to contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"') } end context 'with ensure present and running false' do - let(:params) { {'ensure' => 'present', 'image' => 'base', 'restart' => 'always', 'running' => false} } - it { should compile.with_all_deps } - it { should contain_exec("stop sample with docker").with_command('docker stop --time=0 sample') } + let(:params) { { 'ensure' => 'present', 'image' => 'base', 'restart' => 'always', 'running' => false } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_exec('stop sample with docker').with_command('docker stop --time=0 sample') } end context 'with ensure present and no restart policy' do - let(:params) { {'ensure' => 'present', 'image' => 'base'} } + let(:params) { { 'ensure' => 'present', 'image' => 'base' } } + it do expect { - should_not contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"') + is_expected.not_to contain_file('C:/Users/Administrator/AppData/Local/Temp/docker-sample.cid"') }.to raise_error(Puppet::Error) end end diff --git a/spec/defines/secrets_spec.rb b/spec/defines/secrets_spec.rb index a4ec698b..cdb52ccd 100644 --- a/spec/defines/secrets_spec.rb +++ b/spec/defines/secrets_spec.rb @@ -1,43 +1,51 @@ require 'spec_helper' -describe 'docker::secrets', :type => :define do +describe 'docker::secrets', type: :define do let(:title) { 'test_secret' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end context 'with secret_name => test_secret and secret_path => /root/secret.txt and label => test' do - let(:params) { { - 'secret_name' => 'test_secret', - 'secret_path' => '/root/secret.txt', - 'label' => ['test'], - } } - it { should contain_exec('test_secret docker secret create').with_command(/docker secret create/) } + let(:params) do + { + 'secret_name' => 'test_secret', + 'secret_path' => '/root/secret.txt', + 'label' => ['test'], + } + end + + it { is_expected.to contain_exec('test_secret docker secret create').with_command(%r{docker secret create}) } context 'multiple secrets declaration' do - let(:pre_condition) { + let(:pre_condition) do " docker::secrets{'test_secret_2': secret_name => 'test_secret_2', secret_path => '/root/secret_2.txt', } " - } - it { should contain_exec('test_secret docker secret create').with_command(/docker secret create/) } - it { should contain_exec('test_secret_2 docker secret create').with_command(/docker secret create/) } + end + + it { is_expected.to contain_exec('test_secret docker secret create').with_command(%r{docker secret create}) } + it { is_expected.to contain_exec('test_secret_2 docker secret create').with_command(%r{docker secret create}) } end end context 'with ensure => absent and secret_name => test_secret' do - let(:params) { { - 'ensure' => 'absent', - 'secret_name' => 'test_secret'} } - it { should contain_exec('test_secret docker secret rm').with_command(/docker secret rm/) } - end - + let(:params) do + { + 'ensure' => 'absent', + 'secret_name' => 'test_secret', + } + end + it { is_expected.to contain_exec('test_secret docker secret rm').with_command(%r{docker secret rm}) } + end end diff --git a/spec/defines/services_spec.rb b/spec/defines/services_spec.rb index e35fdff3..a5f80c50 100644 --- a/spec/defines/services_spec.rb +++ b/spec/defines/services_spec.rb @@ -1,40 +1,45 @@ require 'spec_helper' -describe 'docker::services', :type => :define do +describe 'docker::services', type: :define do let(:title) { 'test_service' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end context 'with ensure => present and service create' do - let(:params) { { - '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', - } } + let(:params) do + { + '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', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('test_service docker service create').with_command(/docker service create/) } - it { should contain_exec('test_service docker service create').with_command(/--env MY_ENV=1/) } - it { should contain_exec('test_service docker service create').with_command(/--label bar=baz/) } - it { should contain_exec('test_service docker service create').with_command(/--mount type=bind,src=\/tmp\/b,dst=\/tmp\/b,readonly/) } - it { should contain_exec('test_service docker service create').with_command(/--network overlay/) } - it { should contain_exec('test_service docker service create').with_command(/echo hello world/) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{docker service create}) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{--env MY_ENV=1}) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{--label bar=baz}) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{--mount type=bind,src=\/tmp\/b,dst=\/tmp\/b,readonly}) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{--network overlay}) } + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{echo hello world}) } context 'multiple services declaration' do - let(:pre_condition) { + let(:pre_condition) do " docker::services { 'test_service_2': service_name => 'foo_2', @@ -42,14 +47,15 @@ command => ['echo', 'hello', 'world'], } " - } - it { should contain_exec('test_service docker service create').with_command(/docker service create/) } - it { should contain_exec('test_service_2 docker service create').with_command(/docker service create/) } - it { should contain_exec('test_service_2 docker service create').with_command(/echo hello world/) } + end + + it { is_expected.to contain_exec('test_service docker service create').with_command(%r{docker service create}) } + it { is_expected.to contain_exec('test_service_2 docker service create').with_command(%r{docker service create}) } + it { is_expected.to contain_exec('test_service_2 docker service create').with_command(%r{echo hello world}) } end context 'multiple publish ports and multiple networks' do - let(:pre_condition) { + let(:pre_condition) do " docker::services { 'test_service_3': service_name => 'foo_3', @@ -58,51 +64,63 @@ networks => ['foo_1', 'foo_2'], } " - } - it { should contain_exec('test_service_3 docker service create').with_command(/--publish 80:8080/) } - it { should contain_exec('test_service_3 docker service create').with_command(/--publish 9000:9000/) } - it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_1/) } - it { should contain_exec('test_service_3 docker service create').with_command(/--network foo_2/) } - end + end + it { is_expected.to contain_exec('test_service_3 docker service create').with_command(%r{--publish 80:8080}) } + it { is_expected.to contain_exec('test_service_3 docker service create').with_command(%r{--publish 9000:9000}) } + it { is_expected.to contain_exec('test_service_3 docker service create').with_command(%r{--network foo_1}) } + it { is_expected.to contain_exec('test_service_3 docker service create').with_command(%r{--network foo_2}) } + end end context 'with ensure => present and service update' do - let(:params) { { - 'create' => false, - 'update' => true, - 'service_name' => 'foo', - 'image' => 'bar:latest', - } } + let(:params) do + { + 'create' => false, + 'update' => true, + 'service_name' => 'foo', + 'image' => 'bar:latest', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('test_service docker service update').with_command(/docker service update/) } + it { is_expected.to contain_exec('test_service docker service update').with_command(%r{docker service update}) } end context 'with ensure => present and service scale' do - let(:params) { { - 'create' => false, - 'scale' => true, - 'service_name' => 'bar', - 'replicas' => '5', - } } + let(:params) do + { + 'create' => false, + 'scale' => true, + 'service_name' => 'bar', + 'replicas' => '5', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('test_service docker service scale').with_command(/docker service scale/) } + it { is_expected.to contain_exec('test_service docker service scale').with_command(%r{docker service scale}) } end context 'with ensure => absent' do - let(:params) { { - 'ensure' => 'absent', - 'service_name' => 'foo', - } } + let(:params) do + { + 'ensure' => 'absent', + 'service_name' => 'foo', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('test_service docker service remove').with_command(/docker service rm/) } + it { is_expected.to contain_exec('test_service docker service remove').with_command(%r{docker service rm}) } end context 'when adding a system user' do - let(:params) { { + let(:params) do + { 'user' => ['user1'], - } } + } + end + it { is_expected.to compile.with_all_deps } - it { should_not contain_exec('docker-systemd-reload-before-service') } + it { is_expected.not_to contain_exec('docker-systemd-reload-before-service') } end end diff --git a/spec/defines/stack_spec.rb b/spec/defines/stack_spec.rb index 2f953fe7..ffde8086 100644 --- a/spec/defines/stack_spec.rb +++ b/spec/defines/stack_spec.rb @@ -1,67 +1,87 @@ require 'spec_helper' ['Debian', 'Windows'].each do |osfamily| - describe 'docker::stack', :type => :define do + describe 'docker::stack', type: :define do let(:title) { 'test_stack' } + if osfamily == 'Debian' - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end + elsif osfamily == 'Windows' - let(:facts) { { - :osfamily => 'windows', - :operatingsystem => 'windows', - :kernelrelease => '10.0.14393', - :operatingsystemmajrelease => '2016', - :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', - } } + let(:facts) do + { + osfamily: 'windows', + operatingsystem: 'windows', + kernelrelease: '10.0.14393', + operatingsystemmajrelease: '2016', + 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 + end context 'Create stack with compose file' do - let(:params) { { - 'stack_name' => 'foo', - 'compose_files' => ['/tmp/docker-compose.yaml'], - 'resolve_image' => 'always', - } } - it { should contain_exec('docker stack create foo').with_command(/docker stack deploy/) } - it { should contain_exec('docker stack create foo').with_command(/--compose-file '\/tmp\/docker-compose.yaml'/) } + let(:params) do + { + 'stack_name' => 'foo', + 'compose_files' => ['/tmp/docker-compose.yaml'], + 'resolve_image' => 'always', + } + end + + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{docker stack deploy}) } + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{--compose-file '\/tmp\/docker-compose.yaml'}) } end context 'Create stack with multiple compose files' do - let(:params) { { - 'stack_name' => 'foo', - 'compose_files' => ['/tmp/docker-compose.yaml', '/tmp/docker-compose-2.yaml'], - 'resolve_image' => 'always', - } } - it { should contain_exec('docker stack create foo').with_command(/docker stack deploy/) } - it { should contain_exec('docker stack create foo').with_command(/--compose-file '\/tmp\/docker-compose.yaml'/) } - it { should contain_exec('docker stack create foo').with_command(/--compose-file '\/tmp\/docker-compose-2.yaml'/) } + let(:params) do + { + 'stack_name' => 'foo', + 'compose_files' => ['/tmp/docker-compose.yaml', '/tmp/docker-compose-2.yaml'], + 'resolve_image' => 'always', + } + end + + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{docker stack deploy}) } + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{--compose-file '\/tmp\/docker-compose.yaml'}) } + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{--compose-file '\/tmp\/docker-compose-2.yaml'}) } end context 'with prune' do - let(:params) { { - 'stack_name' => 'foo', - 'compose_files' => ['/tmp/docker-compose.yaml'], - 'prune' => true, - } } - it { should contain_exec('docker stack create foo').with_command(/docker stack deploy/) } - it { should contain_exec('docker stack create foo').with_command(/--compose-file '\/tmp\/docker-compose.yaml'/) } - it { should contain_exec('docker stack create foo').with_command(/--prune/) } + let(:params) do + { + 'stack_name' => 'foo', + 'compose_files' => ['/tmp/docker-compose.yaml'], + 'prune' => true, + } + end + + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{docker stack deploy}) } + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{--compose-file '\/tmp\/docker-compose.yaml'}) } + it { is_expected.to contain_exec('docker stack create foo').with_command(%r{--prune}) } end - context 'with ensure => absent' do - let(:params) { { - 'ensure' => 'absent', - 'stack_name' => 'foo'} } - it { should contain_exec('docker stack destroy foo').with_command(/docker stack rm/) } + context 'with ensure => absent' do + let(:params) do + { + 'ensure' => 'absent', + 'stack_name' => 'foo', + } + end + + it { is_expected.to contain_exec('docker stack destroy foo').with_command(%r{docker stack rm}) } end end -end \ No newline at end of file +end diff --git a/spec/defines/swarm_spec.rb b/spec/defines/swarm_spec.rb index af1516da..2892647a 100644 --- a/spec/defines/swarm_spec.rb +++ b/spec/defines/swarm_spec.rb @@ -1,76 +1,95 @@ require 'spec_helper' ['Debian', 'Windows'].each do |osfamily| - describe 'docker::swarm', :type => :define do + describe 'docker::swarm', type: :define do let(:title) { 'create swarm' } + context "on #{osfamily}" do if osfamily == 'Debian' - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - } } + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + } + end + elsif osfamily == 'Windows' - let(:facts) { { - :osfamily => 'Windows', - :operatingsystem => 'Windows', - :kernelrelease => '10.0.14393', - :operatingsystemmajrelease => '2016', - :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', - } } + let(:facts) do + { + osfamily: 'Windows', + operatingsystem: 'Windows', + kernelrelease: '10.0.14393', + operatingsystemmajrelease: '2016', + 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 + end context 'with ensure => present and swarm init' do - let(:params) { { - 'init' => true, - 'advertise_addr' => '192.168.1.1', - 'listen_addr' => '192.168.1.1', - } } + let(:params) do + { + 'init' => true, + 'advertise_addr' => '192.168.1.1', + 'listen_addr' => '192.168.1.1', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('Swarm init').with_command(/docker swarm init/) } + it { is_expected.to contain_exec('Swarm init').with_command(%r{docker swarm init}) } end context 'with ensure => present and swarm init and default-addr-pool and default_addr_pool_mask_length' do - let(:params) { { - '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', - } } + let(:params) do + { + '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', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('Swarm init').with_command(/docker swarm init/) } + it { is_expected.to contain_exec('Swarm init').with_command(%r{docker swarm init}) } end context 'with ensure => present and swarm join' do - let(:params) { { - 'join' => true, - 'advertise_addr' => '192.168.1.1', - 'listen_addr' => '192.168.1.1', - 'token' => 'foo', - 'manager_ip' => '192.168.1.2' - } } + let(:params) do + { + 'join' => true, + 'advertise_addr' => '192.168.1.1', + 'listen_addr' => '192.168.1.1', + 'token' => 'foo', + 'manager_ip' => '192.168.1.2', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('Swarm join').with_command(/docker swarm join/) } + it { is_expected.to contain_exec('Swarm join').with_command(%r{docker swarm join}) } end context 'with ensure => absent' do - let(:params) { { - 'ensure' => 'absent', - 'join' => true, - 'advertise_addr' => '192.168.1.1', - 'listen_addr' => '192.168.1.1', - 'token' => 'foo', - 'manager_ip' => '192.168.1.2' - } } + let(:params) do + { + 'ensure' => 'absent', + 'join' => true, + 'advertise_addr' => '192.168.1.1', + 'listen_addr' => '192.168.1.1', + 'token' => 'foo', + 'manager_ip' => '192.168.1.2', + } + end + it { is_expected.to compile.with_all_deps } - it { should contain_exec('Leave swarm').with_command(/docker swarm leave --force/) } + it { is_expected.to contain_exec('Leave swarm').with_command(%r{docker swarm leave --force}) } end end end diff --git a/spec/defines/system_user_spec.rb b/spec/defines/system_user_spec.rb index da8a03f3..9e2e1b20 100644 --- a/spec/defines/system_user_spec.rb +++ b/spec/defines/system_user_spec.rb @@ -1,27 +1,30 @@ require 'spec_helper' -describe 'docker::system_user', :type => :define do +describe 'docker::system_user', type: :define do let(:title) { 'testuser' } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :lsbdistid => 'Debian', - :lsbdistcodename => 'jessie', - :kernelrelease => '3.2.0-4-amd64', - :operatingsystemmajrelease => '8', - :os => { :distro => { :codename => 'wheezy' }, :family => 'Debian', :name => 'Debian', :release => { :major => '7', :full => '7.0' } } - } } - + let(:facts) do + { + osfamily: 'Debian', + operatingsystem: 'Debian', + lsbdistid: 'Debian', + lsbdistcodename: 'jessie', + kernelrelease: '3.2.0-4-amd64', + operatingsystemmajrelease: '8', + os: { distro: { codename: 'wheezy' }, family: 'Debian', name: 'Debian', release: { major: '7', full: '7.0' } }, + } + end + context 'with default' do - let(:params) { {'create_user' => true} } - it { should contain_user('testuser') } - it { should contain_exec('docker-system-user-testuser').with_command(/docker testuser/) } - it { should contain_exec('docker-system-user-testuser').with_unless(/grep -qw testuser/) } + let(:params) { { 'create_user' => true } } + + it { is_expected.to contain_user('testuser') } + it { is_expected.to contain_exec('docker-system-user-testuser').with_command(%r{docker testuser}) } + it { is_expected.to contain_exec('docker-system-user-testuser').with_unless(%r{grep -qw testuser}) } end context 'with create_user => false' do - let(:params) { {'create_user' => false} } - it { should contain_exec('docker-system-user-testuser').with_command(/docker testuser/) } - end + let(:params) { { 'create_user' => false } } + it { is_expected.to contain_exec('docker-system-user-testuser').with_command(%r{docker testuser}) } + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3ac4f0da..f0f6d53b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -46,4 +46,30 @@ def ensure_module_defined(module_name) 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 + # 'spec_overrides' from sync.yml will appear below this line diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index b98127ce..b56a2963 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -10,6 +10,20 @@ rescue LoadError # rubocop:disable Lint/HandleExceptions for optional loading end +def idempotent_apply(hosts, manifest, opts = {}, &block) + block_on hosts, opts do |host| + file_path = host.tmpfile('apply_manifest.pp') + create_remote_file(host, file_path, manifest + "\n") + + puppet_apply_opts = { :verbose => nil, 'detailed-exitcodes' => nil } + on_options = { acceptable_exit_codes: [0, 2] } + on host, puppet('apply', file_path, puppet_apply_opts), on_options, &block + puppet_apply_opts2 = { :verbose => nil, 'detailed-exitcodes' => nil } + on_options2 = { acceptable_exit_codes: [0] } + on host, puppet('apply', file_path, puppet_apply_opts2), on_options2, &block + end +end + # 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. diff --git a/spec/unit/docker_network_spec.rb b/spec/unit/docker_network_spec.rb deleted file mode 100644 index 2d07012b..00000000 --- a/spec/unit/docker_network_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'spec_helper' - -network = Puppet::Type.type(:docker_network) - -describe network do - - let :params do - [ - :name, - :provider, - :subnet, - :gateway, - :ip_range, - :aux_address, - :options, - ] - end - - let :properties do - [ - :ensure, - :driver, - :ipam_driver, - :id, - ] - end - - it 'should have expected properties' do - properties.each do |property| - expect(network.properties.map(&:name)).to be_include(property) - end - end - - it 'should have expected parameters' do - params.each do |param| - expect(network.parameters).to be_include(param) - end - end -end - -describe Puppet::Type.type(:docker_network).provider(:docker_network) 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 - Puppet::Util.stubs(:which).with('docker').returns('/usr/local/bin/docker') - 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 \ No newline at end of file diff --git a/spec/unit/docker_facts_spec.rb b/spec/unit/lib/facter/docker_spec.rb similarity index 80% rename from spec/unit/docker_facts_spec.rb rename to spec/unit/lib/facter/docker_spec.rb index 91ee8472..d16ea17e 100644 --- a/spec/unit/docker_facts_spec.rb +++ b/spec/unit/lib/facter/docker_spec.rb @@ -1,8 +1,7 @@ require 'spec_helper' require 'json' - -describe Facter::Util::Fact, type: :fact do +describe 'Facter::Util::Fact' do before :each do Facter.clear if Facter.value(:kernel) == 'windows' @@ -19,27 +18,25 @@ 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 = Array.new - docker_network_list.each_line {|line| docker_network_names.push line.split[1] } + 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 end - after { Facter.clear } + after(:each) { Facter.clear } describe 'docker fact with composer network' do before :each do - docker_info = File.read(fixtures('facts', 'docker_info')) 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) + 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'] + 'network' => facts['network'], ) end end @@ -51,37 +48,37 @@ 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) + 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'] + 'network' => facts['network'], ) end end - describe'docker client version' do - before do + 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' + '17.03.1-ce-client', ) end end describe 'docker server version' do - before 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' + '17.03.1-ce-server', ) end end @@ -89,7 +86,7 @@ describe 'docker info' do it 'has valid entries' do expect(Facter.fact(:docker).value).to include( - 'Architecture' => 'x86_64' + 'Architecture' => 'x86_64', ) end end diff --git a/spec/unit/lib/puppet/provider/docker_network_spec.rb b/spec/unit/lib/puppet/provider/docker_network_spec.rb new file mode 100644 index 00000000..e252c51d --- /dev/null +++ b/spec/unit/lib/puppet/provider/docker_network_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Puppet::Type.type(:docker_network).provider(:docker_network) 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 + Puppet::Util.stubs(:which).with('docker').returns('/usr/local/bin/docker') + 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/docker_compose_spec.rb b/spec/unit/lib/puppet/type/docker_compose_spec.rb similarity index 57% rename from spec/unit/docker_compose_spec.rb rename to spec/unit/lib/puppet/type/docker_compose_spec.rb index 4db1ba63..aec8bb2e 100644 --- a/spec/unit/docker_compose_spec.rb +++ b/spec/unit/lib/puppet/type/docker_compose_spec.rb @@ -3,7 +3,6 @@ compose = Puppet::Type.type(:docker_compose) describe compose do - let :params do [ :name, @@ -20,27 +19,27 @@ ] end - it 'should have expected properties' do + it 'has expected properties' do properties.each do |property| expect(compose.properties.map(&:name)).to be_include(property) end end - it 'should have expected parameters' do + it 'has expected parameters' do params.each do |param| expect(compose.parameters).to be_include(param) end end - it 'should require options to be a string' do - expect(compose).to require_string_for('options') + it 'requires options to be a string' do + expect(compose).to require_string_for('options') end - it 'should require up_args to be a string' do - expect(compose).to require_string_for('up_args') + it 'requires up_args to be a string' do + expect(compose).to require_string_for('up_args') end - it 'should require scale to be a hash' do - expect(compose).to require_hash_for('scale') + 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 new file mode 100644 index 00000000..ed8444bf --- /dev/null +++ b/spec/unit/lib/puppet/type/docker_network_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +network = Puppet::Type.type(:docker_network) + +describe network do + let :params do + [ + :name, + :provider, + :subnet, + :gateway, + :ip_range, + :aux_address, + :options, + ] + 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/docker_stack_spec.rb b/spec/unit/lib/puppet/type/docker_stack_spec.rb similarity index 70% rename from spec/unit/docker_stack_spec.rb rename to spec/unit/lib/puppet/type/docker_stack_spec.rb index 2a5958fe..4cfb8ec4 100644 --- a/spec/unit/docker_stack_spec.rb +++ b/spec/unit/lib/puppet/type/docker_stack_spec.rb @@ -3,7 +3,6 @@ stack = Puppet::Type.type(:docker_stack) describe stack do - let :params do [ :name, @@ -18,19 +17,19 @@ ] end - it 'should have expected properties' do + it 'has expected properties' do properties.each do |property| expect(stack.properties.map(&:name)).to be_include(property) end end - it 'should have expected parameters' do + it 'has expected parameters' do params.each do |param| expect(stack.parameters).to be_include(param) end end - it 'should require up_args to be a string' do - expect(stack).to require_string_for('up_args') + it 'requires up_args to be a string' do + expect(stack).to require_string_for('up_args') end end diff --git a/spec/unit/docker_volume_spec.rb b/spec/unit/lib/puppet/type/docker_volume_spec.rb similarity index 83% rename from spec/unit/docker_volume_spec.rb rename to spec/unit/lib/puppet/type/docker_volume_spec.rb index 8df44af0..992449b4 100644 --- a/spec/unit/docker_volume_spec.rb +++ b/spec/unit/lib/puppet/type/docker_volume_spec.rb @@ -18,15 +18,15 @@ ] end - it 'should have expected properties' do + it 'has expected properties' do properties.each do |property| expect(volume.properties.map(&:name)).to be_include(property) end end - it 'should have expected parameters' do + it 'has expected parameters' do params.each do |param| expect(volume.parameters).to be_include(param) end end -end \ No newline at end of file +end From afe885cc9f3de161cb99b61929d88d0694751d95 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Thu, 16 May 2019 17:22:34 +0100 Subject: [PATCH 36/44] (MODULES-9029) Fix Windows acceptance tests After having made changes to get Windows tests working with Server 2016, the image we changed to "winamd64/hello-world" has removed support for Server 2016. As such I have changed occurances of it to "winamd64/hello-seattle" which still has support. --- spec/acceptance/docker_custom_source_spec.rb | 2 +- spec/acceptance/docker_full_spec.rb | 4 ++-- spec/acceptance_swarm/swarm_spec.rb | 2 +- spec/spec_helper_acceptance.rb | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/acceptance/docker_custom_source_spec.rb b/spec/acceptance/docker_custom_source_spec.rb index a5675e43..a47c8bf3 100644 --- a/spec/acceptance/docker_custom_source_spec.rb +++ b/spec/acceptance/docker_custom_source_spec.rb @@ -4,7 +4,7 @@ if fact('osfamily') == '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-world' + 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. diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 5f3ee2ab..13925bce 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -2,9 +2,9 @@ if fact('kernel') == 'windows' docker_args = 'docker_ee => true' - default_image = 'winamd64/hello-world' + default_image = 'winamd64/hello-seattle' default_image_tag = 'nanoserver-sac2016' - default_digest = 'sha256:88f6207b9281e60dc4a91008e68b542cc7350d06985c7fc3c5132e6f6b9b3ebe' + default_digest = 'sha256:dcba85354678b50608b8c40ec6d17cce063a224aa0e12b6a55dc47b67f039e75' second_image = 'winamd64/hola-mundo' default_dockerfile = 'C:/Users/Administrator/AppData/Local/Temp/Dockerfile' dockerfile_test = 'C:/Windows/Dockerfile_test.txt' diff --git a/spec/acceptance_swarm/swarm_spec.rb b/spec/acceptance_swarm/swarm_spec.rb index 7cffe174..b159a9ce 100644 --- a/spec/acceptance_swarm/swarm_spec.rb +++ b/spec/acceptance_swarm/swarm_spec.rb @@ -2,7 +2,7 @@ if fact('osfamily') == 'windows' docker_args = 'docker_ee => true' - test_docker_image = 'hello-world:nanoserver' + test_docker_image = 'hello-seattle:nanoserver' test_docker_command = 'cmd.exe /C "ping /t 8.8.8.8"' else docker_args = '' diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index b56a2963..39ab4cef 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -126,7 +126,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: winamd64/hello-world + image: winamd64/hello-seattle command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: @@ -137,7 +137,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: winamd64/hello-world:nanoserver-sac2016 + image: winamd64/hello-seattle:nanoserver-sac2016 command: cmd.exe /C "ping 8.8.8.8 -t" networks: default: @@ -148,14 +148,14 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e version: "3" services: compose_test: - image: winamd64/hello-world + 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-world:nanoserver-sac2016 + image: winamd64/hello-seattle:nanoserver-sac2016 EOS if fact_on(host, 'osfamily') == 'windows' create_remote_file(host, '/tmp/docker-compose-v3.yml', docker_compose_content_v3_windows) From e25e5e0f87b8a459d4b52f552886aa18b151578a Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Wed, 22 May 2019 12:28:22 +0100 Subject: [PATCH 37/44] (FM-8100) Update minimum supported Puppet version to 5.5.10 --- metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadata.json b/metadata.json index 90535490..12c94894 100755 --- a/metadata.json +++ b/metadata.json @@ -67,7 +67,7 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">= 4.2.1 < 7.0.0" + "version_requirement": ">= 5.5.10 < 7.0.0" } ], "pdk-version": "1.10.0", From b7e0e241bac3b0d158f8accf5cdb55c8b8f788fb Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Tue, 28 May 2019 16:28:10 +0100 Subject: [PATCH 38/44] (MODULES-9177) Fix version validation regex The regexes used in init.pp assumed that the supplied docker version would have to start with 17, however docker is now at 18. --- manifests/init.pp | 2 +- spec/classes/docker_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 1ccbbc0c..2a986dbd 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -594,7 +594,7 @@ } } - if ( $version == undef ) or ( $version !~ /^(17[.]0[0-5][.][0-1](~|-|\.)ce|1.\d+)/ ) { + if ( $version == undef ) or ( $version !~ /^(1[7-8][.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)/ ) { if ( $docker_ee) { $package_location = $docker::docker_ee_source_location $package_key_source = $docker::docker_ee_key_source diff --git a/spec/classes/docker_spec.rb b/spec/classes/docker_spec.rb index 09558d1a..fa3678de 100755 --- a/spec/classes/docker_spec.rb +++ b/spec/classes/docker_spec.rb @@ -847,11 +847,11 @@ it { is_expected.to contain_file(service_config_file).with_content(%r{-g \/mnt\/docker}) } end - context 'with custom root dir && Docker version > 17.05' do + context 'with custom root dir && Docker version > 18.09' do let(:params) do { 'root_dir' => '/mnt/docker', - 'version' => '18.03', + 'version' => '19.09', } end From 76f38e87e7fe200c0b6ec8fb831c0de8ecb4f35a Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Thu, 30 May 2019 11:46:37 +0100 Subject: [PATCH 39/44] (MODULES-9193) Revert part of MODULES-9177 The changes introduced in MODULES-9177 modified the behaviour of docker installs using older versions. The first part of the modified regex ensured that the correct repository was used. As such I have reverted it but left the rest of the changes to ensure that non 17.y.z versions use the correct repo. --- manifests/init.pp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/manifests/init.pp b/manifests/init.pp index 2a986dbd..0c4fb0d7 100755 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -594,7 +594,7 @@ } } - if ( $version == undef ) or ( $version !~ /^(1[7-8][.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)/ ) { + if ( $version == undef ) or ( $version !~ /^(17[.][0-1][0-9][.][0-1](~|-|\.)ce|1.\d+)/ ) { if ( $docker_ee) { $package_location = $docker::docker_ee_source_location $package_key_source = $docker::docker_ee_key_source @@ -661,6 +661,7 @@ $root_dir_flag = '--data-root' } + if $ensure != 'absent' { contain 'docker::repos' contain 'docker::install' From 70c1421afa8b710f12d4fc57a54031fcdf374039 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Wed, 5 Jun 2019 09:58:44 +0100 Subject: [PATCH 40/44] (FM-8151) Add Windows Server 2019 support --- metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metadata.json b/metadata.json index 12c94894..9b9713d6 100755 --- a/metadata.json +++ b/metadata.json @@ -60,7 +60,8 @@ { "operatingsystem": "Windows", "operatingsystemrelease": [ - "Server 2016" + "2016", + "2019" ] } ], From 9cac9f5544fa3a57136d2f85fe85973dc8468fa2 Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Fri, 7 Jun 2019 10:54:14 +0100 Subject: [PATCH 41/44] Additional changes to account for incompatible image --- spec/acceptance/compose_v3_spec.rb | 6 +++++- spec/acceptance/docker_full_spec.rb | 6 +++++- spec/spec_helper_acceptance.rb | 26 ++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index a7324c73..06eda5ed 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -5,7 +5,11 @@ file_extension = '.exe' docker_args = 'docker_ee => true' tmp_path = 'C:/cygwin64/tmp' - test_container = 'nanoserver-sac2016' + if fact('os.release.major') == '2019' + test_container = 'nanoserver' + else + test_container = 'nanoserver-sac2016' + end else docker_args = if fact('os.name') == 'RedHat' "repo_opt => '--enablerepo=localmirror-extras'" diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 13925bce..20393d97 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -3,7 +3,11 @@ if fact('kernel') == 'windows' docker_args = 'docker_ee => true' default_image = 'winamd64/hello-seattle' - default_image_tag = 'nanoserver-sac2016' + if fact('os.release.major') == '2019' + default_image_tag = 'nanoserver' + else + default_image_tag = 'nanoserver-sac2016' + end default_digest = 'sha256:dcba85354678b50608b8c40ec6d17cce063a224aa0e12b6a55dc47b67f039e75' second_image = 'winamd64/hola-mundo' default_dockerfile = 'C:/Users/Administrator/AppData/Local/Temp/Dockerfile' diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 39ab4cef..7ba19378 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -135,6 +135,17 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e 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_windows_2016 = <<-EOS +version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 @@ -153,6 +164,12 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e EOS docker_stack_override_windows = <<-EOS version: "3" +services: + compose_test: + image: winamd64/hello-seattle:nanoserver + EOS + docker_stack_override_windows_2016 = <<-EOS +version: "3" services: compose_test: image: winamd64/hello-seattle:nanoserver-sac2016 @@ -160,8 +177,13 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e if fact_on(host, 'osfamily') == '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) - 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) + if fact_on(host, 'os.release.major') == '2019' + create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_stack_override_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_stack_override_windows_2016) + create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows_2016) + 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) From 7bf3ea6ebe98283bd8176221eb7c6aeb1aedc25f Mon Sep 17 00:00:00 2001 From: Eimhin Laverty Date: Tue, 11 Jun 2019 12:56:32 +0100 Subject: [PATCH 42/44] Modify tests to fix permissions issues --- spec/acceptance/compose_v3_spec.rb | 10 ++++----- spec/acceptance/docker_full_spec.rb | 35 ++++++++++++++++------------- spec/spec_helper_acceptance.rb | 10 ++++----- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/spec/acceptance/compose_v3_spec.rb b/spec/acceptance/compose_v3_spec.rb index 06eda5ed..df09b4d8 100644 --- a/spec/acceptance/compose_v3_spec.rb +++ b/spec/acceptance/compose_v3_spec.rb @@ -5,11 +5,11 @@ file_extension = '.exe' docker_args = 'docker_ee => true' tmp_path = 'C:/cygwin64/tmp' - if fact('os.release.major') == '2019' - test_container = 'nanoserver' - else - test_container = 'nanoserver-sac2016' - end + test_container = if fact('os.release.major') == '2019' + 'nanoserver' + else + 'nanoserver-sac2016' + end else docker_args = if fact('os.name') == 'RedHat' "repo_opt => '--enablerepo=localmirror-extras'" diff --git a/spec/acceptance/docker_full_spec.rb b/spec/acceptance/docker_full_spec.rb index 20393d97..f76f54ab 100644 --- a/spec/acceptance/docker_full_spec.rb +++ b/spec/acceptance/docker_full_spec.rb @@ -3,11 +3,11 @@ if fact('kernel') == 'windows' docker_args = 'docker_ee => true' default_image = 'winamd64/hello-seattle' - if fact('os.release.major') == '2019' - default_image_tag = 'nanoserver' - else - default_image_tag = 'nanoserver-sac2016' - end + default_image_tag = if fact('os.release.major') == '2019' + 'nanoserver' + else + 'nanoserver-sac2016' + end default_digest = 'sha256:dcba85354678b50608b8c40ec6d17cce063a224aa0e12b6a55dc47b67f039e75' second_image = 'winamd64/hola-mundo' default_dockerfile = 'C:/Users/Administrator/AppData/Local/Temp/Dockerfile' @@ -18,9 +18,9 @@ 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:\windows\temp\test_file.txt"' - default_docker_exec_command = 'cmd /c "echo test > c:\windows\temp\test_file.txt"' - docker_mount_path = 'C:/Users/Administrator/AppData/Local/Temp' + 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 fact('os.family') == 'RedHat' @@ -317,7 +317,7 @@ class { 'docker': #{docker_args} } it 'creates a new image based on a Dockerfile' do run_cmd = if fact('osfamily') == 'windows' - 'RUN echo test > C:\\Windows\\Temp\\Dockerfile_test.txt' + 'RUN echo test > C:\\Users\\Public\\Dockerfile_test.txt' else "RUN echo test > #{dockerfile_test}" end @@ -343,7 +343,7 @@ class { 'docker': #{docker_args} } # A sleep to give docker time to execute properly sleep 4 if fact('osfamily') == 'windows' - shell("#{docker_command} run alpine_with_file cmd /c dir Windows\\\\Temp") do |r| + shell("#{docker_command} run alpine_with_file cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{_test.txt}) end else @@ -471,7 +471,7 @@ class { 'docker': #{docker_args} container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Windows\\\\Temp") do |r| + 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 @@ -559,6 +559,11 @@ class { 'docker': #{docker_args} } #{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'], @@ -572,7 +577,7 @@ class { 'docker': #{docker_args} } sleep 4 container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Users\\\\Administrator\\\\AppData\\\\Local\\\\Temp\\\\mnt") do |r| + 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 @@ -878,7 +883,7 @@ class { 'docker': #{docker_args} } container_id = shell("#{docker_command} ps | awk 'FNR == 2 {print $1}'") if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_id.stdout.strip} cmd /c dir Windows\\\\Temp") do |r| + 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 @@ -916,7 +921,7 @@ class { 'docker': #{docker_args} } sleep 4 if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| + 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 @@ -948,7 +953,7 @@ class { 'docker': #{docker_args} } sleep 4 if fact('osfamily') == 'windows' - shell("#{docker_command} exec #{container_name} cmd /c dir Windows\\\\Temp") do |r| + shell("#{docker_command} exec #{container_name} cmd /c dir Users\\\\Public") do |r| expect(r.stdout).to match(%r{test_file.txt}) end else diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 7ba19378..91021eba 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -144,7 +144,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e external: name: nat EOS - docker_compose_override_v3_windows_2016 = <<-EOS + docker_compose_override_v3_windows2016 = <<-EOS version: "3" services: compose_test: @@ -168,7 +168,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e compose_test: image: winamd64/hello-seattle:nanoserver EOS - docker_stack_override_windows_2016 = <<-EOS + docker_stack_override_windows2016 = <<-EOS version: "3" services: compose_test: @@ -178,11 +178,11 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e 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 fact_on(host, 'os.release.major') == '2019' - create_remote_file(host, '/tmp/docker-compose-override-v3.yml', docker_stack_override_windows) + 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_stack_override_windows_2016) - create_remote_file(host, '/tmp/docker-stack-override.yml', docker_stack_override_windows_2016) + 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) From 763fd4c27cbb11b5b50da9318a68ed2a518c0fda Mon Sep 17 00:00:00 2001 From: Demian Date: Thu, 13 Jun 2019 16:37:50 +0200 Subject: [PATCH 43/44] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 411cb3d3..b7ef5a50 100755 --- a/README.md +++ b/README.md @@ -920,7 +920,7 @@ If using Docker V1.11 or later, the docker login email flag has been deprecated. Add the following code to the manifest file: ```puppet -docker::registry { 'example.docker.io:5000'} +docker::registry { 'example.docker.io:5000': username => 'user', password => 'secret', } From 28265e655b1afb6415bb44e65f2585bf314c5b52 Mon Sep 17 00:00:00 2001 From: Demian Date: Wed, 19 Jun 2019 13:58:10 +0200 Subject: [PATCH 44/44] Fix #239 local_user permission denied (#497) * fix local user permission denied * fix offenses * fix specs --- lib/facter/docker.rb | 12 ++++++++++++ manifests/registry.pp | 7 +++++-- spec/defines/registry_spec.rb | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/facter/docker.rb b/lib/facter/docker.rb index b7cb379b..bdbe15ca 100644 --- a/lib/facter/docker.rb +++ b/lib/facter/docker.rb @@ -2,6 +2,7 @@ require 'facter' require 'json' +require 'etc' Facter.add(:docker_systemroot) do confine osfamily: :windows @@ -31,6 +32,17 @@ end end +Facter.add(:docker_home_dirs) do + confine kernel: 'Linux' + setcode do + home_dirs = {} + Etc.passwd do |user| + home_dirs[user.name] = user.dir + end + home_dirs + end +end + docker_command = if Facter.value(:kernel) == 'windows' 'powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -c docker' else diff --git a/manifests/registry.pp b/manifests/registry.pp index b51052dc..21c40b91 100644 --- a/manifests/registry.pp +++ b/manifests/registry.pp @@ -61,6 +61,7 @@ $exec_provider = undef $password_env = "\${password}" $exec_user = $local_user + $local_user_home = $facts['docker_home_dirs'][$local_user] } if $ensure == 'present' { @@ -103,11 +104,13 @@ Undef => pw_hash($docker_auth, 'SHA-512', $local_user_strip), default => $pass_hash } - $_auth_command = "${auth_cmd} || rm -f \"/root/registry-auth-puppet_receipt_${server_strip}_${local_user}\"" + $_auth_command = "${auth_cmd} || rm -f \"/${local_user_home}/registry-auth-puppet_receipt_${server_strip}_${local_user}\"" - file { "/root/registry-auth-puppet_receipt_${server_strip}_${local_user}": + file { "/${local_user_home}/registry-auth-puppet_receipt_${server_strip}_${local_user}": ensure => $ensure, content => $_pass_hash, + owner => $local_user, + group => $local_user, notify => Exec["${title} auth"], } } else { diff --git a/spec/defines/registry_spec.rb b/spec/defines/registry_spec.rb index 420702d9..ffb71705 100644 --- a/spec/defines/registry_spec.rb +++ b/spec/defines/registry_spec.rb @@ -10,6 +10,9 @@ lsbdistcodename: 'jessie', kernelrelease: '3.2.0-4-amd64', operatingsystemmajrelease: '8', + docker_home_dirs: { + root: '/root', + }, } end let(:params) { { 'version' => '17.06', 'pass_hash' => 'test1234', 'receipt' => false } }