tagfish 1.0.1 → 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: 801be00ea36e0cc2c98c535546c45f1025768ca0
4
- data.tar.gz: 9ce46a51783f66f42f9da2f4d5a5cebc6e459fd4
3
+ metadata.gz: 45ed3de3aea63c3fbb5108caa65a5e4f13fce18b
4
+ data.tar.gz: 58afb32647d0002ae0af805e7e13812f48b96220
5
5
  SHA512:
6
- metadata.gz: ad70b423105855d754bed1ad62d9291dbc18ac4ce113e38e3825aa72765d792572767a6f3df90f2c20c0af5677358cc9281f6499dbb49fb303e5ca312740c182
7
- data.tar.gz: 33dbd5a8faf479d8a10364b7980731bb9c1823915d4aab0d08a4ac6d3a018fde857b22c22c950359bce3c2086fb9fd58eb92dafc358bb3580a753b5bc2ce6efe
6
+ metadata.gz: cfda8b965954cef8c83dd908ed315a067898a0e5143675a95fe6369c11ab64a83f19495c290a24432482b6179391fb6e673e75f9e1b0a2622f014c8cda42ae71
7
+ data.tar.gz: 9cf24c63a9a82178dc03a33918264993a5d3bcdfd6e254ef525da9fc5ec3fd16ef9da232e6409236533174a5eb2b2ea19c50b53daeda67a1edac917fb3376cf1
data/Dockerfile CHANGED
@@ -11,7 +11,7 @@ RUN apk add --update ruby=2.2.3-r1 \
11
11
  rm /var/cache/apk/* && \
12
12
  rm -rf /usr/share/ri
13
13
 
14
- RUN echo -e 'gem: --no-rdoc --no-ri' > /etc/gemrc \
14
+ RUN echo -e 'gem: --no-rdoc --no-ri' > /etc/gemrc && \
15
15
  gem update --system 2.4.8 && \
16
16
  gem install bundler -v 1.10.6 && \
17
17
  rm -rf /usr/share/ri
@@ -0,0 +1,24 @@
1
+ require 'tagfish/docker_registry_v1_client'
2
+ require 'tagfish/docker_registry_v2_client'
3
+
4
+ module Tagfish
5
+ module DockerRegistryClient
6
+
7
+ def self.for(*args)
8
+ [DockerRegistryV2Client, DockerRegistryV1Client].each do |client_class|
9
+ begin
10
+ return client_class.new(*args)
11
+ rescue APIVersionError
12
+ end
13
+ end
14
+ raise APIVersionError, "API version unrecognized!"
15
+ end
16
+
17
+ class AuthenticationError < StandardError
18
+ end
19
+
20
+ class APIVersionError < StandardError
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ require 'tagfish/docker_registry_vboth_client'
2
+
3
+ module Tagfish
4
+ class DockerRegistryV1Client < DockerRegistryVbothClient
5
+
6
+ def api_version
7
+ 'v1'
8
+ end
9
+
10
+ def search(keyword)
11
+ APICall.new(search_uri(keyword)).get_json(http_auth)
12
+ end
13
+
14
+ def tag_names
15
+ tag_map.tag_names
16
+ end
17
+
18
+ def tag_map
19
+ tags_list = tags_api(tags)
20
+ Tagfish::Tags.new(tags_list)
21
+ end
22
+
23
+ private
24
+
25
+ def tags
26
+ APICall.new(tags_uri).get_json(http_auth)
27
+ end
28
+
29
+ def tags_api(api_response_data)
30
+ case api_response_data
31
+ when Hash
32
+ api_response_data
33
+ when Array
34
+ api_response_data.reduce({}) do |images, tag|
35
+ images.merge({tag["name"] => tag["layer"]})
36
+ end
37
+ else
38
+ raise "unexpected type #{api_response_data.class}"
39
+ end
40
+ end
41
+
42
+ def ping_uri
43
+ "#{base_uri}/v1/_ping"
44
+ end
45
+
46
+ def search_uri(keyword)
47
+ "#{base_uri}/v1/search?q=#{keyword}"
48
+ end
49
+
50
+ def tags_uri
51
+ "#{base_uri}/v1/repositories/#{docker_uri.repository}/tags"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ require 'tagfish/docker_registry_vboth_client'
2
+
3
+ module Tagfish
4
+ class DockerRegistryV2Client < DockerRegistryVbothClient
5
+
6
+ def api_version
7
+ 'v2'
8
+ end
9
+
10
+ def catalog
11
+ APICall.new(catalog_uri).get_json(http_auth)
12
+ end
13
+
14
+ def tag_names
15
+ tags["tags"]
16
+ end
17
+
18
+ def tag_map
19
+ Tagfish::Tags.new(tags_logic)
20
+ end
21
+
22
+ private
23
+
24
+ def tags
25
+ APICall.new(tags_uri).get_json(http_auth)
26
+ end
27
+
28
+ def hash(tag)
29
+ APICall.new(hash_uri(tag)).get_json(http_auth)
30
+ end
31
+
32
+ def tags_logic
33
+ if tag_names.nil?
34
+ abort("No Tags found for this repository")
35
+ end
36
+
37
+ tags_with_hashes = tag_names.inject({}) do |dict, tag|
38
+ dict[tag] = hash(tag)["fsLayers"]
39
+ dict
40
+ end
41
+ end
42
+
43
+ def ping_uri
44
+ "#{base_uri}/v2/"
45
+ end
46
+
47
+ def catalog_uri
48
+ "#{base_uri}/v2/_catalog"
49
+ end
50
+
51
+ def tags_uri
52
+ "#{base_uri}/v2/#{docker_uri.repository}/tags/list"
53
+ end
54
+
55
+ def hash_uri(tag)
56
+ "#{base_uri}/v2/#{docker_uri.repository}/manifests/#{tag}"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,32 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'tagfish/docker_uri'
4
+ require 'tagfish/api_call'
5
+ require 'tagfish/tags'
6
+
7
+ module Tagfish
8
+ class DockerRegistryVbothClient
9
+
10
+ attr_accessor :docker_uri
11
+ attr_accessor :http_auth
12
+
13
+ def initialize(docker_uri)
14
+ @docker_uri = docker_uri
15
+ code = APICall.new(ping_uri).response_code
16
+ if code == 401
17
+ @http_auth = DockerHttpAuth.new(docker_uri.registry)
18
+ code = APICall.new(ping_uri).response_code(http_auth)
19
+ end
20
+ if code == 401
21
+ raise DockerRegistryClient::AuthenticationError, "Please `docker login <REGISTRY>` and try again"
22
+ elsif code != 200
23
+ raise DockerRegistryClient::APIVersionError, "Not recognized"
24
+ end
25
+ end
26
+
27
+ def base_uri
28
+ "#{docker_uri.protocol}#{docker_uri.registry}"
29
+ end
30
+
31
+ end
32
+ end
@@ -1,5 +1,4 @@
1
1
  require 'tagfish/docker_http_auth'
2
- require 'tagfish/docker_api'
3
2
 
4
3
  module Tagfish
5
4
  class DockerURI
@@ -14,19 +14,26 @@ module Tagfish
14
14
  docker_api = DockerAPI.new(docker_uri)
15
15
 
16
16
  if docker_api.api_version == 'v2'
17
- repos = docker_api.catalog_v2["repositories"]
18
- if keyword
19
- repos.select! {|repo| repo.include? keyword}
20
- end
21
- repos.each {|repo| puts "#{docker_uri.registry}/#{repo}"}
22
- else # 'v1'
23
- if not keyword
24
- abort("You need to specify a keyword to search a Registry V1")
25
- end
26
- repos_raw = docker_api.search_v1(keyword)
27
- repos = repos_raw["results"].map {|result| result["name"]}
28
- puts repos
17
+ puts search_v2(keyword, docker_api, docker_uri)
18
+ else
19
+ puts search_v1(keyword, docker_api)
29
20
  end
30
21
  end
22
+
23
+ def search_v2(keyword, docker_api, docker_uri)
24
+ repos = docker_api.catalog_v2["repositories"]
25
+ if keyword
26
+ repos.select! {|repo| repo.include? keyword}
27
+ end
28
+ repos.map {|repo| "#{docker_uri.registry}/#{repo}"}
29
+ end
30
+
31
+ def search_v1(keyword, docker_api)
32
+ if not keyword
33
+ abort("You need to specify a keyword to search a Registry V1")
34
+ end
35
+ repos_raw = docker_api.search_v1(keyword)
36
+ repos = repos_raw["results"].map {|result| result["name"]}
37
+ end
31
38
  end
32
39
  end
data/lib/tagfish/tags.rb CHANGED
@@ -4,23 +4,21 @@ require 'json'
4
4
  module Tagfish
5
5
  class Tags
6
6
 
7
- def initialize(tags)
8
- @tags = tags
7
+ attr_reader :tag_map
8
+
9
+ def initialize(tag_map)
10
+ @tag_map = tag_map
9
11
  end
10
12
 
11
13
  def tag_names
12
- @tags.keys.sort
14
+ tag_map.keys.sort
13
15
  end
14
16
 
15
17
  def latest_tag
16
- tag_names.select do |tag_name|
17
- (@tags[tag_name] == @tags["latest"]) && (tag_name != 'latest')
18
+ tag_names.detect do |tag_name|
19
+ (tag_map[tag_name] == tag_map["latest"]) && (tag_name != "latest")
18
20
  end
19
21
  end
20
22
 
21
- def latest_tag_to_s
22
- latest_tag.empty? ? nil : latest_tag[0]
23
- end
24
-
25
23
  end
26
24
  end
@@ -1,5 +1,5 @@
1
- require "tagfish/tags_logic"
2
1
  require "tagfish/docker_uri"
2
+ require "tagfish/docker_registry_client"
3
3
 
4
4
  module Tagfish
5
5
  class TagsCommand < Clamp::Command
@@ -8,23 +8,20 @@ module Tagfish
8
8
  option ["-s", "--short"], :flag, "only return tag, not full image path"
9
9
 
10
10
  def execute
11
- tags_only = latest? ? false : true
12
11
 
13
12
  docker_uri = DockerURI.parse(repository)
14
- docker_api = DockerAPI.new(docker_uri)
15
- tags = TagsLogic.find_tags_by_repository(docker_api, tags_only)
16
-
17
- begin
18
- tags_found = latest? ? tags.latest_tag : tags.tag_names
19
- rescue Exception => e
20
- puts e.message
21
- return
22
- end
23
-
24
- if tags_found.size == 0
25
- puts "ERROR: No image explicitly tagged in this Repository, " +
26
- "only `latest` tag available."
27
- return
13
+ docker_api = DockerRegistryClient.for(docker_uri)
14
+
15
+ if latest?
16
+ tags = docker_api.tag_map
17
+ latest_tag = tags.latest_tag
18
+ if latest_tag.nil?
19
+ signal_error "No image explicitly tagged in this Repository, " +
20
+ "only `latest` tag available."
21
+ end
22
+ tags_found = [latest_tag]
23
+ else
24
+ tags_found = docker_api.tag_names
28
25
  end
29
26
 
30
27
  pretty_tags = tags_found.map do |tag_name|
@@ -1,6 +1,6 @@
1
1
  require 'tagfish/tokeniser'
2
2
  require 'tagfish/docker_uri'
3
- require 'tagfish/tags_logic'
3
+ require 'tagfish/docker_registry_client'
4
4
 
5
5
  module Tagfish
6
6
  module Update
@@ -38,9 +38,9 @@ module Tagfish
38
38
  end
39
39
 
40
40
  def update_uri(docker_uri)
41
- docker_api = DockerAPI.new(docker_uri)
42
- tags = TagsLogic.find_tags_by_repository(docker_api)
43
- newest_tag_name = tags.latest_tag_to_s
41
+ docker_api = DockerRegistryClient.for(docker_uri)
42
+ tags = docker_api.tag_map
43
+ newest_tag_name = tags.latest_tag
44
44
  if newest_tag_name.nil?
45
45
  docker_uri
46
46
  else
@@ -1,3 +1,3 @@
1
1
  module Tagfish
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tagfish
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clement Labbe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-15 00:00:00.000000000 Z
11
+ date: 2016-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -110,13 +110,15 @@ files:
110
110
  - bin/tagfish
111
111
  - lib/tagfish.rb
112
112
  - lib/tagfish/api_call.rb
113
- - lib/tagfish/docker_api.rb
114
113
  - lib/tagfish/docker_http_auth.rb
114
+ - lib/tagfish/docker_registry_client.rb
115
+ - lib/tagfish/docker_registry_v1_client.rb
116
+ - lib/tagfish/docker_registry_v2_client.rb
117
+ - lib/tagfish/docker_registry_vboth_client.rb
115
118
  - lib/tagfish/docker_uri.rb
116
119
  - lib/tagfish/search_command.rb
117
120
  - lib/tagfish/tags.rb
118
121
  - lib/tagfish/tags_command.rb
119
- - lib/tagfish/tags_logic.rb
120
122
  - lib/tagfish/tokeniser.rb
121
123
  - lib/tagfish/update/differ.rb
122
124
  - lib/tagfish/update/update_command.rb
@@ -145,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
147
  version: '0'
146
148
  requirements: []
147
149
  rubyforge_project:
148
- rubygems_version: 2.0.14
150
+ rubygems_version: 2.5.1
149
151
  signing_key:
150
152
  specification_version: 4
151
153
  summary: Command line utility for docker registries
@@ -1,113 +0,0 @@
1
- require 'net/http'
2
- require 'json'
3
- require 'tagfish/docker_uri'
4
- require 'tagfish/api_call'
5
-
6
- module Tagfish
7
- class DockerAPI
8
-
9
- attr_accessor :docker_uri
10
- attr_accessor :api_version
11
- attr_accessor :http_auth
12
-
13
- def initialize(docker_uri)
14
- @docker_uri = docker_uri
15
- retrieve_api_version_and_auth()
16
- end
17
-
18
- def retrieve_api_version_and_auth
19
- code = try_api('v1')
20
- if code != 200
21
- code = try_api('v2')
22
- end
23
- if code == 401
24
- abort("Authentication failed, please `docker login <REGISTRY>` and try again.")
25
- elsif code != 200
26
- abort("API version not recognized")
27
- end
28
- end
29
-
30
- def try_api(version)
31
- code = APICall.new(ping_uri(version)).response_code
32
- if code == 200
33
- @api_version = version
34
- elsif code == 401
35
- code = init_auth(version)
36
- if code == 200
37
- @api_version = version
38
- end
39
- end
40
- return code
41
- end
42
-
43
- def init_auth(api_version)
44
- @http_auth = DockerHttpAuth.new(docker_uri.registry)
45
- if api_version == 'v2'
46
- code = APICall.new(ping_v2_uri).response_code(http_auth)
47
- elsif api_version == 'v1'
48
- code = APICall.new(ping_v1_uri).response_code(http_auth)
49
- end
50
- end
51
-
52
- def tags_v1
53
- APICall.new(tags_v1_uri).get_json(http_auth)
54
- end
55
-
56
- def tags_v2
57
- APICall.new(tags_v2_uri).get_json(http_auth)
58
- end
59
-
60
- def hash_v2(tag)
61
- APICall.new(hash_v2_uri(tag)).get_json(http_auth)
62
- end
63
-
64
- def catalog_v2
65
- APICall.new(catalog_v2_uri).get_json(http_auth)
66
- end
67
-
68
- def search_v1(keyword)
69
- APICall.new(search_v1_uri(keyword)).get_json(http_auth)
70
- end
71
-
72
- def base_uri
73
- "#{docker_uri.protocol}#{docker_uri.registry}"
74
- end
75
-
76
- def ping_uri(version)
77
- if version == 'v1'
78
- ping_v1_uri
79
- elsif version == 'v2'
80
- ping_v2_uri
81
- end
82
- end
83
-
84
- def ping_v2_uri
85
- "#{base_uri}/v2/"
86
- end
87
-
88
- def ping_v1_uri
89
- "#{base_uri}/v1/_ping"
90
- end
91
-
92
- def catalog_v2_uri
93
- "#{base_uri}/v2/_catalog"
94
- end
95
-
96
- def search_v1_uri(keyword)
97
- "#{base_uri}/v1/search?q=#{keyword}"
98
- end
99
-
100
- def tags_v1_uri
101
- "#{base_uri}/v1/repositories/#{docker_uri.repository}/tags"
102
- end
103
-
104
- def tags_v2_uri
105
- "#{base_uri}/v2/#{docker_uri.repository}/tags/list"
106
- end
107
-
108
- def hash_v2_uri(tag)
109
- "#{base_uri}/v2/#{docker_uri.repository}/manifests/#{tag}"
110
- end
111
-
112
- end
113
- end
@@ -1,52 +0,0 @@
1
- require 'json'
2
- require 'tagfish/tags'
3
-
4
- module Tagfish
5
- class TagsLogic
6
- def self.find_tags_by_repository(docker_api, tags_only=false)
7
- if docker_api.api_version == 'v2'
8
- tags_list = tags_v2(docker_api, tags_only)
9
- else
10
- tags_list = tags_v1(docker_api)
11
- end
12
- Tagfish::Tags.new(tags_list)
13
- end
14
-
15
- private
16
-
17
- def self.tags_v1(docker_api)
18
- tags_json = docker_api.tags_v1
19
- tags_v1_api(tags_json)
20
- end
21
-
22
- def self.tags_v1_api(api_response_data)
23
- case api_response_data
24
- when Hash
25
- api_response_data
26
- when Array
27
- api_response_data.reduce({}) do |images, tag|
28
- images.merge({tag["name"] => tag["layer"]})
29
- end
30
- else
31
- raise "unexpected type #{api_response_data.class}"
32
- end
33
- end
34
-
35
- def self.tags_v2(docker_api, tags_only)
36
- tags = docker_api.tags_v2["tags"]
37
- if tags.nil?
38
- abort("No Tags found for this repository")
39
- end
40
-
41
- tags_with_hashes = tags.inject({}) do |dict, tag|
42
- if tags_only
43
- dict[tag] = "dummy_hash"
44
- else
45
- dict[tag] = docker_api.hash_v2(tag)["fsLayers"][0]["blobSum"]
46
- end
47
- dict
48
- end
49
- end
50
-
51
- end
52
- end