summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2016-05-04 14:22:54 +0200
committerKamil Trzcinski <ayufan@ayufan.eu>2016-05-04 14:22:54 +0200
commit9243b6d0197ee7e3f1856d7e16f750fa74341851 (patch)
treece681fa4e77f6155409d50ef5bddbd3005f470f6 /lib
parentb0ddbaa07cd780b0ed86aa4e3c24744c6426b1e1 (diff)
downloadgitlab-ce-9243b6d0197ee7e3f1856d7e16f750fa74341851.tar.gz
Implement Container Registry API client
Diffstat (limited to 'lib')
-rw-r--r--lib/image_registry/blob.rb47
-rw-r--r--lib/image_registry/client.rb64
-rw-r--r--lib/image_registry/config.rb15
-rw-r--r--lib/image_registry/registry.rb14
-rw-r--r--lib/image_registry/repository.rb38
-rw-r--r--lib/image_registry/tag.rb62
-rw-r--r--lib/registry_client.rb38
7 files changed, 240 insertions, 38 deletions
diff --git a/lib/image_registry/blob.rb b/lib/image_registry/blob.rb
new file mode 100644
index 00000000000..1aeeba7a686
--- /dev/null
+++ b/lib/image_registry/blob.rb
@@ -0,0 +1,47 @@
+module ImageRegistry
+ class Blob
+ attr_reader :repository, :config
+
+ def initialize(repository, config)
+ @repository = repository
+ @config = config || {}
+ end
+
+ def valid?
+ digest.present?
+ end
+
+ def digest
+ config['digest']
+ end
+
+ def type
+ config['mediaType']
+ end
+
+ def size
+ config['size']
+ end
+
+ def revision
+ digest.split(':')[1]
+ end
+
+ def short_revision
+ revision[0..8]
+ end
+
+ def client
+ @client ||= repository.client
+ end
+
+ def delete
+ client.delete_blob(repository.name, digest)
+ end
+
+ def data
+ return @data if defined?(@data)
+ @data ||= client.blob(repository.name, digest, type)
+ end
+ end
+end
diff --git a/lib/image_registry/client.rb b/lib/image_registry/client.rb
new file mode 100644
index 00000000000..b2e43ce4aeb
--- /dev/null
+++ b/lib/image_registry/client.rb
@@ -0,0 +1,64 @@
+require 'faraday'
+require 'faraday_middleware'
+
+module ImageRegistry
+ class Client
+ attr_accessor :uri
+
+ MANIFEST_VERSION = 'application/vnd.docker.distribution.manifest.v2+json'
+
+ def initialize(base_uri, options = {})
+ @base_uri = base_uri
+ @faraday = Faraday.new(@base_uri) do |builder|
+ builder.request :json
+ builder.headers['Accept'] = MANIFEST_VERSION
+
+ builder.response :json, :content_type => /\bjson$/
+ builder.response :json, :content_type => 'application/vnd.docker.distribution.manifest.v1+prettyjws'
+
+ if options[:user] && options[:password]
+ builder.request(:basic_auth, options[:user].to_s, options[:password].to_s)
+ elsif options[:token]
+ builder.request(:authentication, :Bearer, options[:token].to_s)
+ end
+
+ builder.adapter :net_http
+ end
+ end
+
+ def repository_tags(name)
+ @faraday.get("/v2/#{name}/tags/list").body
+ end
+
+ def repository_manifest(name, reference)
+ @faraday.get("/v2/#{name}/manifests/#{reference}").body
+ end
+
+ def put_repository_manifest(name, reference, manifest)
+ @faraday.put("/v2/#{name}/manifests/#{reference}", manifest, { "Content-Type" => MANIFEST_VERSION }).success?
+ end
+
+ def repository_mount_blob(name, digest, from)
+ @faraday.post("/v2/#{name}/blobls/uploads/?mount=#{digest}&from=#{from}").status == 201
+ end
+
+ def repository_tag_digest(name, reference)
+ response = @faraday.head("/v2/#{name}/manifests/#{reference}")
+ response.headers['docker-content-digest'] if response.success?
+ end
+
+ def delete_repository_tag(name, reference)
+ @faraday.delete("/v2/#{name}/manifests/#{reference}").success?
+ end
+
+ def blob(name, digest, type = nil)
+ headers = {}
+ headers['Accept'] = type if type
+ @faraday.get("/v2/#{name}/blobs/#{digest}", nil, headers).body
+ end
+
+ def delete_blob(name, digest)
+ @faraday.delete("/v2/#{name}/blobs/#{digest}").success?
+ end
+ end
+end
diff --git a/lib/image_registry/config.rb b/lib/image_registry/config.rb
new file mode 100644
index 00000000000..1c2abec1bfa
--- /dev/null
+++ b/lib/image_registry/config.rb
@@ -0,0 +1,15 @@
+module ImageRegistry
+ class Config
+ attr_reader :tag, :blob, :data
+
+ def initialize(tag, blob)
+ @tag, @blob = tag, blob
+ @data = JSON.parse(blob.data)
+ end
+
+ def [](key)
+ return unless data
+ data[key]
+ end
+ end
+end
diff --git a/lib/image_registry/registry.rb b/lib/image_registry/registry.rb
new file mode 100644
index 00000000000..d8de8e392e9
--- /dev/null
+++ b/lib/image_registry/registry.rb
@@ -0,0 +1,14 @@
+module ImageRegistry
+ class Registry
+ attr_reader :uri, :client
+
+ def initialize(uri, options = {})
+ @uri = URI.parse(uri)
+ @client = ImageRegistry::Client.new(uri, options)
+ end
+
+ def [](name)
+ ImageRegistry::Repository.new(self, name)
+ end
+ end
+end
diff --git a/lib/image_registry/repository.rb b/lib/image_registry/repository.rb
new file mode 100644
index 00000000000..f4f4ba65afc
--- /dev/null
+++ b/lib/image_registry/repository.rb
@@ -0,0 +1,38 @@
+module ImageRegistry
+ class Repository
+ attr_reader :registry, :name
+
+ def initialize(registry, name)
+ @registry, @name = registry, name
+ end
+
+ def client
+ @client ||= registry.client
+ end
+
+ def [](tag)
+ ImageRegistry::Tag.new(self, tag)
+ end
+
+ def manifest
+ return @manifest if defined?(@manifest)
+ @manifest = client.repository_tags(name)
+ end
+
+ def valid?
+ manifest.present?
+ end
+
+ def tags
+ return @tags if defined?(@tags)
+ return unless manifest && manifest['tags']
+ @tags = manifest['tags'].map do |tag|
+ ImageRegistry::Tag.new(self, tag)
+ end
+ end
+
+ def delete
+ tags.each(:delete)
+ end
+ end
+end
diff --git a/lib/image_registry/tag.rb b/lib/image_registry/tag.rb
new file mode 100644
index 00000000000..2bf0b8e345f
--- /dev/null
+++ b/lib/image_registry/tag.rb
@@ -0,0 +1,62 @@
+module ImageRegistry
+ class Tag
+ attr_reader :repository, :name
+
+ def initialize(repository, name)
+ @repository, @name = repository, name
+ end
+
+ def valid?
+ manifest.present?
+ end
+
+ def manifest
+ return @manifest if defined?(@manifest)
+ @manifest = client.repository_manifest(repository.name, name)
+ end
+
+ def [](key)
+ return unless manifest
+ manifest[key]
+ end
+
+ def digest
+ return @digest if defined?(@digest)
+ @digest = client.repository_tag_digest(repository.name, name)
+ end
+
+ def config
+ return @config if defined?(@config)
+ return unless manifest && manifest['config']
+ blob = ImageRegistry::Blob.new(repository, manifest['config'])
+ @config = ImageRegistry::Config.new(self, blob)
+ end
+
+ def created_at
+ return unless config
+ @created_at ||= DateTime.rfc3339(config['created'])
+ end
+
+ def layers
+ return @layers if defined?(@layers)
+ return unless manifest
+ @layers = manifest['layers'].map do |layer|
+ ImageRegistry::Blob.new(repository, layer)
+ end
+ end
+
+ def total_size
+ return unless layers
+ layers.map(&:size).sum
+ end
+
+ def delete
+ return unless digest
+ client.delete_repository_tag(repository.name, digest)
+ end
+
+ def client
+ @client ||= repository.client
+ end
+ end
+end
diff --git a/lib/registry_client.rb b/lib/registry_client.rb
deleted file mode 100644
index 87518a7b39c..00000000000
--- a/lib/registry_client.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require 'HTTParty'
-
-class RegistryClient
- attr_accessor :uri
-
- def initialize(uri)
- @uri = uri
- end
-
- def tags(name)
- response = HTTParty.get("#{uri}/v2/#{name}/tags/list")
- response.parsed_response['tags']
- end
-
- def tag(name, reference)
- response = HTTParty.get("#{uri}/v2/#{name}/manifests/#{reference}")
- JSON.parse(response)
- end
-
- def tag_digest(name, reference)
- response = HTTParty.head("#{uri}/v2/#{name}/manifests/#{reference}")
- response.headers['docker-content-digest'].split(':')
- end
-
- def delete_tag(name, reference)
- response = HTTParty.delete("#{uri}/v2/#{name}/manifests/#{reference}")
- response.parsed_response
- end
-
- def blob_size(name, digest)
- response = HTTParty.head("#{uri}/v2/#{name}/blobs/#{digest}")
- response.headers.content_length
- end
-
- def delete_blob(name, digest)
- HTTParty.delete("#{uri}/v2/#{name}/blobs/#{digest}")
- end
-end