centurion 1.2.0 → 1.3.0
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 +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
|