Add serializer matchers
This commit is contained in:
parent
9772901587
commit
800a5f8ee9
|
|
@ -15,13 +15,13 @@ module Projects
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
respond_to do |format|
|
if tag.delete
|
||||||
format.json do
|
respond_to do |format|
|
||||||
if tag.delete
|
format.json { head :no_content }
|
||||||
format.json { head :no_content }
|
end
|
||||||
else
|
else
|
||||||
format.json { head :bad_request }
|
respond_to do |format|
|
||||||
end
|
format.json { head :bad_request }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,13 @@ describe Projects::Registry::RepositoriesController do
|
||||||
expect { go_to_index }.to change { ContainerRepository.all.count }.by(1)
|
expect { go_to_index }.to change { ContainerRepository.all.count }.by(1)
|
||||||
expect(ContainerRepository.first).to be_root_repository
|
expect(ContainerRepository.first).to be_root_repository
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'json has a list of projects' do
|
||||||
|
go_to_index(format: :json)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(response).to match_response_schema('registry/repositories')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there are no tags for this repository' do
|
context 'when there are no tags for this repository' do
|
||||||
|
|
@ -58,6 +65,31 @@ describe Projects::Registry::RepositoriesController do
|
||||||
it 'does not ensure root container repository' do
|
it 'does not ensure root container repository' do
|
||||||
expect { go_to_index }.not_to change { ContainerRepository.all.count }
|
expect { go_to_index }.not_to change { ContainerRepository.all.count }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'responds with json if asked' do
|
||||||
|
go_to_index(format: :json)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(json_response).to be_kind_of(Array)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE destroy' do
|
||||||
|
context 'when root container repository exists' do
|
||||||
|
let!(:repository) do
|
||||||
|
create(:container_repository, :root, project: project)
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_container_registry_tags(repository: :any, tags: [])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes a repository' do
|
||||||
|
expect { delete_repository(repository) }.to change { ContainerRepository.all.count }.by(-1)
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:no_content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -77,8 +109,16 @@ describe Projects::Registry::RepositoriesController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def go_to_index
|
def go_to_index(format: :html)
|
||||||
get :index, namespace_id: project.namespace,
|
get :index, namespace_id: project.namespace,
|
||||||
project_id: project
|
project_id: project,
|
||||||
|
format: format
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_repository(repository)
|
||||||
|
delete :destroy, namespace_id: project.namespace,
|
||||||
|
project_id: project,
|
||||||
|
id: repository,
|
||||||
|
format: :json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,83 @@ describe Projects::Registry::TagsController do
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let(:project) { create(:project, :private) }
|
let(:project) { create(:project, :private) }
|
||||||
|
|
||||||
|
let(:repository) do
|
||||||
|
create(:container_repository, name: 'image', project: project)
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
stub_container_registry_config(enabled: true)
|
stub_container_registry_config(enabled: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when user has access to registry' do
|
describe 'GET index' do
|
||||||
before do
|
let(:tags) do
|
||||||
project.add_developer(user)
|
40.times.map { |i| "tag#{i}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST destroy' do
|
before do
|
||||||
|
stub_container_registry_tags(repository: /image/, tags: tags)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user can control the registry' do
|
||||||
|
before do
|
||||||
|
project.add_developer(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'receive a list of tags' do
|
||||||
|
get_tags
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(response).to match_response_schema('registry/tags')
|
||||||
|
expect(response).to include_pagination_headers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user can read the registry' do
|
||||||
|
before do
|
||||||
|
project.add_reporter(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'receive a list of tags' do
|
||||||
|
get_tags
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(response).to match_response_schema('registry/tags')
|
||||||
|
expect(response).to include_pagination_headers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user does not have access to registry' do
|
||||||
|
before do
|
||||||
|
project.add_guest(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not receive a list of tags' do
|
||||||
|
get_tags
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:not_found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def get_tags
|
||||||
|
get :index, namespace_id: project.namespace,
|
||||||
|
project_id: project,
|
||||||
|
repository_id: repository,
|
||||||
|
format: :json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST destroy' do
|
||||||
|
context 'when user has access to registry' do
|
||||||
|
before do
|
||||||
|
project.add_developer(user)
|
||||||
|
end
|
||||||
|
|
||||||
context 'when there is matching tag present' do
|
context 'when there is matching tag present' do
|
||||||
before do
|
before do
|
||||||
stub_container_registry_tags(repository: /image/, tags: %w[rc1 test.])
|
stub_container_registry_tags(repository: repository.path, tags: %w[rc1 test.])
|
||||||
end
|
|
||||||
|
|
||||||
let(:repository) do
|
|
||||||
create(:container_repository, name: 'image', project: project)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'makes it possible to delete regular tag' do
|
it 'makes it possible to delete regular tag' do
|
||||||
|
|
@ -37,12 +96,15 @@ describe Projects::Registry::TagsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def destroy_tag(name)
|
private
|
||||||
post :destroy, namespace_id: project.namespace,
|
|
||||||
project_id: project,
|
def destroy_tag(name)
|
||||||
repository_id: repository,
|
post :destroy, namespace_id: project.namespace,
|
||||||
id: name
|
project_id: project,
|
||||||
|
repository_id: repository,
|
||||||
|
id: name,
|
||||||
|
format: :json
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe "Container Registry" do
|
describe "Container Registry", js: true do
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
let(:project) { create(:project) }
|
let(:project) { create(:project) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "repository.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required" : [
|
||||||
|
"id",
|
||||||
|
"path",
|
||||||
|
"location",
|
||||||
|
"tags_path"
|
||||||
|
],
|
||||||
|
"properties" : {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tags_path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"destroy_path": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required" : [
|
||||||
|
"name",
|
||||||
|
"location"
|
||||||
|
],
|
||||||
|
"properties" : {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"revision": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"total_size": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"destroy_path": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "tag.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ContainerRepositoryEntity do
|
||||||
|
let(:entity) do
|
||||||
|
described_class.new(repository, request: request)
|
||||||
|
end
|
||||||
|
|
||||||
|
set(:project) { create(:project) }
|
||||||
|
set(:user) { create(:user) }
|
||||||
|
set(:repository) { create(:container_repository, project: project) }
|
||||||
|
|
||||||
|
let(:request) { double('request') }
|
||||||
|
|
||||||
|
subject { entity.as_json }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_container_registry_config(enabled: true)
|
||||||
|
allow(request).to receive(:project).and_return(project)
|
||||||
|
allow(request).to receive(:current_user).and_return(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exposes required informations' do
|
||||||
|
expect(subject).to include(:id, :path, :location, :tags_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user can manage repositories' do
|
||||||
|
before do
|
||||||
|
project.add_developer(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exposes destroy_path' do
|
||||||
|
expect(subject).to include(:destroy_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user cannot manage repositories' do
|
||||||
|
it 'does not expose destroy_path' do
|
||||||
|
expect(subject).not_to include(:destroy_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ContainerTagEntity do
|
||||||
|
let(:entity) do
|
||||||
|
described_class.new(tag, request: request)
|
||||||
|
end
|
||||||
|
|
||||||
|
set(:project) { create(:project) }
|
||||||
|
set(:user) { create(:user) }
|
||||||
|
set(:repository) { create(:container_repository, name: 'image', project: project) }
|
||||||
|
|
||||||
|
let(:request) { double('request') }
|
||||||
|
let(:tag) { repository.tag('test') }
|
||||||
|
|
||||||
|
subject { entity.as_json }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_container_registry_config(enabled: true)
|
||||||
|
stub_container_registry_tags(repository: /image/, tags: %w[test])
|
||||||
|
allow(request).to receive(:project).and_return(project)
|
||||||
|
allow(request).to receive(:current_user).and_return(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exposes required informations' do
|
||||||
|
expect(subject).to include(:name, :location, :revision, :total_size, :created_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user can manage repositories' do
|
||||||
|
before do
|
||||||
|
project.add_developer(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exposes destroy_path' do
|
||||||
|
expect(subject).to include(:destroy_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user cannot manage repositories' do
|
||||||
|
it 'does not expose destroy_path' do
|
||||||
|
expect(subject).not_to include(:destroy_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -39,11 +39,11 @@ module StubGitlabCalls
|
||||||
.and_return({ 'tags' => tags })
|
.and_return({ 'tags' => tags })
|
||||||
|
|
||||||
allow_any_instance_of(ContainerRegistry::Client)
|
allow_any_instance_of(ContainerRegistry::Client)
|
||||||
.to receive(:repository_manifest).with(repository)
|
.to receive(:repository_manifest).with(repository, anything)
|
||||||
.and_return(stub_container_registry_tag_manifest)
|
.and_return(stub_container_registry_tag_manifest)
|
||||||
|
|
||||||
allow_any_instance_of(ContainerRegistry::Client)
|
allow_any_instance_of(ContainerRegistry::Client)
|
||||||
.to receive(:blob).with(repository)
|
.to receive(:blob).with(repository, anything, 'application/octet-stream')
|
||||||
.and_return(stub_container_registry_blob)
|
.and_return(stub_container_registry_blob)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe 'projects/registry/repositories/index' do
|
|
||||||
let(:group) { create(:group, path: 'group') }
|
|
||||||
let(:project) { create(:project, group: group, path: 'test') }
|
|
||||||
|
|
||||||
let(:repository) do
|
|
||||||
create(:container_repository, project: project, name: 'image')
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
|
||||||
stub_container_registry_config(enabled: true,
|
|
||||||
host_port: 'registry.gitlab',
|
|
||||||
api_url: 'http://registry.gitlab')
|
|
||||||
|
|
||||||
stub_container_registry_tags(repository: :any, tags: [:latest])
|
|
||||||
|
|
||||||
assign(:project, project)
|
|
||||||
assign(:images, [repository])
|
|
||||||
|
|
||||||
allow(view).to receive(:can?).and_return(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'contains container repository path' do
|
|
||||||
render
|
|
||||||
|
|
||||||
expect(rendered).to have_content 'group/test/image'
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'contains attribute for copying tag location into clipboard' do
|
|
||||||
render
|
|
||||||
|
|
||||||
expect(rendered).to have_css 'button[data-clipboard-text="docker pull ' \
|
|
||||||
'registry.gitlab/group/test/image:latest"]'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Loading…
Reference in New Issue