centurion 1.8.10 → 1.9.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.
- checksums.yaml +4 -4
- data/CONTRIBUTORS.md +1 -0
- data/README.md +60 -22
- data/centurion.gemspec +2 -0
- data/lib/centurion/deploy_dsl.rb +19 -9
- data/lib/centurion/docker_server.rb +19 -9
- data/lib/centurion/docker_via_api.rb +60 -33
- data/lib/centurion/docker_via_cli.rb +42 -13
- data/lib/centurion/service.rb +10 -1
- data/lib/centurion/ssh.rb +40 -0
- data/lib/centurion/version.rb +1 -1
- data/spec/deploy_dsl_spec.rb +15 -0
- data/spec/docker_via_api_spec.rb +92 -167
- data/spec/docker_via_cli_spec.rb +57 -39
- data/spec/service_spec.rb +5 -1
- data/spec/spec_helper.rb +13 -0
- metadata +52 -23
@@ -1,34 +1,47 @@
|
|
1
1
|
require 'pty'
|
2
2
|
require_relative 'logging'
|
3
3
|
require_relative 'shell'
|
4
|
+
require 'centurion/ssh'
|
4
5
|
|
5
6
|
module Centurion; end
|
6
7
|
|
7
8
|
class Centurion::DockerViaCli
|
8
9
|
include Centurion::Logging
|
9
10
|
|
10
|
-
def initialize(hostname, port, docker_path,
|
11
|
-
|
11
|
+
def initialize(hostname, port, docker_path, connection_opts = {})
|
12
|
+
if connection_opts[:ssh]
|
13
|
+
@docker_host = hostname
|
14
|
+
else
|
15
|
+
@docker_host = "tcp://#{hostname}:#{port}"
|
16
|
+
end
|
12
17
|
@docker_path = docker_path
|
13
|
-
@
|
18
|
+
@connection_opts = connection_opts
|
14
19
|
end
|
15
20
|
|
16
21
|
def pull(image, tag='latest')
|
17
22
|
info 'Using CLI to pull'
|
18
|
-
|
23
|
+
connect do
|
24
|
+
Centurion::Shell.echo(build_command(:pull, "#{image}:#{tag}"))
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
28
|
def tail(container_id)
|
22
29
|
info "Tailing the logs on #{container_id}"
|
23
|
-
|
30
|
+
connect do
|
31
|
+
Centurion::Shell.echo(build_command(:logs, container_id))
|
32
|
+
end
|
24
33
|
end
|
25
34
|
|
26
35
|
def attach(container_id)
|
27
|
-
|
36
|
+
connect do
|
37
|
+
Centurion::Shell.echo(build_command(:attach, container_id))
|
38
|
+
end
|
28
39
|
end
|
29
40
|
|
30
41
|
def exec(container_id, commandline)
|
31
|
-
|
42
|
+
connect do
|
43
|
+
Centurion::Shell.echo(build_command(:exec, "#{container_id} #{commandline}"))
|
44
|
+
end
|
32
45
|
end
|
33
46
|
|
34
47
|
def exec_it(container_id, commandline)
|
@@ -36,7 +49,9 @@ class Centurion::DockerViaCli
|
|
36
49
|
# because docker exec returns the same exit code as the latest command executed on
|
37
50
|
# the shell, which causes an exception to be raised if the latest comand executed
|
38
51
|
# was unsuccessful when you exit the shell.
|
39
|
-
|
52
|
+
connect do
|
53
|
+
Centurion::Shell.echo(build_command(:exec, "-it #{container_id} #{commandline} || true"))
|
54
|
+
end
|
40
55
|
end
|
41
56
|
|
42
57
|
private
|
@@ -46,28 +61,29 @@ class Centurion::DockerViaCli
|
|
46
61
|
end
|
47
62
|
|
48
63
|
def all_tls_path_available?
|
49
|
-
self.class.tls_keys.all? { |key| @
|
64
|
+
self.class.tls_keys.all? { |key| @connection_opts.key?(key) }
|
50
65
|
end
|
51
66
|
|
52
67
|
def tls_parameters
|
53
|
-
return '' if @
|
68
|
+
return '' if @connection_opts.nil? || @connection_opts.empty?
|
54
69
|
|
55
70
|
tls_flags = ''
|
56
71
|
|
57
72
|
# --tlsverify can be set without passing the cacert, cert and key flags
|
58
|
-
if @
|
73
|
+
if @connection_opts[:tls] == true || all_tls_path_available?
|
59
74
|
tls_flags << ' --tlsverify'
|
60
75
|
end
|
61
76
|
|
62
77
|
self.class.tls_keys.each do |key|
|
63
|
-
tls_flags << " --#{key}=#{@
|
78
|
+
tls_flags << " --#{key}=#{@connection_opts[key]}" if @connection_opts[key]
|
64
79
|
end
|
65
80
|
|
66
81
|
tls_flags
|
67
82
|
end
|
68
83
|
|
69
84
|
def build_command(action, destination)
|
70
|
-
|
85
|
+
host = @socket ? "unix://#{@socket}" : @docker_host
|
86
|
+
command = "#{@docker_path} -H=#{host}"
|
71
87
|
command << tls_parameters || ''
|
72
88
|
command << case action
|
73
89
|
when :pull then ' pull '
|
@@ -78,4 +94,17 @@ class Centurion::DockerViaCli
|
|
78
94
|
command << destination
|
79
95
|
command
|
80
96
|
end
|
97
|
+
|
98
|
+
def connect
|
99
|
+
if @connection_opts[:ssh]
|
100
|
+
Centurion::SSH.with_docker_socket(@docker_host, @connection_opts[:ssh_user], @connection_opts[:ssh_log_level]) do |socket|
|
101
|
+
@socket = socket
|
102
|
+
ret = yield
|
103
|
+
@socket = nil
|
104
|
+
ret
|
105
|
+
end
|
106
|
+
else
|
107
|
+
yield
|
108
|
+
end
|
109
|
+
end
|
81
110
|
end
|
data/lib/centurion/service.rb
CHANGED
@@ -5,7 +5,7 @@ module Centurion
|
|
5
5
|
class Service
|
6
6
|
extend ::Capistrano::DSL
|
7
7
|
|
8
|
-
attr_accessor :command, :dns, :extra_hosts, :image, :name, :volumes, :port_bindings, :network_mode, :cap_adds, :cap_drops, :ipc_mode
|
8
|
+
attr_accessor :command, :dns, :extra_hosts, :image, :name, :volumes, :port_bindings, :network_mode, :cap_adds, :cap_drops, :ipc_mode, :security_opt
|
9
9
|
attr_reader :memory, :cpu_shares, :env_vars, :labels
|
10
10
|
|
11
11
|
def initialize(name)
|
@@ -16,6 +16,7 @@ module Centurion
|
|
16
16
|
@cap_adds = []
|
17
17
|
@cap_drops = []
|
18
18
|
@labels = {}
|
19
|
+
@security_opt = []
|
19
20
|
@network_mode = 'bridge'
|
20
21
|
end
|
21
22
|
|
@@ -38,6 +39,7 @@ module Centurion
|
|
38
39
|
s.memory = fetch(:memory, 0)
|
39
40
|
s.cpu_shares = fetch(:cpu_shares, 0)
|
40
41
|
s.ipc_mode = fetch(:ipc_mode, nil)
|
42
|
+
s.security_opt = fetch(:security_opt, [])
|
41
43
|
|
42
44
|
s.add_labels(fetch(:labels, {}))
|
43
45
|
s.add_env_vars(fetch(:env_vars, {}))
|
@@ -100,6 +102,10 @@ module Centurion
|
|
100
102
|
@ipc_mode = mode
|
101
103
|
end
|
102
104
|
|
105
|
+
def add_security_opt(seccomp)
|
106
|
+
@security_opt << seccomp
|
107
|
+
end
|
108
|
+
|
103
109
|
def build_config(server_hostname, &block)
|
104
110
|
container_config = {}.tap do |c|
|
105
111
|
c['Image'] = image
|
@@ -164,6 +170,9 @@ module Centurion
|
|
164
170
|
# Set ipc mode
|
165
171
|
host_config['IpcMode'] = ipc_mode if ipc_mode
|
166
172
|
|
173
|
+
# Set seccomp profile
|
174
|
+
host_config['SecurityOpt'] = security_opt unless security_opt.nil? || security_opt.empty?
|
175
|
+
|
167
176
|
# Restart Policy
|
168
177
|
if restart_policy
|
169
178
|
host_config['RestartPolicy'] = {}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
require 'sshkit'
|
3
|
+
|
4
|
+
module Centurion; end
|
5
|
+
|
6
|
+
module Centurion::SSH
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def with_docker_socket(hostname, user, log_level = nil)
|
10
|
+
log_level ||= Logger::WARN
|
11
|
+
|
12
|
+
with_sshkit(hostname, user) do
|
13
|
+
with_ssh do |ssh|
|
14
|
+
ssh.logger = Logger.new STDERR
|
15
|
+
ssh.logger.level = log_level
|
16
|
+
|
17
|
+
# Tempfile ensures permissions are 0600
|
18
|
+
local_socket_path_file = Tempfile.new('docker_forward')
|
19
|
+
local_socket_path = local_socket_path_file.path
|
20
|
+
ssh.forward.local_socket(local_socket_path, '/var/run/docker.sock')
|
21
|
+
|
22
|
+
t = Thread.new do
|
23
|
+
yield local_socket_path
|
24
|
+
end
|
25
|
+
|
26
|
+
ssh.loop { t.alive? }
|
27
|
+
ssh.forward.cancel_local_socket local_socket_path
|
28
|
+
local_socket_path_file.delete
|
29
|
+
t.value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_sshkit(hostname, user, &block)
|
35
|
+
uri = hostname
|
36
|
+
uri = "#{user}@#{uri}" if user
|
37
|
+
host = SSHKit::Host.new uri
|
38
|
+
SSHKit::Backend::Netssh.new(host, &block).run
|
39
|
+
end
|
40
|
+
end
|
data/lib/centurion/version.rb
CHANGED
data/spec/deploy_dsl_spec.rb
CHANGED
@@ -210,4 +210,19 @@ describe Centurion::DeployDSL do
|
|
210
210
|
DeployDSLTest.set(:image, 'charlemagne')
|
211
211
|
expect(DeployDSLTest.defined_service.image).to eq('charlemagne:roland')
|
212
212
|
end
|
213
|
+
|
214
|
+
it 'configures ssh connections with no user' do
|
215
|
+
DeployDSLTest.set(:ssh, true)
|
216
|
+
DeployDSLTest.set(:hosts, %w{ host1 })
|
217
|
+
|
218
|
+
DeployDSLTest.on_each_docker_host { |h| expect(h.describe).to eq("host1 via SSH") }
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'configures ssh connections with a user' do
|
222
|
+
DeployDSLTest.set(:ssh, true)
|
223
|
+
DeployDSLTest.set(:ssh_user, 'myuser')
|
224
|
+
DeployDSLTest.set(:hosts, %w{ host1 })
|
225
|
+
|
226
|
+
DeployDSLTest.on_each_docker_host { |h| expect(h.describe).to eq("host1 via SSH user myuser") }
|
227
|
+
end
|
213
228
|
end
|
data/spec/docker_via_api_spec.rb
CHANGED
@@ -3,249 +3,174 @@ 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_version) { '1.12' }
|
8
8
|
let(:json_string) { '[{ "Hello": "World" }]' }
|
9
9
|
let(:json_value) { JSON.load(json_string) }
|
10
10
|
|
11
|
-
|
12
|
-
let(:excon_uri) { "http://#{hostname}:#{port}/" }
|
13
|
-
let(:api) { Centurion::DockerViaApi.new(hostname, port) }
|
14
|
-
|
11
|
+
shared_examples "docker API" do
|
15
12
|
it 'lists processes' do
|
16
|
-
|
17
|
-
with(excon_uri + "v1.12" + "/containers/json", {}).
|
18
|
-
and_return(double(body: json_string, status: 200))
|
13
|
+
Excon.stub(base_req.merge(method: :get, path: '/v1.12/containers/json'), {body: json_string, status: 200})
|
19
14
|
expect(api.ps).to eq(json_value)
|
20
15
|
end
|
21
16
|
|
22
17
|
it 'lists all processes' do
|
23
|
-
|
24
|
-
with(excon_uri + "v1.12" + "/containers/json?all=1", {}).
|
25
|
-
and_return(double(body: json_string, status: 200))
|
18
|
+
Excon.stub(base_req.merge(method: :get, path: '/v1.12/containers/json?all=1'), {body: json_string, status: 200})
|
26
19
|
expect(api.ps(all: true)).to eq(json_value)
|
27
20
|
end
|
28
21
|
|
29
22
|
it 'creates a container' do
|
30
|
-
configuration_as_json =
|
23
|
+
configuration_as_json = 'body'
|
31
24
|
configuration = double(to_json: configuration_as_json)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
Excon.stub(base_req.merge(
|
26
|
+
method: :post,
|
27
|
+
path: '/v1.12/containers/create',
|
28
|
+
body: configuration_as_json,
|
29
|
+
headers: {'Content-Type' => 'application/json'}
|
30
|
+
),
|
31
|
+
{body: json_string, status: 201})
|
38
32
|
api.create_container(configuration)
|
39
33
|
end
|
40
34
|
|
41
35
|
it 'creates a container with a name' do
|
42
|
-
configuration_as_json =
|
36
|
+
configuration_as_json = 'body'
|
43
37
|
configuration = double(to_json: configuration_as_json)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
38
|
+
Excon.stub(base_req.merge(
|
39
|
+
method: :post,
|
40
|
+
path: '/v1.12/containers/create',
|
41
|
+
query: /^name=app1-[a-f0-9]+$/,
|
42
|
+
body: configuration_as_json,
|
43
|
+
headers: {'Content-Type' => 'application/json'}
|
44
|
+
),
|
45
|
+
{body: json_string, status: 201})
|
50
46
|
api.create_container(configuration, 'app1')
|
51
47
|
end
|
52
48
|
|
53
49
|
it 'starts a container' do
|
54
|
-
configuration_as_json =
|
50
|
+
configuration_as_json = 'body'
|
55
51
|
configuration = double(to_json: configuration_as_json)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
Excon.stub(base_req.merge(
|
53
|
+
method: :post,
|
54
|
+
path: '/v1.12/containers/12345/start',
|
55
|
+
body: configuration_as_json,
|
56
|
+
headers: {'Content-Type' => 'application/json'}
|
57
|
+
),
|
58
|
+
{body: json_string, status: 204})
|
61
59
|
api.start_container('12345', configuration)
|
62
60
|
end
|
63
61
|
|
64
62
|
it 'stops a container' do
|
65
|
-
|
66
|
-
with(excon_uri + "v1.12" + "/containers/12345/stop?t=300", {read_timeout: 420}).
|
67
|
-
and_return(double(status: 204))
|
63
|
+
Excon.stub(base_req.merge(method: :post, path: '/v1.12/containers/12345/stop?t=300', read_timeout: 420), {status: 204})
|
68
64
|
api.stop_container('12345', 300)
|
69
65
|
end
|
70
66
|
|
71
67
|
it 'stops a container with a custom timeout' do
|
72
|
-
|
73
|
-
with(excon_uri + "v1.12" + "/containers/12345/stop?t=30", {read_timeout: 150}).
|
74
|
-
and_return(double(status: 204))
|
68
|
+
Excon.stub(base_req.merge(method: :post, path: '/v1.12/containers/12345/stop?t=30', read_timeout: 150), {status: 204})
|
75
69
|
api.stop_container('12345')
|
76
70
|
end
|
77
71
|
|
78
72
|
it 'restarts a container' do
|
79
|
-
|
80
|
-
with(excon_uri + "v1.12" + "/containers/12345/restart?t=30",
|
81
|
-
{read_timeout: 150}).
|
82
|
-
and_return(double(body: json_string, status: 204))
|
73
|
+
Excon.stub(base_req.merge(method: :post, path: '/v1.12/containers/12345/restart?t=30', read_timeout: 150), {status: 204})
|
83
74
|
api.restart_container('12345')
|
84
75
|
end
|
85
76
|
|
86
77
|
it 'restarts a container with a custom timeout' do
|
87
|
-
|
88
|
-
with(excon_uri + "v1.12" + "/containers/12345/restart?t=300", {:read_timeout=>420}).
|
89
|
-
and_return(double(body: json_string, status: 204))
|
78
|
+
Excon.stub(base_req.merge(method: :post, path: '/v1.12/containers/12345/restart?t=300', read_timeout: 420), {status: 204})
|
90
79
|
api.restart_container('12345', 300)
|
91
80
|
end
|
92
81
|
|
93
82
|
it 'inspects a container' do
|
94
|
-
|
95
|
-
with(excon_uri + "v1.12" + "/containers/12345/json", {}).
|
96
|
-
and_return(double(body: json_string, status: 200))
|
83
|
+
Excon.stub(base_req.merge(method: :get, path: '/v1.12/containers/12345/json'), {body: json_string, status: 200})
|
97
84
|
expect(api.inspect_container('12345')).to eq(json_value)
|
98
85
|
end
|
99
86
|
|
100
87
|
it 'removes a container' do
|
101
|
-
|
102
|
-
with(excon_uri + "v1.12" + "/containers/12345", {}).
|
103
|
-
and_return(double(status: 204))
|
88
|
+
Excon.stub(base_req.merge(method: :delete, path: '/v1.12/containers/12345'), {body: json_string, status: 204})
|
104
89
|
expect(api.remove_container('12345')).to eq(true)
|
105
90
|
end
|
106
91
|
|
107
92
|
it 'inspects an image' do
|
108
|
-
|
109
|
-
with(excon_uri + "v1.12" + "/images/foo:bar/json",
|
110
|
-
headers: {'Accept' => 'application/json'}).
|
111
|
-
and_return(double(body: json_string, status: 200))
|
93
|
+
Excon.stub(base_req.merge(method: :get, path: '/v1.12/images/foo:bar/json', headers: {'Accept' => 'application/json'}), {body: json_string, status: 200})
|
112
94
|
expect(api.inspect_image('foo', 'bar')).to eq(json_value)
|
113
95
|
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'without TLS certificates' do
|
99
|
+
let(:api) { Centurion::DockerViaApi.new(hostname, port) }
|
100
|
+
let(:base_req) { {hostname: hostname, port: port} }
|
114
101
|
|
102
|
+
it_behaves_like 'docker API'
|
115
103
|
end
|
116
104
|
|
117
105
|
context 'with TLS certificates' do
|
118
|
-
let(:excon_uri) { "https://#{hostname}:#{port}/" }
|
119
106
|
let(:tls_args) { { tls: true, tlscacert: '/certs/ca.pem',
|
120
107
|
tlscert: '/certs/cert.pem', tlskey: '/certs/key.pem' } }
|
108
|
+
let(:base_req) { {
|
109
|
+
hostname: hostname,
|
110
|
+
port: port,
|
111
|
+
client_cert: '/certs/cert.pem',
|
112
|
+
client_key: '/certs/key.pem',
|
113
|
+
} }
|
121
114
|
let(:api) { Centurion::DockerViaApi.new(hostname, port, tls_args) }
|
122
115
|
|
123
|
-
|
124
|
-
|
125
|
-
with(excon_uri + "v1.12" + "/containers/json",
|
126
|
-
client_cert: '/certs/cert.pem',
|
127
|
-
client_key: '/certs/key.pem').
|
128
|
-
and_return(double(body: json_string, status: 200))
|
129
|
-
expect(api.ps).to eq(json_value)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'lists all processes' do
|
133
|
-
expect(Excon).to receive(:get).
|
134
|
-
with(excon_uri + "v1.12" + "/containers/json?all=1",
|
135
|
-
client_cert: '/certs/cert.pem',
|
136
|
-
client_key: '/certs/key.pem').
|
137
|
-
and_return(double(body: json_string, status: 200))
|
138
|
-
expect(api.ps(all: true)).to eq(json_value)
|
139
|
-
end
|
116
|
+
it_behaves_like 'docker API'
|
117
|
+
end
|
140
118
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
119
|
+
context 'with default TLS certificates' do
|
120
|
+
let(:tls_args) { { tls: true } }
|
121
|
+
let(:base_req) { {
|
122
|
+
hostname: hostname,
|
123
|
+
port: port,
|
124
|
+
client_cert: File.expand_path('~/.docker/cert.pem'),
|
125
|
+
client_key: File.expand_path('~/.docker/key.pem'),
|
126
|
+
} }
|
127
|
+
let(:api) { Centurion::DockerViaApi.new(hostname, port, tls_args) }
|
150
128
|
|
151
|
-
|
152
|
-
|
153
|
-
configuration = double(to_json: configuration_as_json)
|
154
|
-
expect(Excon).to receive(:post).
|
155
|
-
with(excon_uri + "v1.12" + "/containers/create",
|
156
|
-
client_cert: '/certs/cert.pem',
|
157
|
-
client_key: '/certs/key.pem',
|
158
|
-
query: nil,
|
159
|
-
body: configuration_as_json,
|
160
|
-
headers: {'Content-Type' => 'application/json'}).
|
161
|
-
and_return(double(body: json_string, status: 201))
|
162
|
-
api.create_container(configuration)
|
163
|
-
end
|
129
|
+
it_behaves_like 'docker API'
|
130
|
+
end
|
164
131
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
132
|
+
context 'with a SSH connection' do
|
133
|
+
let(:hostname) { 'hostname' }
|
134
|
+
let(:port) { nil }
|
135
|
+
let(:ssh_user) { 'myuser' }
|
136
|
+
let(:ssh_log_level) { nil }
|
137
|
+
let(:base_req) { {
|
138
|
+
socket: '/tmp/socket/path'
|
139
|
+
} }
|
140
|
+
let(:api) { Centurion::DockerViaApi.new(hostname, port, params) }
|
141
|
+
let(:params) do
|
142
|
+
p = { ssh: true}
|
143
|
+
p[:ssh_user] = ssh_user if ssh_user
|
144
|
+
p[:ssh_log_level] = ssh_log_level if ssh_log_level
|
145
|
+
p
|
176
146
|
end
|
177
147
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
client_key: '/certs/key.pem',
|
183
|
-
read_timeout: 420).
|
184
|
-
and_return(double(status: 204))
|
185
|
-
api.stop_container('12345', 300)
|
186
|
-
end
|
148
|
+
context 'with no log level' do
|
149
|
+
before do
|
150
|
+
expect(Centurion::SSH).to receive(:with_docker_socket).with(hostname, ssh_user, nil).and_yield('/tmp/socket/path')
|
151
|
+
end
|
187
152
|
|
188
|
-
|
189
|
-
expect(Excon).to receive(:post).
|
190
|
-
with(excon_uri + "v1.12" + "/containers/12345/stop?t=30",
|
191
|
-
client_cert: '/certs/cert.pem',
|
192
|
-
client_key: '/certs/key.pem',
|
193
|
-
read_timeout: 150).
|
194
|
-
and_return(double(status: 204))
|
195
|
-
api.stop_container('12345')
|
153
|
+
it_behaves_like 'docker API'
|
196
154
|
end
|
197
155
|
|
198
|
-
|
199
|
-
|
200
|
-
with(excon_uri + "v1.12" + "/containers/12345/restart?t=30",
|
201
|
-
client_cert: '/certs/cert.pem',
|
202
|
-
client_key: '/certs/key.pem',
|
203
|
-
read_timeout: 150).
|
204
|
-
and_return(double(body: json_string, status: 204))
|
205
|
-
api.restart_container('12345')
|
206
|
-
end
|
156
|
+
context 'with no user' do
|
157
|
+
let(:ssh_user) { nil }
|
207
158
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
client_cert: '/certs/cert.pem',
|
212
|
-
client_key: '/certs/key.pem',
|
213
|
-
read_timeout: 420).
|
214
|
-
and_return(double(body: json_string, status: 204))
|
215
|
-
api.restart_container('12345', 300)
|
216
|
-
end
|
159
|
+
before do
|
160
|
+
expect(Centurion::SSH).to receive(:with_docker_socket).with(hostname, nil, nil).and_yield('/tmp/socket/path')
|
161
|
+
end
|
217
162
|
|
218
|
-
|
219
|
-
expect(Excon).to receive(:get).
|
220
|
-
with(excon_uri + "v1.12" + "/containers/12345/json",
|
221
|
-
client_cert: '/certs/cert.pem',
|
222
|
-
client_key: '/certs/key.pem').
|
223
|
-
and_return(double(body: json_string, status: 200))
|
224
|
-
expect(api.inspect_container('12345')).to eq(json_value)
|
163
|
+
it_behaves_like 'docker API'
|
225
164
|
end
|
226
165
|
|
227
|
-
|
228
|
-
|
229
|
-
with(excon_uri + "v1.12" + "/containers/12345",
|
230
|
-
client_cert: '/certs/cert.pem',
|
231
|
-
client_key: '/certs/key.pem').
|
232
|
-
and_return(double(status: 204))
|
233
|
-
expect(api.remove_container('12345')).to eq(true)
|
234
|
-
end
|
235
|
-
end
|
166
|
+
context 'with a log level set' do
|
167
|
+
let(:ssh_log_level) { Logger::DEBUG }
|
236
168
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
let(:api) { Centurion::DockerViaApi.new(hostname, port, tls_args) }
|
169
|
+
before do
|
170
|
+
expect(Centurion::SSH).to receive(:with_docker_socket).with(hostname, ssh_user, Logger::DEBUG).and_yield('/tmp/socket/path')
|
171
|
+
end
|
241
172
|
|
242
|
-
|
243
|
-
expect(Excon).to receive(:get).
|
244
|
-
with(excon_uri + "v1.12" + "/containers/json",
|
245
|
-
client_cert: File.expand_path('~/.docker/cert.pem'),
|
246
|
-
client_key: File.expand_path('~/.docker/key.pem')).
|
247
|
-
and_return(double(body: json_string, status: 200))
|
248
|
-
expect(api.ps).to eq(json_value)
|
173
|
+
it_behaves_like 'docker API'
|
249
174
|
end
|
250
175
|
end
|
251
176
|
end
|