docker-distribution-api 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTQxNTU3OWExYzg0ZjI5MDkxNTY0OTJhNmI3YmZjZjZkNGUyZDUwZQ==
5
+ data.tar.gz: !binary |-
6
+ NzBiZTIxYmNiZmUwYWUxOGQ5ODg1NmUwOGMwNjMyMWJhNjMzMmUzMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NzVkNmM1OTk4MzAzNmE5MDcyZWM3OGUxMDFkOTI5MjczMjE5OTliNGU0MmU2
10
+ NTRkZTk3MzA4NTJlZmUzMGJmNmE1MmZkNGJmMDU0MGIxYmMwZjM5OGRmYWEx
11
+ OGJlNWUwNzUxNjdmOGEzZDE3ODExMDZhMjk1NDA0ODM4YzA3NGU=
12
+ data.tar.gz: !binary |-
13
+ NDc1MTFjYTQ5NGY1MmYxMzZkMDU2YWUxMWVlODZhOGI0N2M4OTM2OTViMjg0
14
+ YzVkNDFkNGRlMGVmZGIxYWQ1MjIwOWI5NjMyYTAyZTZlY2ZhYjE3MWUwYTgy
15
+ MWFjZjNlZGUzMjk0ZThkMDNmYTE1YzE2NTI5ZWFlZGY5ODc2NzI=
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /docker-distribution-api.iml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ before_install:
5
+ - gem install bundler -v 1.11.2
6
+ - docker pull registry:2.5
7
+ - docker run -d -p 127.0.0.1:5000:5000 -v "$(pwd)/spec/registry.config.yml:/etc/docker/registry/config.yml" registry:2.5
8
+ sudo: required
9
+ services:
10
+ - docker
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in docker-distribution-api.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # Docker::Distribution::Api
2
+
3
+ Simple swipley/docker-api like API client for docker-distribution with limited support of endpoints
4
+
5
+
6
+ [![Build Status](https://travis-ci.org/bazilio91/docker-distribution-api.svg?branch=master)](https://travis-ci.org/bazilio91/docker-distribution-api)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'docker-distribution-api'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install docker-distribution-api
23
+
24
+ ## Usage
25
+
26
+ API:
27
+
28
+ ```ruby
29
+ Docker::Distribution::Api.logger # to set your logger
30
+ Docker::Distribution::Api.url= # set registry url
31
+ Docker::Distribution::Api.options= # set registry connection options
32
+ Docker::Distribution::Api.version # get registry version
33
+ Docker::Distribution::Api.tags('test') # get tags for repository 'test'
34
+ ```
35
+
36
+ Manifest:
37
+
38
+ ```ruby
39
+ Docker::Distribution::Api.url='http://localhost:5000'
40
+ Docker::Distribution::Api.options={:user => 'username', :password => 'password'} # basic auth
41
+ manifest = Docker::Distribution::Api::Manifest.find_by_tag('repository', 'tag') # get manifest
42
+ manifest.delete # delete manifest
43
+ ```
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bazilio91/docker-distribution-api.
54
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "docker/distribution/api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'docker/distribution/api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'docker-distribution-api'
8
+ spec.version = Docker::Distribution::Api::VERSION
9
+ spec.authors = ['Vasily Ostanin']
10
+ spec.email = ['bazilio91@gmail.com']
11
+
12
+ spec.summary = %q{API client for docker distribution.}
13
+ spec.description = %q{docker-api like client for docker self-hosted registry (distribution).}
14
+ spec.homepage = 'https://github.com/bazilio91/docker-distribution-api'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'excon', '~> 0.38'
23
+ spec.add_development_dependency 'bundler', '~> 1.11'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ end
@@ -0,0 +1,55 @@
1
+ module Docker
2
+ module Distribution
3
+ module Api
4
+ attr_accessor :creds, :logger
5
+
6
+ require 'docker/distribution/api/connection'
7
+ require 'docker/distribution/api/manifest'
8
+ require 'docker/distribution/api/util'
9
+ require 'docker/distribution/api/version'
10
+ require 'docker/distribution/error'
11
+
12
+ def version(connection = self.connection)
13
+ response = connection.get('/')
14
+ response.headers['Docker-Distribution-Api-Version']
15
+ end
16
+
17
+ def tags(repository, connection = self.connection)
18
+ response = connection.get("/#{repository}/tags/list")
19
+ Util.parse_json(response.body)['tags']
20
+ end
21
+
22
+ def url
23
+ @url ||= 'localhost:5000'
24
+ end
25
+
26
+ def url=(new_url)
27
+ @url = new_url
28
+ reset_connection!
29
+ end
30
+
31
+ def options
32
+ @options ||= {}
33
+ end
34
+
35
+ def options=(new_options)
36
+ @options = @options.merge(new_options || {})
37
+ reset_connection!
38
+ end
39
+
40
+ def connection
41
+ @connection ||= Connection.new(url, options)
42
+ end
43
+
44
+ def reset_connection!
45
+ @connection = nil
46
+ end
47
+
48
+ module_function :url, :url=,
49
+ :options, :options=,
50
+ :connection, :reset_connection!,
51
+ :logger, :logger=,
52
+ :version, :tags
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,97 @@
1
+ module Docker
2
+ module Distribution
3
+ class Connection
4
+ require 'excon'
5
+ require 'docker/distribution/error'
6
+
7
+ include Docker::Distribution::Error
8
+
9
+ attr_reader :url, :options
10
+
11
+ # Create a new Connection. This method takes a url (String) and options
12
+ # (Hash). These are passed to Excon, so any options valid for `Excon.new`
13
+ # can be passed here.
14
+ def initialize(url, opts)
15
+ case
16
+ when !url.is_a?(String)
17
+ raise ArgumentError, "Expected a String, got: '#{url}'"
18
+ when !opts.is_a?(Hash)
19
+ raise ArgumentError, "Expected a Hash, got: '#{opts}'"
20
+ else
21
+ uri = URI.parse(url)
22
+ if uri.scheme == 'https'
23
+ @url, @options = url, opts
24
+ else
25
+ @url, @options = "http://#{uri}", opts
26
+ end
27
+ end
28
+ end
29
+
30
+ # The actual client that sends HTTP methods to the Docker server. This value
31
+ # is not cached, since doing so may cause socket errors after bad requests.
32
+ def resource
33
+ Excon.new(url, options)
34
+ end
35
+
36
+ private :resource
37
+
38
+ # Send a request to the server with the `
39
+ def request(*args, &block)
40
+ request = compile_request_params(*args, &block)
41
+ log_request(request)
42
+ resource.request(request)
43
+ rescue Excon::Errors::BadRequest => ex
44
+ raise ClientError, ex.response.body
45
+ rescue Excon::Errors::Unauthorized => ex
46
+ raise UnauthorizedError, ex.response.body
47
+ rescue Excon::Errors::NotFound => ex
48
+ raise NotFoundError, ex.response.body
49
+ rescue Excon::Errors::Conflict => ex
50
+ raise ConflictError, ex.response.body
51
+ rescue Excon::Errors::InternalServerError => ex
52
+ raise ServerError, ex.response.body
53
+ rescue Excon::Errors::Timeout => ex
54
+ raise TimeoutError, ex.message
55
+ end
56
+
57
+ def log_request(request)
58
+ if Api.logger
59
+ Api.logger.debug(
60
+ [request[:method], request[:path], request[:query], request[:body]]
61
+ )
62
+ end
63
+ end
64
+
65
+ # Delegate all HTTP methods to the #request.
66
+ [:get, :put, :post, :delete].each do |method|
67
+ define_method(method) { |*args, &block| request(method, *args, &block) }
68
+ end
69
+
70
+ def to_s
71
+ "Docker::Distribution::Connection { :url => #{url}, :options => #{options} }"
72
+ end
73
+
74
+ private
75
+ # Given an HTTP method, path, optional query, extra options, and block,
76
+ # compiles a request.
77
+ def compile_request_params(http_method, path, query = nil, opts = nil, &block)
78
+ query ||= {}
79
+ opts ||= {}
80
+ headers = opts.delete(:headers) || {}
81
+ content_type = opts[:body].nil? ? 'text/plain' : 'application/json'
82
+ user_agent = "bazilio91/docker-distribution-api #{Api::VERSION}"
83
+ {
84
+ :method => http_method,
85
+ :path => "/v#{Api::API_VERSION}#{path}",
86
+ :query => query,
87
+ :headers => {'Content-Type' => content_type,
88
+ 'User-Agent' => user_agent,
89
+ }.merge(headers),
90
+ :expects => (200..204).to_a << 301 << 304,
91
+ :idempotent => http_method == :get,
92
+ :request_block => block,
93
+ }.merge(opts).reject { |_, v| v.nil? }
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,40 @@
1
+ module Docker
2
+ module Distribution
3
+ module Api
4
+ class Manifest
5
+ attr_accessor :connection, :info
6
+
7
+ require 'docker/distribution/error'
8
+ require 'docker/distribution/api/util'
9
+
10
+ def initialize(connection, hash={})
11
+ unless connection.is_a?(Docker::Distribution::Connection)
12
+ raise ArgumentError, "Expected a Docker::Distribution::Connection, got: #{connection}."
13
+ end
14
+ @connection, @info = connection, hash
15
+ end
16
+
17
+ def delete
18
+ @connection.delete(
19
+ "/#{@info['repository']}/manifests/#{@info['digest']}",
20
+ nil,
21
+ :expects => [202]
22
+ )
23
+ nil
24
+ end
25
+
26
+ def self.get_by_tag(repository, tag, connection = Api.connection)
27
+ response = connection.get(
28
+ "/#{repository}/manifests/#{tag}", nil, :headers => {:Accept => 'application/vnd.docker.distribution.manifest.v2+json'}
29
+ )
30
+ manifest_json = Util.parse_json(response.body)
31
+ hash = manifest_json
32
+ hash['digest'] = response.headers['Docker-Content-Digest']
33
+ hash['repository'] = repository
34
+ hash['tag'] = tag
35
+ new(connection, hash)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ module Docker
2
+ module Distribution
3
+ module Api
4
+ module Util
5
+ require 'json'
6
+ module_function
7
+
8
+ def parse_json(body)
9
+ JSON.parse(body) unless body.nil? || body.empty? || (body == 'null')
10
+ rescue JSON::ParserError => ex
11
+ raise UnexpectedResponseError, ex.message
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module Docker
2
+ module Distribution
3
+ module Api
4
+ VERSION = '0.1.0'
5
+ API_VERSION = '2'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,56 @@
1
+ module Docker
2
+ module Distribution
3
+ # This module holds the Errors for the gem.
4
+ module Error
5
+
6
+ # The default error. It's never actually raised, but can be used to catch all
7
+ # gem-specific errors that are thrown as they all subclass from this.
8
+ class DockerDistributionError < StandardError;
9
+ end
10
+
11
+ # Raised when invalid arguments are passed to a method.
12
+ class ArgumentError < DockerDistributionError;
13
+ end
14
+
15
+ # Raised when a request returns a 400.
16
+ class ClientError < DockerDistributionError;
17
+ end
18
+
19
+ # Raised when a request returns a 401.
20
+ class UnauthorizedError < DockerDistributionError;
21
+ end
22
+
23
+ # Raised when a request returns a 404.
24
+ class NotFoundError < DockerDistributionError;
25
+ end
26
+
27
+ # Raised when a request returns a 409.
28
+ class ConflictError < DockerDistributionError;
29
+ end
30
+
31
+ # Raised when a request returns a 500.
32
+ class ServerError < DockerDistributionError;
33
+ end
34
+
35
+ # Raised when there is an unexpected response code / body.
36
+ class UnexpectedResponseError < DockerDistributionError;
37
+ end
38
+
39
+ # Raised when there is an incompatible version of Docker.
40
+ class VersionError < DockerDistributionError;
41
+ end
42
+
43
+ # Raised when a request times out.
44
+ class TimeoutError < DockerDistributionError;
45
+ end
46
+
47
+ # Raised when login fails.
48
+ class AuthenticationError < DockerDistributionError;
49
+ end
50
+
51
+ # Raised when an IO action fails.
52
+ class IOError < DockerDistributionError;
53
+ end
54
+ end
55
+ end
56
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: docker-distribution-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vasily Ostanin
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: excon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.38'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.38'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.11'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: docker-api like client for docker self-hosted registry (distribution).
70
+ email:
71
+ - bazilio91@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - .travis.yml
79
+ - Gemfile
80
+ - README.md
81
+ - Rakefile
82
+ - bin/console
83
+ - bin/setup
84
+ - docker-distribution-api.gemspec
85
+ - lib/docker/distribution/api.rb
86
+ - lib/docker/distribution/api/connection.rb
87
+ - lib/docker/distribution/api/manifest.rb
88
+ - lib/docker/distribution/api/util.rb
89
+ - lib/docker/distribution/api/version.rb
90
+ - lib/docker/distribution/error.rb
91
+ homepage: https://github.com/bazilio91/docker-distribution-api
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.4.8
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: API client for docker distribution.
115
+ test_files: []
116
+ has_rdoc: