Skip to content

Commit

Permalink
Update ar_internal_metadata after remote restore
Browse files Browse the repository at this point in the history
This change updates the local development restore operation to update the
`ar_internal_metadata` table if it's present, setting the environment
value to `development`.

If the table is not present (either for older Rails applications or
non-Rails applications), this anonymous PG function will no-op.

Fix #147
  • Loading branch information
geoffharcourt committed Sep 15, 2018
1 parent 12397c4 commit e5e025a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 46 deletions.
12 changes: 12 additions & 0 deletions lib/parity/backup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def restore_to_development
wipe_development_database
restore_from_local_temp_backup
delete_local_temp_backup
delete_rails_production_environment_settings
end

def wipe_development_database
Expand Down Expand Up @@ -81,6 +82,17 @@ def delete_local_temp_backup
Kernel.system("rm tmp/latest.backup")
end

def delete_rails_production_environment_settings
Kernel.system(
"psql #{development_db} -c "\
"\"DO $$ BEGIN IF EXISTS "\
"(SELECT 1 FROM pg_tables WHERE tablename = 'ar_internal_metadata') "\
"THEN UPDATE ar_internal_metadata "\
"SET value = 'development' "\
"WHERE key = 'environment'; ELSE END IF; END $$;\"",
)
end

def restore_to_remote_environment
reset_remote_database
Kernel.system(
Expand Down
128 changes: 82 additions & 46 deletions spec/parity/backup_spec.rb
Original file line number Diff line number Diff line change
@@ -1,52 +1,79 @@
require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'parity')

describe Parity::Backup do
it "restores backups to development (after dropping the development DB)" do
allow(IO).to receive(:read).and_return(database_fixture)
allow(Kernel).to receive(:system)
allow(Etc).to receive(:nprocessors).and_return(number_of_processes)

Parity::Backup.new(from: "production", to: "development").restore

expect(Kernel).
to have_received(:system).
with(make_temp_directory_command)
expect(Kernel).
to have_received(:system).
with(download_remote_database_command)
expect(Kernel).
to have_received(:system).
with(drop_development_database_drop_command)
expect(Kernel).
to have_received(:system).
with(restore_from_local_temp_backup_command)
expect(Kernel).
to have_received(:system).
with(delete_local_temp_backup_command)
end

it "restores backups to development with Rubies that do not support Etc.nprocessors" do
allow(IO).to receive(:read).and_return(database_fixture)
allow(Kernel).to receive(:system)
allow(Etc).to receive(:respond_to?).with(:nprocessors).and_return(false)

Parity::Backup.new(from: "production", to: "development").restore

expect(Kernel).
to have_received(:system).
with(make_temp_directory_command)
expect(Kernel).
to have_received(:system).
with(download_remote_database_command)
expect(Kernel).
to have_received(:system).
with(drop_development_database_drop_command)
expect(Kernel).
to have_received(:system).
with(restore_from_local_temp_backup_command(cores: 2))
expect(Kernel).
to have_received(:system).
with(delete_local_temp_backup_command)
context "restoring to the local development environment" do
it "restores backups to development (after dropping the development DB)" do
allow(IO).to receive(:read).and_return(database_fixture)
allow(Kernel).to receive(:system)
allow(Etc).to receive(:nprocessors).and_return(number_of_processes)

Parity::Backup.new(from: "production", to: "development").restore

expect(Kernel).
to have_received(:system).
with(make_temp_directory_command)
expect(Kernel).
to have_received(:system).
with(download_remote_database_command)
expect(Kernel).
to have_received(:system).
with(drop_development_database_drop_command)
expect(Kernel).
to have_received(:system).
with(restore_from_local_temp_backup_command)
expect(Kernel).
to have_received(:system).
with(delete_local_temp_backup_command)
end

it "restores backups to development with Rubies that do not support Etc.nprocessors" do
allow(IO).to receive(:read).and_return(database_fixture)
allow(Kernel).to receive(:system)
allow(Etc).to receive(:respond_to?).with(:nprocessors).and_return(false)

Parity::Backup.new(from: "production", to: "development").restore

expect(Kernel).
to have_received(:system).
with(make_temp_directory_command)
expect(Kernel).
to have_received(:system).
with(download_remote_database_command)
expect(Kernel).
to have_received(:system).
with(drop_development_database_drop_command)
expect(Kernel).
to have_received(:system).
with(restore_from_local_temp_backup_command(cores: 2))
expect(Kernel).
to have_received(:system).
with(delete_local_temp_backup_command)
end

it "drops the 'ar_internal_metadata' table if it exists" do
allow(IO).to receive(:read).and_return(database_fixture)
allow(Kernel).to receive(:system)
allow(Etc).to receive(:nprocessors).and_return(number_of_processes)

Parity::Backup.new(from: "production", to: "development").restore

expect(Kernel).
to have_received(:system).
with(make_temp_directory_command)
expect(Kernel).
to have_received(:system).
with(download_remote_database_command)
expect(Kernel).
to have_received(:system).
with(drop_development_database_drop_command)
expect(Kernel).
to have_received(:system).
with(restore_from_local_temp_backup_command)
expect(Kernel).
to have_received(:system).
with(delete_local_temp_backup_command)
expect(Kernel).to have_received(:system).with(set_db_metadata_sql)
end
end

it "restores backups to staging from production" do
Expand Down Expand Up @@ -156,4 +183,13 @@ def additional_argument_pass_through
def default_db_name
"parity_development"
end

def set_db_metadata_sql
"psql parity_development -c "\
"\"DO $$ BEGIN IF EXISTS "\
"(SELECT 1 FROM pg_tables WHERE tablename = 'ar_internal_metadata') "\
"THEN UPDATE ar_internal_metadata "\
"SET value = 'development' "\
"WHERE key = 'environment'; ELSE END IF; END $$;\""
end
end

0 comments on commit e5e025a

Please sign in to comment.