Commit d8f7bfe3 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch '299054-fj-update-groups-repository-storage-class' into 'master'

Include logic to move storage in Groups::RepositoryStorageMove class

See merge request gitlab-org/gitlab!52513
parents 8e39f635 ebfc54b0
...@@ -5,11 +5,26 @@ ...@@ -5,11 +5,26 @@
# balance storage capacity. # balance storage capacity.
module Groups module Groups
class RepositoryStorageMove < ApplicationRecord class RepositoryStorageMove < ApplicationRecord
extend ::Gitlab::Utils::Override
include RepositoryStorageMovable
self.table_name = 'group_repository_storage_moves' self.table_name = 'group_repository_storage_moves'
belongs_to :container, class_name: 'Group', inverse_of: :repository_storage_moves, foreign_key: :group_id belongs_to :container, class_name: 'Group', inverse_of: :repository_storage_moves, foreign_key: :group_id
alias_attribute :group, :container alias_attribute :group, :container
scope :with_groups, -> { includes(container: :route) } scope :with_groups, -> { includes(container: :route) }
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
# No-op. It will be implemented in https://gitlab.com/gitlab-org/gitlab/-/issues/299059
end
private
override :error_key
def error_key
:group
end
end end
end end
# frozen_string_literal: true
FactoryBot.define do
factory :group_repository_storage_move, class: 'Groups::RepositoryStorageMove' do
container { association(:group) }
source_storage_name { 'default' }
trait :scheduled do
state { Groups::RepositoryStorageMove.state_machines[:state].states[:scheduled].value }
end
trait :started do
state { Groups::RepositoryStorageMove.state_machines[:state].states[:started].value }
end
trait :replicated do
state { Groups::RepositoryStorageMove.state_machines[:state].states[:replicated].value }
end
trait :finished do
state { Groups::RepositoryStorageMove.state_machines[:state].states[:finished].value }
end
trait :failed do
state { Groups::RepositoryStorageMove.state_machines[:state].states[:failed].value }
end
end
end
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Groups::RepositoryStorageMove, type: :model do RSpec.describe Groups::RepositoryStorageMove, type: :model do
describe 'associations' do it_behaves_like 'handles repository moves', check_worker: false do
it { is_expected.to belong_to(:container).class_name('Group') } let_it_be_with_refind(:container) { create(:group) }
let(:repository_storage_factory_key) { :group_repository_storage_move }
let(:error_key) { :group }
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'handles repository moves' do RSpec.shared_examples 'handles repository moves' do |check_worker: true|
describe 'associations' do describe 'associations' do
it { is_expected.to belong_to(:container) } it { is_expected.to belong_to(:container) }
end end
...@@ -33,7 +33,7 @@ RSpec.shared_examples 'handles repository moves' do ...@@ -33,7 +33,7 @@ RSpec.shared_examples 'handles repository moves' do
subject { build(repository_storage_factory_key, container: container) } subject { build(repository_storage_factory_key, container: container) }
it "does not allow the container to be read-only on create" do it "does not allow the container to be read-only on create" do
container.update!(repository_read_only: true) container.set_repository_read_only!
expect(subject).not_to be_valid expect(subject).not_to be_valid
expect(subject.errors[error_key].first).to match(/is read only/) expect(subject.errors[error_key].first).to match(/is read only/)
...@@ -61,23 +61,25 @@ RSpec.shared_examples 'handles repository moves' do ...@@ -61,23 +61,25 @@ RSpec.shared_examples 'handles repository moves' do
context 'when in the default state' do context 'when in the default state' do
subject(:storage_move) { create(repository_storage_factory_key, container: container, destination_storage_name: 'test_second_storage') } subject(:storage_move) { create(repository_storage_factory_key, container: container, destination_storage_name: 'test_second_storage') }
context 'and transits to scheduled' do if check_worker
it 'triggers the corresponding repository storage worker' do context 'and transits to scheduled' do
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id) it 'triggers the corresponding repository storage worker' do
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id)
storage_move.schedule! storage_move.schedule!
expect(container).to be_repository_read_only expect(container).to be_repository_read_only
end end
context 'when the transition fails' do context 'when the transition fails' do
it 'does not trigger the corresponding repository storage worker and adds an error' do it 'does not trigger the corresponding repository storage worker and adds an error' do
allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar') allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(repository_storage_worker).not_to receive(:perform_async) expect(repository_storage_worker).not_to receive(:perform_async)
storage_move.schedule! storage_move.schedule!
expect(storage_move.errors[error_key]).to include('foobar') expect(storage_move.errors[error_key]).to include('foobar')
end
end end
end 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