docker_registry2 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1566198b0c293c0e466c50b69a93087d19aa4d5
4
+ data.tar.gz: 785c90f7876ef4eed0afe80a7fc1150d8e30b325
5
+ SHA512:
6
+ metadata.gz: a79f5c43888ec5484e93c3a6e363f90d744daf6eefa6321046d8f7ca69b5e50575f992a6e29d844d14d429eb08c48d6b22c68bdac49fd6b60e92723dd56068a8
7
+ data.tar.gz: d3e2a3ca2d227f8deb22e77621f6ff94fed058ccaa3872ac77e08d9e43fc450f1e2cff0862c95111f541dbc418c56fff48ee51d37cbcb998a67d0d2c44bd9848
@@ -0,0 +1 @@
1
+ docker_registry2*.gem
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
4
+ gem 'rest-client'
5
+
6
+
7
+ group :test do
8
+ gem 'rake'
9
+ end
@@ -0,0 +1,125 @@
1
+ # Docker Registry
2
+
3
+ ## Introduction
4
+
5
+ This is a simple gem that provides direct http access to a docker registry v2 without going through a docker server. You do **not** requires docker installed on your system to provide access.
6
+
7
+ ````ruby
8
+ reg = DockerRegistry.new("https://my.registy.corp.com")
9
+ repos = reg.search("foo/repo")
10
+ tags = reg.tags("foo/repo")
11
+ ````
12
+
13
+ Supports anonymous access, http authorization and v2 token access.
14
+
15
+ Inspired by https://github.com/rosylilly/docker_registry but written separately.
16
+
17
+
18
+ ## Installation
19
+
20
+ Add the following to your Gemfile:
21
+
22
+ gem 'docker_registry2`
23
+
24
+ And execute:
25
+
26
+ bundle install
27
+
28
+ ## Usage
29
+
30
+ Once it is installed, you first *open* a connection to a registry, and then *request* from the registry.
31
+
32
+ ### Connecting
33
+
34
+ #### Anonymous
35
+ To connect to a registry:
36
+
37
+ ````ruby
38
+ reg = DockerRegistry.new("https://my.registy.corp.com")
39
+ ````
40
+
41
+ The above will connect anonymously to the registry via the endpoint `https://my.registry.corp.com/v2/`.
42
+
43
+ The following exceptions are thrown:
44
+
45
+ * `RegistryAuthenticationException`: registry does not support anonymous access
46
+ * `RegistryUnknownException`: registry does not exist at the given URL
47
+ * `RegistrySSLException`: registry SSL certificate cannot be validated
48
+
49
+ #### Authenticated
50
+ If you wish to authenticate, pass a username and password as the second and third parameters.
51
+
52
+ ````ruby
53
+ reg = DockerRegistry.connect("https://myuser:mypass@my.registy.corp.com")
54
+ ````
55
+
56
+ The following exceptions are thrown:
57
+
58
+ * `RegistryAuthenticationException`: username/password combination is invalid
59
+ * `RegistryAuthorizationException`: username/password does not have sufficient rights to access this registry
60
+ * `RegistryUnknownException`: registry does not exist at the given URL
61
+ * `RegistrySSLException`: registry SSL certificate cannot be validated
62
+
63
+
64
+ ### Requests
65
+ Once you have a valid `reg` object return by `DockerRegistry.new()`, you can make requests. As of this version, only search and tags are supported. Others will be added over time.
66
+
67
+
68
+ #### search
69
+ ````ruby
70
+ results = reg.search("mylibs")
71
+ ````
72
+
73
+ Returns all repositories whose name contains `"mylibs"`.
74
+
75
+ **Note:** The v2 registry does not support search directly server-side. Thus, this is simulated by using the `catalog/` endpoint. It is highly recommended to avoid using this function until the v2 registry supports direct search, as it will be slow. It pulls a list of all repositories to the client and then does a pattern match on them.
76
+
77
+ Returns an array of strings, each of which is the full name of a repository.
78
+
79
+ If no results are found, will return an empty array `[]`. An empty array will not throw an exception.
80
+
81
+ The following exceptions are thrown:
82
+
83
+ * `RegistryAuthenticationException`: username and password are invalid
84
+ * `RegistryAuthorizationException`: user does not have sufficient rights to search in this registry
85
+
86
+ **NOTE:** The search endpoint relies on the catalog endpoint, which only is available from registry:2.1. If you try it prior to 2.1, you will get a `404` error.
87
+
88
+ #### tags
89
+ ````ruby
90
+ results = reg.tags("mylibs")
91
+ ````
92
+
93
+ Returns all known tags for the repository precisely named `"mylibs"`.
94
+
95
+ Returns an object with the following key value pairs:
96
+ array of objects, each of which has the following key/value pairs:
97
+
98
+ * `name`: full name of repository, e.g. `redis` or `user/redis`
99
+ * `tags`: array of strings, each of which is a tag for ths given repository
100
+
101
+ Other fields may be added later. Do *not* assume those are the only fields.
102
+
103
+ If no tags are found, or the named repository does not exist, return an empty object `{}`. An unknown repository will not throw an exception.
104
+
105
+ The following exceptions are thrown:
106
+
107
+ * `RegistryAuthenticationException`: username and password are invalid
108
+ * `RegistryAuthorizationException`: registry does not support tags using the given credentials, probably because the repository is private and the credentials provided do not have access
109
+
110
+ ### Exceptions
111
+
112
+ All exceptions thrown inherit from `DockerRegistry::Exception`.
113
+
114
+ ## License
115
+
116
+ MIT License.
117
+
118
+ ## Contribution
119
+
120
+ Developed by Avi Deitcher http://github.com/deitch
121
+ Contributions courtesy of TraderTools, Inc. http://tradertools.com
122
+
123
+
124
+
125
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'registry/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'docker_registry2'
8
+ spec.version = DockerRegistry::VERSION
9
+ spec.authors = ['Avi Deitcher']
10
+ spec.summary = 'Docker v2 registry HTTP API client'
11
+ spec.description = 'Docker v2 registry HTTP API client with support for token authentication'
12
+ spec.homepage = 'https://github.com/deitch/docker_registry2'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'rake', '~> 10.0'
22
+ spec.add_development_dependency 'rubocop', '>= 0.26.0'
23
+
24
+ spec.add_dependency 'rest-client', '>= 1.8.0'
25
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/registry/version'
2
+ require File.dirname(__FILE__) + '/registry/registry'
3
+ require File.dirname(__FILE__) + '/registry/exceptions'
4
+
5
+
6
+ module DockerRegistry
7
+ def self.connect(uri)
8
+ @reg = DockerRegistry::Registry.new(uri)
9
+ end
10
+
11
+ def self.search(query = '')
12
+ @reg.search(query)
13
+ end
14
+
15
+ def self.tags(repository)
16
+ @reg.tags(repository)
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ module DockerRegistry
2
+ class Exception < RuntimeError
3
+
4
+ end
5
+
6
+ class RegistryAuthenticationException < Exception
7
+ end
8
+
9
+ class RegistryAuthorizationException < Exception
10
+ end
11
+
12
+ class RegistryUnknownException < Exception
13
+ end
14
+
15
+ class RegistrySSLException < Exception
16
+ end
17
+
18
+ class ReauthenticatedException < Exception
19
+ end
20
+
21
+ class UnknownRegistryException < Exception
22
+ end
23
+ end
@@ -0,0 +1,101 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+
4
+ class DockerRegistry::Registry
5
+ # @param [#to_s] base_uri Docker registry base URI
6
+ # @param [Hash] options Client options
7
+ # @option options [#to_s] :user User name for basic authentication
8
+ # @option options [#to_s] :password Password for basic authentication
9
+ def initialize(uri, options = {})
10
+ @uri = URI.parse(uri)
11
+ @base_uri = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
12
+ @user = @uri.user
13
+ @password = @uri.password
14
+ # make a ping connection
15
+ ping
16
+ end
17
+
18
+ def doget(url, token=nil)
19
+ begin
20
+ # do we already have a token to authenticate?
21
+ if token.nil?
22
+ response = RestClient.get @base_uri+url
23
+ else
24
+ response = RestClient.get @base_uri+url, Authorization: 'Bearer '+token
25
+ end
26
+ rescue SocketError
27
+ raise DockerRegistry::RegistryUnknownException
28
+ rescue RestClient::Unauthorized => e
29
+ # unauthorized
30
+ # did we already try for this realm and service and scope and have insufficient privileges?
31
+ if token.nil?
32
+ token = authenticate e.response.headers[:www_authenticate]
33
+ # go do whatever you were going to do again
34
+ response = doget url, token
35
+ else
36
+ throw DockerRegistry::RegistryAuthorizationException
37
+ end
38
+ rescue RestClient::ResourceNotFound
39
+ raise DockerRegistry::RegistryUnknownException
40
+ end
41
+ return response
42
+ end
43
+
44
+ def authenticate(header)
45
+ # get the parts we need
46
+ target = split_auth_header(header)
47
+ # did we have a username and password?
48
+ if defined? @user and @user.to_s.strip.length != 0
49
+ target[:params][:account] = @user
50
+ end
51
+ # authenticate against the realm
52
+ uri = URI.parse(target[:realm])
53
+ uri.user = @user if defined? @user
54
+ uri.password = @password if defined? @password
55
+ begin
56
+ response = RestClient.get uri.to_s, {params: target[:params]}
57
+ rescue RestClient::Unauthorized
58
+ # bad authentication
59
+ raise DockerRegistry::RegistryAuthenticationException
60
+ end
61
+ # now save the web token
62
+ return JSON.parse(response)["token"]
63
+ end
64
+
65
+ def split_auth_header(header = '')
66
+ h = Hash.new
67
+ h = {params: {}}
68
+ header.split(/[\s,]+/).each {|entry|
69
+ p = entry.split('=')
70
+ case p[0]
71
+ when 'Bearer'
72
+ when 'realm'
73
+ h[:realm] = p[1].gsub(/(^\"|\"$)/,'')
74
+ else
75
+ h[:params][p[0]] = p[1].gsub(/(^\"|\"$)/,'')
76
+ end
77
+ }
78
+ h
79
+ end
80
+
81
+ def ping
82
+ response = doget '/v2/'
83
+ end
84
+
85
+ def search(query = '')
86
+ response = doget "/v2/_catalog"
87
+ # parse the response
88
+ repos = JSON.parse(response)["repositories"]
89
+ if query.strip.length > 0
90
+ re = Regexp.new query
91
+ repos = repos.find_all {|e| re =~ e }
92
+ end
93
+ return repos
94
+ end
95
+
96
+ def tags(repo)
97
+ response = doget "/v2/#{repo}/tags/list"
98
+ # parse the response
99
+ JSON.parse response
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module DockerRegistry
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: docker_registry2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Avi Deitcher
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.26.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.26.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rest-client
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 1.8.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 1.8.0
69
+ description: Docker v2 registry HTTP API client with support for token authentication
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".gitignore"
76
+ - Gemfile
77
+ - README.md
78
+ - docker_registry2.gemspec
79
+ - lib/docker_registry2.rb
80
+ - lib/registry/exceptions.rb
81
+ - lib/registry/registry.rb
82
+ - lib/registry/version.rb
83
+ homepage: https://github.com/deitch/docker_registry2
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.4.5
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Docker v2 registry HTTP API client
107
+ test_files: []
108
+ has_rdoc: