chef-metal-docker 0.1 → 0.1.1
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/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
|