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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2c6f926be1ddd326fc9850e14dcb146ce3ff3f5d
4
- data.tar.gz: e8a636cb1fb78e910302806e64bd709bc94d3cc1
3
+ metadata.gz: a106532b6fa395835377aed7d7e8952db0f78552
4
+ data.tar.gz: 3f8998e4a21485428004f1d93273eff5639d1cb3
5
5
  SHA512:
6
- metadata.gz: e4538affcb8653d66726425196d8473372b0901c2320f19ffeacc5539232b2dfade9809bb6c4db5c7e3b7debce6767df9e5068ee98af35368234af3ae7d5e094
7
- data.tar.gz: 790d6e055e0a754a37097a2fae755e722a3c0295b07ef61f6e8e3de9d3394b4b57de1baac94d178abcf85b47be0ddbe4b81f2ee86a9f7f2760f1c19a62c62583
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
- read_timeout = execute_timeout(options)
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
- Chef::Log.debug("Grabbing exit status from #{container_name}")
83
- # Capture exit code
84
- exit_status = @container.wait(read_timeout)
85
- attach_thread.join
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
- Chef::Log.debug("Execute complete: status #{exit_status['StatusCode']}")
93
- DockerResult.new(command, options, stdout, stderr, exit_status['StatusCode'])
94
- ensure
95
- Thread.kill(attach_thread) if attach_thread.alive?
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
- # Copy of container.attach with timeout support
186
- def attach_with_timeout(container, options = {}, read_timeout, &block)
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.post(
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
- [msgs.stdout_messages, msgs.stderr_messages]
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
@@ -1,3 +1,3 @@
1
1
  module ChefMetalDocker
2
- VERSION = '0.1'
2
+ VERSION = '0.1.1'
3
3
  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: '0.1'
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 00:00:00.000000000 Z
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