docker-cake 0.1 → 0.2

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: c65060c27c01fce55231395ee5ad9200948a4be7
4
- data.tar.gz: e9fc17acf691b35fbb212bb18fcd74b50d908308
3
+ metadata.gz: bb308277d72c9e12243d29048577958bcb3143fb
4
+ data.tar.gz: 0bebde5d78dddf58e42f16a86266b05fecf0f030
5
5
  SHA512:
6
- metadata.gz: da38d0dffb2c6e0eee7de50ec7f2f870e539878f67f65377da781011ad8df84985b96d6ec32e1029740e21dd2b1512985438be6fc8f9cc11b49e1c0986eee33b
7
- data.tar.gz: 31857508135384c7a536cb8ce8dc304d26d943916741827d227f81adc0cfdb069703864725230dac4d0b2f33ae7c39752ec0e124834730d5121853850d36e200
6
+ metadata.gz: 46f7c1023778cbb0d8aa626d6df4676f700d5b66ff55c0065f4f0fc2158f1efc4b3dd1410e9cb2bbd4c581e1dab80f9b1c7e72ba7c4fe0ee7f04564bcba61268
7
+ data.tar.gz: bc7334825b0e6c7c4a59ef374af115bfc76f80bc34d4bdc52fceebfba26202ec06a3e6b4525b7c8a64aebd2d19a1357a17d09408c011264608eb070968e6adac
data/docker-cake.gemspec CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |gem|
2
2
  gem.specification_version = 3
3
3
 
4
4
  gem.name = 'docker-cake'
5
- gem.version = "0.1"
5
+ gem.version = "0.2"
6
6
  gem.authors = ["Pavel Evstigneev"]
7
7
  gem.email = ["pavel.evst@gmail.com"]
8
8
  gem.license = 'MIT'
data/lib/docker_cake.rb CHANGED
@@ -7,7 +7,7 @@ class DockerCake
7
7
  attr_accessor :registry
8
8
 
9
9
  def initialize(url: nil, user: nil, password: nil)
10
- @registry ||= RegistryApiClient.new(user: user, password: password)
10
+ @registry ||= RegistryApiClient.new(user: user, password: password, url: url)
11
11
  end
12
12
 
13
13
  def repo_info(name, tag = 'latest')
@@ -17,10 +17,19 @@ class DockerCake
17
17
 
18
18
  def compare_versions(repo_name, filter: /.+/, max: 10)
19
19
  tags = registry.tags(repo_name, false)['tags']
20
+
21
+ if ENV['DEBUG']
22
+ puts "Found tags: #{tags.join(", ")}"
23
+ end
24
+
20
25
  tags.select! {|t| t =~ filter}
21
26
 
22
27
  selected_tags = tags.last(max)
23
28
 
29
+ if ENV['DEBUG']
30
+ puts "Analyzing #{selected_tags.size} tags: #{selected_tags.join(", ")}..."
31
+ end
32
+
24
33
  manifests = {}
25
34
  procs = selected_tags.map do |tag|
26
35
  lambda { manifests[tag] = registry.manifest_layers(repo_name, tag) }
@@ -1,4 +1,5 @@
1
1
  require 'optparse'
2
+ require 'socket'
2
3
  require_relative '../docker_cake'
3
4
 
4
5
  options = {}
@@ -49,13 +50,48 @@ if !repo || repo == ''
49
50
  exit(1)
50
51
  end
51
52
 
52
- connect_options = {user: options[:user], password: options[:password]}
53
- connect_options[:url] = options[:url] if options[:url]
53
+ connect_options = {
54
+ user: options[:user],
55
+ password: options[:password],
56
+ url: options[:url]
57
+ }
54
58
 
55
- if options[:layers]
56
- DockerCake.new(connect_options).repo_info(repo, tag || 'latest')
57
- else
58
- opts = {}
59
- opts[:max] = options[:max].to_i if options[:max]
60
- DockerCake.new(connect_options).compare_versions(repo, opts)
61
- end
59
+ begin
60
+ if options[:layers]
61
+ DockerCake.new(connect_options).repo_info(repo, tag || 'latest')
62
+ else
63
+ opts = {}
64
+ opts[:max] = options[:max].to_i if options[:max]
65
+ DockerCake.new(connect_options).compare_versions(repo, opts)
66
+ end
67
+ rescue RegistryApiClient::RegistryAuthenticationException => e
68
+ puts "Permission denied, make sure username and password are correct"
69
+ puts "Server response: #{e.message}"
70
+ puts "Example:"
71
+ puts " docker-cake bob/private_repo -u bob -p ***"
72
+ exit 1
73
+ rescue RegistryApiClient::HTTP::NotFound => e
74
+ if options[:layers]
75
+ puts "Repository or tag not found"
76
+ else
77
+ puts "Repository not found"
78
+ end
79
+ puts "Example:"
80
+ puts " docker-cake library/ruby"
81
+ exit 1
82
+ rescue RegistryApiClient::JsonError => error
83
+ message = error.message.size > 300 ? error.message[0..300] + "..." : error.message
84
+ puts "Error parsing JSON response: #{message} (#{(error.parent || error).class})"
85
+ body = error.response.size > 300 ? error.response[0..300] + "..." : error.response
86
+ puts "Server response body: #{body}"
87
+ if ENV['DEBUG']
88
+ headers = error.response.headers.to_a.map {|pair| pair.join(": ")}.join("\n ")
89
+ puts "Headers:\n #{headers}"
90
+ end
91
+ exit 1
92
+ rescue SocketError => e
93
+ puts "Can not connect to registery:"
94
+ puts "#{e.class}: #{e.message}"
95
+ puts e.backtrace if ENV['DEBUG']
96
+ exit 1
97
+ end
@@ -26,6 +26,16 @@ class RegistryApiClient
26
26
  class InvalidMethod < Exception
27
27
  end
28
28
 
29
+ class JsonError < Exception
30
+ attr_reader :response
31
+ attr_reader :parent
32
+ def initialize(message, response = nil)
33
+ super(message)
34
+ @parent = message if message.is_a?(Exception)
35
+ @response = response
36
+ end
37
+ end
38
+
29
39
  class Waiter
30
40
  def initialize
31
41
  @queue = Queue.new
@@ -70,6 +80,7 @@ class RegistryApiClient
70
80
  # @option options [#to_s] :user User name for basic authentication
71
81
  # @option options [#to_s] :password Password for basic authentication
72
82
  def initialize(url: DEFAULT_REGISTRY, user: nil, password: nil)
83
+ url = url || DEFAULT_REGISTRY
73
84
  @url = url
74
85
  uri = URI.parse(url)
75
86
  @base_uri = "#{uri.scheme}://#{uri.host}:#{uri.port}"
@@ -112,7 +123,11 @@ class RegistryApiClient
112
123
  def tags(repo, withHashes = false)
113
124
  response = http_get("/v2/#{repo}/tags/list")
114
125
  # parse the response
115
- resp = JSON.parse(response)
126
+ resp = begin
127
+ JSON.parse(response)
128
+ rescue JSON::ParserError => e
129
+ raise JsonError.new(e, response)
130
+ end
116
131
  # do we include the hashes?
117
132
  if withHashes then
118
133
  useGet = false
@@ -200,7 +215,9 @@ class RegistryApiClient
200
215
  end
201
216
  end
202
217
 
203
- threads.map(&:join)
218
+ threads.each do |t|
219
+ t.alive? && t.join
220
+ end
204
221
 
205
222
  if errors.size > 0
206
223
  raise errors.first
@@ -232,9 +249,9 @@ class RegistryApiClient
232
249
  else
233
250
  return req_no_auth(type, url, stream: stream, manifest: manifest)
234
251
  end
235
- rescue SocketError => e
236
- p e
237
- raise RegistryUnknownException
252
+ # rescue SocketError => e
253
+ # p e
254
+ # raise RegistryUnknownException
238
255
  rescue HTTP::Unauthorized => e
239
256
  header = e.response.headers[:www_authenticate]
240
257
  method = header.downcase.split(' ')[0]
@@ -279,11 +296,11 @@ class RegistryApiClient
279
296
  headers: {Accept: manifest || @manifest_format},
280
297
  block_response: block
281
298
  )
282
- rescue SocketError
283
- raise RegistryUnknownException
284
- rescue HTTP::Unauthorized
285
- raise RegistryAuthenticationException
286
- rescue MethodNotAllowed
299
+ # rescue SocketError
300
+ # raise RegistryUnknownException
301
+ rescue HTTP::Unauthorized => error
302
+ raise RegistryAuthenticationException.new(error)
303
+ rescue HTTP::MethodNotAllowed
287
304
  raise InvalidMethod
288
305
  end
289
306
  return response
@@ -303,11 +320,11 @@ class RegistryApiClient
303
320
  headers: {Authorization: 'Bearer ' + token, Accept: manifest || @manifest_format},
304
321
  block_response: block
305
322
  )
306
- rescue SocketError
307
- raise RegistryUnknownException
308
- rescue HTTP::Unauthorized
309
- raise RegistryAuthenticationException
310
- rescue MethodNotAllowed
323
+ # rescue SocketError
324
+ # raise RegistryUnknownException
325
+ rescue HTTP::Unauthorized => e
326
+ raise RegistryAuthenticationException.new(e)
327
+ rescue HTTP::MethodNotAllowed
311
328
  raise InvalidMethod
312
329
  end
313
330
 
@@ -324,7 +341,12 @@ class RegistryApiClient
324
341
  if AUTH_CACHE[scope].is_a?(String)
325
342
  return AUTH_CACHE[scope]
326
343
  elsif AUTH_CACHE[scope].is_a?(PubSub)
327
- return AUTH_CACHE[scope].wait
344
+ result = AUTH_CACHE[scope].wait
345
+ if result.is_a?(Exception)
346
+ raise result
347
+ else
348
+ return result
349
+ end
328
350
  else
329
351
  AUTH_CACHE[scope] = PubSub.new
330
352
  end
@@ -343,9 +365,10 @@ class RegistryApiClient
343
365
  user: @user,
344
366
  password: @password
345
367
  )
346
- rescue HTTP::Unauthorized
368
+ rescue HTTP::Unauthorized => error
347
369
  # bad authentication
348
- raise RegistryAuthenticationException
370
+ AUTH_CACHE[scope].notify(error)
371
+ raise RegistryAuthenticationException.new(error)
349
372
  end
350
373
  # now save the web token
351
374
  token = JSON.parse(response)["token"]
@@ -373,7 +396,7 @@ class RegistryApiClient
373
396
  module HTTP
374
397
  extend self
375
398
 
376
- class Unauthorized < Exception
399
+ class ResponseError < Exception
377
400
  attr_accessor :response
378
401
  def initialize(message, response)
379
402
  super(message)
@@ -381,12 +404,13 @@ class RegistryApiClient
381
404
  end
382
405
  end
383
406
 
384
- class MethodNotAllowed < Exception
385
- attr_accessor :response
386
- def initialize(message, response)
387
- super(message)
388
- @response = response
389
- end
407
+ class Unauthorized < ResponseError
408
+ end
409
+
410
+ class MethodNotAllowed < ResponseError
411
+ end
412
+
413
+ class NotFound < ResponseError
390
414
  end
391
415
 
392
416
  def execute(method:, url:, headers: {}, user: nil, password: nil, block_response: nil, body: nil, query: nil)
@@ -439,6 +463,10 @@ class RegistryApiClient
439
463
  raise MethodNotAllowed.new(http_resp.body, response)
440
464
  end
441
465
 
466
+ if http_resp.code.to_s == '404'
467
+ raise NotFound.new(http_resp.body, response)
468
+ end
469
+
442
470
  return response
443
471
  end
444
472
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docker-cake
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Evstigneev