diff options
Diffstat (limited to 'spec/tasks/gitlab/db')
-rw-r--r-- | spec/tasks/gitlab/db/validate_config_rake_spec.rb | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/spec/tasks/gitlab/db/validate_config_rake_spec.rb b/spec/tasks/gitlab/db/validate_config_rake_spec.rb new file mode 100644 index 00000000000..0b2c844a91f --- /dev/null +++ b/spec/tasks/gitlab/db/validate_config_rake_spec.rb @@ -0,0 +1,205 @@ +# frozen_string_literal: true + +require 'rake_helper' + +RSpec.describe 'gitlab:db:validate_config', :silence_stdout do + before :all do + Rake.application.rake_require 'active_record/railties/databases' + Rake.application.rake_require 'tasks/seed_fu' + Rake.application.rake_require 'tasks/gitlab/db/validate_config' + + # empty task as env is already loaded + Rake::Task.define_task :environment + end + + context "when validating config" do + let(:main_database_config) do + Rails.application.config.load_database_yaml + .dig('test', 'main') + .slice('adapter', 'encoding', 'database', 'username', 'password', 'host') + .symbolize_keys + end + + let(:additional_database_config) do + # Use built-in postgres database + main_database_config.merge(database: 'postgres') + end + + around do |example| + with_reestablished_active_record_base(reconnect: true) do + with_db_configs(test: test_config) do + example.run + end + end + end + + shared_examples 'validates successfully' do + it 'by default' do + expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr + expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error + end + + it 'for production' do + allow(Gitlab).to receive(:dev_or_test_env?).and_return(false) + + expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr + expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error + end + + it 'always re-establishes ActiveRecord::Base connection to main config' do + run_rake_task('gitlab:db:validate_config') + + expect(ActiveRecord::Base.connection_db_config.configuration_hash).to include(main_database_config) # rubocop: disable Database/MultipleDatabases + end + + it 'if GITLAB_VALIDATE_DATABASE_CONFIG is set' do + stub_env('GITLAB_VALIDATE_DATABASE_CONFIG', '1') + allow(Gitlab).to receive(:dev_or_test_env?).and_return(false) + + expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr + expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error + end + + context 'when finding the initializer fails' do + where(:raised_error) { [ActiveRecord::NoDatabaseError, ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad] } + with_them do + it "does not raise an error for #{params[:raised_error]}" do + allow(ActiveRecord::Base.connection).to receive(:select_one).and_raise(raised_error) # rubocop: disable Database/MultipleDatabases + + expect { run_rake_task('gitlab:db:validate_config') }.not_to output(/Database config validation failure/).to_stderr + expect { run_rake_task('gitlab:db:validate_config') }.not_to raise_error + end + end + end + end + + shared_examples 'raises an error' do |match| + it 'by default' do + expect { run_rake_task('gitlab:db:validate_config') }.to raise_error(match) + end + + it 'for production' do + allow(Gitlab).to receive(:dev_or_test_env?).and_return(false) + + expect { run_rake_task('gitlab:db:validate_config') }.to raise_error(match) + end + + it 'always re-establishes ActiveRecord::Base connection to main config' do + expect { run_rake_task('gitlab:db:validate_config') }.to raise_error(match) + + expect(ActiveRecord::Base.connection_db_config.configuration_hash).to include(main_database_config) # rubocop: disable Database/MultipleDatabases + end + + it 'if GITLAB_VALIDATE_DATABASE_CONFIG=1' do + stub_env('GITLAB_VALIDATE_DATABASE_CONFIG', '1') + + expect { run_rake_task('gitlab:db:validate_config') }.to raise_error(match) + end + + it 'to stderr if GITLAB_VALIDATE_DATABASE_CONFIG=0' do + stub_env('GITLAB_VALIDATE_DATABASE_CONFIG', '0') + + expect { run_rake_task('gitlab:db:validate_config') }.to output(match).to_stderr + end + end + + context 'when only main: is specified' do + let(:test_config) do + { + main: main_database_config + } + end + + it_behaves_like 'validates successfully' + end + + context 'when main: uses database_tasks=false' do + let(:test_config) do + { + main: main_database_config.merge(database_tasks: false) + } + end + + it_behaves_like 'raises an error', /The 'main' is required to use 'database_tasks: true'/ + end + + context 'when many configurations share the same database' do + context 'when no database_tasks is specified, assumes true' do + let(:test_config) do + { + main: main_database_config, + ci: main_database_config + } + end + + it_behaves_like 'raises an error', /Many configurations \(main, ci\) share the same database/ + end + + context 'when database_tasks is specified' do + let(:test_config) do + { + main: main_database_config.merge(database_tasks: true), + ci: main_database_config.merge(database_tasks: true) + } + end + + it_behaves_like 'raises an error', /Many configurations \(main, ci\) share the same database/ + end + + context "when there's no main: but something different, as currently we only can share with main:" do + let(:test_config) do + { + archive: main_database_config, + ci: main_database_config.merge(database_tasks: false) + } + end + + it_behaves_like 'raises an error', /The 'ci' is expecting to share configuration with 'main', but no such is to be found/ + end + end + + context 'when ci: uses different database' do + context 'and does not specify database_tasks which indicates using dedicated database' do + let(:test_config) do + { + main: main_database_config, + ci: additional_database_config + } + end + + it_behaves_like 'validates successfully' + end + + context 'and does specify database_tasks=false which indicates sharing with main:' do + let(:test_config) do + { + main: main_database_config, + ci: additional_database_config.merge(database_tasks: false) + } + end + + it_behaves_like 'raises an error', /The 'ci' since it is using 'database_tasks: false' should share database with 'main:'/ + end + end + end + + %w[db:migrate db:schema:load db:schema:dump].each do |task| + context "when running #{task}" do + it "does run gitlab:db:validate_config before" do + expect(Rake::Task['gitlab:db:validate_config']).to receive(:execute).and_return(true) + expect(Rake::Task[task]).to receive(:execute).and_return(true) + + Rake::Task['gitlab:db:validate_config'].reenable + run_rake_task(task) + end + end + end + + def with_db_configs(test: test_config) + current_configurations = ActiveRecord::Base.configurations # rubocop:disable Database/MultipleDatabases + ActiveRecord::Base.configurations = { test: test_config } + yield + ensure + ActiveRecord::Base.configurations = current_configurations + end +end |