Skip to content

Commit 39e70c9

Browse files
author
Mark Wilson
committed
(WIP)-CLOUD-2069 Adding support for multiple compose files.
1 parent b71811e commit 39e70c9

File tree

5 files changed

+93
-45
lines changed

5 files changed

+93
-45
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,16 @@ docker_compose { '/tmp/docker-compose.yml':
558558

559559
Give options to the ```docker-compose up``` command, such as ```--remove-orphans```, by using the ```up_args``` option.
560560

561+
To supply multiple overide compose files add the following to the manifest file:
562+
563+
```puppet
564+
class {'docker::compose':
565+
compose_files => ['master-docker-compose.yml', 'override-compose.yml],
566+
}
567+
```
568+
569+
Please note you should supply your master docker-compose file as the first element in the array. As per docker multi compose file support compose files will be merged in the order they are specified in the array.
570+
561571
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.
562572

563573
To deploy the stack, add the following code to the manifest file:

lib/puppet/provider/docker_compose/ruby.rb

+44-39
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,46 @@
77

88
def exists?
99
Puppet.info("Checking for compose project #{project}")
10-
compose_file = YAML.safe_load(File.read(name))
1110
compose_services = {}
12-
containers = docker([
13-
'ps',
14-
'--format',
15-
"{{.Label \"com.docker.compose.service\"}}-{{.Image}}",
16-
'--filter',
17-
"label=com.docker.compose.project=#{project}",
18-
]).split("\n")
19-
case compose_file['version']
20-
when %r{^2(\.[0-3])?$}, %r{^3(\.[0-6])?$}
21-
compose_services = compose_file['services']
22-
# in compose v1 "version" parameter is not specified
23-
when nil
24-
compose_services = compose_file
25-
else
26-
raise(Puppet::Error, "Unsupported docker compose file syntax version \"#{compose_file['version']}\"!")
27-
end
11+
resource[:compose_files].each do |file|
12+
compose_file = YAML.safe_load(File.read(file))
13+
containers = docker([
14+
'ps',
15+
'--format',
16+
"{{.Label \"com.docker.compose.service\"}}-{{.Image}}",
17+
'--filter',
18+
"label=com.docker.compose.project=#{project}",
19+
]).split("\n")
20+
case compose_file['version']
21+
when %r{^2(\.[0-3])?$}, %r{^3(\.[0-6])?$}
22+
compose_services = compose_services.merge(compose_file['services'])
23+
# in compose v1 "version" parameter is not specified
24+
when nil
25+
compose_services = compose_services.merge(compose_file)
26+
else
27+
raise(Puppet::Error, "Unsupported docker compose file syntax version \"#{compose_file['version']}\"!")
28+
end
2829

29-
if compose_services.count != containers.count
30-
return false
31-
end
30+
if compose_services.count != containers.count
31+
return false
32+
end
3233

33-
counts = Hash[*compose_services.each.map { |key, array|
34-
image = (array['image']) ? array['image'] : get_image(key, compose_services)
35-
Puppet.info("Checking for compose service #{key} #{image}")
36-
["#{key}-#{image}", containers.count("#{key}-#{image}")]
37-
}.flatten]
34+
counts = Hash[*compose_services.each.map { |key, array|
35+
image = (array['image']) ? array['image'] : get_image(key, compose_services)
36+
Puppet.info("Checking for compose service #{key} #{image}")
37+
["#{key}-#{image}", containers.count("#{key}-#{image}")]
38+
}.flatten]
3839

39-
# No containers found for the project
40-
if counts.empty? ||
41-
# Containers described in the compose file are not running
42-
counts.any? { |_k, v| v.zero? } ||
43-
# The scaling factors in the resource do not match the number of running containers
44-
resource[:scale] && counts.merge(resource[:scale]) != counts
45-
false
46-
else
47-
true
40+
# No containers found for the project
41+
if counts.empty? ||
42+
# Containers described in the compose file are not running
43+
counts.any? { |_k, v| v.zero? } ||
44+
# The scaling factors in the resource do not match the number of running containers
45+
resource[:scale] && counts.merge(resource[:scale]) != counts
46+
false
47+
else
48+
true
49+
end
4850
end
4951
end
5052

@@ -62,20 +64,22 @@ def get_image(service_name, compose_services)
6264

6365
def create
6466
Puppet.info("Running compose project #{project}")
65-
args = ['-f', name, 'up', '-d', '--remove-orphans'].insert(2, resource[:options]).insert(5, resource[:up_args]).compact
67+
compose_files_cmd = resource[:compose_files].map { |x| ["-f", x] }.flatten
68+
args = [compose_files_cmd, 'up', '-d', '--remove-orphans'].insert(2, resource[:options]).insert(5, resource[:up_args]).compact
6669
dockercompose(args)
6770
return unless resource[:scale]
6871
instructions = resource[:scale].map { |k, v| "#{k}=#{v}" }
6972
Puppet.info("Scaling compose project #{project}: #{instructions.join(' ')}")
70-
args = ['-f', name, 'scale'].insert(2, resource[:options]).compact + instructions
73+
args = [compose_files_cmd, 'scale'].insert(2, resource[:options]).compact + instructions
7174
dockercompose(args)
7275
end
7376

7477
def destroy
7578
Puppet.info("Removing all containers for compose project #{project}")
76-
kill_args = ['-f', name, 'kill'].insert(2, resource[:options]).compact
79+
compose_files_cmd = resource[:compose_files].map { |x| ["-f", x] }.flatten
80+
kill_args = [compose_files_cmd, 'kill'].insert(2, resource[:options]).compact
7781
dockercompose(kill_args)
78-
rm_args = ['-f', name, 'rm', '--force', '-v'].insert(2, resource[:options]).compact
82+
rm_args = [compose_files_cmd, 'rm', '--force', '-v'].insert(2, resource[:options]).compact
7983
dockercompose(rm_args)
8084
end
8185

@@ -92,6 +96,7 @@ def restart
9296
private
9397

9498
def project
95-
File.basename(File.dirname(name)).downcase.gsub(%r{[^0-9a-z ]}i, '')
99+
project = name
100+
project
96101
end
97102
end

lib/puppet/type/docker_compose.rb

+10-6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ def refresh
77
provider.restart
88
end
99

10-
newparam(:name) do
11-
desc 'Docker compose file path.'
12-
end
13-
1410
newparam(:scale) do
1511
desc 'A hash of compose services and number of containers.'
1612
validate do |value|
@@ -38,7 +34,15 @@ def refresh
3834
end
3935
end
4036

41-
autorequire(:file) do
42-
self[:name]
37+
newparam(:compose_files, :array_matching => :all) do
38+
desc 'An array of Docker Compose Files paths.'
39+
validate do |value|
40+
raise _('compose files should be an array') unless value.is_a? Array
41+
end
42+
end
43+
44+
newparam(:name) do
45+
isnamevar
46+
desc 'The name of the project'
4347
end
4448
end

spec/acceptance/compose_v3_spec.rb

+21
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,27 @@ class { 'docker::compose':
4848
end
4949
end
5050

51+
context 'multi compose file override' do
52+
before(:all) do
53+
@install = <<-code
54+
docker_compose { 'override_test':
55+
compose_files => ['#{tmp_path}/docker-compose-v3.yml', '#{tmp_path}/docker-compose-override-v3.yml'],
56+
ensure => present,
57+
}
58+
code
59+
apply_manifest(@install, :catch_failures=>true)
60+
end
61+
62+
it 'should be idempotent' do
63+
apply_manifest(@install, :catch_changes=>true)
64+
end
65+
66+
it 'should find container with debian tag' do
67+
shell('docker inspect tmp_compose_test', :acceptable_exit_codes => [0])
68+
end
69+
end
70+
71+
5172
context 'Destroying compose v3 projects' do
5273
before(:all) do
5374
install = <<-code

spec/spec_helper_acceptance.rb

+8
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e
110110
image: ubuntu:14.04
111111
command: /bin/sh -c "while true; do echo hello world; sleep 1; done"
112112
EOS
113+
docker_compose_override_content_v3 = <<-EOS
114+
version: "3"
115+
services:
116+
compose_test:
117+
image: debian: jessie
118+
command: /bin/sh -c "while true; do echo hello world; sleep 1; done"
119+
EOS
113120
docker_compose_content_v3_windows = <<-EOS
114121
version: "3"
115122
services:
@@ -127,6 +134,7 @@ def retry_on_error_matching(max_retry_count = 3, retry_wait_interval_secs = 5, e
127134
create_remote_file(host, "/tmp/docker-compose-v3.yml", docker_compose_content_v3_windows)
128135
else
129136
create_remote_file(host, "/tmp/docker-compose-v3.yml", docker_compose_content_v3)
137+
create_remote_file(host, "/tmp/docker-compose-override-v3.yml", docker_compose_override_content_v3)
130138
end
131139

132140
if fact_on(host, 'osfamily') == 'windows'

0 commit comments

Comments
 (0)