summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/projects.rb8
-rw-r--r--spec/models/project_spec.rb78
-rw-r--r--spec/services/projects/hashed_storage_migration_service_spec.rb74
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb52
-rw-r--r--spec/workers/project_migrate_hashed_storage_worker_spec.rb29
-rw-r--r--spec/workers/storage_migrator_worker_spec.rb30
6 files changed, 269 insertions, 2 deletions
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 4842efc86a1..958d62181a2 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -143,7 +143,13 @@ FactoryGirl.define do
end
end
- trait :read_only_repository do
+ trait :wiki_repo do
+ after(:create) do |project|
+ raise 'Failed to create wiki repository!' unless project.create_wiki
+ end
+ end
+
+ trait :readonly do
repository_read_only true
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 78226c6c3fa..3ca88071ced 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2363,10 +2363,22 @@ describe Project do
describe '#legacy_storage?' do
it 'returns true when storage_version is nil' do
- project = build(:project)
+ project = build(:project, storage_version: nil)
expect(project.legacy_storage?).to be_truthy
end
+
+ it 'returns true when the storage_version is 0' do
+ project = build(:project, storage_version: 0)
+
+ expect(project.legacy_storage?).to be_truthy
+ end
+ end
+
+ describe '#hashed_storage?' do
+ it 'returns false' do
+ expect(project.hashed_storage?).to be_falsey
+ end
end
describe '#rename_repo' do
@@ -2425,6 +2437,38 @@ describe Project do
expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
end
end
+
+ describe '#migrate_to_hashed_storage!' do
+ it 'returns true' do
+ expect(project.migrate_to_hashed_storage!).to be_truthy
+ end
+
+ it 'flags as readonly' do
+ expect { project.migrate_to_hashed_storage! }.to change { project.repository_read_only }.to(true)
+ end
+
+ it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the project repo is in use' do
+ Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: false)).increase
+
+ expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in)
+
+ project.migrate_to_hashed_storage!
+ end
+
+ it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the wiki repo is in use' do
+ Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: true)).increase
+
+ expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in)
+
+ project.migrate_to_hashed_storage!
+ end
+
+ it 'schedules ProjectMigrateHashedStorageWorker' do
+ expect(ProjectMigrateHashedStorageWorker).to receive(:perform_async).with(project.id)
+
+ project.migrate_to_hashed_storage!
+ end
+ end
end
context 'hashed storage' do
@@ -2438,6 +2482,18 @@ describe Project do
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
end
+ describe '#legacy_storage?' do
+ it 'returns false' do
+ expect(project.legacy_storage?).to be_falsey
+ end
+ end
+
+ describe '#hashed_storage?' do
+ it 'returns true' do
+ expect(project.hashed_storage?).to be_truthy
+ end
+ end
+
describe '#base_dir' do
it 'returns base_dir based on hash of project id' do
expect(project.base_dir).to eq('@hashed/6b/86')
@@ -2508,6 +2564,26 @@ describe Project do
expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
end
end
+
+ describe '#migrate_to_hashed_storage!' do
+ it 'returns nil' do
+ expect(project.migrate_to_hashed_storage!).to be_nil
+ end
+
+ it 'does not flag as readonly' do
+ expect { project.migrate_to_hashed_storage! }.not_to change { project.repository_read_only }
+ end
+ end
+ end
+
+ describe '#gl_repository' do
+ let(:project) { create(:project) }
+
+ it 'delegates to Gitlab::GlRepository.gl_repository' do
+ expect(Gitlab::GlRepository).to receive(:gl_repository).with(project, true)
+
+ project.gl_repository(is_wiki: true)
+ end
end
describe '#has_ci?' do
diff --git a/spec/services/projects/hashed_storage_migration_service_spec.rb b/spec/services/projects/hashed_storage_migration_service_spec.rb
new file mode 100644
index 00000000000..1b61207b550
--- /dev/null
+++ b/spec/services/projects/hashed_storage_migration_service_spec.rb
@@ -0,0 +1,74 @@
+require 'spec_helper'
+
+describe Projects::HashedStorageMigrationService do
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:project) { create(:project, :empty_repo, :wiki_repo) }
+ let(:service) { described_class.new(project) }
+ let(:legacy_storage) { Storage::LegacyProject.new(project) }
+ let(:hashed_storage) { Storage::HashedProject.new(project) }
+
+ describe '#execute' do
+ before do
+ allow(service).to receive(:gitlab_shell) { gitlab_shell }
+ end
+
+ context 'when succeeds' do
+ it 'renames project and wiki repositories' do
+ service.execute
+
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{hashed_storage.disk_path}.git")).to be_truthy
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{hashed_storage.disk_path}.wiki.git")).to be_truthy
+ end
+
+ it 'updates project to be hashed and not readonly' do
+ service.execute
+
+ expect(project.hashed_storage?).to be_truthy
+ expect(project.repository_read_only).to be_falsey
+ end
+
+ it 'move operation is called for both repositories' do
+ expect_move_repository(project.disk_path, hashed_storage.disk_path)
+ expect_move_repository("#{project.disk_path}.wiki", "#{hashed_storage.disk_path}.wiki")
+
+ service.execute
+ end
+ end
+
+ context 'when one move fails' do
+ it 'rollsback repositories to original name' do
+ from_name = project.disk_path
+ to_name = hashed_storage.disk_path
+ allow(service).to receive(:move_repository).and_call_original
+ allow(service).to receive(:move_repository).with(from_name, to_name).once { false } # will disable first move only
+
+ expect(service).to receive(:rollback_folder_move).and_call_original
+
+ service.execute
+
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{hashed_storage.disk_path}.git")).to be_falsey
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{hashed_storage.disk_path}.wiki.git")).to be_falsey
+ end
+
+ context 'when rollback fails' do
+ before do
+ from_name = legacy_storage.disk_path
+ to_name = hashed_storage.disk_path
+
+ hashed_storage.ensure_storage_path_exists
+ gitlab_shell.mv_repository(project.repository_storage_path, from_name, to_name)
+ end
+
+ it 'does not try to move nil repository over hashed' do
+ expect_move_repository("#{project.disk_path}.wiki", "#{hashed_storage.disk_path}.wiki")
+
+ service.execute
+ end
+ end
+ end
+
+ def expect_move_repository(from_name, to_name)
+ expect(gitlab_shell).to receive(:mv_repository).with(project.repository_storage_path, from_name, to_name).and_call_original
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
new file mode 100644
index 00000000000..f59792c3d36
--- /dev/null
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -0,0 +1,52 @@
+require 'rake_helper'
+
+describe 'gitlab:storage rake tasks' do
+ before do
+ Rake.application.rake_require 'tasks/gitlab/storage'
+
+ stub_warn_user_is_not_gitlab
+ end
+
+ describe 'migrate_to_hashed rake task' do
+ context '0 legacy projects' do
+ it 'does nothing' do
+ expect(StorageMigratorWorker).not_to receive(:perform_async)
+
+ run_rake_task('gitlab:storage:migrate_to_hashed')
+ end
+ end
+
+ context '5 legacy projects' do
+ let(:projects) { create_list(:project, 5, storage_version: 0) }
+
+ context 'in batches of 1' do
+ before do
+ stub_env('BATCH' => 1)
+ end
+
+ it 'enqueues one StorageMigratorWorker per project' do
+ projects.each do |project|
+ expect(StorageMigratorWorker).to receive(:perform_async).with(project.id, project.id)
+ end
+
+ run_rake_task('gitlab:storage:migrate_to_hashed')
+ end
+ end
+
+ context 'in batches of 2' do
+ before do
+ stub_env('BATCH' => 2)
+ end
+
+ it 'enqueues one StorageMigratorWorker per 2 projects' do
+ projects.map(&:id).sort.each_slice(2) do |first, last|
+ last ||= first
+ expect(StorageMigratorWorker).to receive(:perform_async).with(first, last)
+ end
+
+ run_rake_task('gitlab:storage:migrate_to_hashed')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/project_migrate_hashed_storage_worker_spec.rb b/spec/workers/project_migrate_hashed_storage_worker_spec.rb
new file mode 100644
index 00000000000..f5226dee0ad
--- /dev/null
+++ b/spec/workers/project_migrate_hashed_storage_worker_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe ProjectMigrateHashedStorageWorker do
+ describe '#perform' do
+ let(:project) { create(:project, :empty_repo) }
+ let(:pending_delete_project) { create(:project, :empty_repo, pending_delete: true) }
+
+ it 'skips when project no longer exists' do
+ nonexistent_id = 999999999999
+
+ expect(::Projects::HashedStorageMigrationService).not_to receive(:new)
+ subject.perform(nonexistent_id)
+ end
+
+ it 'skips when project is pending delete' do
+ expect(::Projects::HashedStorageMigrationService).not_to receive(:new)
+
+ subject.perform(pending_delete_project.id)
+ end
+
+ it 'delegates removal to service class' do
+ service = double('service')
+ expect(::Projects::HashedStorageMigrationService).to receive(:new).with(project, subject.logger).and_return(service)
+ expect(service).to receive(:execute)
+
+ subject.perform(project.id)
+ end
+ end
+end
diff --git a/spec/workers/storage_migrator_worker_spec.rb b/spec/workers/storage_migrator_worker_spec.rb
new file mode 100644
index 00000000000..8619ff2f7da
--- /dev/null
+++ b/spec/workers/storage_migrator_worker_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe StorageMigratorWorker do
+ subject(:worker) { described_class.new }
+ let(:projects) { create_list(:project, 2) }
+
+ describe '#perform' do
+ let(:ids) { projects.map(&:id) }
+
+ it 'enqueue jobs to ProjectMigrateHashedStorageWorker' do
+ expect(ProjectMigrateHashedStorageWorker).to receive(:perform_async).twice
+
+ worker.perform(ids.min, ids.max)
+ end
+
+ it 'sets projects as read only' do
+ allow(ProjectMigrateHashedStorageWorker).to receive(:perform_async).twice
+ worker.perform(ids.min, ids.max)
+
+ projects.each do |project|
+ expect(project.reload.repository_read_only?).to be_truthy
+ end
+ end
+
+ it 'rescues and log exceptions' do
+ allow_any_instance_of(Project).to receive(:migrate_to_hashed_storage!).and_raise(StandardError)
+ expect { worker.perform(ids.min, ids.max) }.not_to raise_error
+ end
+ end
+end