docker-compose-api 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -61,6 +61,11 @@ compose.stop(['container1', 'container2', ...]) # stop a list of specific contai
61
61
  compose.kill # kill all containers
62
62
  compose.kill(['container1', 'container2', ...]) # kill a list of specific containers
63
63
 
64
+ # Deleting containers
65
+ # (ps: container dependencies will keep running)
66
+ compose.delete # delete all containers
67
+ compose.delete(['container1', 'container2', ...]) # delete a list of specific containers
68
+
64
69
  # Checking if a container is running or not
65
70
  a_container = compose.containers['a_container']
66
71
  a_container.running?
@@ -58,16 +58,27 @@ class Compose
58
58
  end
59
59
 
60
60
  #
61
- # Stop a container
61
+ # Kill a container
62
62
  #
63
63
  # This method accepts an array of labels.
64
- # If labels is informed, only those containers with label present in array will be stopped.
65
- # Otherwise, all containers are stopped
64
+ # If labels is informed, only those containers with label present in array will be killed.
65
+ # Otherwise, all containers are killed
66
66
  #
67
67
  def kill(labels = [])
68
68
  call_container_method(:kill, labels)
69
69
  end
70
70
 
71
+ #
72
+ # Delete a container
73
+ #
74
+ # This method accepts an array of labels.
75
+ # If labels is informed, only those containers with label present in array will be deleted.
76
+ # Otherwise, all containers are deleted
77
+ #
78
+ def delete(labels = [])
79
+ call_container_method(:delete, labels)
80
+ end
81
+
71
82
  private
72
83
 
73
84
  def call_container_method(method, labels = [])
@@ -15,7 +15,7 @@ class ComposeContainer
15
15
  ports: prepare_ports(hash_attributes[:ports]),
16
16
  volumes: hash_attributes[:volumes],
17
17
  command: ComposeUtils.format_command(hash_attributes[:command]),
18
- environment: hash_attributes[:environment]
18
+ environment: prepare_environment(hash_attributes[:environment])
19
19
  }.reject{ |key, value| value.nil? }
20
20
 
21
21
  # Docker client variables
@@ -49,28 +49,15 @@ class ComposeContainer
49
49
 
50
50
  #
51
51
  # Start a new container with parameters informed in object construction
52
- # (TODO: start container from a Dockerfile)
53
52
  #
54
53
  def prepare_container
55
- exposed_ports = {}
56
- port_bindings = {}
57
- links = []
54
+ # Prepare attributes
55
+ port_bindings = prepare_port_bindings
56
+ links = prepare_links
58
57
 
59
- # Build expose and port binding parameters
60
- if !@attributes[:ports].nil?
61
- @attributes[:ports].each do |port|
62
- exposed_ports["#{port.container_port}/tcp"] = {}
63
- port_bindings["#{port.container_port}/tcp"] = [{
64
- "HostIp" => port.host_ip || '',
65
- "HostPort" => port.host_port || ''
66
- }]
67
- end
68
- end
69
-
70
- # Build link parameters
71
- @dependencies.each do |dependency|
72
- links << "#{dependency.stats['Id']}:#{dependency.attributes[:label]}"
73
- end
58
+ # Exposed ports are port bindings with an empty hash as value
59
+ exposed_ports = {}
60
+ port_bindings.each {|k, v| exposed_ports[k] = {}}
74
61
 
75
62
  container_config = {
76
63
  Image: @internal_image,
@@ -87,6 +74,40 @@ class ComposeContainer
87
74
  @container = Docker::Container.create(container_config)
88
75
  end
89
76
 
77
+ #
78
+ # Prepare port binding attribute based on ports
79
+ # received from compose file
80
+ #
81
+ def prepare_port_bindings
82
+ port_bindings = {}
83
+
84
+ return port_bindings if @attributes[:ports].nil?
85
+
86
+ @attributes[:ports].each do |port|
87
+ port_bindings["#{port.container_port}/tcp"] = [{
88
+ "HostIp" => port.host_ip || '',
89
+ "HostPort" => port.host_port || ''
90
+ }]
91
+ end
92
+
93
+ port_bindings
94
+ end
95
+
96
+ #
97
+ # Prepare link entries based on
98
+ # attributes received from compose
99
+ #
100
+ def prepare_links
101
+ links = []
102
+
103
+ @dependencies.each do |dependency|
104
+ link_name = @attributes[:links][dependency.attributes[:label]]
105
+ links << "#{dependency.stats['Id']}:#{link_name}"
106
+ end
107
+
108
+ links
109
+ end
110
+
90
111
  #
91
112
  # Process each port entry in docker compose file and
92
113
  # create structure recognized by docker client
@@ -105,6 +126,14 @@ class ComposeContainer
105
126
  ports
106
127
  end
107
128
 
129
+ #
130
+ # Forces the environment structure to use the array format.
131
+ #
132
+ def prepare_environment(env_entries)
133
+ return env_entries unless env_entries.is_a?(Hash)
134
+ env_entries.to_a.map { |x| x.join('=') }
135
+ end
136
+
108
137
  #
109
138
  # Check if a given image already exists in host
110
139
  #
@@ -136,7 +165,7 @@ class ComposeContainer
136
165
  # Stop the container
137
166
  #
138
167
  def stop
139
- @container.kill unless @container.nil?
168
+ @container.stop unless @container.nil?
140
169
  end
141
170
 
142
171
  #
@@ -175,4 +204,11 @@ class ComposeContainer
175
204
  def running?
176
205
  @container.nil? ? false : self.stats['State']['Running']
177
206
  end
207
+
208
+ #
209
+ # Check if the container exists or not
210
+ #
211
+ def exist?
212
+ !@container.nil?
213
+ end
178
214
  end
@@ -62,6 +62,8 @@ module ComposeUtils
62
62
  # Generate a pair key:hash with
63
63
  # format {service:label}
64
64
  #
65
+ # The label will be the conainer name if not specified.
66
+ #
65
67
  def self.format_links(links_array)
66
68
  links = {}
67
69
 
@@ -72,7 +74,7 @@ module ComposeUtils
72
74
 
73
75
  case parts.length
74
76
  when 1
75
- links[parts[0]] = SecureRandom.hex
77
+ links[parts[0]] = parts[0]
76
78
 
77
79
  when 2
78
80
  links[parts[0]] = parts[1]
@@ -1,5 +1,5 @@
1
1
  module DockerCompose
2
2
  def self.version
3
- "1.0.2"
3
+ "1.0.4"
4
4
  end
5
5
  end
@@ -14,7 +14,7 @@ describe DockerCompose do
14
14
  end
15
15
 
16
16
  it 'should read a YAML file correctly' do
17
- expect(@compose.containers.length).to eq(2)
17
+ expect(@compose.containers.length).to eq(3)
18
18
  end
19
19
 
20
20
  it 'should raise error when reading an invalid YAML file' do
@@ -49,13 +49,27 @@ describe DockerCompose do
49
49
  expect(container.running?).to be false
50
50
  end
51
51
  end
52
+
53
+ it 'should start/delete all containers' do
54
+ # Start containers to test Delete
55
+ @compose.start
56
+ @compose.containers.values.each do |container|
57
+ expect(container.running?).to be true
58
+ end
59
+
60
+ # Delete containers
61
+ @compose.delete
62
+ @compose.containers.values.each do |container|
63
+ expect(container.exist?).to be false
64
+ end
65
+ end
52
66
  end
53
67
 
54
68
  context 'Single container' do
55
69
  context 'Without dependencies' do
56
70
  it 'should start/stop a single container' do
57
71
  container1 = @compose.containers.values.first.attributes[:label]
58
- container2 = @compose.containers.values.last.attributes[:label]
72
+ container2 = @compose.containers.values[1].attributes[:label]
59
73
 
60
74
  # Should start Redis only, since it hasn't dependencies
61
75
  @compose.start([container2])
@@ -70,7 +84,7 @@ describe DockerCompose do
70
84
 
71
85
  it 'should start/kill a single container' do
72
86
  container1 = @compose.containers.values.first.attributes[:label]
73
- container2 = @compose.containers.values.last.attributes[:label]
87
+ container2 = @compose.containers.values[1].attributes[:label]
74
88
 
75
89
  # Should start Redis only, since it hasn't dependencies
76
90
  @compose.start([container2])
@@ -87,7 +101,7 @@ describe DockerCompose do
87
101
  context 'With dependencies' do
88
102
  it 'should start/stop a single container' do
89
103
  container1 = @compose.containers.values.first.attributes[:label]
90
- container2 = @compose.containers.values.last.attributes[:label]
104
+ container2 = @compose.containers.values[1].attributes[:label]
91
105
 
92
106
  # Should start Ubuntu and Redis, since Ubuntu depends on Redis
93
107
  @compose.start([container1])
@@ -106,7 +120,7 @@ describe DockerCompose do
106
120
 
107
121
  it 'should start/kill a single container' do
108
122
  container1 = @compose.containers.values.first.attributes[:label]
109
- container2 = @compose.containers.values.last.attributes[:label]
123
+ container2 = @compose.containers.values[1].attributes[:label]
110
124
 
111
125
  # Should start Ubuntu and Redis, since Ubuntu depends on Redis
112
126
  @compose.start([container1])
@@ -125,7 +139,7 @@ describe DockerCompose do
125
139
 
126
140
  it 'should be able to ping a dependent container' do
127
141
  container1 = @compose.containers.values.first.attributes[:label]
128
- container2 = @compose.containers.values.last.attributes[:label]
142
+ container2 = @compose.containers.values[1].attributes[:label]
129
143
 
130
144
  # Start all containers
131
145
  @compose.start
@@ -136,6 +150,20 @@ describe DockerCompose do
136
150
  ping_response = @compose.containers[container1].container.exec(['ping', '-c', '3', 'busybox2'])
137
151
  expect(ping_response[2]).to eq(0) # Status 0 = OK
138
152
  end
153
+
154
+ it 'should be able to ping a dependent aliased container' do
155
+ container2 = @compose.containers.values[1].attributes[:label]
156
+ container3 = @compose.containers.values[2].attributes[:label]
157
+
158
+ # Start all containers
159
+ @compose.start
160
+ expect(@compose.containers[container2].running?).to be true
161
+ expect(@compose.containers[container3].running?).to be true
162
+
163
+ # Ping container3 from container1
164
+ ping_response = @compose.containers[container3].container.exec(['ping', '-c', '3', 'bb2'])
165
+ expect(ping_response[2]).to eq(0) # Status 0 = OK
166
+ end
139
167
  end # context 'with dependencies'
140
168
  end # context 'Single container'
141
169
 
@@ -177,9 +205,33 @@ describe DockerCompose do
177
205
  container1.stop
178
206
  end
179
207
 
208
+ it 'supports setting environment as array' do
209
+ container1 = @compose.containers.values.first
210
+
211
+ # Start container
212
+ container1.start
213
+
214
+ env = container1.stats['Config']['Env']
215
+ expect(env).to eq(%w(MYENV1=variable1))
216
+
217
+ # Stop container
218
+ container1.stop
219
+ end
220
+
221
+ it 'supports setting environment as hash' do
222
+ container1 = @compose.containers.values[1]
223
+
224
+ # Start container
225
+ container1.start
226
+
227
+ env = container1.stats['Config']['Env']
228
+ expect(env).to eq(%w(MYENV2=variable2))
229
+
230
+ # Stop container
231
+ container1.stop
232
+ end
233
+
180
234
  after(:all) do
181
- @compose.containers.values.each do |entry|
182
- entry.delete
183
- end
235
+ @compose.delete
184
236
  end
185
237
  end
@@ -9,9 +9,19 @@ busybox1:
9
9
  links:
10
10
  - busybox2
11
11
  command: ping busybox2
12
+ environment:
13
+ - MYENV1=variable1
12
14
 
13
15
  busybox2:
14
16
  image: busybox
15
17
  expose:
16
18
  - "6000"
17
19
  command: ping localhost
20
+ environment:
21
+ MYENV2: variable2
22
+
23
+ busybox3:
24
+ image: busybox
25
+ links:
26
+ - busybox2:bb2
27
+ command: ping localhost
@@ -5,7 +5,7 @@ describe ComposeContainer do
5
5
  before(:all) do
6
6
  @attributes = {
7
7
  image: 'busybox:latest',
8
- links: ['service:label'],
8
+ links: ['service1:label', 'service2'],
9
9
  ports: ['3000', '8000:8000', '127.0.0.1:8001:8001'],
10
10
  volumes: {'/tmp' => {}},
11
11
  command: 'ping -c 3 localhost',
@@ -17,7 +17,8 @@ describe ComposeContainer do
17
17
 
18
18
  it 'should prepare attributes correctly' do
19
19
  expect(@entry.attributes[:image]).to eq(@attributes[:image])
20
- expect(@entry.attributes[:links]).to eq({'service' => 'label'})
20
+ expect(@entry.attributes[:links])
21
+ .to eq({'service1' => 'label', 'service2' => 'service2'})
21
22
  expect(@entry.attributes[:volumes]).to eq(@attributes[:volumes])
22
23
  expect(@entry.attributes[:command]).to eq(@attributes[:command].split(' '))
23
24
  expect(@entry.attributes[:environment]).to eq(@attributes[:environment])
@@ -133,4 +134,20 @@ describe ComposeContainer do
133
134
  expect{@entry.start}.to raise_error(ArgumentError)
134
135
  end
135
136
  end
137
+
138
+ context 'With environment as a hash' do
139
+ before(:all) do
140
+ @attributes = {
141
+ image: 'busybox:latest',
142
+ command: 'ping -c 3 localhost',
143
+ environment: { ENVIRONMENT: 'VALUE' }
144
+ }
145
+
146
+ @entry = ComposeContainer.new(@attributes)
147
+ end
148
+
149
+ it 'should prepare environment attribute correctly' do
150
+ expect(@entry.attributes[:environment]).to eq(%w(ENVIRONMENT=VALUE))
151
+ end
152
+ end
136
153
  end
@@ -56,7 +56,7 @@ describe ComposeUtils do
56
56
  it 'should recognize pattern "[service]"' do
57
57
  links = ComposeUtils.format_links(['service'])
58
58
  expect(links.key?('service')).to be true
59
- expect(links['service']).to_not be_nil
59
+ expect(links['service']).to eq('service')
60
60
  end
61
61
 
62
62
  it 'should recognize pattern "[service:label]"' do
@@ -3,7 +3,10 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
3
  require 'simplecov'
4
4
  require 'codeclimate-test-reporter'
5
5
 
6
- SimpleCov.start
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ end
9
+
7
10
  CodeClimate::TestReporter.start
8
11
 
9
12
  require 'docker-compose'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-compose-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-10-27 00:00:00.000000000 Z
12
+ date: 2015-12-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: docker-api