summaryrefslogtreecommitdiff
path: root/spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb')
-rw-r--r--spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb108
1 files changed, 108 insertions, 0 deletions
diff --git a/spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb b/spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb
new file mode 100644
index 00000000000..b5bb86edce2
--- /dev/null
+++ b/spec/migrations/move_security_findings_table_to_gitlab_partitions_dynamic_schema_spec.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe MoveSecurityFindingsTableToGitlabPartitionsDynamicSchema do
+ let(:partitions_sql) do
+ <<~SQL
+ SELECT
+ partitions.relname AS partition_name
+ FROM pg_inherits
+ JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
+ JOIN pg_class partitions ON pg_inherits.inhrelid = partitions.oid
+ WHERE
+ parent.relname = 'security_findings'
+ SQL
+ end
+
+ describe '#up' do
+ it 'changes the `security_findings` table to be partitioned' do
+ expect { migrate! }.to change { security_findings_partitioned? }.from(false).to(true)
+ .and change { execute(partitions_sql) }.from([]).to(['security_findings_1'])
+ end
+ end
+
+ describe '#down' do
+ context 'when there is a partition' do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:security_scans) { table(:security_scans) }
+ let(:security_findings) { table(:security_findings) }
+
+ let(:user) { users.create!(email: 'test@gitlab.com', projects_limit: 5) }
+ let(:namespace) { namespaces.create!(name: 'gtlb', path: 'gitlab', type: Namespaces::UserNamespace.sti_name) }
+ let(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id, name: 'foo') }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'bandit', name: 'Bandit') }
+ let(:security_scan) { security_scans.create!(build_id: 1, scan_type: 1) }
+
+ let(:security_findings_count_sql) { 'SELECT COUNT(*) FROM security_findings' }
+
+ before do
+ migrate!
+
+ security_findings.create!(
+ scan_id: security_scan.id,
+ scanner_id: scanner.id,
+ uuid: SecureRandom.uuid,
+ severity: 0,
+ confidence: 0
+ )
+ end
+
+ it 'creates the original table with the data from the existing partition' do
+ expect { schema_migrate_down! }.to change { security_findings_partitioned? }.from(true).to(false)
+ .and not_change { execute(security_findings_count_sql) }.from([1])
+ end
+
+ context 'when there are more than one partitions' do
+ before do
+ migrate!
+
+ execute(<<~SQL)
+ CREATE TABLE gitlab_partitions_dynamic.security_findings_11
+ PARTITION OF security_findings FOR VALUES IN (11)
+ SQL
+ end
+
+ it 'creates the original table from the latest existing partition' do
+ expect { schema_migrate_down! }.to change { security_findings_partitioned? }.from(true).to(false)
+ .and change { execute(security_findings_count_sql) }.from([1]).to([0])
+ end
+ end
+ end
+
+ context 'when there is no partition' do
+ before do
+ migrate!
+
+ execute(partitions_sql).each do |partition_name|
+ execute("DROP TABLE gitlab_partitions_dynamic.#{partition_name}")
+ end
+ end
+
+ it 'creates the original table' do
+ expect { schema_migrate_down! }.to change { security_findings_partitioned? }.from(true).to(false)
+ end
+ end
+ end
+
+ def security_findings_partitioned?
+ sql = <<~SQL
+ SELECT
+ COUNT(*)
+ FROM
+ pg_partitioned_table
+ INNER JOIN pg_class ON pg_class.oid = pg_partitioned_table.partrelid
+ WHERE pg_class.relname = 'security_findings'
+ SQL
+
+ execute(sql).first != 0
+ end
+
+ def execute(sql)
+ ActiveRecord::Base.connection.execute(sql).values.flatten
+ end
+end