centurion 1.0.6

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.
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'centurion/docker_server'
3
+
4
+ describe Centurion::DockerServer do
5
+ let(:host) { 'host1' }
6
+ let(:docker_path) { 'docker' }
7
+ let(:server) { Centurion::DockerServer.new(host, docker_path) }
8
+
9
+ it 'knows its hostname' do
10
+ expect(server.hostname).to eq('host1')
11
+ end
12
+
13
+ it 'knows its port' do
14
+ expect(server.port).to eq('4243')
15
+ end
16
+
17
+ describe 'when host includes a port' do
18
+ let(:host) { 'host2:4321' }
19
+ it 'knows that port' do
20
+ expect(server.port).to eq('4321')
21
+ end
22
+ end
23
+
24
+ { docker_via_api: [:create_container, :inspect_container, :inspect_image,
25
+ :ps, :start_container, :stop_container],
26
+ docker_via_cli: [:pull, :tail] }.each do |delegate, methods|
27
+ methods.each do |method|
28
+ it "delegates '#{method}' to #{delegate}" do
29
+ dummy_result = double
30
+ dummy_delegate = double(method => dummy_result)
31
+ server.stub(delegate => dummy_delegate)
32
+ expect(dummy_delegate).to receive(method)
33
+ expect(server.send(method)).to be(dummy_result)
34
+ end
35
+ end
36
+ end
37
+
38
+ it 'returns tags associated with an image' do
39
+ image_names = %w[target:latest target:production other:latest]
40
+ server.stub(ps: image_names.map {|name| { 'Image' => name } })
41
+ expect(server.current_tags_for('target')).to eq(%w[latest production])
42
+ end
43
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ require 'centurion/docker_via_api'
3
+
4
+ describe Centurion::DockerViaApi do
5
+ let(:hostname) { 'example.com' }
6
+ let(:port) { '4243' }
7
+ let(:api) { Centurion::DockerViaApi.new(hostname, port) }
8
+ let(:excon_uri) { "http://#{hostname}:#{port}/v1.7" }
9
+ let(:json_string) { '[{ "Hello": "World" }]' }
10
+ let(:json_value) { JSON.load(json_string) }
11
+ let(:inspected_containers) do
12
+ [
13
+ {"Id" => "123", "Status" => "Exit 0"},
14
+ {"Id" => "456", "Status" => "Running blah blah"},
15
+ {"Id" => "789", "Status" => "Exit 1"},
16
+ ]
17
+ end
18
+
19
+ it 'lists processes' do
20
+ expect(Excon).to receive(:get).
21
+ with(excon_uri + "/containers/json").
22
+ and_return(double(body: json_string, status: 200))
23
+ expect(api.ps).to eq(json_value)
24
+ end
25
+
26
+ it 'lists all processes' do
27
+ expect(Excon).to receive(:get).
28
+ with(excon_uri + "/containers/json?all=1").
29
+ and_return(double(body: json_string, status: 200))
30
+ expect(api.ps(all: true)).to eq(json_value)
31
+ end
32
+
33
+ it 'inspects an image' do
34
+ expect(Excon).to receive(:get).
35
+ with(excon_uri + "/images/foo:bar/json",
36
+ headers: {'Accept' => 'application/json'}).
37
+ and_return(double(body: json_string, status: 200))
38
+ expect(api.inspect_image('foo', 'bar')).to eq(json_value)
39
+ end
40
+
41
+ it 'creates a container' do
42
+ configuration_as_json = double
43
+ configuration = double(:to_json => configuration_as_json)
44
+ expect(Excon).to receive(:post).
45
+ with(excon_uri + "/containers/create",
46
+ body: configuration_as_json,
47
+ headers: {'Content-Type' => 'application/json'}).
48
+ and_return(double(body: json_string, status: 201))
49
+ api.create_container(configuration)
50
+ end
51
+
52
+ it 'starts a container' do
53
+ configuration_as_json = double
54
+ configuration = double(:to_json => configuration_as_json)
55
+ expect(Excon).to receive(:post).
56
+ with(excon_uri + "/containers/12345/start",
57
+ body: configuration_as_json,
58
+ headers: {'Content-Type' => 'application/json'}).
59
+ and_return(double(body: json_string, status: 204))
60
+ api.start_container('12345', configuration)
61
+ end
62
+
63
+ it 'stops a container' do
64
+ expect(Excon).to receive(:post).
65
+ with(excon_uri + "/containers/12345/stop?t=30").
66
+ and_return(double(status: 204))
67
+ api.stop_container('12345')
68
+ end
69
+
70
+ it 'inspects a container' do
71
+ expect(Excon).to receive(:get).
72
+ with(excon_uri + "/containers/12345/json").
73
+ and_return(double(body: json_string, status: 200))
74
+ expect(api.inspect_container('12345')).to eq(json_value)
75
+ end
76
+
77
+ it 'removes a container' do
78
+ expect(Excon).to receive(:delete).
79
+ with(excon_uri + "/containers/12345").
80
+ and_return(double(status: 204))
81
+ expect(api.remove_container('12345')).to eq(true)
82
+ end
83
+
84
+ it 'lists old containers for a port' do
85
+ expect(Excon).to receive(:get).
86
+ with(excon_uri + "/containers/json?all=1").
87
+ and_return(double(body: inspected_containers.to_json, status: 200))
88
+ expect(Excon).to receive(:get).
89
+ with(excon_uri + "/containers/123/json").
90
+ and_return(double(body: inspected_container_on_port("123", 8485).to_json, status: 200))
91
+ expect(Excon).to receive(:get).
92
+ with(excon_uri + "/containers/789/json").
93
+ and_return(double(body: inspected_container_on_port("789", 8486).to_json, status: 200))
94
+
95
+ expect(api.old_containers_for_port(8485)).to eq([{"Id" => "123", "Status" => "Exit 0"}])
96
+ end
97
+
98
+ def inspected_container_on_port(id, port)
99
+ {
100
+ "Id" => id.to_s,
101
+ "HostConfig" => {
102
+ "PortBindings" => {
103
+ "80/tcp" => [
104
+ "HostIp" => "0.0.0.0",
105
+ "HostPort" => port.to_s
106
+ ]
107
+ }
108
+ }
109
+ }
110
+ end
111
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'centurion/docker_via_cli'
3
+
4
+ describe Centurion::DockerViaCli do
5
+ let(:docker_path) { 'docker' }
6
+ let(:docker_via_cli) { Centurion::DockerViaCli.new('host1', 4243, docker_path) }
7
+
8
+ it 'pulls the latest image given its name' do
9
+ expect(docker_via_cli).to receive(:echo).
10
+ with("docker -H=tcp://host1:4243 pull foo:latest")
11
+ docker_via_cli.pull('foo')
12
+ end
13
+
14
+ it 'pulls an image given its name & tag' do
15
+ expect(docker_via_cli).to receive(:echo).
16
+ with("docker -H=tcp://host1:4243 pull foo:bar")
17
+ docker_via_cli.pull('foo', 'bar')
18
+ end
19
+
20
+ it 'tails logs on a container' do
21
+ id = '12345abcdef'
22
+ expect(docker_via_cli).to receive(:echo).
23
+ with("docker -H=tcp://host1:4243 logs -f #{id}")
24
+ docker_via_cli.tail(id)
25
+ end
26
+
27
+ it 'should print all chars when one thread is running' do
28
+ expect(docker_via_cli).to receive(:run_with_echo)
29
+
30
+ allow(Thread).to receive(:list) {[double(:status => 'run')]}
31
+
32
+ docker_via_cli.pull('foo')
33
+ end
34
+
35
+ it 'should only print lines when multiple threads are running' do
36
+ expect(docker_via_cli).to receive(:run_without_echo)
37
+
38
+ allow(Thread).to receive(:list) {[double(:status => 'run'), double(:status => 'run')]}
39
+
40
+ docker_via_cli.pull('foo')
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'centurion/logging'
3
+
4
+ class TestLogging
5
+ extend Centurion::Logging
6
+ def self.logger
7
+ log
8
+ end
9
+ end
10
+
11
+ describe Centurion::Logging do
12
+ let(:message) { %w{ something something_else } }
13
+
14
+ context '#info' do
15
+ it 'passes through to Logger' do
16
+ expect(TestLogging.logger).to receive(:info).with(message.join(' '))
17
+ TestLogging.info(*message)
18
+ end
19
+ end
20
+
21
+ context '#warn' do
22
+ it 'passes through to Logger' do
23
+ expect(TestLogging.logger).to receive(:warn).with(message.join(' '))
24
+ TestLogging.warn(*message)
25
+ end
26
+ end
27
+
28
+ context '#debug' do
29
+ it 'passes through to Logger' do
30
+ expect(TestLogging.logger).to receive(:debug).with(message.join(' '))
31
+ TestLogging.debug(*message)
32
+ end
33
+ end
34
+
35
+ context '#error' do
36
+ it 'passes through to Logger' do
37
+ expect(TestLogging.logger).to receive(:error).with(message.join(' '))
38
+ TestLogging.error(*message)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec'
4
+ end
5
+
6
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|f| require f}
@@ -0,0 +1,13 @@
1
+ RSpec::Matchers.define :have_key_and_value do |expected_key, expected_value|
2
+ match do |actual|
3
+ actual.env[actual.current_environment].has_key?(expected_key.to_sym) && (actual.fetch(expected_key.to_sym) == expected_value)
4
+ end
5
+
6
+ failure_message_for_should do |actual|
7
+ "expected that #{actual.env[actual.current_environment].keys.inspect} would include #{expected_key.inspect} with value #{expected_value.inspect}"
8
+ end
9
+
10
+ failure_message_for_should_not do |actual|
11
+ "expected that #{actual.env[actual.current_environment].keys.join(', ')} would not include #{expected_key.inspect} with value #{expected_value.inspect}"
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,243 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: centurion
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.6
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nic Benders
9
+ - Karl Matthias
10
+ - Andrew Bloomgarden
11
+ - Aaron Bento
12
+ - Paul Showalter
13
+ - David Kerr
14
+ - Jonathan Owens
15
+ - Jon Guymon
16
+ - Merlyn Albery-Speyer
17
+ - Amjith Ramanujam
18
+ - David Celis
19
+ - Emily Hyland
20
+ - Bryan Stearns
21
+ autorequire:
22
+ bindir: bin
23
+ cert_chain: []
24
+ date: 2014-06-08 00:00:00.000000000 Z
25
+ dependencies:
26
+ - !ruby/object:Gem::Dependency
27
+ name: trollop
28
+ requirement: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: excon
44
+ requirement: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '0.33'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: '0.33'
58
+ - !ruby/object:Gem::Dependency
59
+ name: logger-colors
60
+ requirement: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: bundler
76
+ requirement: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ - !ruby/object:Gem::Dependency
91
+ name: rake
92
+ requirement: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ type: :development
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ - !ruby/object:Gem::Dependency
107
+ name: rspec
108
+ requirement: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ type: :development
115
+ prerelease: false
116
+ version_requirements: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ - !ruby/object:Gem::Dependency
123
+ name: pry
124
+ requirement: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: simplecov
140
+ requirement: !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ description:
155
+ email:
156
+ - nic@newrelic.com
157
+ - kmatthias@newrelic.com
158
+ - andrew@newrelic.com
159
+ - aaron@newrelic.com
160
+ - poeslacker@gmail.com
161
+ - dkerr@newrelic.com
162
+ - jonathan@newrelic.com
163
+ - jon@newrelic.com
164
+ - merlyn@newrelic.com
165
+ - amjith@newrelic.com
166
+ - dcelis@newrelic.com
167
+ - ehyland@newrelic.com
168
+ - bryan@newrelic.com
169
+ executables:
170
+ - centurion
171
+ - centurionize
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - .gitignore
176
+ - CONTRIBUTORS.md
177
+ - Gemfile
178
+ - LICENSE
179
+ - README.md
180
+ - Rakefile
181
+ - bin/centurion
182
+ - bin/centurionize
183
+ - centurion.gemspec
184
+ - lib/capistrano_dsl.rb
185
+ - lib/centurion.rb
186
+ - lib/centurion/deploy.rb
187
+ - lib/centurion/deploy_dsl.rb
188
+ - lib/centurion/docker_registry.rb
189
+ - lib/centurion/docker_server.rb
190
+ - lib/centurion/docker_server_group.rb
191
+ - lib/centurion/docker_via_api.rb
192
+ - lib/centurion/docker_via_cli.rb
193
+ - lib/centurion/logging.rb
194
+ - lib/centurion/version.rb
195
+ - lib/tasks/deploy.rake
196
+ - lib/tasks/info.rake
197
+ - lib/tasks/list.rake
198
+ - spec/capistrano_dsl_spec.rb
199
+ - spec/deploy_dsl_spec.rb
200
+ - spec/deploy_spec.rb
201
+ - spec/docker_server_group_spec.rb
202
+ - spec/docker_server_spec.rb
203
+ - spec/docker_via_api_spec.rb
204
+ - spec/docker_via_cli_spec.rb
205
+ - spec/logging_spec.rb
206
+ - spec/spec_helper.rb
207
+ - spec/support/matchers/capistrano_dsl_matchers.rb
208
+ homepage: https://github.com/newrelic/centurion
209
+ licenses:
210
+ - MIT
211
+ post_install_message:
212
+ rdoc_options: []
213
+ require_paths:
214
+ - lib
215
+ required_ruby_version: !ruby/object:Gem::Requirement
216
+ none: false
217
+ requirements:
218
+ - - ! '>='
219
+ - !ruby/object:Gem::Version
220
+ version: 1.9.3
221
+ required_rubygems_version: !ruby/object:Gem::Requirement
222
+ none: false
223
+ requirements:
224
+ - - ! '>='
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ requirements: []
228
+ rubyforge_project:
229
+ rubygems_version: 1.8.23
230
+ signing_key:
231
+ specification_version: 3
232
+ summary: Deploy images to a fleet of Docker servers
233
+ test_files:
234
+ - spec/capistrano_dsl_spec.rb
235
+ - spec/deploy_dsl_spec.rb
236
+ - spec/deploy_spec.rb
237
+ - spec/docker_server_group_spec.rb
238
+ - spec/docker_server_spec.rb
239
+ - spec/docker_via_api_spec.rb
240
+ - spec/docker_via_cli_spec.rb
241
+ - spec/logging_spec.rb
242
+ - spec/spec_helper.rb
243
+ - spec/support/matchers/capistrano_dsl_matchers.rb