Skip to content

Commit

Permalink
Add docker stack tests (puppetlabs#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
florindragos authored and MarkW committed Oct 22, 2018
1 parent b53adc6 commit fdf2b78
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 15 deletions.
6 changes: 4 additions & 2 deletions lib/puppet/parser/functions/docker_stack_flags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ module Puppet::Parser::Functions
flags << "--bundle-file '#{opts['bundle_file']}'"
end

if opts['compose_file'].to_s != 'undef'
flags << "--compose-file '#{opts['compose_file']}'"
if opts['compose_files'].to_s != 'undef'
opts['compose_files'].each do |file|
flags << "--compose-file '#{file}'"
end
end

if opts['resolve_image'].to_s != 'undef'
Expand Down
25 changes: 15 additions & 10 deletions manifests/stack.pp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
Optional[Pattern[/^present$|^absent$/]] $ensure = 'present',
Optional[String] $stack_name = undef,
Optional[String] $bundle_file = undef,
Optional[String] $compose_file = undef,
Optional[Array] $compose_files = undef,
Optional[String] $prune = undef,
Optional[String] $with_registry_auth = undef,
Optional[Pattern[/^always$|^changed$|^never$/]] $resolve_image = undef,
Expand All @@ -51,17 +51,20 @@

if $::osfamily == 'windows' {
$exec_path = ['C:/Program Files/Docker/']
$check_stack = "${docker_command} ls | select-string -pattern ${stack_name}"
$check_stack = '$info = docker stack ls | select-string -pattern web
if ($info -eq $null) { Exit 1 } else { Exit 0 }'
$provider = 'powershell'
} else {
$exec_path = ['/bin', '/usr/bin']
$check_stack = "${docker_command} ls | grep ${stack_name}"
$provider = undef
}

if $ensure == 'present'{
$docker_stack_flags = docker_stack_flags ({
stack_name => $stack_name,
bundle_file => $bundle_file,
compose_file => $compose_file,
compose_files => $compose_files,
prune => $prune,
with_registry_auth => $with_registry_auth,
resolve_image => $resolve_image,
Expand All @@ -70,18 +73,20 @@
$exec_stack = "${docker_command} deploy ${docker_stack_flags} ${stack_name}"

exec { "docker stack create ${stack_name}":
command => $exec_stack,
unless => $check_stack,
path => $exec_path,
command => $exec_stack,
unless => $check_stack,
path => $exec_path,
provider => $provider,
}
}

if $ensure == 'absent'{

exec { "docker stack ${stack_name}":
command => "${docker_command} rm ${stack_name}",
onlyif => $check_stack,
path => $exec_path,
exec { "docker stack destroy ${stack_name}":
command => "${docker_command} rm ${stack_name}",
onlyif => $check_stack,
path => $exec_path,
provider => $provider,
}
}
}
147 changes: 147 additions & 0 deletions spec/acceptance/stack_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
require 'spec_helper_acceptance'

if fact('osfamily') == 'windows'
docker_args = 'docker_ee => true'
tmp_path = 'C:/cygwin64/tmp'
test_container = 'nanoserver-sac2016'
wait_for_container_seconds = 120
else
docker_args = ''
tmp_path = '/tmp'
test_container = 'debian'
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
class { 'docker': #{docker_args} }
docker::swarm {'cluster_manager':
init => true,
ensure => 'present',
}
code
apply_manifest(@install_code, :catch_failures=>true)
end
end

context 'Creating stack' do
let(:install) {"
docker::stack { 'web':
stack_name => 'web',
compose_files => ['#{tmp_path}/docker-stack.yml'],
ensure => present,
}"
}

it 'should deploy stack' do
apply_manifest(install, :catch_failures=>true)
sleep wait_for_container_seconds
end

it 'should be idempotent' do
apply_manifest(install, :catch_changes=>true)
end

it 'should find a stack' do
shell('docker stack ls') do |r|
expect(r.stdout).to match(/web/)
end
end

it 'should find a docker container' do
shell("docker ps | grep web_compose_test", :acceptable_exit_codes => [0])
end
end

context 'Destroying stack' do
let(:install) {"
docker::stack { 'web':
stack_name => 'web',
compose_files => ['#{tmp_path}/docker-stack.yml'],
ensure => present,
}"
}
let(:destroy) {"
docker::stack { 'web':
stack_name => 'web',
compose_files => ['#{tmp_path}/docker-stack.yml'],
ensure => absent,
}"
}
it 'should run successfully' do
apply_manifest(destroy, :catch_failures=>true)
end

it 'should be idempotent' do
apply_manifest(destroy, :catch_changes=>true)
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':
stack_name => '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
end

context 'Destroying project with multiple compose files' do
before(:all) do
@install_code = <<-code
docker::stack { 'web':
stack_name => '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':
stack_name => '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 5 # wait for containers to stop
end

it 'should be idempotent' do
apply_manifest(@destroy_code, :catch_changes=>true)
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 | grep #{test_container}", :acceptable_exit_codes => [1])
end
end

end
18 changes: 15 additions & 3 deletions spec/defines/stack.rb → spec/defines/stack_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,29 @@
context 'Create stack with compose file' do
let(:params) { {
'stack_name' => 'foo',
'compose_file' => '/tmp/docker-compose.yaml',
'compose_files' => ['/tmp/docker-compose.yaml'],
'resolve_image' => 'always',
} }
it { should contain_exec('docker stack deploy').with_command(/docker stack deploy/) }
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'/) }
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'/) }
end

context 'with ensure => absent' do
let(:params) { {
'ensure' => 'absent',
'stack_name' => 'foo'} }
it { should contain_exec('docker stack rm').with_command(/docker stack rm/) }
it { should contain_exec('docker stack destroy foo').with_command(/docker stack rm/) }
end
end
end
25 changes: 25 additions & 0 deletions spec/spec_helper_acceptance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e
EOS
docker_compose_override_v3 = <<-EOS
version: "3.4"
services:
compose_test:
image: debian:jessie
command: /bin/sh -c "while true; do echo hello world; sleep 1; done"
EOS
docker_stack_override_v3 = <<-EOS
version: "3.4"
services:
compose_test:
image: debian:jessie
Expand All @@ -108,13 +115,31 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e
default:
external:
name: nat
EOS
docker_stack_content_windows = <<-EOS
version: "3"
services:
compose_test:
image: hello-world:nanoserver
command: cmd.exe /C "ping /t 8.8.8.8"
EOS
docker_stack_override_windows = <<-EOS
version: "3"
services:
compose_test:
image: hello-world:nanoserver-sac2016
command: cmd.exe /C "ping /t 8.8.8.8"
EOS
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)
else
create_remote_file(host, "/tmp/docker-compose-v3.yml", docker_compose_content_v3)
create_remote_file(host, "/tmp/docker-stack.yml", docker_compose_content_v3)
create_remote_file(host, "/tmp/docker-compose-override-v3.yml", docker_compose_override_v3)
create_remote_file(host, "/tmp/docker-stack-override.yml", docker_stack_override_v3)
end

if fact_on(host, 'osfamily') == 'windows'
Expand Down

0 comments on commit fdf2b78

Please sign in to comment.