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:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-19 12:09:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-19 12:09:08 +0300
commit3fbfc0075a306ad85c70c006b978a2e96bd4283a (patch)
tree077f6cf9013638b21a1242355d2fd13069533f73 /spec/tasks
parent224d2fe16768ee5b270d894a5ed47101bf454d04 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/tasks')
-rw-r--r--spec/tasks/gitlab/db/lock_writes_rake_spec.rb152
1 files changed, 152 insertions, 0 deletions
diff --git a/spec/tasks/gitlab/db/lock_writes_rake_spec.rb b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
new file mode 100644
index 00000000000..da62d136c25
--- /dev/null
+++ b/spec/tasks/gitlab/db/lock_writes_rake_spec.rb
@@ -0,0 +1,152 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:db:lock_writes', :silence_stdout, :reestablished_active_record_base 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'
+ Rake.application.rake_require 'tasks/gitlab/db/lock_writes'
+
+ # empty task as env is already loaded
+ Rake::Task.define_task :environment
+ end
+
+ let!(:project) { create(:project) }
+ let!(:ci_build) { create(:ci_build) }
+ let(:main_connection) { ApplicationRecord.connection }
+ let(:ci_connection) { Ci::ApplicationRecord.connection }
+
+ context 'single database' do
+ before do
+ skip_if_multiple_databases_are_setup
+ end
+
+ context 'when locking writes' do
+ it 'does not add any triggers to the main schema tables' do
+ expect do
+ run_rake_task('gitlab:db:lock_writes')
+ end.to change {
+ number_of_triggers(main_connection)
+ }.by(0)
+ end
+
+ it 'will be still able to modify tables that belong to the main two schemas' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ Project.last.touch
+ Ci::Build.last.touch
+ end.not_to raise_error
+ end
+ end
+ end
+
+ context 'multiple databases' do
+ before do
+ skip_if_multiple_databases_not_setup
+ end
+
+ context 'when locking writes' do
+ it 'adds 3 triggers to the ci schema tables on the main database' do
+ expect do
+ run_rake_task('gitlab:db:lock_writes')
+ end.to change {
+ number_of_triggers_on(main_connection, Ci::Build.table_name)
+ }.by(3) # Triggers to block INSERT / UPDATE / DELETE
+ # Triggers on TRUNCATE are not added to the information_schema.triggers
+ # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
+ end
+
+ it 'adds 3 triggers to the main schema tables on the ci database' do
+ expect do
+ run_rake_task('gitlab:db:lock_writes')
+ end.to change {
+ number_of_triggers_on(ci_connection, Project.table_name)
+ }.by(3) # Triggers to block INSERT / UPDATE / DELETE
+ # Triggers on TRUNCATE are not added to the information_schema.triggers
+ # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
+ end
+
+ it 'still allows writes on the tables with the correct connections' do
+ Project.update_all(updated_at: Time.now)
+ Ci::Build.update_all(updated_at: Time.now)
+ end
+
+ it 'still allows writing to gitlab_shared schema on any connection' do
+ connections = [main_connection, ci_connection]
+ connections.each do |connection|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ LooseForeignKeys::DeletedRecord.create!(
+ fully_qualified_table_name: "public.projects",
+ primary_key_value: 1,
+ cleanup_attempts: 0
+ )
+ end
+ end
+ end
+
+ it 'prevents writes on the main tables on the ci database' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ ci_connection.execute("delete from projects")
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "projects" is write protected/)
+ end
+
+ it 'prevents writes on the ci tables on the main database' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ main_connection.execute("delete from ci_builds")
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "ci_builds" is write protected/)
+ end
+
+ it 'prevents truncating a ci table on the main database' do
+ run_rake_task('gitlab:db:lock_writes')
+ expect do
+ main_connection.execute("truncate ci_build_needs")
+ end.to raise_error(ActiveRecord::StatementInvalid, /Table: "ci_build_needs" is write protected/)
+ end
+ end
+
+ context 'when unlocking writes' do
+ before do
+ run_rake_task('gitlab:db:lock_writes')
+ end
+
+ it 'removes the write protection triggers from the gitlab_main tables on the ci database' do
+ expect do
+ run_rake_task('gitlab:db:unlock_writes')
+ end.to change {
+ number_of_triggers_on(ci_connection, Project.table_name)
+ }.by(-3) # Triggers to block INSERT / UPDATE / DELETE
+ # Triggers on TRUNCATE are not added to the information_schema.triggers
+ # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us
+
+ expect do
+ ci_connection.execute("delete from projects")
+ end.not_to raise_error
+ end
+
+ it 'removes the write protection triggers from the gitlab_ci tables on the main database' do
+ expect do
+ run_rake_task('gitlab:db:unlock_writes')
+ end.to change {
+ number_of_triggers_on(main_connection, Ci::Build.table_name)
+ }.by(-3)
+
+ expect do
+ main_connection.execute("delete from ci_builds")
+ end.not_to raise_error
+ end
+ end
+ end
+
+ def number_of_triggers(connection)
+ connection.select_value("SELECT count(*) FROM information_schema.triggers")
+ end
+
+ def number_of_triggers_on(connection, table_name)
+ connection
+ .select_value("SELECT count(*) FROM information_schema.triggers WHERE event_object_table=$1", nil, [table_name])
+ end
+end