FEATURE: Remap uploads during restore when S3 or CDN changes

In order for this to work the Backuper stores a couple of site settings
in the new backup_metadata table, because the old setting values might
not be available on restore anymore.
This commit is contained in:
Gerhard Schlager 2019-07-09 13:57:31 +02:00
parent 5ffb722999
commit a65a9a85d5
4 changed files with 79 additions and 6 deletions

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class BackupMetadata < ActiveRecord::Base
def self.value_for(name)
where(name: name).pluck(:value).first
end
end
# == Schema Information
#
# Table name: backup_metadata
#
# id :bigint not null, primary key
# name :string not null
# value :string
#

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
class CreateBackupMetadata < ActiveRecord::Migration[5.2]
def change
create_table :backup_metadata do |t|
t.string :name, null: false
t.string :value
end
end
end

View File

@ -32,6 +32,8 @@ module BackupRestore
ensure_directory_exists(@tmp_directory)
ensure_directory_exists(@archive_directory)
update_metadata
### READ-ONLY / START ###
enable_readonly_mode
@ -117,6 +119,16 @@ module BackupRestore
BackupRestore.mark_as_running!
end
def update_metadata
log "Updating metadata..."
BackupMetadata.delete_all
BackupMetadata.create!(name: "base_url", value: Discourse.base_url)
BackupMetadata.create!(name: "cdn_url", value: Discourse.asset_host)
BackupMetadata.create!(name: "s3_base_url", value: SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_base_url : nil)
BackupMetadata.create!(name: "s3_cdn_url", value: SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_cdn_url : nil)
BackupMetadata.create!(name: "db_name", value: RailsMultisite::ConnectionManagement.current_db)
end
def enable_readonly_mode
return if @readonly_mode_was_enabled
log "Enabling readonly mode..."

View File

@ -434,7 +434,7 @@ module BackupRestore
FileUtils.mkdir_p("uploads")
tmp_uploads_path = Dir.glob(File.join(@tmp_directory, "uploads", "*")).first
previous_db_name = File.basename(tmp_uploads_path)
previous_db_name = BackupMetadata.value_for("db_name") || File.basename(tmp_uploads_path)
current_db_name = RailsMultisite::ConnectionManagement.current_db
optimized_images_exist = File.exist?(File.join(tmp_uploads_path, 'optimized'))
@ -443,10 +443,7 @@ module BackupRestore
failure_message: "Failed to restore uploads."
)
if previous_db_name != current_db_name
log "Remapping uploads..."
DbHelper.remap("uploads/#{previous_db_name}", "uploads/#{current_db_name}")
end
remap_uploads(previous_db_name, current_db_name)
if SiteSetting.Upload.enable_s3_uploads
migrate_to_s3
@ -458,6 +455,45 @@ module BackupRestore
end
end
def remap_uploads(previous_db_name, current_db_name)
log "Remapping uploads..."
if (old_base_url = BackupMetadata.value_for("base_url")) && old_base_url != Discourse.base_url
DbHelper.remap(old_base_url, Discourse.base_url)
end
current_s3_base_url = SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_base_url : nil
if (old_s3_base_url = BackupMetadata.value_for("s3_base_url")) && old_base_url != current_s3_base_url
DbHelper.remap("#{old_s3_base_url}/", "/uploads/#{current_db_name}/")
end
current_s3_cdn_url = SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_cdn_url : nil
if (old_s3_cdn_url = BackupMetadata.value_for("s3_cdn_url")) && old_s3_cdn_url != current_s3_cdn_url
base_url = SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_cdn_url : Discourse.base_url
DbHelper.remap("#{old_s3_cdn_url}/", UrlHelper.schemaless("#{base_url}/uploads/#{current_db_name}/"))
old_host = URI.parse(old_s3_cdn_url).host
new_host = URI.parse(base_url.presence || Discourse.base_url).host
DbHelper.remap(old_host, new_host)
end
if (old_cdn_url = BackupMetadata.value_for("cdn_url")) && old_cdn_url != Discourse.asset_host
base_url = SiteSetting.Upload.enable_s3_uploads ? SiteSetting.Upload.s3_base_url : Discourse.base_url
DbHelper.remap("#{old_cdn_url}/", UrlHelper.schemaless("#{base_url}/"))
old_host = URI.parse(old_cdn_url).host
new_host = URI.parse(base_url.presence || Discourse.base_url).host
DbHelper.remap(old_host, new_host)
end
if previous_db_name != current_db_name
DbHelper.remap("uploads/#{previous_db_name}", "uploads/#{current_db_name}")
end
rescue => ex
log "Something went wrong while remapping uploads.", ex
end
def migrate_to_s3
log "Migrating uploads to S3..."
ENV["SKIP_FAILED"] = "1"
@ -589,5 +625,4 @@ module BackupRestore
end
end
end