Commit 24145592 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Provide full test coverage to lib/container_registry API implementation

parent a82109ee
......@@ -22,6 +22,6 @@ class Projects::ContainerRegistryController < Projects::ApplicationController
end
def tag
@tag ||= container_registry_repository[params[:id]]
@tag ||= container_registry_repository.tag(params[:id])
end
end
......@@ -336,7 +336,7 @@ class Project < ActiveRecord::Base
url = Gitlab.config.registry.api_url
host_port = Gitlab.config.registry.host_port
registry = ContainerRegistry::Registry.new(url, token: token, path: host_port)
registry[path_with_namespace]
registry.repository(path_with_namespace)
end
end
......
......@@ -2,6 +2,8 @@ module ContainerRegistry
class Blob
attr_reader :repository, :config
delegate :registry, :client, to: :repository
def initialize(repository, config)
@repository = repository
@config = config || {}
......@@ -35,10 +37,6 @@ module ContainerRegistry
revision[0..8]
end
def client
@client ||= repository.client
end
def delete
client.delete_blob(repository.name, digest)
end
......@@ -46,9 +44,5 @@ module ContainerRegistry
def 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
......@@ -22,14 +22,6 @@ module ContainerRegistry
@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?
......
......@@ -8,7 +8,7 @@ module ContainerRegistry
@client = ContainerRegistry::Client.new(uri, options)
end
def [](name)
def repository(name)
ContainerRegistry::Repository.new(self, name)
end
......
......@@ -2,19 +2,17 @@ module ContainerRegistry
class Repository
attr_reader :registry, :name
delegate :client, to: :registry
def initialize(registry, name)
@registry, @name = registry, name
end
def client
@client ||= registry.client
end
def path
[registry.path, name].compact.join('/')
end
def [](tag)
def tag(tag)
ContainerRegistry::Tag.new(self, tag)
end
......@@ -37,26 +35,14 @@ module ContainerRegistry
end
end
def blob(config)
ContainerRegistry::Blob.new(self, config)
end
def delete_tags
return unless tags
tags.all?(&: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
......@@ -2,6 +2,8 @@ module ContainerRegistry
class Tag
attr_reader :repository, :name
delegate :registry, :client, to: :repository
def initialize(repository, name)
@repository, @name = repository, name
end
......@@ -36,7 +38,7 @@ module ContainerRegistry
return @config_blob if defined?(@config_blob)
return unless manifest && manifest['config']
@config_blob = ContainerRegistry::Blob.new(repository, manifest['config'])
@config_blob = repository.blob(manifest['config'])
end
def config
......@@ -56,7 +58,7 @@ module ContainerRegistry
return unless manifest
@layers = manifest['layers'].map do |layer|
ContainerRegistry::Blob.new(repository, layer)
repository.blob(layer)
end
end
......@@ -71,19 +73,5 @@ module ContainerRegistry
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
require 'spec_helper'
describe ContainerRegistry::Blob do
let(:digest) { 'sha256:0123456789012345' }
let(:config) do
{
'digest' => digest,
'mediaType' => 'binary',
'size' => 1000
}
end
let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
let(:repository) { registry.repository('group/test') }
let(:blob) { repository.blob(config) }
it { expect(blob).to respond_to(:repository) }
it { expect(blob).to delegate_method(:registry).to(:repository) }
it { expect(blob).to delegate_method(:client).to(:repository) }
context '#path' do
subject { blob.path }
it { is_expected.to eq('example.com/group/test@sha256:0123456789012345') }
end
context '#digest' do
subject { blob.digest }
it { is_expected.to eq(digest) }
end
context '#type' do
subject { blob.type }
it { is_expected.to eq('binary') }
end
context '#revision' do
subject { blob.revision }
it { is_expected.to eq('0123456789012345') }
end
context '#short_revision' do
subject { blob.short_revision }
it { is_expected.to eq('012345678') }
end
context '#delete' do
before do
stub_request(:delete, 'http://example.com/v2/group/test/blobs/sha256:0123456789012345').
to_return(status: 200)
end
subject { blob.delete }
it { is_expected.to be_truthy }
end
end
......@@ -10,7 +10,7 @@ describe ContainerRegistry::Registry do
it { is_expected.to respond_to(:uri) }
it { is_expected.to respond_to(:path) }
it { expect(subject['test']).to_not be_nil }
it { expect(subject.repository('test')).to_not be_nil }
context '#path' do
subject { registry.path }
......
require 'spec_helper'
describe ContainerRegistry::Repository do
let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
let(:repository) { registry.repository('group/test') }
it { expect(repository).to respond_to(:registry) }
it { expect(repository).to delegate_method(:client).to(:registry) }
it { expect(repository.tag('test')).to_not be_nil }
context '#path' do
subject { repository.path }
it { is_expected.to eq('example.com/group/test') }
end
context 'manifest processing' do
before do
stub_request(:get, 'http://example.com/v2/group/test/tags/list').
with(headers: { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' }).
to_return(
status: 200,
body: JSON.dump(tags: ['test']),
headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
end
context '#manifest' do
subject { repository.manifest }
it { is_expected.to_not be_nil }
end
context '#valid?' do
subject { repository.valid? }
it { is_expected.to be_truthy }
end
context '#tags' do
subject { repository.tags }
it { is_expected.to_not be_empty }
end
end
context '#delete_tags' do
let(:tag) { ContainerRegistry::Tag.new(repository, 'tag') }
before { expect(repository).to receive(:tags).twice.and_return([tag]) }
subject { repository.delete_tags }
context 'succeeds' do
before { expect(tag).to receive(:delete).and_return(true) }
it { is_expected.to be_truthy }
end
context 'any fails' do
before { expect(tag).to receive(:delete).and_return(false) }
it { is_expected.to be_falsey }
end
end
end
require 'spec_helper'
describe ContainerRegistry::Tag do
let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
let(:repository) { registry.repository('group/test') }
let(:tag) { repository.tag('tag') }
let(:headers) { { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' } }
it { expect(tag).to respond_to(:repository) }
it { expect(tag).to delegate_method(:registry).to(:repository) }
it { expect(tag).to delegate_method(:client).to(:repository) }
context '#path' do
subject { tag.path }
it { is_expected.to eq('example.com/group/test:tag') }
end
context 'manifest processing' do
before do
stub_request(:get, 'http://example.com/v2/group/test/manifests/tag').
with(headers: headers).
to_return(
status: 200,
body: File.read(Rails.root + 'spec/fixtures/container_registry/tag_manifest.json'),
headers: { 'Content-Type' => 'application/vnd.docker.distribution.manifest.v2+json' })
end
context '#layers' do
subject { tag.layers }
it { expect(subject.length).to eq(1) }
end
context '#total_size' do
subject { tag.total_size }
it { is_expected.to eq(2319870) }
end
context 'config processing' do
before do
stub_request(:get, 'http://example.com/v2/group/test/blobs/sha256:d7a513a663c1a6dcdba9ed832ca53c02ac2af0c333322cd6ca92936d1d9917ac').
with(headers: { 'Accept' => 'application/octet-stream' }).
to_return(
status: 200,
body: File.read(Rails.root + 'spec/fixtures/container_registry/config_blob.json'))
end
context '#config' do
subject { tag.config }
it { is_expected.to_not be_nil }
end
context '#created_at' do
subject { tag.created_at }
it { is_expected.to_not be_nil }
end
end
end
context 'manifest digest' do
before do
stub_request(:head, 'http://example.com/v2/group/test/manifests/tag').
with(headers: headers).
to_return(status: 200, headers: { 'Docker-Content-Digest' => 'sha256:digest' })
end
context '#digest' do
subject { tag.digest }
it { is_expected.to eq('sha256:digest') }
end
context '#delete' do
before do
stub_request(:delete, 'http://example.com/v2/group/test/manifests/sha256:digest').
with(headers: headers).
to_return(status: 200)
end
subject { tag.delete }
it { is_expected.to be_truthy }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment