Fixes broken and missing tests
This commit is contained in:
parent
246df2bd11
commit
e4fa80f3b6
32 changed files with 211 additions and 210 deletions
|
@ -3,14 +3,14 @@
|
|||
*/
|
||||
|
||||
.container-image {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid $white-normal;
|
||||
}
|
||||
|
||||
.container-image-head {
|
||||
padding: 0px 16px;
|
||||
padding: 0 16px;
|
||||
line-height: 4;
|
||||
}
|
||||
|
||||
.table.tags {
|
||||
margin-bottom: 0px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ class Projects::ContainerRegistryController < Projects::ApplicationController
|
|||
redirect_to url, alert: 'Failed to remove image'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -22,7 +22,7 @@ class ContainerImage < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def name_with_namespace
|
||||
[container_registry_path_with_namespace, name].compact.join('/')
|
||||
[container_registry_path_with_namespace, name].reject(&:blank?).join('/')
|
||||
end
|
||||
|
||||
def tag(tag)
|
||||
|
@ -55,6 +55,8 @@ class ContainerImage < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
# rubocop:disable RedundantReturn
|
||||
|
||||
def self.split_namespace(full_path)
|
||||
image_name = full_path.split('/').last
|
||||
namespace = full_path.gsub(/(.*)(#{Regexp.escape('/' + image_name)})/, '\1')
|
||||
|
|
|
@ -118,8 +118,8 @@ class Namespace < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def move_dir
|
||||
if any_project_has_container_registry_tags?
|
||||
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
|
||||
if any_project_has_container_registry_images?
|
||||
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has images in container registry')
|
||||
end
|
||||
|
||||
# Move the namespace directory in all storages paths used by member projects
|
||||
|
@ -154,8 +154,8 @@ class Namespace < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def any_project_has_container_registry_tags?
|
||||
projects.any?(&:has_container_registry_tags?)
|
||||
def any_project_has_container_registry_images?
|
||||
projects.any? { |project| project.container_images.present? }
|
||||
end
|
||||
|
||||
def send_update_instructions
|
||||
|
|
|
@ -421,18 +421,12 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def container_registry_repository_url
|
||||
def container_registry_url
|
||||
if Gitlab.config.registry.enabled
|
||||
"#{Gitlab.config.registry.host_port}/#{container_registry_path_with_namespace}"
|
||||
end
|
||||
end
|
||||
|
||||
def has_container_registry_tags?
|
||||
return unless container_images
|
||||
|
||||
container_images.first.tags.any?
|
||||
end
|
||||
|
||||
def commit(ref = 'HEAD')
|
||||
repository.commit(ref)
|
||||
end
|
||||
|
@ -913,11 +907,11 @@ class Project < ActiveRecord::Base
|
|||
|
||||
expire_caches_before_rename(old_path_with_namespace)
|
||||
|
||||
if has_container_registry_tags?
|
||||
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present"
|
||||
if container_images.present?
|
||||
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry images are present"
|
||||
|
||||
# we currently doesn't support renaming repository if it contains tags in container registry
|
||||
raise StandardError.new('Project cannot be renamed, because tags are present in its container registry')
|
||||
# we currently doesn't support renaming repository if it contains images in container registry
|
||||
raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
|
||||
end
|
||||
|
||||
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
|
||||
|
@ -1264,7 +1258,7 @@ class Project < ActiveRecord::Base
|
|||
]
|
||||
|
||||
if container_registry_enabled?
|
||||
variables << { key: 'CI_REGISTRY_IMAGE', value: container_registry_repository_url, public: true }
|
||||
variables << { key: 'CI_REGISTRY_IMAGE', value: container_registry_url, public: true }
|
||||
end
|
||||
|
||||
variables
|
||||
|
|
|
@ -16,7 +16,8 @@ module Auth
|
|||
{ token: authorized_token(scope).encoded }
|
||||
end
|
||||
|
||||
def self.full_access_token(names)
|
||||
def self.full_access_token(*names)
|
||||
names = names.flatten
|
||||
registry = Gitlab.config.registry
|
||||
token = JSONWebToken::RSAToken.new(registry.key)
|
||||
token.issuer = registry.issuer
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module ContainerImages
|
||||
class DestroyService < BaseService
|
||||
|
||||
class DestroyError < StandardError; end
|
||||
|
||||
def execute(container_image)
|
||||
|
|
|
@ -36,9 +36,9 @@ module Projects
|
|||
raise TransferError.new("Project with same path in target namespace already exists")
|
||||
end
|
||||
|
||||
if project.has_container_registry_tags?
|
||||
# we currently doesn't support renaming repository if it contains tags in container registry
|
||||
raise TransferError.new('Project cannot be transferred, because tags are present in its container registry')
|
||||
unless project.container_images.empty?
|
||||
# we currently doesn't support renaming repository if it contains images in container registry
|
||||
raise TransferError.new('Project cannot be transferred, because images are present in its container registry')
|
||||
end
|
||||
|
||||
project.expire_caches_before_rename(old_path)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
= escape_once(image.name)
|
||||
= clipboard_button(clipboard_text: "docker pull #{image.path}")
|
||||
.controls.hidden-xs.pull-right
|
||||
= link_to namespace_project_container_registry_path(@project.namespace, @project, image.id), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do
|
||||
= link_to namespace_project_container_registry_path(@project.namespace, @project, image.id), class: 'btn btn-remove has-tooltip', title: "Remove image", data: { confirm: "Are you sure?" }, method: :delete do
|
||||
= icon("trash cred")
|
||||
|
||||
|
||||
|
|
|
@ -25,5 +25,5 @@
|
|||
- if can?(current_user, :update_container_image, @project)
|
||||
%td.content
|
||||
.controls.hidden-xs.pull-right
|
||||
= link_to namespace_project_container_registry_path(@project.namespace, @project, { id: tag.repository.id, tag: tag.name} ), class: 'btn btn-remove has-tooltip', title: "Remove", data: { confirm: "Are you sure?" }, method: :delete do
|
||||
= link_to namespace_project_container_registry_path(@project.namespace, @project, { id: tag.repository.id, tag: tag.name} ), class: 'btn btn-remove has-tooltip', title: "Remove tag", data: { confirm: "Are you sure?" }, method: :delete do
|
||||
= icon("trash cred")
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
%br
|
||||
Then you are free to create and upload a container image with build and push commands:
|
||||
%pre
|
||||
docker build -t #{escape_once(@project.container_registry_repository_url)} .
|
||||
docker build -t #{escape_once(@project.container_registry_url)} .
|
||||
%br
|
||||
docker push #{escape_once(@project.container_registry_repository_url)}
|
||||
docker push #{escape_once(@project.container_registry_url)}
|
||||
|
||||
- if @images.blank?
|
||||
.nothing-here-block No container images in Container Registry for this project.
|
||||
|
|
|
@ -109,6 +109,7 @@ ActiveRecord::Schema.define(version: 20170215200045) do
|
|||
t.boolean "html_emails_enabled", default: true
|
||||
t.string "plantuml_url"
|
||||
t.boolean "plantuml_enabled"
|
||||
t.string "container_registry_access_token"
|
||||
t.integer "max_pages_size", default: 100, null: false
|
||||
t.integer "terminal_max_session_time", default: 0, null: false
|
||||
end
|
||||
|
@ -392,6 +393,11 @@ ActiveRecord::Schema.define(version: 20170215200045) do
|
|||
|
||||
add_index "ci_variables", ["gl_project_id"], name: "index_ci_variables_on_gl_project_id", using: :btree
|
||||
|
||||
create_table "container_images", force: :cascade do |t|
|
||||
t.integer "project_id"
|
||||
t.string "name"
|
||||
end
|
||||
|
||||
create_table "deploy_keys_projects", force: :cascade do |t|
|
||||
t.integer "deploy_key_id", null: false
|
||||
t.integer "project_id", null: false
|
||||
|
|
|
@ -46,9 +46,7 @@ module API
|
|||
if project
|
||||
container_image = project.container_images.find_or_create_by(name: container_image_name)
|
||||
|
||||
if container_image.valid?
|
||||
puts('Valid!')
|
||||
else
|
||||
unless container_image.valid?
|
||||
render_api_error!({ error: "Failed to create container image!" }, 400)
|
||||
end
|
||||
else
|
||||
|
|
|
@ -38,11 +38,11 @@ module ContainerRegistry
|
|||
end
|
||||
|
||||
def delete
|
||||
client.delete_blob(repository.name, digest)
|
||||
client.delete_blob(repository.name_with_namespace, digest)
|
||||
end
|
||||
|
||||
def data
|
||||
@data ||= client.blob(repository.name, digest, type)
|
||||
@data ||= client.blob(repository.name_with_namespace, digest, type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,10 +8,6 @@ module ContainerRegistry
|
|||
@client = ContainerRegistry::Client.new(uri, options)
|
||||
end
|
||||
|
||||
def repository(name)
|
||||
ContainerRegistry::Repository.new(self, name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_path
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
module ContainerRegistry
|
||||
class Repository
|
||||
attr_reader :registry, :name
|
||||
|
||||
delegate :client, to: :registry
|
||||
|
||||
def initialize(registry, name)
|
||||
@registry, @name = registry, name
|
||||
end
|
||||
|
||||
def path
|
||||
[registry.path, name].compact.join('/')
|
||||
end
|
||||
|
||||
def tag(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
|
||||
end
|
||||
|
||||
def blob(config)
|
||||
ContainerRegistry::Blob.new(self, config)
|
||||
end
|
||||
|
||||
def delete_tags
|
||||
return unless tags
|
||||
|
||||
tags.all?(&:delete)
|
||||
end
|
||||
end
|
||||
end
|
21
spec/factories/container_images.rb
Normal file
21
spec/factories/container_images.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
FactoryGirl.define do
|
||||
factory :container_image do
|
||||
name "test_container_image"
|
||||
project
|
||||
|
||||
transient do
|
||||
tags ['tag']
|
||||
stubbed true
|
||||
end
|
||||
|
||||
after(:build) do |image, evaluator|
|
||||
if evaluator.stubbed
|
||||
allow(Gitlab.config.registry).to receive(:enabled).and_return(true)
|
||||
allow(image.client).to receive(:repository_tags).and_return({
|
||||
name: image.name_with_namespace,
|
||||
tags: evaluator.tags
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,15 +2,18 @@ require 'spec_helper'
|
|||
|
||||
describe "Container Registry" do
|
||||
let(:project) { create(:empty_project) }
|
||||
let(:repository) { project.container_registry_repository }
|
||||
let(:registry) { project.container_registry }
|
||||
let(:tag_name) { 'latest' }
|
||||
let(:tags) { [tag_name] }
|
||||
let(:container_image) { create(:container_image) }
|
||||
let(:image_name) { container_image.name }
|
||||
|
||||
before do
|
||||
login_as(:user)
|
||||
project.team << [@user, :developer]
|
||||
stub_container_registry_tags(*tags)
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags(*tags)
|
||||
project.container_images << container_image unless container_image.nil?
|
||||
allow(Auth::ContainerRegistryAuthenticationService).to receive(:full_access_token).and_return('token')
|
||||
end
|
||||
|
||||
|
@ -19,15 +22,26 @@ describe "Container Registry" do
|
|||
visit namespace_project_container_registry_index_path(project.namespace, project)
|
||||
end
|
||||
|
||||
context 'when no tags' do
|
||||
let(:tags) { [] }
|
||||
context 'when no images' do
|
||||
let(:container_image) { }
|
||||
|
||||
it { expect(page).to have_content('No images in Container Registry for this project') }
|
||||
it { expect(page).to have_content('No container images in Container Registry for this project') }
|
||||
end
|
||||
|
||||
context 'when there are tags' do
|
||||
it { expect(page).to have_content(tag_name) }
|
||||
it { expect(page).to have_content('d7a513a66') }
|
||||
context 'when there are images' do
|
||||
it { expect(page).to have_content(image_name) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'DELETE /:project/container_registry/:image_id' do
|
||||
before do
|
||||
visit namespace_project_container_registry_index_path(project.namespace, project)
|
||||
end
|
||||
|
||||
it do
|
||||
expect_any_instance_of(ContainerImage).to receive(:delete_tags).and_return(true)
|
||||
|
||||
click_on 'Remove image'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,7 +53,7 @@ describe "Container Registry" do
|
|||
it do
|
||||
expect_any_instance_of(::ContainerRegistry::Tag).to receive(:delete).and_return(true)
|
||||
|
||||
click_on 'Remove'
|
||||
click_on 'Remove tag'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -429,9 +429,12 @@ describe "Internal Project Access", feature: true do
|
|||
end
|
||||
|
||||
describe "GET /:project_path/container_registry" do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_tags('latest')
|
||||
stub_container_registry_config(enabled: true)
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
subject { namespace_project_container_registry_index_path(project.namespace, project) }
|
||||
|
|
|
@ -418,9 +418,12 @@ describe "Private Project Access", feature: true do
|
|||
end
|
||||
|
||||
describe "GET /:project_path/container_registry" do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_tags('latest')
|
||||
stub_container_registry_config(enabled: true)
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
subject { namespace_project_container_registry_index_path(project.namespace, project) }
|
||||
|
|
|
@ -429,9 +429,12 @@ describe "Public Project Access", feature: true do
|
|||
end
|
||||
|
||||
describe "GET /:project_path/container_registry" do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_tags('latest')
|
||||
stub_container_registry_config(enabled: true)
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
subject { namespace_project_container_registry_index_path(project.namespace, project) }
|
||||
|
|
|
@ -9,12 +9,19 @@ describe ContainerRegistry::Blob do
|
|||
'size' => 1000
|
||||
}
|
||||
end
|
||||
let(:token) { 'authorization-token' }
|
||||
|
||||
let(:registry) { ContainerRegistry::Registry.new('http://example.com', token: token) }
|
||||
let(:repository) { registry.repository('group/test') }
|
||||
let(:token) { 'token' }
|
||||
|
||||
let(:group) { create(:group, name: 'group') }
|
||||
let(:project) { create(:project, path: 'test', group: group) }
|
||||
let(:example_host) { 'example.com' }
|
||||
let(:registry_url) { 'http://' + example_host }
|
||||
let(:repository) { create(:container_image, name: '', project: project) }
|
||||
let(:blob) { repository.blob(config) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true, api_url: registry_url, host_port: example_host)
|
||||
end
|
||||
|
||||
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) }
|
||||
|
|
|
@ -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.repository('test')).not_to be_nil }
|
||||
it { expect(subject).not_to be_nil }
|
||||
|
||||
context '#path' do
|
||||
subject { registry.path }
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
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')).not_to 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/json' })
|
||||
end
|
||||
|
||||
context '#manifest' do
|
||||
subject { repository.manifest }
|
||||
|
||||
it { is_expected.not_to 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.not_to 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
|
|
@ -1,11 +1,18 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ContainerRegistry::Tag do
|
||||
let(:registry) { ContainerRegistry::Registry.new('http://example.com') }
|
||||
let(:repository) { registry.repository('group/test') }
|
||||
let(:group) { create(:group, name: 'group') }
|
||||
let(:project) { create(:project, path: 'test', group: group) }
|
||||
let(:example_host) { 'example.com' }
|
||||
let(:registry_url) { 'http://' + example_host }
|
||||
let(:repository) { create(:container_image, name: '', project: project) }
|
||||
let(:tag) { repository.tag('tag') }
|
||||
let(:headers) { { 'Accept' => 'application/vnd.docker.distribution.manifest.v2+json' } }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true, api_url: registry_url, host_port: example_host)
|
||||
end
|
||||
|
||||
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) }
|
||||
|
|
|
@ -114,6 +114,8 @@ merge_access_levels:
|
|||
- protected_branch
|
||||
push_access_levels:
|
||||
- protected_branch
|
||||
container_images:
|
||||
- name
|
||||
project:
|
||||
- taggings
|
||||
- base_tags
|
||||
|
@ -197,6 +199,7 @@ project:
|
|||
- project_authorizations
|
||||
- route
|
||||
- statistics
|
||||
- container_images
|
||||
award_emoji:
|
||||
- awardable
|
||||
- user
|
||||
|
|
|
@ -1397,7 +1397,7 @@ describe Ci::Build, :models do
|
|||
{ key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
|
||||
end
|
||||
let(:ci_registry_image) do
|
||||
{ key: 'CI_REGISTRY_IMAGE', value: project.container_registry_repository_url, public: true }
|
||||
{ key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
|
||||
end
|
||||
|
||||
context 'and is disabled for project' do
|
||||
|
|
73
spec/models/container_image_spec.rb
Normal file
73
spec/models/container_image_spec.rb
Normal file
|
@ -0,0 +1,73 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ContainerImage do
|
||||
let(:group) { create(:group, name: 'group') }
|
||||
let(:project) { create(:project, path: 'test', group: group) }
|
||||
let(:example_host) { 'example.com' }
|
||||
let(:registry_url) { 'http://' + example_host }
|
||||
let(:container_image) { create(:container_image, name: '', project: project, stubbed: false) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true, api_url: registry_url, host_port: example_host)
|
||||
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/json' })
|
||||
end
|
||||
|
||||
it { expect(container_image).to respond_to(:project) }
|
||||
it { expect(container_image).to delegate_method(:container_registry).to(:project) }
|
||||
it { expect(container_image).to delegate_method(:client).to(:container_registry) }
|
||||
it { expect(container_image.tag('test')).not_to be_nil }
|
||||
|
||||
context '#path' do
|
||||
subject { container_image.path }
|
||||
|
||||
it { is_expected.to eq('example.com/group/test') }
|
||||
end
|
||||
|
||||
context 'manifest processing' do
|
||||
context '#manifest' do
|
||||
subject { container_image.manifest }
|
||||
|
||||
it { is_expected.not_to be_nil }
|
||||
end
|
||||
|
||||
context '#valid?' do
|
||||
subject { container_image.valid? }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context '#tags' do
|
||||
subject { container_image.tags }
|
||||
|
||||
it { is_expected.not_to be_empty }
|
||||
end
|
||||
end
|
||||
|
||||
context '#delete_tags' do
|
||||
let(:tag) { ContainerRegistry::Tag.new(container_image, 'tag') }
|
||||
|
||||
before do
|
||||
expect(container_image).to receive(:tags).twice.and_return([tag])
|
||||
expect(tag).to receive(:digest).and_return('sha256:4c8e63ca4cb663ce6c688cb06f1c3672a172b088dac5b6d7ad7d49cd620d85cf')
|
||||
end
|
||||
|
||||
subject { container_image.delete_tags }
|
||||
|
||||
context 'succeeds' do
|
||||
before { expect(container_image.client).to receive(:delete_repository_tag).and_return(true) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'any fails' do
|
||||
before { expect(container_image.client).to receive(:delete_repository_tag).and_return(false) }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -134,18 +134,20 @@ describe Namespace, models: true do
|
|||
expect(@namespace.move_dir).to be_truthy
|
||||
end
|
||||
|
||||
context "when any project has container tags" do
|
||||
context "when any project has container images" do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags('tag')
|
||||
|
||||
create(:empty_project, namespace: @namespace)
|
||||
create(:empty_project, namespace: @namespace, container_images: [container_image])
|
||||
|
||||
allow(@namespace).to receive(:path_was).and_return(@namespace.path)
|
||||
allow(@namespace).to receive(:path).and_return('new_path')
|
||||
end
|
||||
|
||||
it { expect { @namespace.move_dir }.to raise_error('Namespace cannot be moved, because at least one project has tags in container registry') }
|
||||
it { expect { @namespace.move_dir }.to raise_error('Namespace cannot be moved, because at least one project has images in container registry') }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1173,10 +1173,13 @@ describe Project, models: true do
|
|||
project.rename_repo
|
||||
end
|
||||
|
||||
context 'container registry with tags' do
|
||||
context 'container registry with images' do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags('tag')
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
subject { project.rename_repo }
|
||||
|
@ -1383,20 +1386,20 @@ describe Project, models: true do
|
|||
it { is_expected.to eq(project.path_with_namespace.downcase) }
|
||||
end
|
||||
|
||||
describe '#container_registry_repository' do
|
||||
describe '#container_registry' do
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
before { stub_container_registry_config(enabled: true) }
|
||||
|
||||
subject { project.container_registry_repository }
|
||||
subject { project.container_registry }
|
||||
|
||||
it { is_expected.not_to be_nil }
|
||||
end
|
||||
|
||||
describe '#container_registry_repository_url' do
|
||||
describe '#container_registry_url' do
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
subject { project.container_registry_repository_url }
|
||||
subject { project.container_registry_url }
|
||||
|
||||
before { stub_container_registry_config(**registry_settings) }
|
||||
|
||||
|
@ -1422,34 +1425,6 @@ describe Project, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#has_container_registry_tags?' do
|
||||
let(:project) { create(:empty_project) }
|
||||
|
||||
subject { project.has_container_registry_tags? }
|
||||
|
||||
context 'for enabled registry' do
|
||||
before { stub_container_registry_config(enabled: true) }
|
||||
|
||||
context 'with tags' do
|
||||
before { stub_container_registry_tags('test', 'test2') }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when no tags' do
|
||||
before { stub_container_registry_tags }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
context 'for disabled registry' do
|
||||
before { stub_container_registry_config(enabled: false) }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#latest_successful_builds_for' do
|
||||
def create_pipeline(status = 'success')
|
||||
create(:ci_pipeline, project: project,
|
||||
|
|
|
@ -90,25 +90,30 @@ describe Projects::DestroyService, services: true do
|
|||
end
|
||||
|
||||
context 'container registry' do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags('tag')
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
context 'tags deletion succeeds' do
|
||||
context 'images deletion succeeds' do
|
||||
it do
|
||||
expect_any_instance_of(ContainerRegistry::Tag).to receive(:delete).and_return(true)
|
||||
expect_any_instance_of(ContainerImage).to receive(:delete_tags).and_return(true)
|
||||
|
||||
destroy_project(project, user, {})
|
||||
end
|
||||
end
|
||||
|
||||
context 'tags deletion fails' do
|
||||
before { expect_any_instance_of(ContainerRegistry::Tag).to receive(:delete).and_return(false) }
|
||||
context 'images deletion fails' do
|
||||
before do
|
||||
expect_any_instance_of(ContainerImage).to receive(:delete_tags).and_return(false)
|
||||
end
|
||||
|
||||
subject { destroy_project(project, user, {}) }
|
||||
|
||||
it { expect{subject}.to raise_error(Projects::DestroyService::DestroyError) }
|
||||
it { expect{subject}.to raise_error(ActiveRecord::RecordNotDestroyed) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -29,9 +29,12 @@ describe Projects::TransferService, services: true do
|
|||
end
|
||||
|
||||
context 'disallow transfering of project with tags' do
|
||||
let(:container_image) { create(:container_image) }
|
||||
|
||||
before do
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags('tag')
|
||||
project.container_images << container_image
|
||||
end
|
||||
|
||||
subject { transfer_project(project, user, group) }
|
||||
|
|
Loading…
Reference in a new issue