Commit 0618ad12 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'fix/gb/recover-from-renaming-project-with-container-images' into 'master'

Recover from renaming project that has container images

Closes #23019

See merge request !12840
parents 78f7080e bfdd34c5
...@@ -50,10 +50,13 @@ class ProjectsController < Projects::ApplicationController ...@@ -50,10 +50,13 @@ class ProjectsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
if result[:status] == :success if result[:status] == :success
flash[:notice] = _("Project '%{project_name}' was successfully updated.") % { project_name: @project.name } flash[:notice] = _("Project '%{project_name}' was successfully updated.") % { project_name: @project.name }
format.html do format.html do
redirect_to(edit_project_path(@project)) redirect_to(edit_project_path(@project))
end end
else else
flash[:alert] = result[:message]
format.html { render 'edit' } format.html { render 'edit' }
end end
......
...@@ -486,7 +486,9 @@ class Project < ActiveRecord::Base ...@@ -486,7 +486,9 @@ class Project < ActiveRecord::Base
end end
def has_container_registry_tags? def has_container_registry_tags?
container_repositories.to_a.any?(&:has_tags?) || return @images if defined?(@images)
@images = container_repositories.to_a.any?(&:has_tags?) ||
has_root_container_repository_tags? has_root_container_repository_tags?
end end
...@@ -977,8 +979,6 @@ class Project < ActiveRecord::Base ...@@ -977,8 +979,6 @@ class Project < ActiveRecord::Base
Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}" Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
expire_caches_before_rename(old_path_with_namespace)
if has_container_registry_tags? if has_container_registry_tags?
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!" Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
...@@ -986,6 +986,8 @@ class Project < ActiveRecord::Base ...@@ -986,6 +986,8 @@ class Project < ActiveRecord::Base
raise StandardError.new('Project cannot be renamed, because images are present in its container registry') raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
end end
expire_caches_before_rename(old_path_with_namespace)
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace) if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
# If repository moved successfully we need to send update instructions to users. # If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository # However we cannot allow rollback since we moved repository
......
module Projects module Projects
class UpdateService < BaseService class UpdateService < BaseService
def execute def execute
# check that user is allowed to set specified visibility_level unless visibility_level_allowed?
new_visibility = params[:visibility_level] return error('New visibility level not allowed!')
if new_visibility && new_visibility.to_i != project.visibility_level
unless can?(current_user, :change_visibility_level, project) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(project, new_visibility)
return error('Visibility level unallowed')
end
end end
new_branch = params[:default_branch] if project.has_container_registry_tags?
return error('Cannot rename project because it contains container registry tags!')
end
if project.repository.exists? && new_branch && new_branch != project.default_branch if changing_default_branch?
project.change_head(new_branch) project.change_head(params[:default_branch])
end end
if project.update_attributes(params.except(:default_branch)) if project.update_attributes(params.except(:default_branch))
...@@ -28,8 +22,33 @@ module Projects ...@@ -28,8 +22,33 @@ module Projects
success success
else else
error('Project could not be updated') error('Project could not be updated!')
end
end end
private
def visibility_level_allowed?
# check that user is allowed to set specified visibility_level
new_visibility = params[:visibility_level]
if new_visibility && new_visibility.to_i != project.visibility_level
unless can?(current_user, :change_visibility_level, project) &&
Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
deny_visibility_level(project, new_visibility)
return false
end
end
true
end
def changing_default_branch?
new_branch = params[:default_branch]
project.repository.exists? &&
new_branch && new_branch != project.default_branch
end end
end end
end end
---
title: Recover from renaming project that has container images
merge_request: 12840
author:
...@@ -211,27 +211,46 @@ describe ProjectsController do ...@@ -211,27 +211,46 @@ describe ProjectsController do
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:new_path) { 'renamed_path' }
let(:project_params) { { path: new_path } }
before do before do
sign_in(admin) sign_in(admin)
end end
context 'when only renaming a project path' do
it "sets the repository to the right path after a rename" do it "sets the repository to the right path after a rename" do
controller.instance_variable_set(:@project, project) expect { update_project path: 'renamed_path' }
.to change { project.reload.path }
put :update, expect(project.path).to include 'renamed_path'
namespace_id: project.namespace, expect(assigns(:repository).path).to include project.path
id: project.id,
project: project_params
expect(project.repository.path).to include(new_path)
expect(assigns(:repository).path).to eq(project.repository.path)
expect(response).to have_http_status(302) expect(response).to have_http_status(302)
end end
end end
context 'when project has container repositories with tags' do
before do
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: /image/, tags: %w[rc1])
create(:container_repository, project: project, name: :image)
end
it 'does not allow to rename the project' do
expect { update_project path: 'renamed_path' }
.not_to change { project.reload.path }
expect(controller).to set_flash[:alert].to(/container registry tags/)
expect(response).to have_http_status(200)
end
end
def update_project(**parameters)
put :update,
namespace_id: project.namespace.path,
id: project.path,
project: parameters
end
end
describe '#transfer' do describe '#transfer' do
render_views render_views
......
...@@ -1236,7 +1236,7 @@ describe Project, models: true do ...@@ -1236,7 +1236,7 @@ describe Project, models: true do
subject { project.rename_repo } subject { project.rename_repo }
it { expect{subject}.to raise_error(Exception) } it { expect{subject}.to raise_error(StandardError) }
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe Projects::UpdateService, services: true do describe Projects::UpdateService, '#execute', :services do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:admin) { create(:admin) } let(:admin) { create(:admin) }
let(:project) { create(:empty_project, creator_id: user.id, namespace: user.namespace) }
describe 'update_by_user' do let(:project) do
create(:empty_project, creator: user, namespace: user.namespace)
end
context 'when changing visibility level' do
context 'when visibility_level is INTERNAL' do context 'when visibility_level is INTERNAL' do
it 'updates the project to internal' do it 'updates the project to internal' do
result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::INTERNAL) result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
...@@ -40,7 +43,7 @@ describe Projects::UpdateService, services: true do ...@@ -40,7 +43,7 @@ describe Projects::UpdateService, services: true do
it 'does not update the project to public' do it 'does not update the project to public' do
result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PUBLIC) result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
expect(result).to eq({ status: :error, message: 'Visibility level unallowed' }) expect(result).to eq({ status: :error, message: 'New visibility level not allowed!' })
expect(project).to be_private expect(project).to be_private
end end
...@@ -55,12 +58,13 @@ describe Projects::UpdateService, services: true do ...@@ -55,12 +58,13 @@ describe Projects::UpdateService, services: true do
end end
end end
describe 'visibility_level' do describe 'when updating project that has forks' do
let(:project) { create(:empty_project, :internal) } let(:project) { create(:empty_project, :internal) }
let(:forked_project) { create(:forked_project_with_submodules, :internal) } let(:forked_project) { create(:forked_project_with_submodules, :internal) }
before do before do
forked_project.build_forked_project_link(forked_to_project_id: forked_project.id, forked_from_project_id: project.id) forked_project.build_forked_project_link(forked_to_project_id: forked_project.id,
forked_from_project_id: project.id)
forked_project.save forked_project.save
end end
...@@ -89,10 +93,38 @@ describe Projects::UpdateService, services: true do ...@@ -89,10 +93,38 @@ describe Projects::UpdateService, services: true do
end end
end end
context 'when updating a default branch' do
let(:project) { create(:project, :repository) }
it 'changes a default branch' do
update_project(project, admin, default_branch: 'feature')
expect(Project.find(project.id).default_branch).to eq 'feature'
end
end
context 'when renaming project that contains container images' do
before do
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: /image/, tags: %w[rc1])
create(:container_repository, project: project, name: :image)
end
it 'does not allow to rename the project' do
result = update_project(project, admin, path: 'renamed')
expect(result).to include(status: :error)
expect(result[:message]).to match(/contains container registry tags/)
end
end
context 'when passing invalid parameters' do
it 'returns an error result when record cannot be updated' do it 'returns an error result when record cannot be updated' do
result = update_project(project, admin, { name: 'foo&bar' }) result = update_project(project, admin, { name: 'foo&bar' })
expect(result).to eq({ status: :error, message: 'Project could not be updated' }) expect(result).to eq({ status: :error,
message: 'Project could not be updated!' })
end
end end
def update_project(project, user, opts) def update_project(project, user, opts)
......
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