Commit a8e254a5 authored by Krasimir Angelov's avatar Krasimir Angelov

Implement database flavor detection

Try to detect the PostgreSQL flavor used be executing flavor specific
statements.

https://gitlab.com/gitlab-org/database-team/team-tasks/-/issues/218
parent a5237380
......@@ -105,6 +105,35 @@ module Gitlab
row['system_identifier']
end
def flavor
{
# Based on https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/
'Amazon Aurora PostgreSQL' => { statement: 'SELECT AURORA_VERSION()', error: /PG::UndefinedFunction/ },
# Based on https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions,
# this is also available for both Aurora and RDS, so we need to check for the former first.
'PostgreSQL on Amazon RDS' => { statement: 'SHOW rds.extensions', error: /PG::UndefinedObject/ },
# Based on https://cloud.google.com/sql/docs/postgres/flags#postgres-c this should be specific
# to Cloud SQL for PostgreSQL
'Cloud SQL for PostgreSQL' => { statement: 'SHOW cloudsql.iam_authentication', error: /PG::UndefinedObject/ },
# Based on
# - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions
# - https://docs.microsoft.com/en-us/azure/postgresql/concepts-extensions
# this should be available only for Azure Database for PostgreSQL - Flexible Server.
'Azure Database for PostgreSQL - Flexible Server' => { statement: 'SHOW azure.extensions', error: /PG::UndefinedObject/ },
# Based on
# - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-servers
# - https://docs.microsoft.com/en-us/azure/postgresql/concepts-servers#managing-your-server
# this database is present on both Flexible and Single server, so we should check the former first.
'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" }
}.each do |flavor, conditions|
return flavor if connection.execute(conditions[:statement]).to_a.present?
rescue ActiveRecord::StatementInvalid => e
raise if conditions[:error] && !e.message.match?(conditions[:error])
end
nil
end
private
def connection
......
......@@ -259,6 +259,66 @@ RSpec.describe Gitlab::Database::Reflection do
end
end
describe '#flavor', :delete do
let(:result) { [double] }
let(:connection) { database.model.connection }
def stub_statements(statements)
statements = Array.wrap(statements)
execute = connection.method(:execute)
allow(connection).to receive(:execute) do |arg|
if statements.include?(arg)
result
else
execute.call(arg)
end
end
end
it 're-raises exceptions not matching expected messages' do
expect(database.model.connection)
.to receive(:execute)
.and_raise(ActiveRecord::StatementInvalid, 'Something else')
expect { database.flavor }.to raise_error ActiveRecord::StatementInvalid, /Something else/
end
it 'recognizes Amazon Aurora PostgreSQL' do
stub_statements(['SHOW rds.extensions', 'SELECT AURORA_VERSION()'])
expect(database.flavor).to eq('Amazon Aurora PostgreSQL')
end
it 'recognizes PostgreSQL on Amazon RDS' do
stub_statements('SHOW rds.extensions')
expect(database.flavor).to eq('PostgreSQL on Amazon RDS')
end
it 'recognizes CloudSQL for PostgreSQL' do
stub_statements('SHOW cloudsql.iam_authentication')
expect(database.flavor).to eq('Cloud SQL for PostgreSQL')
end
it 'recognizes Azure Database for PostgreSQL - Flexible Server' do
stub_statements(["SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'", 'SHOW azure.extensions'])
expect(database.flavor).to eq('Azure Database for PostgreSQL - Flexible Server')
end
it 'recognizes Azure Database for PostgreSQL - Single Server' do
stub_statements("SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'")
expect(database.flavor).to eq('Azure Database for PostgreSQL - Single Server')
end
it 'returns nil if can not recognize the flavor' do
expect(database.flavor).to be_nil
end
end
describe '#config' do
it 'returns a HashWithIndifferentAccess' do
expect(database.config)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment