summaryrefslogtreecommitdiff
path: root/spec/tasks/gitlab/db/validate_config_rake_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/tasks/gitlab/db/validate_config_rake_spec.rb')
-rw-r--r--spec/tasks/gitlab/db/validate_config_rake_spec.rb205
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