mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-01 16:04:19 +00:00
152 lines
4.2 KiB
Ruby
152 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
RSpec.describe Gitlab::Backup::Cli::Targets::Database do
|
|
let(:context) { build_test_context }
|
|
let(:database) { described_class.new(context) }
|
|
let(:pipeline_success) { instance_double(Gitlab::Backup::Cli::Shell::Pipeline::Result, success?: true) }
|
|
|
|
after do
|
|
context.cleanup!
|
|
end
|
|
|
|
describe '#dump', :silence_output do
|
|
let(:destination) { Pathname(Dir.mktmpdir('database-target', temp_path)) }
|
|
|
|
after do
|
|
FileUtils.rm_rf(destination)
|
|
end
|
|
|
|
it 'creates the destination directory' do
|
|
mock_database_dump!
|
|
|
|
expect(destination).to be_directory
|
|
|
|
database.dump(destination)
|
|
end
|
|
|
|
it 'triggers a database snapshot' do
|
|
mock_database_dump!
|
|
|
|
expect_next_instance_of(Gitlab::Backup::Cli::Services::Database) do |db|
|
|
expect(db).to receive(:export_snapshot!).and_call_original
|
|
end.at_least(:once)
|
|
|
|
database.dump(destination)
|
|
end
|
|
|
|
it 'dumps the database' do
|
|
database.dump(destination)
|
|
|
|
database_dump_files = Dir.glob(destination.join('*.sql.gz'))
|
|
|
|
expect(database_dump_files).not_to be_empty
|
|
end
|
|
|
|
it 'releases the snapshot after dumping' do
|
|
mock_database_dump!
|
|
|
|
expect_next_instance_of(Gitlab::Backup::Cli::Services::Database) do |db|
|
|
expect(db).to receive(:release_snapshot!).and_call_original
|
|
end.at_least(:once)
|
|
|
|
database.dump(destination)
|
|
end
|
|
|
|
it 'restores timeout after dumping' do
|
|
mock_database_dump!
|
|
|
|
expect_next_instance_of(Gitlab::Backup::Cli::Services::Database) do |db|
|
|
expect(db).to receive(:restore_timeouts!).and_call_original
|
|
end.at_least(:once)
|
|
|
|
database.dump(destination)
|
|
end
|
|
|
|
it 'raises an error if the dump fails' do
|
|
false_command = Gitlab::Backup::Cli::Shell::Command.new(%q(false))
|
|
replace_database_dump_command!(false_command)
|
|
|
|
expect { database.dump(destination) }.to raise_error(Gitlab::Backup::Cli::Errors::DatabaseBackupError)
|
|
end
|
|
end
|
|
|
|
describe '#restore' do
|
|
let(:source) { Pathname(Dir.mktmpdir('database-target', temp_path)) }
|
|
|
|
after do
|
|
FileUtils.rm_rf(source)
|
|
end
|
|
|
|
context 'with an invalid backup source' do
|
|
it 'raises an error when main database backup file is missing' do
|
|
mock_databases_collection('main')
|
|
|
|
expect { database.restore(source) }.to raise_error(Gitlab::Backup::Cli::Error).with_message(
|
|
/Database backup file '[^']*' for the main database does not exist/
|
|
)
|
|
end
|
|
|
|
it 'raises an warning when other database backup files are missing' do
|
|
mock_databases_collection('ci')
|
|
|
|
expect { database.restore(source) }.to output(
|
|
/Database backup file '[^']*' for the ci database does not exist/
|
|
).to_stderr
|
|
end
|
|
end
|
|
|
|
context 'with a valid backup file' do
|
|
it 'drops all tables before restoring' do
|
|
allow(database).to receive(:restore_tables).and_return(
|
|
pipeline_success
|
|
)
|
|
|
|
mock_databases_collection('main') do |_|
|
|
FileUtils.touch(source.join('database.sql.gz'))
|
|
end
|
|
|
|
expect(database).to receive(:drop_tables!)
|
|
|
|
database.restore(source)
|
|
end
|
|
|
|
it 'restores the database' do
|
|
mock_databases_collection('main') do |db|
|
|
filepath = source.join('database.sql.gz')
|
|
FileUtils.touch(filepath)
|
|
|
|
expect(database).to receive(:restore_tables).with(database: db, filepath: filepath).and_return(
|
|
pipeline_success
|
|
)
|
|
end
|
|
|
|
database.restore(source)
|
|
end
|
|
end
|
|
end
|
|
|
|
def mock_databases_collection(dbname)
|
|
allow_next_instance_of(Gitlab::Backup::Cli::Services::Postgres) do |databases|
|
|
entry = databases.send(:entries).find { |db| db.configuration.name == dbname }
|
|
|
|
allow(databases).to receive(:each).and_yield(entry)
|
|
|
|
yield entry if block_given?
|
|
end
|
|
end
|
|
|
|
def mock_database_dump!
|
|
echo_command = Gitlab::Backup::Cli::Shell::Command.new(%q(echo ''))
|
|
|
|
replace_database_dump_command!(echo_command)
|
|
end
|
|
|
|
def replace_database_dump_command!(new_command)
|
|
allow_next_instance_of(::Gitlab::Backup::Cli::Utils::PgDump) do |pg_dump|
|
|
allow(pg_dump).to receive(:build_command).and_return(new_command)
|
|
end
|
|
end
|
|
end
|