Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/database/decomposition/migrate_spec.rb')
-rw-r--r--spec/lib/gitlab/database/decomposition/migrate_spec.rb180
1 files changed, 180 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/decomposition/migrate_spec.rb b/spec/lib/gitlab/database/decomposition/migrate_spec.rb
new file mode 100644
index 00000000000..fa2248e8d84
--- /dev/null
+++ b/spec/lib/gitlab/database/decomposition/migrate_spec.rb
@@ -0,0 +1,180 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Decomposition::Migrate, :delete, query_analyzers: false, feature_category: :cell do
+ let(:ci_database_name) do
+ config = ActiveRecord::Base.configurations.find_db_config(Rails.env).configuration_hash
+
+ "#{config[:database]}_ci"
+ end
+
+ let(:ci_connection) do
+ database_model = self.class.const_set(:TestCiApplicationRecord, Class.new(ApplicationRecord))
+
+ database_model.establish_connection(
+ ActiveRecord::DatabaseConfigurations::HashConfig.new(
+ ActiveRecord::Base.connection_db_config.env_name,
+ 'ci',
+ ActiveRecord::Base.connection_db_config.configuration_hash.dup.merge(database: ci_database_name)
+ )
+ )
+
+ Gitlab::Database::LoadBalancing::Setup.new(database_model).setup
+
+ database_model.connection
+ end
+
+ let(:backup_location_postfix) { SecureRandom.alphanumeric(10) }
+
+ before do
+ skip_if_database_exists(:ci)
+
+ allow(SecureRandom).to receive(:alphanumeric).with(10).and_return(backup_location_postfix)
+ end
+
+ after do
+ Milestone.delete_all
+ Ci::Pipeline.delete_all
+ end
+
+ describe '#new' do
+ context 'when backup_location is not specified' do
+ subject(:instance) { described_class.new }
+
+ it 'defaults to subdirectory of configured backup location' do
+ expect(instance.instance_variable_get(:@backup_location)).to eq(
+ File.join(Gitlab.config.backup.path, "migration_#{backup_location_postfix}")
+ )
+ end
+ end
+
+ context 'when backup_location is specified' do
+ let(:backup_base_location) { Rails.root.join('tmp') }
+
+ subject(:instance) { described_class.new(backup_base_location: backup_base_location) }
+
+ it 'uses subdirectory of specified backup_location' do
+ expect(instance.instance_variable_get(:@backup_location)).to eq(
+ File.join(backup_base_location, "migration_#{backup_location_postfix}")
+ )
+ end
+
+ context 'when specified_backup_location does not exist' do
+ let(:backup_base_location) { Rails.root.join('tmp', SecureRandom.alphanumeric(10)) }
+
+ context 'and creation of the directory succeeds' do
+ it 'uses subdirectory of specified backup_location' do
+ expect(instance.instance_variable_get(:@backup_location)).to eq(
+ File.join(backup_base_location, "migration_#{backup_location_postfix}")
+ )
+ end
+ end
+
+ context 'and creation of the directory fails' do
+ before do
+ allow(FileUtils).to receive(:mkdir_p).with(backup_base_location).and_raise(Errno::EROFS.new)
+ end
+
+ it 'raises error' do
+ expect { instance.process! }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ "Failed to create directory #{backup_base_location}: Read-only file system"
+ )
+ end
+ end
+ end
+ end
+ end
+
+ describe '#process!' do
+ subject(:process) { described_class.new.process! }
+
+ before do
+ # Database `ci` is not configured. But it can still exist. So drop and create it
+ ActiveRecord::Base.connection.execute("DROP DATABASE IF EXISTS #{ci_database_name} WITH (FORCE)")
+ ActiveRecord::Base.connection.execute("CREATE DATABASE #{ci_database_name}")
+ end
+
+ context 'when the checks pass' do
+ let!(:milestone) { create(:milestone) }
+ let!(:ci_pipeline) { create(:ci_pipeline) }
+
+ it 'copies main database to ci database' do
+ process
+
+ ci_milestones = ci_connection.execute("SELECT COUNT(*) FROM milestones").getvalue(0, 0)
+ ci_pipelines = ci_connection.execute("SELECT COUNT(*) FROM ci_pipelines").getvalue(0, 0)
+
+ expect(ci_milestones).to be(Milestone.count)
+ expect(ci_pipelines).to be(Ci::Pipeline.count)
+ end
+ end
+
+ context 'when local diskspace is not enough' do
+ let(:backup_location) { described_class.new.backup_location }
+ let(:fake_stats) { instance_double(Sys::Filesystem::Stat, bytes_free: 1000) }
+
+ before do
+ allow(Sys::Filesystem).to receive(:stat).with(File.expand_path("#{backup_location}/../")).and_return(fake_stats)
+ end
+
+ it 'raises error' do
+ expect { process }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ /Not enough diskspace available on #{backup_location}: Available: (.+?), Needed: (.+?)/
+ )
+ end
+ end
+
+ context 'when connection to ci database fails' do
+ before do
+ ActiveRecord::Base.connection.execute("DROP DATABASE IF EXISTS #{ci_database_name} WITH (FORCE)")
+ end
+
+ it 'raises error' do
+ host = ActiveRecord::Base.configurations.find_db_config(Rails.env).configuration_hash[:host]
+ expect { process }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ "Can't connect to database '#{ci_database_name} on host '#{host}'. Ensure the database has been created.")
+ end
+ end
+
+ context 'when ci database is not empty' do
+ before do
+ ci_connection.execute("CREATE TABLE IF NOT EXISTS _test_table (id integer, primary key (id))")
+ end
+
+ it 'raises error' do
+ expect { process }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ "Database '#{ci_database_name}' is not empty"
+ )
+ end
+ end
+
+ context 'when already on decomposed setup' do
+ before do
+ allow(Gitlab::Database).to receive(:database_mode).and_return(Gitlab::Database::MODE_MULTIPLE_DATABASES)
+ end
+
+ it 'raises error' do
+ expect { process }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ "GitLab is already configured to run on multiple databases"
+ )
+ end
+ end
+
+ context 'when not all background migrations are finished' do
+ let!(:batched_migration) { create(:batched_background_migration, :active) }
+
+ it 'raises error' do
+ expect { process }.to raise_error(
+ Gitlab::Database::Decomposition::MigrateError,
+ "Found 1 unfinished Background Migration(s). Please wait until they are finished."
+ )
+ end
+ end
+ end
+end