docker-compose-api 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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