diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-05-04 14:22:54 +0200 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-05-04 14:22:54 +0200 |
commit | 9243b6d0197ee7e3f1856d7e16f750fa74341851 (patch) | |
tree | ce681fa4e77f6155409d50ef5bddbd3005f470f6 /lib | |
parent | b0ddbaa07cd780b0ed86aa4e3c24744c6426b1e1 (diff) | |
download | gitlab-ce-9243b6d0197ee7e3f1856d7e16f750fa74341851.tar.gz |
Implement Container Registry API client
Diffstat (limited to 'lib')
-rw-r--r-- | lib/image_registry/blob.rb | 47 | ||||
-rw-r--r-- | lib/image_registry/client.rb | 64 | ||||
-rw-r--r-- | lib/image_registry/config.rb | 15 | ||||
-rw-r--r-- | lib/image_registry/registry.rb | 14 | ||||
-rw-r--r-- | lib/image_registry/repository.rb | 38 | ||||
-rw-r--r-- | lib/image_registry/tag.rb | 62 | ||||
-rw-r--r-- | lib/registry_client.rb | 38 |
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 |