From 08396be619eee2e71c2f5f7aa27eea6f5ddf10ff Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 9 May 2016 22:14:46 +0300 Subject: Rename ImageRegistry to ContainerRegistry --- lib/container_registry/blob.rb | 51 ++++++++++++++++++++++++ lib/container_registry/client.rb | 64 ++++++++++++++++++++++++++++++ lib/container_registry/config.rb | 15 ++++++++ lib/container_registry/registry.rb | 14 +++++++ lib/container_registry/repository.rb | 55 ++++++++++++++++++++++++++ lib/container_registry/tag.rb | 75 ++++++++++++++++++++++++++++++++++++ 6 files changed, 274 insertions(+) create mode 100644 lib/container_registry/blob.rb create mode 100644 lib/container_registry/client.rb create mode 100644 lib/container_registry/config.rb create mode 100644 lib/container_registry/registry.rb create mode 100644 lib/container_registry/repository.rb create mode 100644 lib/container_registry/tag.rb (limited to 'lib/container_registry') diff --git a/lib/container_registry/blob.rb b/lib/container_registry/blob.rb new file mode 100644 index 00000000000..e0d9923f217 --- /dev/null +++ b/lib/container_registry/blob.rb @@ -0,0 +1,51 @@ +module ContainerRegistry + 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 + + def mount_to(to_repository) + client.repository_mount_blob(to_repository.name, digest, repository.name) + end + end +end diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb new file mode 100644 index 00000000000..b823428344b --- /dev/null +++ b/lib/container_registry/client.rb @@ -0,0 +1,64 @@ +require 'faraday' +require 'faraday_middleware' + +module ContainerRegistry + 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(:authorization, :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}/blobs/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/container_registry/config.rb b/lib/container_registry/config.rb new file mode 100644 index 00000000000..626b36cbaa9 --- /dev/null +++ b/lib/container_registry/config.rb @@ -0,0 +1,15 @@ +module ContainerRegistry + 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/container_registry/registry.rb b/lib/container_registry/registry.rb new file mode 100644 index 00000000000..f866862db22 --- /dev/null +++ b/lib/container_registry/registry.rb @@ -0,0 +1,14 @@ +module ContainerRegistry + class Registry + attr_reader :uri, :client + + def initialize(uri, options = {}) + @uri = URI.parse(uri) + @client = ContainerRegistry::Client.new(uri, options) + end + + def [](name) + ContainerRegistry::Repository.new(self, name) + end + end +end diff --git a/lib/container_registry/repository.rb b/lib/container_registry/repository.rb new file mode 100644 index 00000000000..c930878d265 --- /dev/null +++ b/lib/container_registry/repository.rb @@ -0,0 +1,55 @@ +module ContainerRegistry + class Repository + attr_reader :registry, :name + + def initialize(registry, name) + @registry, @name = registry, name + end + + def client + @client ||= registry.client + end + + def [](tag) + ContainerRegistry::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| + ContainerRegistry::Tag.new(self, tag) + end + @tags ||= [] + end + + def delete_tags + return unless tags + tags.each(:delete) + end + + def mount_blob(blob) + return unless blob + client.repository_mount_blob(name, blob.digest, blob.repository.name) + end + + def mount_manifest(tag, manifest) + client.put_repository_manifest(name, tag, manifest) + end + + def copy_to(other_repository) + tags.all? do |tag| + tag.copy_to(other_repository) + end + end + end +end diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb new file mode 100644 index 00000000000..324778bdf2a --- /dev/null +++ b/lib/container_registry/tag.rb @@ -0,0 +1,75 @@ +module ContainerRegistry + 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_blob + return @config_blob if defined?(@config_blob) + return unless manifest && manifest['config'] + @config_blob = ContainerRegistry::Blob.new(repository, manifest['config']) + end + + def config + return unless config_blob + @config ||= ContainerRegistry::Config.new(self, config_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| + ContainerRegistry::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 copy_to(repository) + return unless manifest + layers.each do |blob| + repository.mount_blob(blob) + end + repository.mount_blob(config_blob) + repository.mount_manifest(name, manifest.to_json) + end + + def client + @client ||= repository.client + end + end +end -- cgit v1.2.3