chef-metal-docker 0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef_metal_docker/docker_transport.rb +122 -65
- data/lib/chef_metal_docker/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a106532b6fa395835377aed7d7e8952db0f78552
|
4
|
+
data.tar.gz: 3f8998e4a21485428004f1d93273eff5639d1cb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1d1150a775d7b98c59004b3f365c35aa08a31cbb3241cd5640e1cd14002ce4390f9f90ab21a2a8743e668bd8b0d48384ac22dc5a17457ddd5a0cc64c6972e0b
|
7
|
+
data.tar.gz: 45407348ba54a5d1ebefc101bd490581261a6e2f7b9957cf01a36bf3af7c8d3f5ea643c8625a79e1cc54b7ff7eaad1f521047ee681e4bcf27da687ed0afc8554
|
@@ -4,6 +4,8 @@ require 'archive/tar/minitar'
|
|
4
4
|
require 'shellwords'
|
5
5
|
require 'uri'
|
6
6
|
require 'socket'
|
7
|
+
require 'em-proxy'
|
8
|
+
require 'mixlib/shellout'
|
7
9
|
|
8
10
|
module ChefMetalDocker
|
9
11
|
class DockerTransport < ChefMetal::Transport
|
@@ -15,6 +17,8 @@ module ChefMetalDocker
|
|
15
17
|
@connection = connection
|
16
18
|
end
|
17
19
|
|
20
|
+
include Chef::Mixin::ShellOut
|
21
|
+
|
18
22
|
attr_reader :container_name
|
19
23
|
attr_reader :repository_name
|
20
24
|
attr_reader :image
|
@@ -34,70 +38,26 @@ module ChefMetalDocker
|
|
34
38
|
Chef::Log.debug("deleted /containers/#{container_name}")
|
35
39
|
rescue Docker::Error::NotFoundError
|
36
40
|
end
|
37
|
-
Chef::Log.debug("Creating #{container_name} from #{repository_name}:latest")
|
38
|
-
@container = Docker::Container.create({
|
39
|
-
'name' => container_name,
|
40
|
-
'Image' => "#{repository_name}:latest",
|
41
|
-
'Cmd' => (command.is_a?(String) ? Shellwords.shellsplit(command) : command),
|
42
|
-
'AttachStdout' => true,
|
43
|
-
'AttachStderr' => true,
|
44
|
-
'TTY' => false
|
45
|
-
}, connection)
|
46
41
|
|
47
|
-
|
48
|
-
read_timeout = nil if read_timeout == 0
|
49
|
-
Docker.options[:read_timeout] = read_timeout
|
50
|
-
begin
|
51
|
-
stdout = ''
|
52
|
-
stderr = ''
|
53
|
-
|
54
|
-
attach_thread = Thread.new do
|
55
|
-
Chef::Log.debug("Setting timeout to 15 minutes")
|
56
|
-
Docker.options[:read_timeout] = (15 * 60)
|
57
|
-
|
58
|
-
Chef::Log.debug("Attaching to #{container_name}")
|
59
|
-
# Capture stdout / stderr
|
60
|
-
@container.attach do |type, str|
|
61
|
-
case type
|
62
|
-
when :stdout
|
63
|
-
stdout << str
|
64
|
-
stream_chunk(options, stdout, nil)
|
65
|
-
when :stderr
|
66
|
-
stderr << str
|
67
|
-
stream_chunk(options, nil, stderr)
|
68
|
-
else
|
69
|
-
raise "unexpected message type #{type}"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
Chef::Log.debug("Removing temporary read timeout")
|
74
|
-
Docker.options.delete(:read_timeout)
|
75
|
-
end
|
76
|
-
|
77
|
-
begin
|
78
|
-
Chef::Log.debug("Starting #{container_name}")
|
79
|
-
# Start the container
|
80
|
-
@container.start
|
42
|
+
command = Shellwords.split(command) if command.is_a?(String)
|
81
43
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
44
|
+
# TODO shell_out has no way to live stream stderr???
|
45
|
+
live_stream = nil
|
46
|
+
live_stream = STDOUT if options[:stream]
|
47
|
+
live_stream = options[:stream_stdout] if options[:stream_stdout]
|
48
|
+
cmd = Mixlib::ShellOut.new(Shellwords.join(['docker', 'run', '--name', container_name, "#{repository_name}:latest" ] + command),
|
49
|
+
:live_stream => live_stream, :timeout => execute_timeout(options))
|
50
|
+
cmd.run_command
|
86
51
|
|
87
|
-
unless options[:read_only]
|
88
|
-
Chef::Log.debug("Committing #{container_name} as #{repository_name}")
|
89
|
-
@image = @container.commit('repo' => repository_name)
|
90
|
-
end
|
91
52
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
ensure
|
98
|
-
Chef::Log.debug("Removing temporary read timeout")
|
99
|
-
Docker.options.delete(:read_timeout)
|
53
|
+
unless options[:read_only]
|
54
|
+
Chef::Log.debug("Committing #{container_name} as #{repository_name}")
|
55
|
+
container = Docker::Container.get(container_name)
|
56
|
+
@image = container.commit('repo' => repository_name)
|
100
57
|
end
|
58
|
+
|
59
|
+
Chef::Log.debug("Execute complete: status #{cmd.exitstatus}")
|
60
|
+
cmd
|
101
61
|
end
|
102
62
|
|
103
63
|
def read_file(path)
|
@@ -162,10 +122,20 @@ module ChefMetalDocker
|
|
162
122
|
# The host is already open to the container. Just find out its address and return it!
|
163
123
|
uri = URI(url)
|
164
124
|
host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
|
165
|
-
if host == '127.0.0.1'
|
125
|
+
if host == '127.0.0.1' || host == '[::1]'
|
166
126
|
result = execute('ip route ls', :read_only => true)
|
167
127
|
if result.stdout =~ /default via (\S+)/
|
168
128
|
uri.host = $1
|
129
|
+
|
130
|
+
if !@proxy_thread
|
131
|
+
# Listen to docker instances only, and forward to localhost
|
132
|
+
@proxy_thread = Thread.new do
|
133
|
+
Proxy.start(:host => uri.host, :port => uri.port, :debug => true) do |conn|
|
134
|
+
conn.server :srv, :host => host, :port => uri.port
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
169
139
|
return uri.to_s
|
170
140
|
else
|
171
141
|
raise "Cannot forward port: ip route ls did not show default in expected format.\nSTDOUT: #{result.stdout}"
|
@@ -175,6 +145,7 @@ module ChefMetalDocker
|
|
175
145
|
end
|
176
146
|
|
177
147
|
def disconnect
|
148
|
+
@proxy_thread.kill if @proxy_thread
|
178
149
|
end
|
179
150
|
|
180
151
|
def available?
|
@@ -182,20 +153,83 @@ module ChefMetalDocker
|
|
182
153
|
|
183
154
|
private
|
184
155
|
|
185
|
-
|
186
|
-
|
156
|
+
def old_execute
|
157
|
+
Chef::Log.debug("Creating #{container_name} from #{repository_name}:latest")
|
158
|
+
@container = Docker::Container.create({
|
159
|
+
'name' => container_name,
|
160
|
+
'Image' => "#{repository_name}:latest",
|
161
|
+
'Cmd' => (command.is_a?(String) ? Shellwords.shellsplit(command) : command),
|
162
|
+
'AttachStdout' => true,
|
163
|
+
'AttachStderr' => true,
|
164
|
+
'TTY' => false
|
165
|
+
}, connection)
|
166
|
+
|
167
|
+
Docker.options[:read_timeout] = read_timeout
|
168
|
+
begin
|
169
|
+
stdout = ''
|
170
|
+
stderr = ''
|
171
|
+
|
172
|
+
Chef::Log.debug("Attaching to #{container_name}")
|
173
|
+
# Capture stdout / stderr
|
174
|
+
excon, attach_datum = attach_with_timeout(@container, read_timeout) do |type, str|
|
175
|
+
puts "got something"
|
176
|
+
case type
|
177
|
+
when :stdout
|
178
|
+
stdout << str
|
179
|
+
stream_chunk(options, stdout, nil)
|
180
|
+
when :stderr
|
181
|
+
stderr << str
|
182
|
+
stream_chunk(options, nil, stderr)
|
183
|
+
else
|
184
|
+
raise "unexpected message type #{type}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
begin
|
189
|
+
Chef::Log.debug("Starting #{container_name}")
|
190
|
+
# Start the container
|
191
|
+
@container.start
|
192
|
+
|
193
|
+
Chef::Log.debug("Grabbing exit status from #{container_name}")
|
194
|
+
# Capture exit code
|
195
|
+
exit_status = @container.wait(read_timeout)
|
196
|
+
|
197
|
+
Chef::Log.debug("Waiting for attach to complete ...")
|
198
|
+
wait_for_attach(excon, attach_datum)
|
199
|
+
|
200
|
+
Chef::Log.debug("Execute complete: status #{exit_status['StatusCode']}")
|
201
|
+
DockerResult.new(command, options, stdout, stderr, exit_status['StatusCode'])
|
202
|
+
rescue
|
203
|
+
# Make sure we close off outstanding connections if we exit the method
|
204
|
+
excon.reset
|
205
|
+
raise
|
206
|
+
end
|
207
|
+
ensure
|
208
|
+
Chef::Log.debug("Removing temporary read timeout")
|
209
|
+
Docker.options.delete(:read_timeout)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Copy of container.attach with timeout support and pipeline
|
214
|
+
def attach_with_timeout(container, read_timeout, options = {}, &block)
|
187
215
|
opts = {
|
188
216
|
:stream => true, :stdout => true, :stderr => true
|
189
217
|
}.merge(options)
|
190
218
|
# Creates list to store stdout and stderr messages
|
191
219
|
msgs = Docker::Messages.new
|
192
|
-
connection.
|
220
|
+
connection.start_request(
|
221
|
+
:post,
|
193
222
|
"/containers/#{container.id}/attach",
|
194
223
|
opts,
|
195
224
|
:response_block => attach_for(block, msgs),
|
196
|
-
:read_timeout => read_timeout
|
225
|
+
:read_timeout => read_timeout,
|
226
|
+
:pipeline => true,
|
227
|
+
:persistent => true
|
197
228
|
)
|
198
|
-
|
229
|
+
end
|
230
|
+
|
231
|
+
def wait_for_attach(excon, datum)
|
232
|
+
Excon::Response.new(excon.send(:response, datum)[:response])
|
199
233
|
end
|
200
234
|
|
201
235
|
# Method that takes chunks and calls the attached block for each mux'd message
|
@@ -242,3 +276,26 @@ module ChefMetalDocker
|
|
242
276
|
end
|
243
277
|
end
|
244
278
|
end
|
279
|
+
|
280
|
+
class Docker::Connection
|
281
|
+
def start_request(method, *args, &block)
|
282
|
+
request = compile_request_params(method, *args, &block)
|
283
|
+
if Docker.logger
|
284
|
+
Docker.logger.debug(
|
285
|
+
[request[:method], request[:path], request[:query], request[:body]]
|
286
|
+
)
|
287
|
+
end
|
288
|
+
excon = resource
|
289
|
+
[ excon, excon.request(request) ]
|
290
|
+
rescue Excon::Errors::BadRequest => ex
|
291
|
+
raise ClientError, ex.message
|
292
|
+
rescue Excon::Errors::Unauthorized => ex
|
293
|
+
raise UnauthorizedError, ex.message
|
294
|
+
rescue Excon::Errors::NotFound => ex
|
295
|
+
raise NotFoundError, ex.message
|
296
|
+
rescue Excon::Errors::InternalServerError => ex
|
297
|
+
raise ServerError, ex.message
|
298
|
+
rescue Excon::Errors::Timeout => ex
|
299
|
+
raise TimeoutError, ex.message
|
300
|
+
end
|
301
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-metal-docker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Duffield
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: em-proxy
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|