centurion 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +66 -16
- data/bin/centurion +13 -9
- data/centurion.gemspec +1 -1
- data/lib/centurion/deploy.rb +7 -4
- data/lib/centurion/deploy_dsl.rb +1 -1
- data/lib/centurion/docker_registry.rb +23 -11
- data/lib/centurion/dogestry.rb +16 -9
- data/lib/centurion/version.rb +1 -1
- data/lib/tasks/deploy.rake +49 -26
- data/lib/tasks/list.rake +5 -1
- data/spec/deploy_spec.rb +6 -1
- data/spec/docker_registry_spec.rb +26 -1
- data/spec/dogestry_spec.rb +1 -0
- metadata +4 -4
data/README.md
CHANGED
@@ -15,14 +15,19 @@ tools directly so you can use anything they currently support via the normal
|
|
15
15
|
registry mechanism.
|
16
16
|
|
17
17
|
If you haven't been using a registry, you should read up on how to do that
|
18
|
-
before trying to deploy anything with Centurion.
|
19
|
-
repositories](https://index.docker.io/), including the main public repository.
|
20
|
-
Alternatively, you can [host your
|
21
|
-
own](https://github.com/dotcloud/docker-registry), or
|
22
|
-
[Quay.io](https://quay.io) is another commercial option.
|
18
|
+
before trying to deploy anything with Centurion.
|
23
19
|
|
24
|
-
|
25
|
-
|
20
|
+
Commercial Docker Registry Providers:
|
21
|
+
- Docker, Inc. [provides repositories](https://index.docker.io/), and hosts the
|
22
|
+
main public Docker repository.
|
23
|
+
- [Quay.io](https://quay.io) from the CoreOS team
|
24
|
+
|
25
|
+
Open-source:
|
26
|
+
- The [Docker registry](https://github.com/dotcloud/docker-registry) project,
|
27
|
+
built and maintained by Docker. You host this yourself.
|
28
|
+
- (*NEW!*) [Dogestry](https://github.com/newrelic-forks/dogestry) is an
|
29
|
+
s3-backed Docker registry alternative that removes the requirement to set up
|
30
|
+
a centralized registry service or host anything yourself.
|
26
31
|
|
27
32
|
Status
|
28
33
|
------
|
@@ -89,7 +94,7 @@ will have the following effects:
|
|
89
94
|
Any time you add a new project you can scaffold it in the same manner even
|
90
95
|
in the same repo.
|
91
96
|
|
92
|
-
###Writing configs
|
97
|
+
### Writing configs
|
93
98
|
|
94
99
|
If you used `centurionize` you will have a base config scaffolded for you.
|
95
100
|
But you'll still need to specify all of your configuration.
|
@@ -139,12 +144,22 @@ Most of the DSL items (`host_port`, `host_volume`, `env_vars`, `host`) can be
|
|
139
144
|
specified more than once and will append to the configuration. However, there
|
140
145
|
can only be one `command`; the last one will take priority.
|
141
146
|
|
142
|
-
|
147
|
+
You can cause your container to be started with a specific DNS server
|
148
|
+
IP address (the equivalent of `docker run --dns 172.17.42.1 ...`) like this:
|
149
|
+
```ruby
|
150
|
+
task :production => :common do
|
151
|
+
set :custom_dns, '172.17.42.1'
|
152
|
+
# ...
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
### Interpolation
|
143
157
|
|
144
158
|
Currently there is one special string for interpolation that can be added to
|
145
|
-
any `env_var` value in the DSL. `%
|
159
|
+
any `env_var` value in the DSL. `%DOCKER_HOSTNAME%` will be replaced with the
|
146
160
|
current server's hostname in the environment variable at deployment time.
|
147
161
|
|
162
|
+
|
148
163
|
Deploying
|
149
164
|
---------
|
150
165
|
|
@@ -182,6 +197,11 @@ are the same everywhere. Settings are per-project.
|
|
182
197
|
`rolling_deployment_wait_time` is the total time Centurion will wait for
|
183
198
|
an individual container to come up before giving up as a failure. Defaults
|
184
199
|
to 24 attempts.
|
200
|
+
* `rolling_deploy_skip_ports` => Either a single port, or an array of ports
|
201
|
+
that should be skipped for status checks. Status checking assumes an HTTP
|
202
|
+
server is on the other end and if you are deploying a container where some
|
203
|
+
ports are not HTTP services, this allows you to only health check the ports
|
204
|
+
that are. The default is an empty array.
|
185
205
|
|
186
206
|
###Deploy a project to a fleet of Docker servers
|
187
207
|
|
@@ -231,15 +251,45 @@ Returns a list of all the images for this project in the registry.
|
|
231
251
|
$ bundle exec centurion -p radio-radio -e staging -a list
|
232
252
|
````
|
233
253
|
|
234
|
-
###
|
254
|
+
### Registry
|
255
|
+
|
256
|
+
Centurion needs to have access to some registry in order to pull images to
|
257
|
+
remote Docker servers. This needs to be either a hosted registry (public or
|
258
|
+
private), or [Dogestry](https://github.com/newrelic-forks/dogestry).
|
259
|
+
|
260
|
+
#### Access to the registry
|
261
|
+
|
262
|
+
If you are not using either Dogestry, or the public registry, you may need to
|
263
|
+
provide authentication credentials. Centurion needs to access the Docker
|
264
|
+
registry hosting your images directly to retrive image ids and tags.This is
|
265
|
+
supported in both the config file and also as command line arguments.
|
266
|
+
|
267
|
+
The command line arguments are:
|
268
|
+
* `--registry-user` => The username to pass to the registry
|
269
|
+
* `--registry-password` => The password
|
270
|
+
|
271
|
+
These correspond to the following settings:
|
272
|
+
|
273
|
+
* `registry_user`
|
274
|
+
* `registry_password`
|
275
|
+
|
276
|
+
#### Alternative Docker Registry
|
235
277
|
|
236
|
-
Centurion normally uses the built-in registry support in the Docker daemon to
|
237
|
-
|
278
|
+
Centurion normally uses the built-in registry support in the Docker daemon to
|
279
|
+
handle pushing and pulling images.But Centurion also has the ability to use
|
280
|
+
external tooling to support hosting your registry on Amazon S3. That tooling is
|
281
|
+
from a project called [Dogestry](https://github.com/newrelic-forks/dogestry).
|
282
|
+
We have recently improved that tooling substantially in coordination with the
|
283
|
+
Centurion support.
|
238
284
|
|
239
|
-
Dogestry uses the Docker daemon's import/export functionality in combination
|
285
|
+
Dogestry uses the Docker daemon's import/export functionality in combination
|
286
|
+
with Amazon S3 to provide reliable hosting of images. Setting Centurion up to
|
287
|
+
use Dogestry is pretty trivial:
|
240
288
|
|
241
|
-
1. Install Dogestry binaries on the client from which Dogestry is run.
|
242
|
-
|
289
|
+
1. Install Dogestry binaries on the client from which Dogestry is run.
|
290
|
+
Binaries are provided in the GitHub release.
|
291
|
+
1. Add the settings necessary to get Centurion to pull from Dogestry. A config
|
292
|
+
example is provided below:
|
243
293
|
|
244
294
|
See example below to use `dogestry`:
|
245
295
|
|
data/bin/centurion
CHANGED
@@ -22,14 +22,16 @@ Dir.glob(File.join(task_dir, '*.rake')).each { |file| load file }
|
|
22
22
|
require 'trollop'
|
23
23
|
|
24
24
|
opts = Trollop::options do
|
25
|
-
opt :project,
|
26
|
-
opt :environment,
|
27
|
-
opt :action,
|
28
|
-
opt :image,
|
29
|
-
opt :tag,
|
30
|
-
opt :hosts,
|
31
|
-
opt :docker_path,
|
32
|
-
opt :nopull,
|
25
|
+
opt :project, 'project (blog, forums...)', type: String, required: true, short: '-p'
|
26
|
+
opt :environment, "environment (production, staging...)", type: String, required: true, short: '-e'
|
27
|
+
opt :action, 'action (deploy, list...)', type: String, default: 'list', short: '-a'
|
28
|
+
opt :image, 'image (yourco/project...)', type: String, required: false, short: '-i'
|
29
|
+
opt :tag, 'tag (latest...)', type: String, required: false, short: '-t'
|
30
|
+
opt :hosts, 'hosts, comma separated', type: String, required: false, short: '-h'
|
31
|
+
opt :docker_path, 'path to docker executable (default: docker)', type: String, default: 'docker', short: '-d'
|
32
|
+
opt :nopull, 'Skip the pull_image step', type: :flag, default: false, long: '--no-pull'
|
33
|
+
opt :registry_user, 'user for registry auth (default: nil)', type: String, default: nil, short: :none
|
34
|
+
opt :registry_password,'password for registry auth (default: nil)', type: String, default: nil, short: :none
|
33
35
|
end
|
34
36
|
|
35
37
|
set_current_environment(opts[:environment].to_sym)
|
@@ -60,6 +62,8 @@ set :docker_registry, Centurion::DockerRegistry::OFFICIAL_URL unless any?(:docke
|
|
60
62
|
# Specify a path to docker executable
|
61
63
|
set :docker_path, opts[:docker_path]
|
62
64
|
|
63
|
-
set :no_pull, opts[:
|
65
|
+
set :no_pull, opts[:registry_user]
|
66
|
+
set :registry_user, opts[:registry_user] if opts[:registry_user]
|
67
|
+
set :registry_password, opts[:registry_password] if opts[:registry_password]
|
64
68
|
|
65
69
|
invoke(opts[:action])
|
data/centurion.gemspec
CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |spec|
|
|
39
39
|
|
40
40
|
spec.add_development_dependency 'bundler'
|
41
41
|
spec.add_development_dependency 'rake'
|
42
|
-
spec.add_development_dependency 'rspec', '~>
|
42
|
+
spec.add_development_dependency 'rspec', '~> 3.1.0'
|
43
43
|
spec.add_development_dependency 'pry'
|
44
44
|
spec.add_development_dependency 'simplecov'
|
45
45
|
|
data/lib/centurion/deploy.rb
CHANGED
@@ -58,7 +58,7 @@ module Centurion::Deploy
|
|
58
58
|
def http_status_ok?(target_server, port, endpoint)
|
59
59
|
url = "http://#{target_server.hostname}:#{port}#{endpoint}"
|
60
60
|
response = begin
|
61
|
-
Excon.get(url)
|
61
|
+
Excon.get(url, :headers => {'Accept' => '*/*'})
|
62
62
|
rescue Excon::Errors::SocketError
|
63
63
|
warn "Failed to connect to #{url}, no socket open."
|
64
64
|
nil
|
@@ -67,7 +67,7 @@ module Centurion::Deploy
|
|
67
67
|
return false unless response
|
68
68
|
return true if response.status >= 200 && response.status < 300
|
69
69
|
|
70
|
-
warn "Got HTTP status: #{response.status}"
|
70
|
+
warn "Got HTTP status: #{response.status}"
|
71
71
|
false
|
72
72
|
end
|
73
73
|
|
@@ -137,7 +137,7 @@ module Centurion::Deploy
|
|
137
137
|
end
|
138
138
|
|
139
139
|
private
|
140
|
-
|
140
|
+
|
141
141
|
def start_container_with_config(target_server, volumes, port_bindings, container_config)
|
142
142
|
info "Creating new container for #{container_config['Image'][0..7]}"
|
143
143
|
new_container = target_server.create_container(container_config)
|
@@ -146,7 +146,10 @@ module Centurion::Deploy
|
|
146
146
|
# Map some host volumes if needed
|
147
147
|
host_config['Binds'] = volumes if volumes && !volumes.empty?
|
148
148
|
# Bind the ports
|
149
|
-
host_config['PortBindings'] = port_bindings
|
149
|
+
host_config['PortBindings'] = port_bindings
|
150
|
+
# DNS if specified
|
151
|
+
dns = fetch(:custom_dns)
|
152
|
+
host_config['Dns'] = dns if dns
|
150
153
|
|
151
154
|
info "Starting new container #{new_container['Id'][0..7]}"
|
152
155
|
target_server.start_container(new_container['Id'], host_config)
|
data/lib/centurion/deploy_dsl.rb
CHANGED
@@ -7,17 +7,24 @@ module Centurion; end
|
|
7
7
|
class Centurion::DockerRegistry
|
8
8
|
OFFICIAL_URL = 'https://registry.hub.docker.com'
|
9
9
|
|
10
|
-
def initialize(base_uri)
|
10
|
+
def initialize(base_uri, registry_user=nil, registry_password=nil)
|
11
11
|
@base_uri = base_uri
|
12
|
+
@user = registry_user
|
13
|
+
@password = registry_password
|
12
14
|
end
|
13
15
|
|
14
16
|
def digest_for_tag(repository, tag)
|
15
17
|
path = "/v1/repositories/#{repository}/tags/#{tag}"
|
16
18
|
uri = uri_for_repository_path(repository, path)
|
17
19
|
$stderr.puts "GET: #{uri}"
|
20
|
+
options = { :headers => { "Content-Type" => "application/json" } }
|
21
|
+
if @user
|
22
|
+
options[:user] = @user
|
23
|
+
options[:password] = @password
|
24
|
+
end
|
18
25
|
response = Excon.get(
|
19
26
|
uri,
|
20
|
-
|
27
|
+
options
|
21
28
|
)
|
22
29
|
raise response.inspect unless response.status == 200
|
23
30
|
|
@@ -30,8 +37,18 @@ class Centurion::DockerRegistry
|
|
30
37
|
def repository_tags(repository)
|
31
38
|
path = "/v1/repositories/#{repository}/tags"
|
32
39
|
uri = uri_for_repository_path(repository, path)
|
40
|
+
|
33
41
|
$stderr.puts "GET: #{uri.inspect}"
|
34
|
-
|
42
|
+
|
43
|
+
# Need to workaround a bug in Docker Hub to now pass port in Host header
|
44
|
+
options = { omit_default_port: true }
|
45
|
+
|
46
|
+
if @user
|
47
|
+
options[:user] = @user
|
48
|
+
options[:password] = @password
|
49
|
+
end
|
50
|
+
|
51
|
+
response = Excon.get(uri, options)
|
35
52
|
raise response.inspect unless response.status == 200
|
36
53
|
|
37
54
|
tags = JSON.load(response.body)
|
@@ -46,10 +63,8 @@ class Centurion::DockerRegistry
|
|
46
63
|
# [1]: https://docs.docker.com/v1.1/reference/api/registry_api/
|
47
64
|
|
48
65
|
if is_official_registry?(repository)
|
49
|
-
{}
|
50
|
-
|
51
|
-
hash[tag['name']] = tag['layer']
|
52
|
-
end
|
66
|
+
tags.each_with_object({}) do |tag, hash|
|
67
|
+
hash[tag['name']] = tag['layer']
|
53
68
|
end
|
54
69
|
else
|
55
70
|
tags
|
@@ -59,10 +74,7 @@ class Centurion::DockerRegistry
|
|
59
74
|
private
|
60
75
|
|
61
76
|
def is_official_registry?(repository)
|
62
|
-
|
63
|
-
return !repository.match(/^[a-z0-9]+[a-z0-9\-\.]+(?::[1-9][0-9]*)?\//)
|
64
|
-
end
|
65
|
-
false
|
77
|
+
return @base_uri == OFFICIAL_URL
|
66
78
|
end
|
67
79
|
|
68
80
|
def uri_for_repository_path(repository, path)
|
data/lib/centurion/dogestry.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require_relative 'logging'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module Centurion; end
|
4
5
|
|
5
6
|
class Centurion::Dogestry
|
6
7
|
include Centurion::Logging
|
8
|
+
attr_accessor :options
|
7
9
|
|
8
10
|
def initialize(options = {})
|
9
11
|
@options = options
|
@@ -54,7 +56,7 @@ class Centurion::Dogestry
|
|
54
56
|
@options[:docker_host] || 'tcp://localhost:2375'
|
55
57
|
end
|
56
58
|
|
57
|
-
def set_envs
|
59
|
+
def set_envs(docker_host)
|
58
60
|
ENV['DOCKER_HOST'] = docker_host
|
59
61
|
ENV['AWS_ACCESS_KEY'] = aws_access_key_id
|
60
62
|
ENV['AWS_SECRET_KEY'] = aws_secret_key
|
@@ -62,23 +64,28 @@ class Centurion::Dogestry
|
|
62
64
|
info "Dogestry ENV: #{ENV.inspect}"
|
63
65
|
end
|
64
66
|
|
65
|
-
def exec_command(command, repo)
|
66
|
-
command = "dogestry #{command} #{s3_url} #{repo}"
|
67
|
+
def exec_command(command, repo, flags="")
|
68
|
+
command = "dogestry #{flags} #{command} #{s3_url} #{repo}"
|
67
69
|
info "Executing: #{command}"
|
68
70
|
command
|
69
71
|
end
|
70
72
|
|
71
|
-
def
|
73
|
+
def download_image_to_temp_dir(repo, local_dir)
|
72
74
|
validate_before_exec
|
73
|
-
set_envs
|
75
|
+
set_envs("")
|
74
76
|
|
75
|
-
|
77
|
+
flags = "-tempdir #{File.expand_path(local_dir)}"
|
78
|
+
|
79
|
+
echo(exec_command('download', repo, flags=flags))
|
76
80
|
end
|
77
81
|
|
78
|
-
def
|
82
|
+
def upload_temp_dir_image_to_docker(repo, local_dir, docker_host)
|
79
83
|
validate_before_exec
|
80
|
-
set_envs
|
84
|
+
set_envs(docker_host)
|
85
|
+
|
86
|
+
command = "dogestry upload #{local_dir} #{repo}"
|
87
|
+
info "Executing: #{command}"
|
81
88
|
|
82
|
-
echo(
|
89
|
+
echo(command)
|
83
90
|
end
|
84
91
|
end
|
data/lib/centurion/version.rb
CHANGED
data/lib/tasks/deploy.rake
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'excon'
|
3
3
|
require 'centurion/deploy'
|
4
|
+
require 'tmpdir'
|
4
5
|
|
5
6
|
task :deploy do
|
6
7
|
invoke 'deploy:get_image'
|
@@ -31,7 +32,7 @@ namespace :deploy do
|
|
31
32
|
task :validate_pull_image do
|
32
33
|
['aws_access_key_id', 'aws_secret_key', 's3_bucket'].each do |env_var|
|
33
34
|
unless fetch(env_var.to_sym)
|
34
|
-
|
35
|
+
error "\n\n#{env_var} is not defined."
|
35
36
|
exit(1)
|
36
37
|
end
|
37
38
|
end
|
@@ -40,21 +41,32 @@ namespace :deploy do
|
|
40
41
|
task :pull_image do
|
41
42
|
invoke 'deploy:dogestry:validate_pull_image'
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
# Create Centurion::Dogestry instance
|
45
|
+
registry = Centurion::Dogestry.new(
|
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
|
+
)
|
51
|
+
|
52
|
+
# Download image from S3 to local /tmp/directory
|
53
|
+
Dir.mktmpdir("dogestry") do |local_dir|
|
54
|
+
|
55
|
+
info "** Downloading image(#{fetch(:image)}:#{fetch(:tag)}) from S3 to local directory"
|
56
|
+
registry.download_image_to_temp_dir("#{fetch(:image)}:#{fetch(:tag)}", local_dir)
|
57
|
+
|
58
|
+
# Upload image from local /tmp/directory to specified Docker hosts
|
59
|
+
target_servers = Centurion::DockerServerGroup.new(fetch(:hosts), fetch(:docker_path))
|
60
|
+
target_servers.each_in_parallel do |target_server|
|
52
61
|
|
53
|
-
|
62
|
+
docker_host = "tcp://#{target_server.hostname}:#{target_server.port}"
|
54
63
|
|
55
|
-
|
64
|
+
image_and_tag = "#{fetch(:image)}:#{fetch(:tag)}"
|
56
65
|
|
57
|
-
|
66
|
+
info "** Pushing image(#{image_and_tag}) from #{local_dir} to Docker: #{docker_host}"
|
67
|
+
|
68
|
+
registry.upload_temp_dir_image_to_docker(image_and_tag, local_dir, docker_host)
|
69
|
+
end
|
58
70
|
end
|
59
71
|
end
|
60
72
|
end
|
@@ -85,7 +97,8 @@ namespace :deploy do
|
|
85
97
|
fetch(:image_id),
|
86
98
|
fetch(:port_bindings),
|
87
99
|
fetch(:binds),
|
88
|
-
fetch(:env_vars)
|
100
|
+
fetch(:env_vars),
|
101
|
+
fetch(:command)
|
89
102
|
)
|
90
103
|
end
|
91
104
|
end
|
@@ -111,13 +124,19 @@ namespace :deploy do
|
|
111
124
|
fetch(:image_id),
|
112
125
|
fetch(:port_bindings),
|
113
126
|
fetch(:binds),
|
114
|
-
fetch(:env_vars)
|
127
|
+
fetch(:env_vars),
|
128
|
+
fetch(:command)
|
115
129
|
)
|
116
130
|
|
131
|
+
skip_ports = Array(fetch(:rolling_deploy_skip_ports, [])).map(&:to_s)
|
132
|
+
|
117
133
|
fetch(:port_bindings).each_pair do |container_port, host_ports|
|
134
|
+
port = host_ports.first['HostPort']
|
135
|
+
next if skip_ports.include?(port)
|
136
|
+
|
118
137
|
wait_for_http_status_ok(
|
119
138
|
server,
|
120
|
-
|
139
|
+
port,
|
121
140
|
fetch(:status_endpoint, '/'),
|
122
141
|
fetch(:image),
|
123
142
|
fetch(:tag),
|
@@ -137,10 +156,14 @@ namespace :deploy do
|
|
137
156
|
end
|
138
157
|
|
139
158
|
task :determine_image_id do
|
140
|
-
registry = Centurion::DockerRegistry.new(
|
159
|
+
registry = Centurion::DockerRegistry.new(
|
160
|
+
fetch(:docker_registry),
|
161
|
+
fetch(:registry_user),
|
162
|
+
fetch(:registry_password)
|
163
|
+
)
|
141
164
|
exact_image = registry.digest_for_tag(fetch(:image), fetch(:tag))
|
142
165
|
set :image_id, exact_image
|
143
|
-
|
166
|
+
info "RESOLVED #{fetch(:image)}:#{fetch(:tag)} => #{exact_image[0..11]}"
|
144
167
|
end
|
145
168
|
|
146
169
|
task :determine_image_id_from_first_server do
|
@@ -148,7 +171,7 @@ namespace :deploy do
|
|
148
171
|
image_detail = target_server.inspect_image(fetch(:image), fetch(:tag))
|
149
172
|
exact_image = image_detail["id"]
|
150
173
|
set :image_id, exact_image
|
151
|
-
|
174
|
+
info "RESOLVED #{fetch(:image)}:#{fetch(:tag)} => #{exact_image[0..11]}"
|
152
175
|
break
|
153
176
|
end
|
154
177
|
end
|
@@ -159,7 +182,7 @@ namespace :deploy do
|
|
159
182
|
next
|
160
183
|
end
|
161
184
|
|
162
|
-
|
185
|
+
info "Fetching image #{fetch(:image)}:#{fetch(:tag)} IN PARALLEL\n"
|
163
186
|
|
164
187
|
if fetch(:registry) == 'dogestry'
|
165
188
|
invoke 'deploy:dogestry:pull_image'
|
@@ -177,21 +200,21 @@ namespace :deploy do
|
|
177
200
|
found_image_id = image_detail["id"]
|
178
201
|
|
179
202
|
if found_image_id == fetch(:image_id)
|
180
|
-
|
203
|
+
info "Image #{found_image_id[0..7]} found on #{target_server.hostname}"
|
181
204
|
else
|
182
205
|
raise "Did not find image #{fetch(:image_id)} on host #{target_server.hostname}!"
|
183
206
|
end
|
184
207
|
|
185
208
|
# Print the container config
|
186
209
|
image_detail["container_config"].each_pair do |key,value|
|
187
|
-
|
210
|
+
info "\t#{key} => #{value.inspect}"
|
188
211
|
end
|
189
212
|
end
|
190
213
|
end
|
191
214
|
|
192
215
|
task :promote_from_staging do
|
193
216
|
if fetch(:environment) == 'staging'
|
194
|
-
|
217
|
+
error "\n\nYour target environment needs to not be 'staging' to promote from staging."
|
195
218
|
exit(1)
|
196
219
|
end
|
197
220
|
|
@@ -203,17 +226,17 @@ namespace :deploy do
|
|
203
226
|
staging_tags = get_current_tags_for(fetch(:image)).map { |t| t[:tags] }.flatten.uniq
|
204
227
|
|
205
228
|
if staging_tags.size != 1
|
206
|
-
|
229
|
+
error "\n\nUh, oh: Not sure which staging tag to deploy! Found:(#{staging_tags.join(', ')})"
|
207
230
|
exit(1)
|
208
231
|
end
|
209
232
|
|
210
|
-
|
233
|
+
info "Staging environment has #{staging_tags.first} deployed."
|
211
234
|
|
212
235
|
# Make sure that we set our env back to production, then update the tag.
|
213
236
|
set_current_environment(starting_environment)
|
214
237
|
set :tag, staging_tags.first
|
215
238
|
|
216
|
-
|
239
|
+
info "Deploying #{fetch(:tag)} to the #{starting_environment} environment"
|
217
240
|
|
218
241
|
invoke 'deploy'
|
219
242
|
end
|
data/lib/tasks/list.rake
CHANGED
@@ -24,7 +24,11 @@ namespace :list do
|
|
24
24
|
|
25
25
|
task :tags do
|
26
26
|
begin
|
27
|
-
registry = Centurion::DockerRegistry.new(
|
27
|
+
registry = Centurion::DockerRegistry.new(
|
28
|
+
fetch(:docker_registry),
|
29
|
+
fetch(:registry_user),
|
30
|
+
fetch(:registry_password)
|
31
|
+
)
|
28
32
|
tags = registry.repository_tags(fetch(:image))
|
29
33
|
tags.each do |tag|
|
30
34
|
puts "\t#{tag[0]}\t-> #{tag[1][0..11]}"
|
data/spec/deploy_spec.rb
CHANGED
@@ -226,10 +226,13 @@ describe Centurion::Deploy do
|
|
226
226
|
|
227
227
|
server.stub(:inspect_container)
|
228
228
|
|
229
|
+
allow(test_deploy).to receive(:fetch).with(:custom_dns).and_return('8.8.8.8')
|
230
|
+
|
229
231
|
expect(server).to receive(:start_container).with(
|
230
232
|
'abc123456',
|
231
233
|
{
|
232
|
-
'PortBindings' => bindings
|
234
|
+
'PortBindings' => bindings,
|
235
|
+
'Dns' => '8.8.8.8'
|
233
236
|
}
|
234
237
|
).once
|
235
238
|
|
@@ -258,6 +261,8 @@ describe Centurion::Deploy do
|
|
258
261
|
end
|
259
262
|
|
260
263
|
it 'ultimately asks the server object to do the work' do
|
264
|
+
allow(test_deploy).to receive(:fetch).with(:custom_dns).and_return(nil)
|
265
|
+
|
261
266
|
server.should_receive(:create_container).with(
|
262
267
|
hash_including(
|
263
268
|
'Image'=>'image_id',
|
@@ -46,7 +46,7 @@ describe Centurion::DockerRegistry do
|
|
46
46
|
let(:registry_url) { Centurion::DockerRegistry::OFFICIAL_URL }
|
47
47
|
let(:repository) { 'docker-reg.example.com/foobar' }
|
48
48
|
let(:response) { <<-JSON.strip }
|
49
|
-
{"#{
|
49
|
+
[{"layer": "#{image_id}", "name": "#{tag_name}"}]
|
50
50
|
JSON
|
51
51
|
|
52
52
|
it 'fetches from the image-referenced registry' do
|
@@ -77,4 +77,29 @@ describe Centurion::DockerRegistry do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
describe '#repository_auth' do
|
82
|
+
let(:tag_name) { 'arbitrary_tag' }
|
83
|
+
let(:image_id) { 'deadbeef0000' }
|
84
|
+
let(:user) { 'user_foo' }
|
85
|
+
let(:password) { 'pass_bar' }
|
86
|
+
let(:registry) { Centurion::DockerRegistry.new(registry_url, user, password) }
|
87
|
+
|
88
|
+
context 'when authentication data is provided to the DockerRegistry object' do
|
89
|
+
let(:registry_url) { Centurion::DockerRegistry::OFFICIAL_URL }
|
90
|
+
let(:repository) { 'docker-reg.example.com/foobar' }
|
91
|
+
let(:response) { <<-JSON.strip }
|
92
|
+
[{"layer": "#{image_id}", "name": "#{tag_name}"}]
|
93
|
+
JSON
|
94
|
+
|
95
|
+
before do
|
96
|
+
expect(Excon).to receive(:get).with(kind_of(String), hash_including(:user => user, :password => password)).and_return(
|
97
|
+
double(status: 200, body: response)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
it 'uses it to connect to the registry' do
|
101
|
+
registry.repository_tags(repository)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
80
105
|
end
|
data/spec/dogestry_spec.rb
CHANGED
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.3.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-
|
24
|
+
date: 2014-11-20 00:00:00.000000000 Z
|
25
25
|
dependencies:
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: trollop
|
@@ -110,7 +110,7 @@ dependencies:
|
|
110
110
|
requirements:
|
111
111
|
- - ~>
|
112
112
|
- !ruby/object:Gem::Version
|
113
|
-
version:
|
113
|
+
version: 3.1.0
|
114
114
|
type: :development
|
115
115
|
prerelease: false
|
116
116
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -118,7 +118,7 @@ dependencies:
|
|
118
118
|
requirements:
|
119
119
|
- - ~>
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
version:
|
121
|
+
version: 3.1.0
|
122
122
|
- !ruby/object:Gem::Dependency
|
123
123
|
name: pry
|
124
124
|
requirement: !ruby/object:Gem::Requirement
|