centurion 1.8.10 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ec921ec16391c51e0941a6a9e2d6fe2e060155da
4
- data.tar.gz: 5ee10d7e3028d1135e5fe4eb1f8075e1146e643c
3
+ metadata.gz: 43be6c7bcc352c334aa0e84044443a9f4c6f055a
4
+ data.tar.gz: 49f52dfe1bc7dc4dfa5e200650f2b786b7c2bdbf
5
5
  SHA512:
6
- metadata.gz: f8a80e7c694b008596459d7ce7b05000c2a50e6d7e89d388e7589a59287059b2bd487b6dea8fb683e9d283f333e372854aa3900673094d98202e817e6b1bbe5d
7
- data.tar.gz: cb23d715dff77b5cb3b0d20fe9d8e3e9dbb74f14c34322e4553024f098ba9b4cc6e6d833b96a355fd970400e9a95aa1a0624448d6e85f9cd928fa35166a1156c
6
+ metadata.gz: 9ce70d7443f88d79e17a8e0ce9890ad7104cbf89061cee1f957f84c8016b31ced9712fc4e357127e14e945c9d13df2e871fa57cc4a87a41ff4eda0481f3e70eb
7
+ data.tar.gz: 362f4d002b00c232d32731fbbfcf5ca069bdd3c8a9902e5ba8f2b28715d6e5cb3f0198974a46fded276f30b642545c6620f380b3181e0ed311ba049af24c4be9
@@ -16,6 +16,7 @@ Your name could be here!
16
16
  * [Hugo Chinchilla][hugochinchilla]
17
17
  * [Dan Selans][dselans]
18
18
  * [Dan Young][idleyoungman]
19
+ * [Trevor Strieber][tstrieber]
19
20
 
20
21
  Pre-release
21
22
  -----------
data/README.md CHANGED
@@ -25,9 +25,6 @@ Commercial Docker Registry Providers:
25
25
  Open-source:
26
26
  - The [Docker Distribution](https://github.com/docker/distribution) project,
27
27
  built and maintained by Docker. You host this yourself.
28
- - (*NEW!*) [Dogestry](https://github.com/dogestry/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.
31
28
 
32
29
  Status
33
30
  ------
@@ -292,6 +289,25 @@ drop_capability 'SOME_CAPABILITY'
292
289
  For more information on which kernel capabilities may be specified, see the
293
290
  [Docker docs](https://docs.docker.com/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration).
294
291
 
292
+ ### Setting the security options
293
+
294
+ Some Docker platforms support container security overlays called `seccomp`.
295
+ During container creation, you may specify security options to control the
296
+ seccomp permissions.
297
+
298
+ To set a seccomp path:
299
+ ```ruby
300
+ add_security_opt 'seccomp=/path/to/seccomp/profile.json'
301
+ ```
302
+
303
+ Or, to unblock all syscalls in a container:
304
+
305
+ ```ruby
306
+ add_security_opt 'seccomp=unconfined'
307
+ ```
308
+
309
+ For more information on this argument, see the [Docker docs](https://docs.docker.com/engine/security/seccomp/).
310
+
295
311
  ### Interpolation
296
312
 
297
313
  Currently there a couple of special strings for interpolation that can be added
@@ -336,13 +352,34 @@ You have to set the following keys:
336
352
 
337
353
  Modify the paths as appropriate for your cert, ca, and key files.
338
354
 
355
+ ### Use SSH to connect *beta*
356
+
357
+ If your Docker server does not expose its HTTP service over TCP, you can
358
+ instead talk to it via SSH.
359
+
360
+ This functions by creating a local Unix socket that forwards to the remote
361
+ Docker Unix socket, so it requires that the user you connect as has access to
362
+ the Docker socket without any `sudo`. Currently it also assumes that you
363
+ authenticate via public key, so be sure that you have `ssh-add`ed your key to
364
+ your SSH agent if it has a passcode.
365
+
366
+ You can configure it with a few options:
367
+
368
+ ```ruby
369
+ task :common do
370
+ set :ssh, true # enable ssh connections
371
+ set :ssh_user, "myuser" # if you want to specify the user to connect as, otherwise your current user
372
+ set :ssh_log_level, Logger::DEBUG # passed on to net/ssh, can be noisy; defaults to Logger::WARN
373
+ end
374
+ ```
375
+
339
376
  Deploying
340
377
  ---------
341
378
 
342
379
  Centurion supports a number of tasks out of the box that make working with
343
380
  distributed containers easy. Here are some examples:
344
381
 
345
- ###Do a rolling deployment to a fleet of Docker servers
382
+ ### Do a rolling deployment to a fleet of Docker servers
346
383
 
347
384
  A rolling deployment will stop and start each container one at a time to make
348
385
  sure that the application stays available from the viewpoint of the load
@@ -352,9 +389,9 @@ the root path of the application. The healthcheck endpoint is configurable by ad
352
389
  `set(:status_endpoint, '/somewhere/else')` in your config. The status endpoint
353
390
  must respond with a valid response in the 200 status range.
354
391
 
355
- ````bash
392
+ ```bash
356
393
  $ bundle exec centurion -p radio-radio -e staging -a rolling_deploy
357
- ````
394
+ ```
358
395
 
359
396
  **Custom Health Check**:
360
397
  You can use a custom health check by specifying a callable object (anything that
@@ -365,7 +402,7 @@ should return a truthy value, falsey otherwise. Here's an example of a custom
365
402
  health check that verifies that an elasticsearch node is up and has joined the
366
403
  cluster.
367
404
 
368
- ````ruby
405
+ ```ruby
369
406
  def cluster_green?(target_server, port, endpoint)
370
407
  response = begin
371
408
  Excon.get("http://#{target_server.hostname}:#{port}#{endpoint}")
@@ -386,7 +423,7 @@ task :production => :common do
386
423
  host 'es-01.example.com'
387
424
  host 'es-02.example.com'
388
425
  end
389
- ````
426
+ ```
390
427
 
391
428
  **Rolling Deployment Settings**:
392
429
  You can change the following settings in your config to tune how the rolling
@@ -412,35 +449,36 @@ are the same everywhere. Settings are per-project.
412
449
  that are. The default is an empty array. If you have non-HTTP services that you
413
450
  want to check, see Custom Health Checks in the previous section.
414
451
 
415
- ###Deploy a project to a fleet of Docker servers
452
+ ### Deploy a project to a fleet of Docker servers
416
453
 
417
454
  This will hard stop, then start containers on all the specified hosts. This
418
455
  is not recommended for apps where one endpoint needs to be available at all
419
456
  times. It is fast.
420
457
 
421
- ````bash
458
+ ```bash
422
459
  $ bundle exec centurion -p radio-radio -e staging -a deploy
423
- ````
460
+ ```
424
461
 
425
- ###Deploy a bash console on a host
462
+ ### Deploy a bash console on a host
426
463
 
427
464
  This will give you a command line shell with all of your existing environment
428
465
  passed to the container. The `CMD` from the `Dockerfile` will be replaced
429
466
  with `/bin/bash`. It will use the first host from the host list.
430
467
 
431
- ````bash
468
+ ```bash
432
469
  $ bundle exec centurion -p radio-radio -e staging -a deploy_console
433
- ````
470
+ ```
471
+
434
472
  ### Repair unhealthy docker containers
435
473
 
436
474
  This will preform a health check on each host using rolling deployment
437
475
  health check settings and redeploy to the host if a health check fails.
438
476
 
439
- ````bash
477
+ ```bash
440
478
  $ bundle exec centurion -p radio-radio -e staging -a repair
441
- ````
479
+ ```
442
480
 
443
- ###List all the tags running on your servers for a particular project
481
+ ### List all the tags running on your servers for a particular project
444
482
 
445
483
  Returns a nicely-formatted list of all the current tags and which machines they
446
484
  are running on. Gives a unique list of tags across all hosts as well. This is
@@ -451,7 +489,7 @@ goes wrong mid-deploy.
451
489
  $ bundle exec centurion -p radio-radio -e staging -a list:running_container_tags
452
490
  ```
453
491
 
454
- ###List all the containers currently running for this project
492
+ ### List all the containers currently running for this project
455
493
 
456
494
  Returns a (as yet not very nicely formatted) list of all the containers for
457
495
  this project on each of the servers from the config.
@@ -460,13 +498,13 @@ this project on each of the servers from the config.
460
498
  $ bundle exec centurion -p radio-radio -e staging -a list:running_containers
461
499
  ```
462
500
 
463
- ###List registry images
501
+ ### List registry images
464
502
 
465
503
  Returns a list of all the images for this project in the registry.
466
504
 
467
- ````bash
505
+ ```bash
468
506
  $ bundle exec centurion -p radio-radio -e staging -a list
469
- ````
507
+ ```
470
508
 
471
509
  ### Registry
472
510
 
@@ -609,4 +647,4 @@ patents, and ideas in that code in our products if we so choose. You also agree
609
647
  the code is provided as-is and you provide no warranties as to its fitness or
610
648
  correctness for any purpose
611
649
 
612
- Copyright (c) 2014-2016 New Relic, Inc. All rights reserved.
650
+ Copyright (c) 2014-2017 New Relic, Inc. All rights reserved.
@@ -36,6 +36,8 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency 'trollop'
37
37
  spec.add_dependency 'excon', '~> 0.33'
38
38
  spec.add_dependency 'logger-colors'
39
+ spec.add_dependency 'net-ssh'
40
+ spec.add_dependency 'sshkit'
39
41
 
40
42
  spec.add_development_dependency 'bundler'
41
43
  spec.add_development_dependency 'rake', '~> 10.5'
@@ -150,7 +150,7 @@ module Centurion::DeployDSL
150
150
 
151
151
  def build_server_group
152
152
  hosts, docker_path = fetch(:hosts, []), fetch(:docker_path)
153
- Centurion::DockerServerGroup.new(hosts, docker_path, build_tls_params)
153
+ Centurion::DockerServerGroup.new(hosts, docker_path, build_server_params)
154
154
  end
155
155
 
156
156
  def validate_options_keys(options, valid_keys)
@@ -180,13 +180,23 @@ module Centurion::DeployDSL
180
180
  Centurion::DockerViaCli.tls_keys.all? { |key| fetch(key).present? }
181
181
  end
182
182
 
183
- def build_tls_params
184
- return {} unless fetch(:tlsverify)
185
- {
186
- tls: fetch(:tlsverify || tls_paths_available?),
187
- tlscacert: fetch(:tlscacert),
188
- tlscert: fetch(:tlscert),
189
- tlskey: fetch(:tlskey)
190
- }
183
+ def build_server_params
184
+ opts = {}
185
+ if fetch(:tlsverify)
186
+ opts[:tls] = fetch(:tlsverify || tls_paths_available?)
187
+ opts[:tlscacert] = fetch(:tlscacert)
188
+ opts[:tlscert] = fetch(:tlscert)
189
+ opts[:tlskey] = fetch(:tlskey)
190
+ end
191
+
192
+ if fetch(:ssh, false) == true
193
+ opts[:ssh] = true
194
+
195
+ # nil is OK for both of these, defaults applied internally
196
+ opts[:ssh_user] = fetch(:ssh_user)
197
+ opts[:ssh_log_level] = fetch(:ssh_log_level)
198
+ end
199
+
200
+ opts
191
201
  end
192
202
  end
@@ -18,15 +18,15 @@ class Centurion::DockerServer
18
18
  :remove_container, :restart_container
19
19
  def_delegators :docker_via_cli, :pull, :tail, :attach, :exec, :exec_it
20
20
 
21
- def initialize(host, docker_path, tls_params = {})
21
+ def initialize(host, docker_path, connection_opts = {})
22
22
  @docker_path = docker_path
23
23
  @hostname, @port = host.split(':')
24
- @port ||= if tls_params.empty?
25
- '2375'
26
- else
27
- '2376'
28
- end
29
- @tls_params = tls_params
24
+ @port ||= if connection_opts[:tls]
25
+ '2376'
26
+ else
27
+ '2375'
28
+ end
29
+ @connection_opts = connection_opts
30
30
  end
31
31
 
32
32
  def current_tags_for(image)
@@ -64,16 +64,26 @@ class Centurion::DockerServer
64
64
  end
65
65
  end
66
66
 
67
+ def describe
68
+ desc = hostname
69
+ desc += " via TLS" if @connection_opts[:tls]
70
+ if @connection_opts[:ssh]
71
+ desc += " via SSH"
72
+ desc += " user #{@connection_opts[:ssh_user]}" if @connection_opts[:ssh_user]
73
+ end
74
+ desc
75
+ end
76
+
67
77
  private
68
78
 
69
79
  def docker_via_api
70
80
  @docker_via_api ||= Centurion::DockerViaApi.new(@hostname, @port,
71
- @tls_params, nil)
81
+ @connection_opts, nil)
72
82
  end
73
83
 
74
84
  def docker_via_cli
75
85
  @docker_via_cli ||= Centurion::DockerViaCli.new(@hostname, @port,
76
- @docker_path, @tls_params)
86
+ @docker_path, @connection_opts)
77
87
  end
78
88
 
79
89
  def parse_image_tags_for(running_containers)
@@ -2,13 +2,21 @@ require 'excon'
2
2
  require 'json'
3
3
  require 'uri'
4
4
  require 'securerandom'
5
+ require 'centurion/ssh'
5
6
 
6
7
  module Centurion; end
7
8
 
8
9
  class Centurion::DockerViaApi
9
- def initialize(hostname, port, tls_args = {}, api_version = nil)
10
- @tls_args = default_tls_args(tls_args[:tls]).merge(tls_args.reject { |k, v| v.nil? }) # Required by tls_enable?
11
- @base_uri = "http#{'s' if tls_enable?}://#{hostname}:#{port}"
10
+ def initialize(hostname, port, connection_opts = {}, api_version = nil)
11
+ @tls_args = default_tls_args(connection_opts[:tls]).merge(connection_opts.reject { |k, v| v.nil? }) # Required by tls_enable?
12
+ if connection_opts[:ssh]
13
+ @base_uri = hostname
14
+ @ssh = true
15
+ @ssh_user = connection_opts[:ssh_user]
16
+ @ssh_log_level = connection_opts[:ssh_log_level]
17
+ else
18
+ @base_uri = "http#{'s' if tls_enable?}://#{hostname}:#{port}"
19
+ end
12
20
  api_version ||= "/v1.12"
13
21
  @docker_api_version = api_version
14
22
  configure_excon_globally
@@ -17,7 +25,7 @@ class Centurion::DockerViaApi
17
25
  def ps(options={})
18
26
  path = @docker_api_version + "/containers/json"
19
27
  path += "?all=1" if options[:all]
20
- response = Excon.get(@base_uri + path, tls_excon_arguments)
28
+ response = with_excon {|e| e.get(path: path)}
21
29
 
22
30
  raise unless response.status == 200
23
31
  JSON.load(response.body)
@@ -27,61 +35,64 @@ class Centurion::DockerViaApi
27
35
  repository = "#{image}:#{tag}"
28
36
  path = @docker_api_version + "/images/#{repository}/json"
29
37
 
30
- response = Excon.get(
31
- @base_uri + path,
32
- tls_excon_arguments.merge(headers: {'Accept' => 'application/json'})
33
- )
38
+ response = with_excon do |e|
39
+ e.get(
40
+ path: path,
41
+ headers: {'Accept' => 'application/json'}
42
+ )
43
+ end
34
44
  raise response.inspect unless response.status == 200
35
45
  JSON.load(response.body)
36
46
  end
37
47
 
38
48
  def remove_container(container_id)
39
49
  path = @docker_api_version + "/containers/#{container_id}"
40
- response = Excon.delete(
41
- @base_uri + path,
42
- tls_excon_arguments
43
- )
50
+ response = with_excon do |e|
51
+ e.delete(
52
+ path: path,
53
+ )
54
+ end
44
55
  raise response.inspect unless response.status == 204
45
56
  true
46
57
  end
47
58
 
48
59
  def stop_container(container_id, timeout = 30)
49
60
  path = @docker_api_version + "/containers/#{container_id}/stop?t=#{timeout}"
50
- response = Excon.post(
51
- @base_uri + path,
52
- tls_excon_arguments.merge(
61
+ response = with_excon do |e|
62
+ e.post(
63
+ path: path,
53
64
  # Wait for both the docker stop timeout AND the kill AND
54
65
  # potentially a very slow HTTP server.
55
66
  read_timeout: timeout + 120
56
67
  )
57
- )
68
+ end
58
69
  raise response.inspect unless response.status == 204
59
70
  true
60
71
  end
61
72
 
62
73
  def create_container(configuration, name = nil)
63
74
  path = @docker_api_version + "/containers/create"
64
- response = Excon.post(
65
- @base_uri + path,
66
- tls_excon_arguments.merge(
67
- query: name ? {name: "#{name}-#{SecureRandom.hex(7)}"} : nil,
75
+ response = with_excon do |e|
76
+ e.post(
77
+ path: path,
78
+ query: name ? "name=#{name}-#{SecureRandom.hex(7)}" : nil,
68
79
  body: configuration.to_json,
69
80
  headers: { "Content-Type" => "application/json" }
70
81
  )
71
- )
82
+ end
72
83
  raise response.inspect unless response.status == 201
73
84
  JSON.load(response.body)
74
85
  end
75
86
 
76
87
  def start_container(container_id, configuration)
77
88
  path = @docker_api_version + "/containers/#{container_id}/start"
78
- response = Excon.post(
79
- @base_uri + path,
80
- tls_excon_arguments.merge(
89
+ response = with_excon do |e|
90
+ e.post(
91
+ path: path,
81
92
  body: configuration.to_json,
82
93
  headers: { "Content-Type" => "application/json" }
83
94
  )
84
- )
95
+ end
85
96
  case response.status
86
97
  when 204
87
98
  true
@@ -94,14 +105,14 @@ class Centurion::DockerViaApi
94
105
 
95
106
  def restart_container(container_id, timeout = 30)
96
107
  path = @docker_api_version + "/containers/#{container_id}/restart?t=#{timeout}"
97
- response = Excon.post(
98
- @base_uri + path,
99
- tls_excon_arguments.merge(
108
+ response = with_excon do |e|
109
+ e.post(
110
+ path: path,
100
111
  # Wait for both the docker stop timeout AND the kill AND
101
112
  # potentially a very slow HTTP server.
102
113
  read_timeout: timeout + 120
103
114
  )
104
- )
115
+ end
105
116
  case response.status
106
117
  when 204
107
118
  true
@@ -116,10 +127,11 @@ class Centurion::DockerViaApi
116
127
 
117
128
  def inspect_container(container_id)
118
129
  path = @docker_api_version + "/containers/#{container_id}/json"
119
- response = Excon.get(
120
- @base_uri + path,
121
- tls_excon_arguments
122
- )
130
+ response = with_excon do |e|
131
+ e.get(
132
+ path: path,
133
+ )
134
+ end
123
135
  raise response.inspect unless response.status == 200
124
136
  JSON.load(response.body)
125
137
  end
@@ -172,4 +184,19 @@ class Centurion::DockerViaApi
172
184
  {}
173
185
  end
174
186
  end
187
+
188
+ def with_excon(&block)
189
+ if @ssh
190
+ with_excon_via_ssh(&block)
191
+ else
192
+ yield Excon.new(@base_uri, tls_excon_arguments)
193
+ end
194
+ end
195
+
196
+ def with_excon_via_ssh
197
+ Centurion::SSH.with_docker_socket(@base_uri, @ssh_user, @ssh_log_level) do |socket|
198
+ conn = Excon.new('unix:///', socket: socket)
199
+ yield conn
200
+ end
201
+ end
175
202
  end