docker_registry2 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: