centurion 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +27 -0
- data/bin/centurionize +17 -0
- data/lib/centurion/deploy_dsl.rb +5 -1
- data/lib/centurion/docker_registry.rb +2 -2
- data/lib/centurion/docker_server.rb +1 -1
- data/lib/centurion/docker_via_cli.rb +0 -45
- data/lib/centurion/dogestry.rb +84 -0
- data/lib/centurion/logging.rb +43 -0
- data/lib/centurion/version.rb +1 -1
- data/lib/tasks/deploy.rake +40 -3
- data/spec/capistrano_dsl_spec.rb +3 -3
- data/spec/deploy_spec.rb +11 -11
- data/spec/docker_registry_spec.rb +47 -26
- data/spec/docker_server_group_spec.rb +1 -1
- data/spec/docker_server_spec.rb +1 -1
- data/spec/docker_via_api_spec.rb +1 -1
- data/spec/docker_via_cli_spec.rb +4 -4
- data/spec/dogestry_spec.rb +56 -0
- metadata +5 -2
data/README.md
CHANGED
@@ -21,6 +21,9 @@ Alternatively, you can [host your
|
|
21
21
|
own](https://github.com/dotcloud/docker-registry), or
|
22
22
|
[Quay.io](https://quay.io) is another commercial option.
|
23
23
|
|
24
|
+
Centurion also now supports [Dogestry](https://github.com/newrelic-forks/dogestry)!
|
25
|
+
See details below for more information.
|
26
|
+
|
24
27
|
Status
|
25
28
|
------
|
26
29
|
|
@@ -228,6 +231,30 @@ Returns a list of all the images for this project in the registry.
|
|
228
231
|
$ bundle exec centurion -p radio-radio -e staging -a list
|
229
232
|
````
|
230
233
|
|
234
|
+
###Alternative Docker Registry
|
235
|
+
|
236
|
+
Centurion normally uses the built-in registry support in the Docker daemon to handle pushing and pulling images.But Centurion also has the ability to use external tooling to support hosting your registry on Amazon S3. That tooling is from a project called [Dogestry](https://github.com/newrelic-forks/dogestry). We have recently improved that tooling
|
237
|
+
substantially in coordination with the Centurion support.
|
238
|
+
|
239
|
+
Dogestry uses the Docker daemon's import/export functionality in combination with Amazon S3 to provide reliable hosting of images. Setting Centurion up to use Dogestry is pretty trivial:
|
240
|
+
|
241
|
+
1. Install Dogestry binaries on the client from which Dogestry is run. Binaries are provided in the GitHub release.
|
242
|
+
1. Add the settings necessary to get Centurion to pull from Dogestry. A config example is provided below:
|
243
|
+
|
244
|
+
See example below to use `dogestry`:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
namespace :environment do
|
248
|
+
task :common do
|
249
|
+
registry :dogestry # Required
|
250
|
+
set :aws_access_key_id, 'abc123' # Required
|
251
|
+
set :aws_secret_key, 'xyz' # Required
|
252
|
+
set :s3_bucket, 'docker-images-bucket' # Required
|
253
|
+
set :s3_region, 'us-east-1' # Optional
|
254
|
+
end
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
231
258
|
Future Additions
|
232
259
|
----------------
|
233
260
|
|
data/bin/centurionize
CHANGED
@@ -24,6 +24,20 @@ unless File.exists?(project_file)
|
|
24
24
|
set :image, '#{opts[:registry_base]}#{opts[:project]}'
|
25
25
|
# Point this to an appropriate health check endpoint for rolling deploys (defaults to '/')
|
26
26
|
# set :status_endpoint, '/status/check'
|
27
|
+
|
28
|
+
# Example on how to change docker registry to Dogestry.
|
29
|
+
# This requires:
|
30
|
+
# - aws_access_key_id
|
31
|
+
# - aws_secret_key
|
32
|
+
# - s3_bucket
|
33
|
+
#
|
34
|
+
# And optionally:
|
35
|
+
# - s3_region (default to us-east-1)
|
36
|
+
#
|
37
|
+
# registry :dogestry
|
38
|
+
# set :aws_access_key_id, 'abc123'
|
39
|
+
# set :aws_secret_key, 'xyz'
|
40
|
+
# set :s3_bucket, 'bucket-for-docker-images'
|
27
41
|
end
|
28
42
|
|
29
43
|
desc 'Staging environment'
|
@@ -33,6 +47,9 @@ unless File.exists?(project_file)
|
|
33
47
|
# host_port 10234, container_port: 9292
|
34
48
|
# host 'docker-server-staging-1.example.com'
|
35
49
|
# host 'docker-server-staging-2.example.com'
|
50
|
+
|
51
|
+
# You can assign different docker daemon port. Example:
|
52
|
+
# host 'docker-server-staging-3.example.com:4243'
|
36
53
|
end
|
37
54
|
|
38
55
|
desc 'Production environment'
|
data/lib/centurion/deploy_dsl.rb
CHANGED
@@ -27,7 +27,7 @@ module Centurion::DeployDSL
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def localhost
|
30
|
-
# DOCKER_HOST is like 'tcp://127.0.0.1:
|
30
|
+
# DOCKER_HOST is like 'tcp://127.0.0.1:2375'
|
31
31
|
docker_host_uri = URI.parse(ENV['DOCKER_HOST'] || "tcp://127.0.0.1")
|
32
32
|
host_and_port = [docker_host_uri.host, docker_host_uri.port].compact.join(':')
|
33
33
|
host(host_and_port)
|
@@ -71,6 +71,10 @@ module Centurion::DeployDSL
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def registry(type)
|
75
|
+
set(:registry, type)
|
76
|
+
end
|
77
|
+
|
74
78
|
private
|
75
79
|
|
76
80
|
def add_to_bindings(host_ip, container_port, port, type='tcp')
|
@@ -60,13 +60,13 @@ class Centurion::DockerRegistry
|
|
60
60
|
|
61
61
|
def is_official_registry?(repository)
|
62
62
|
if @base_uri == OFFICIAL_URL
|
63
|
-
return !repository.match(/^[a-z0-9
|
63
|
+
return !repository.match(/^[a-z0-9]+[a-z0-9\-\.]+(?::[1-9][0-9]*)?\//)
|
64
64
|
end
|
65
65
|
false
|
66
66
|
end
|
67
67
|
|
68
68
|
def uri_for_repository_path(repository, path)
|
69
|
-
if repository.match(/\A([a-z0-9
|
69
|
+
if repository.match(/\A([a-z0-9]+[a-z0-9\-\.]+(?::[1-9][0-9]*)?)\/(.*)\z/)
|
70
70
|
host = $1
|
71
71
|
short_image_name = $2
|
72
72
|
"https://#{host}#{path.gsub(repository, short_image_name)}"
|
@@ -24,49 +24,4 @@ class Centurion::DockerViaCli
|
|
24
24
|
def attach(container_id)
|
25
25
|
Process.exec("#{@docker_path} -H=#{@docker_host} attach #{container_id}")
|
26
26
|
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def echo(command)
|
31
|
-
if Thread.list.find_all { |t| t.status == 'run' }.count > 1
|
32
|
-
run_without_echo(command)
|
33
|
-
else
|
34
|
-
run_with_echo(command)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def run_without_echo(command)
|
39
|
-
output = Queue.new
|
40
|
-
output_thread = Thread.new do
|
41
|
-
while true do
|
42
|
-
begin
|
43
|
-
puts output.pop
|
44
|
-
rescue => e
|
45
|
-
info "Rescuing... #{e.message}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
IO.popen(command) do |io|
|
51
|
-
io.each_line { |line| output << line }
|
52
|
-
end
|
53
|
-
|
54
|
-
output_thread.kill
|
55
|
-
validate_status(command)
|
56
|
-
end
|
57
|
-
|
58
|
-
def run_with_echo(command)
|
59
|
-
$stdout.sync = true
|
60
|
-
$stderr.sync = true
|
61
|
-
IO.popen(command) do |io|
|
62
|
-
io.each_char { |char| print char }
|
63
|
-
end
|
64
|
-
validate_status(command)
|
65
|
-
end
|
66
|
-
|
67
|
-
def validate_status(command)
|
68
|
-
unless $?.success?
|
69
|
-
raise "The command failed with a non-zero exit status: #{$?.exitstatus}. Command: '#{command}'"
|
70
|
-
end
|
71
|
-
end
|
72
27
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative 'logging'
|
2
|
+
|
3
|
+
module Centurion; end
|
4
|
+
|
5
|
+
class Centurion::Dogestry
|
6
|
+
include Centurion::Logging
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
# Cross-platform way of finding an executable in the $PATH.
|
13
|
+
# which('ruby') #=> /usr/bin/ruby
|
14
|
+
def which(cmd)
|
15
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
16
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
17
|
+
exts.each { |ext|
|
18
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
19
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
return nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_before_exec
|
26
|
+
unless which('dogestry')
|
27
|
+
message = 'Unable to find "dogestry" executable'
|
28
|
+
error message
|
29
|
+
raise message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def aws_access_key_id
|
34
|
+
@options[:aws_access_key_id]
|
35
|
+
end
|
36
|
+
|
37
|
+
def aws_secret_key
|
38
|
+
@options[:aws_secret_key]
|
39
|
+
end
|
40
|
+
|
41
|
+
def s3_bucket
|
42
|
+
@options[:s3_bucket]
|
43
|
+
end
|
44
|
+
|
45
|
+
def s3_region
|
46
|
+
@options[:s3_region] || 'us-east-1'
|
47
|
+
end
|
48
|
+
|
49
|
+
def s3_url
|
50
|
+
"s3://#{s3_bucket}/?region=#{s3_region}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def docker_host
|
54
|
+
@options[:docker_host] || 'tcp://localhost:2375'
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_envs
|
58
|
+
ENV['DOCKER_HOST'] = docker_host
|
59
|
+
ENV['AWS_ACCESS_KEY'] = aws_access_key_id
|
60
|
+
ENV['AWS_SECRET_KEY'] = aws_secret_key
|
61
|
+
|
62
|
+
info "Dogestry ENV: #{ENV.inspect}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def exec_command(command, repo)
|
66
|
+
command = "dogestry #{command} #{s3_url} #{repo}"
|
67
|
+
info "Executing: #{command}"
|
68
|
+
command
|
69
|
+
end
|
70
|
+
|
71
|
+
def pull(repo)
|
72
|
+
validate_before_exec
|
73
|
+
set_envs
|
74
|
+
|
75
|
+
echo(exec_command('pull', repo))
|
76
|
+
end
|
77
|
+
|
78
|
+
def push(repo)
|
79
|
+
validate_before_exec
|
80
|
+
set_envs
|
81
|
+
|
82
|
+
echo(exec_command('push', repo))
|
83
|
+
end
|
84
|
+
end
|
data/lib/centurion/logging.rb
CHANGED
@@ -20,6 +20,49 @@ module Centurion::Logging
|
|
20
20
|
log.debug args.join(' ')
|
21
21
|
end
|
22
22
|
|
23
|
+
def echo(command)
|
24
|
+
if Thread.list.find_all { |t| t.status == 'run' }.count > 1
|
25
|
+
run_without_echo(command)
|
26
|
+
else
|
27
|
+
run_with_echo(command)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_without_echo(command)
|
32
|
+
output = Queue.new
|
33
|
+
output_thread = Thread.new do
|
34
|
+
while true do
|
35
|
+
begin
|
36
|
+
puts output.pop
|
37
|
+
rescue => e
|
38
|
+
info "Rescuing... #{e.message}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
IO.popen(command) do |io|
|
44
|
+
io.each_line { |line| output << line }
|
45
|
+
end
|
46
|
+
|
47
|
+
output_thread.kill
|
48
|
+
validate_status(command)
|
49
|
+
end
|
50
|
+
|
51
|
+
def run_with_echo(command)
|
52
|
+
$stdout.sync = true
|
53
|
+
$stderr.sync = true
|
54
|
+
IO.popen(command) do |io|
|
55
|
+
io.each_char { |char| print char }
|
56
|
+
end
|
57
|
+
validate_status(command)
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_status(command)
|
61
|
+
unless $?.success?
|
62
|
+
raise "The command failed with a non-zero exit status: #{$?.exitstatus}. Command: '#{command}'"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
23
66
|
private
|
24
67
|
|
25
68
|
def log(*args)
|
data/lib/centurion/version.rb
CHANGED
data/lib/tasks/deploy.rake
CHANGED
@@ -27,6 +27,38 @@ task :stop => ['deploy:stop']
|
|
27
27
|
namespace :deploy do
|
28
28
|
include Centurion::Deploy
|
29
29
|
|
30
|
+
namespace :dogestry do
|
31
|
+
task :validate_pull_image do
|
32
|
+
['aws_access_key_id', 'aws_secret_key', 's3_bucket'].each do |env_var|
|
33
|
+
unless fetch(env_var.to_sym)
|
34
|
+
$stderr.puts "\n\n#{env_var} is not defined."
|
35
|
+
exit(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :pull_image do
|
41
|
+
invoke 'deploy:dogestry:validate_pull_image'
|
42
|
+
|
43
|
+
target_servers = Centurion::DockerServerGroup.new(fetch(:hosts), fetch(:docker_path))
|
44
|
+
target_servers.each_in_parallel do |target_server|
|
45
|
+
dogestry_options = {
|
46
|
+
aws_access_key_id: fetch(:aws_access_key_id),
|
47
|
+
aws_secret_key: fetch(:aws_secret_key),
|
48
|
+
s3_bucket: fetch(:s3_bucket),
|
49
|
+
s3_region: fetch(:s3_region) || 'us-east-1',
|
50
|
+
docker_host: "tcp://#{target_server.hostname}:#{target_server.port}"
|
51
|
+
}
|
52
|
+
|
53
|
+
$stdout.puts "** Pulling image(#{fetch(:image)}:#{fetch(:tag)}) from Dogestry: #{dogestry_options.inspect}"
|
54
|
+
|
55
|
+
registry = Centurion::Dogestry.new(dogestry_options)
|
56
|
+
|
57
|
+
registry.pull("#{fetch(:image)}:#{fetch(:tag)}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
30
62
|
task :get_image do
|
31
63
|
invoke 'deploy:pull_image'
|
32
64
|
invoke 'deploy:determine_image_id_from_first_server'
|
@@ -126,11 +158,16 @@ namespace :deploy do
|
|
126
158
|
info "--no-pull option specified: skipping pull"
|
127
159
|
next
|
128
160
|
end
|
161
|
+
|
129
162
|
$stderr.puts "Fetching image #{fetch(:image)}:#{fetch(:tag)} IN PARALLEL\n"
|
130
163
|
|
131
|
-
|
132
|
-
|
133
|
-
|
164
|
+
if fetch(:registry) == 'dogestry'
|
165
|
+
invoke 'deploy:dogestry:pull_image'
|
166
|
+
else
|
167
|
+
target_servers = Centurion::DockerServerGroup.new(fetch(:hosts), fetch(:docker_path))
|
168
|
+
target_servers.each_in_parallel do |target_server|
|
169
|
+
target_server.pull(fetch(:image), fetch(:tag))
|
170
|
+
end
|
134
171
|
end
|
135
172
|
end
|
136
173
|
|
data/spec/capistrano_dsl_spec.rb
CHANGED
@@ -27,7 +27,7 @@ describe Capistrano::DSL do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
context 'with a current environment set' do
|
30
|
+
context 'with a current environment set' do
|
31
31
|
before do
|
32
32
|
DSLTest.set_current_environment(:test)
|
33
33
|
end
|
@@ -46,11 +46,11 @@ describe Capistrano::DSL do
|
|
46
46
|
|
47
47
|
it 'returns true for any? when the value exists' do
|
48
48
|
DSLTest.set(:foo, 'bar')
|
49
|
-
expect(DSLTest.any?(:foo)).to
|
49
|
+
expect(DSLTest.any?(:foo)).to be_truthy
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'returns false for any? when the value does not exist' do
|
53
|
-
expect(DSLTest.any?(:foo)).to
|
53
|
+
expect(DSLTest.any?(:foo)).to be_falsey
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'passes through the any? method to values that support it' do
|
data/spec/deploy_spec.rb
CHANGED
@@ -9,8 +9,8 @@ describe Centurion::Deploy do
|
|
9
9
|
let(:port) { 8484 }
|
10
10
|
let(:container) { { 'Ports' => [{ 'PublicPort' => port }, 'Created' => Time.now.to_i ], 'Id' => '21adfd2ef2ef2349494a', 'Names' => [ 'name1' ] } }
|
11
11
|
let(:endpoint) { '/status/check' }
|
12
|
-
let(:test_deploy) do
|
13
|
-
Object.new.tap do |o|
|
12
|
+
let(:test_deploy) do
|
13
|
+
Object.new.tap do |o|
|
14
14
|
o.send(:extend, Centurion::Deploy)
|
15
15
|
o.send(:extend, Centurion::DeployDSL)
|
16
16
|
o.send(:extend, Centurion::Logging)
|
@@ -20,25 +20,25 @@ describe Centurion::Deploy do
|
|
20
20
|
describe '#http_status_ok?' do
|
21
21
|
it 'validates HTTP status checks when the response is good' do
|
22
22
|
expect(Excon).to receive(:get).and_return(mock_ok_status)
|
23
|
-
expect(test_deploy.http_status_ok?(server, port, endpoint)).to
|
23
|
+
expect(test_deploy.http_status_ok?(server, port, endpoint)).to be_truthy
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'identifies bad HTTP responses' do
|
27
27
|
expect(Excon).to receive(:get).and_return(mock_bad_status)
|
28
28
|
test_deploy.stub(:warn)
|
29
|
-
expect(test_deploy.http_status_ok?(server, port, endpoint)).to
|
29
|
+
expect(test_deploy.http_status_ok?(server, port, endpoint)).to be_falsey
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'outputs the HTTP status when it is not OK' do
|
33
33
|
expect(Excon).to receive(:get).and_return(mock_bad_status)
|
34
34
|
expect(test_deploy).to receive(:warn).with(/Got HTTP status: 500/)
|
35
|
-
expect(test_deploy.http_status_ok?(server, port, endpoint)).to
|
35
|
+
expect(test_deploy.http_status_ok?(server, port, endpoint)).to be_falsey
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'handles SocketErrors and outputs a message' do
|
39
39
|
expect(Excon).to receive(:get).and_raise(Excon::Errors::SocketError.new(RuntimeError.new()))
|
40
40
|
expect(test_deploy).to receive(:warn).with(/Failed to connect/)
|
41
|
-
expect(test_deploy.http_status_ok?(server, port, endpoint)).to
|
41
|
+
expect(test_deploy.http_status_ok?(server, port, endpoint)).to be_falsey
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -46,21 +46,21 @@ describe Centurion::Deploy do
|
|
46
46
|
it 'recognizes when no containers are running' do
|
47
47
|
expect(server).to receive(:find_containers_by_public_port).and_return([])
|
48
48
|
|
49
|
-
test_deploy.container_up?(server, port).should
|
49
|
+
test_deploy.container_up?(server, port).should be_falsey
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'complains when more than one container is bound to this port' do
|
53
53
|
expect(server).to receive(:find_containers_by_public_port).and_return([1,2])
|
54
54
|
expect(test_deploy).to receive(:error).with /More than one container/
|
55
55
|
|
56
|
-
test_deploy.container_up?(server, port).should
|
56
|
+
test_deploy.container_up?(server, port).should be_falsey
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'recognizes when the container is actually running' do
|
60
60
|
expect(server).to receive(:find_containers_by_public_port).and_return([container])
|
61
61
|
expect(test_deploy).to receive(:info).with /Found container/
|
62
62
|
|
63
|
-
test_deploy.container_up?(server, port).should
|
63
|
+
test_deploy.container_up?(server, port).should be_truthy
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -84,7 +84,7 @@ describe Centurion::Deploy do
|
|
84
84
|
test_deploy.stub(:warn)
|
85
85
|
expect(test_deploy).to receive(:exit)
|
86
86
|
expect(test_deploy).to receive(:sleep).with(0)
|
87
|
-
|
87
|
+
|
88
88
|
test_deploy.wait_for_http_status_ok(server, port, '/foo', 'image_id', 'chaucer', 0, 1)
|
89
89
|
expect(test_deploy).to have_received(:info).with(/Waiting for the port/)
|
90
90
|
end
|
@@ -95,7 +95,7 @@ describe Centurion::Deploy do
|
|
95
95
|
test_deploy.stub(:error)
|
96
96
|
test_deploy.stub(:warn)
|
97
97
|
expect(test_deploy).to receive(:exit)
|
98
|
-
|
98
|
+
|
99
99
|
test_deploy.wait_for_http_status_ok(server, port, '/foo', 'image_id', 'chaucer', 1, 0)
|
100
100
|
expect(test_deploy).to have_received(:info).with(/Waiting for the port/)
|
101
101
|
end
|
@@ -3,57 +3,78 @@ require 'centurion/docker_registry'
|
|
3
3
|
|
4
4
|
describe Centurion::DockerRegistry do
|
5
5
|
let(:registry_url) { 'http://localhost/' }
|
6
|
-
let(:registry)
|
6
|
+
let(:registry) { Centurion::DockerRegistry.new(registry_url) }
|
7
7
|
|
8
8
|
describe '#repository_tags' do
|
9
9
|
let(:repository) { 'foobar' }
|
10
|
-
let(:tag_name)
|
11
|
-
let(:image_id)
|
12
|
-
let(:url)
|
10
|
+
let(:tag_name) { 'arbitrary_tag' }
|
11
|
+
let(:image_id) { 'deadbeef0000' }
|
12
|
+
let(:url) { any_args() }
|
13
13
|
|
14
14
|
before do
|
15
|
-
expect(Excon).to receive(:get).
|
16
|
-
|
17
|
-
|
15
|
+
expect(Excon).to receive(:get).with(url).and_return(
|
16
|
+
double(status: 200, body: response)
|
17
|
+
)
|
18
18
|
end
|
19
19
|
|
20
20
|
subject { registry.repository_tags(repository) }
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
describe 'handling different responses from open source and official registries' do
|
23
|
+
context 'when given a response from the official Docker registry' do
|
24
|
+
let(:registry_url) { Centurion::DockerRegistry::OFFICIAL_URL }
|
25
|
+
let(:response) { <<-JSON.strip }
|
26
|
+
[{"layer": "#{image_id}", "name": "#{tag_name}"}]
|
27
|
+
JSON
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
it 'normalizes the response' do
|
30
|
+
expect(subject).to eq(tag_name => image_id)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when given a response from the open-source Docker registry' do
|
35
|
+
let(:response) { <<-JSON.strip }
|
36
|
+
{"#{tag_name}": "#{image_id}"}
|
37
|
+
JSON
|
38
|
+
|
39
|
+
it 'normalizes the response' do
|
40
|
+
expect(subject).to eq(tag_name => image_id)
|
41
|
+
end
|
30
42
|
end
|
31
43
|
end
|
32
44
|
|
33
|
-
context 'when given
|
34
|
-
let(:
|
45
|
+
context 'when given the official Docker registry and a repository with a hostname' do
|
46
|
+
let(:registry_url) { Centurion::DockerRegistry::OFFICIAL_URL }
|
47
|
+
let(:repository) { 'docker-reg.example.com/foobar' }
|
48
|
+
let(:response) { <<-JSON.strip }
|
35
49
|
{"#{tag_name}": "#{image_id}"}
|
36
50
|
JSON
|
37
51
|
|
38
|
-
it '
|
52
|
+
it 'fetches from the image-referenced registry' do
|
39
53
|
expect(subject).to eq(tag_name => image_id)
|
40
54
|
end
|
41
55
|
end
|
42
56
|
|
43
|
-
context 'when given
|
44
|
-
let(:registry_url) {
|
45
|
-
let(:
|
46
|
-
|
47
|
-
let(:response) { <<-JSON.strip }
|
57
|
+
context 'when given any other registry' do
|
58
|
+
let(:registry_url) { 'http://my-registry.example.com' }
|
59
|
+
let(:response) { <<-JSON.strip }
|
48
60
|
{"#{tag_name}": "#{image_id}"}
|
49
61
|
JSON
|
50
62
|
|
51
|
-
|
63
|
+
context 'and a repository with a hostname' do
|
64
|
+
let(:repository) { 'docker-reg.example.com/foobar' }
|
52
65
|
|
53
|
-
|
54
|
-
|
66
|
+
it 'fetches from the image-referenced registry' do
|
67
|
+
expect(subject).to eq(tag_name => image_id)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'and a repository with no hostname' do
|
72
|
+
let(:repository) { 'foobar' }
|
73
|
+
|
74
|
+
it 'fetches from the image-referenced registry' do
|
75
|
+
expect(subject).to eq(tag_name => image_id)
|
76
|
+
end
|
55
77
|
end
|
56
78
|
end
|
57
79
|
end
|
58
|
-
|
59
80
|
end
|
@@ -7,7 +7,7 @@ describe Centurion::DockerServerGroup do
|
|
7
7
|
let(:group) { Centurion::DockerServerGroup.new(['host1', 'host2'], docker_path) }
|
8
8
|
|
9
9
|
it 'takes a hostlist and instantiates DockerServers' do
|
10
|
-
expect(group.hosts).to
|
10
|
+
expect(group.hosts.length).to equal(2)
|
11
11
|
expect(group.hosts.first).to be_a(Centurion::DockerServer)
|
12
12
|
expect(group.hosts.last).to be_a(Centurion::DockerServer)
|
13
13
|
end
|
data/spec/docker_server_spec.rb
CHANGED
data/spec/docker_via_api_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'centurion/docker_via_api'
|
|
3
3
|
|
4
4
|
describe Centurion::DockerViaApi do
|
5
5
|
let(:hostname) { 'example.com' }
|
6
|
-
let(:port) { '
|
6
|
+
let(:port) { '2375' }
|
7
7
|
let(:api) { Centurion::DockerViaApi.new(hostname, port) }
|
8
8
|
let(:excon_uri) { "http://#{hostname}:#{port}/" }
|
9
9
|
let(:json_string) { '[{ "Hello": "World" }]' }
|
data/spec/docker_via_cli_spec.rb
CHANGED
@@ -3,24 +3,24 @@ require 'centurion/docker_via_cli'
|
|
3
3
|
|
4
4
|
describe Centurion::DockerViaCli do
|
5
5
|
let(:docker_path) { 'docker' }
|
6
|
-
let(:docker_via_cli) { Centurion::DockerViaCli.new('host1',
|
6
|
+
let(:docker_via_cli) { Centurion::DockerViaCli.new('host1', 2375, docker_path) }
|
7
7
|
|
8
8
|
it 'pulls the latest image given its name' do
|
9
9
|
expect(docker_via_cli).to receive(:echo).
|
10
|
-
with("docker -H=tcp://host1:
|
10
|
+
with("docker -H=tcp://host1:2375 pull foo:latest")
|
11
11
|
docker_via_cli.pull('foo')
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'pulls an image given its name & tag' do
|
15
15
|
expect(docker_via_cli).to receive(:echo).
|
16
|
-
with("docker -H=tcp://host1:
|
16
|
+
with("docker -H=tcp://host1:2375 pull foo:bar")
|
17
17
|
docker_via_cli.pull('foo', 'bar')
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'tails logs on a container' do
|
21
21
|
id = '12345abcdef'
|
22
22
|
expect(docker_via_cli).to receive(:echo).
|
23
|
-
with("docker -H=tcp://host1:
|
23
|
+
with("docker -H=tcp://host1:2375 logs -f #{id}")
|
24
24
|
docker_via_cli.tail(id)
|
25
25
|
end
|
26
26
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'centurion/dogestry'
|
3
|
+
|
4
|
+
describe Centurion::Dogestry do
|
5
|
+
let(:dogestry_options) {
|
6
|
+
{
|
7
|
+
aws_access_key_id: "abc",
|
8
|
+
aws_secret_key: "xyz",
|
9
|
+
s3_bucket: "s3-registry-test"
|
10
|
+
}
|
11
|
+
}
|
12
|
+
let(:registry) { Centurion::Dogestry.new(dogestry_options) }
|
13
|
+
let(:repo) { 'google/golang' }
|
14
|
+
|
15
|
+
describe '#aws_access_key_id' do
|
16
|
+
it 'returns correct value' do
|
17
|
+
registry.aws_access_key_id.should == dogestry_options[:aws_access_key_id]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#aws_secret_key' do
|
22
|
+
it 'returns correct value' do
|
23
|
+
registry.aws_secret_key.should == dogestry_options[:aws_secret_key]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#s3_bucket' do
|
28
|
+
it 'returns correct value' do
|
29
|
+
registry.s3_bucket.should == dogestry_options[:s3_bucket]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#s3_region' do
|
34
|
+
it 'returns correct default value' do
|
35
|
+
registry.s3_region.should == "us-east-1"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#s3_url' do
|
40
|
+
it 'returns correct value' do
|
41
|
+
registry.s3_url.should == "s3://#{registry.s3_bucket}/?region=#{registry.s3_region}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#exec_command' do
|
46
|
+
it 'returns correct value' do
|
47
|
+
registry.exec_command('pull', repo).should start_with('dogestry')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#which' do
|
52
|
+
it 'finds dogestry command line' do
|
53
|
+
registry.which('dogestry').should_not == nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: centurion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -21,7 +21,7 @@ authors:
|
|
21
21
|
autorequire:
|
22
22
|
bindir: bin
|
23
23
|
cert_chain: []
|
24
|
-
date: 2014-10-
|
24
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
25
25
|
dependencies:
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: trollop
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/centurion/docker_server_group.rb
|
191
191
|
- lib/centurion/docker_via_api.rb
|
192
192
|
- lib/centurion/docker_via_cli.rb
|
193
|
+
- lib/centurion/dogestry.rb
|
193
194
|
- lib/centurion/logging.rb
|
194
195
|
- lib/centurion/version.rb
|
195
196
|
- lib/tasks/deploy.rake
|
@@ -203,6 +204,7 @@ files:
|
|
203
204
|
- spec/docker_server_spec.rb
|
204
205
|
- spec/docker_via_api_spec.rb
|
205
206
|
- spec/docker_via_cli_spec.rb
|
207
|
+
- spec/dogestry_spec.rb
|
206
208
|
- spec/logging_spec.rb
|
207
209
|
- spec/spec_helper.rb
|
208
210
|
- spec/support/matchers/capistrano_dsl_matchers.rb
|
@@ -243,6 +245,7 @@ test_files:
|
|
243
245
|
- spec/docker_server_spec.rb
|
244
246
|
- spec/docker_via_api_spec.rb
|
245
247
|
- spec/docker_via_cli_spec.rb
|
248
|
+
- spec/dogestry_spec.rb
|
246
249
|
- spec/logging_spec.rb
|
247
250
|
- spec/spec_helper.rb
|
248
251
|
- spec/support/matchers/capistrano_dsl_matchers.rb
|