FIX: automatic backup uploads to S3 when using a region

This commit is contained in:
Régis Hanol
2014-09-24 22:52:09 +02:00
parent 6c275cd64d
commit bfdbb70b3b
9 changed files with 345 additions and 212 deletions

View File

@@ -1,3 +1,5 @@
require "s3_helper"
class Backup
include UrlHelper
include ActiveModel::SerializerSupport
@@ -38,14 +40,26 @@ class Backup
remove_from_s3 if SiteSetting.enable_s3_backups?
end
def s3_bucket
return @s3_bucket if @s3_bucket
raise Discourse::SiteSettingMissing.new("s3_backup_bucket") if SiteSetting.s3_backup_bucket.blank?
@s3_bucket = SiteSetting.s3_backup_bucket.downcase
end
def s3
return @s3_helper if @s3_helper
@s3_helper = S3Helper.new(s3_bucket)
end
def upload_to_s3
return unless fog_directory
fog_directory.files.create(key: @filename, public: false, body: File.read(@path))
return unless s3
file = File.read(@path)
s3.upload(file, @filename)
end
def remove_from_s3
return unless fog
fog.delete_object(SiteSetting.s3_backup_bucket, @filename)
return unless s3
s3.remove(@filename)
end
def self.base_directory
@@ -67,40 +81,8 @@ class Backup
def self.remove_old
return if Rails.env.development?
all_backups = Backup.all
return unless all_backups.size > SiteSetting.maximum_backups
return if all_backups.size <= SiteSetting.maximum_backups
all_backups[SiteSetting.maximum_backups..-1].each(&:remove)
end
private
def s3_options
options = {
provider: 'AWS',
region: SiteSetting.s3_region.blank? ? "us-east-1" : SiteSetting.s3_region,
}
if (SiteSetting.s3_use_iam_profile.present?)
options.merge!(:use_iam_profile => true)
else
options.merge!(:aws_access_key_id => SiteSetting.s3_access_key_id,
:aws_secret_access_key => SiteSetting.s3_secret_access_key)
end
options
end
def fog
return @fog if @fog
return unless ((SiteSetting.s3_access_key_id.present? &&
SiteSetting.s3_secret_access_key.present?) ||
SiteSetting.s3_use_iam_profile.present?) &&
SiteSetting.s3_backup_bucket.present?
require 'fog'
@fog = Fog::Storage.new(s3_options)
end
def fog_directory
return @fog_directory if @fog_directory
return unless fog
@fog_directory ||= fog.directories.get(SiteSetting.s3_backup_bucket)
end
end

View File

@@ -19,40 +19,45 @@ class OptimizedImage < ActiveRecord::Base
unless thumbnail
external_copy = Discourse.store.download(upload) if Discourse.store.external?
original_path = if Discourse.store.external?
external_copy.path
external_copy.try(:path)
else
Discourse.store.path_for(upload)
end
# create a temp file with the same extension as the original
extension = File.extname(original_path)
temp_file = Tempfile.new(["discourse-thumbnail", extension])
temp_path = temp_file.path
original_path += "[0]" unless opts[:allow_animation]
if resize(original_path, temp_path, width, height)
thumbnail = OptimizedImage.create!(
upload_id: upload.id,
sha1: Digest::SHA1.file(temp_path).hexdigest,
extension: File.extname(temp_path),
width: width,
height: height,
url: "",
)
# store the optimized image and update its url
url = Discourse.store.store_optimized_image(temp_file, thumbnail)
if url.present?
thumbnail.url = url
thumbnail.save
else
Rails.logger.error("Failed to store avatar #{size} for #{upload.url} from #{source}")
end
if original_path.blank?
Rails.logger.error("Could not find file in the store located at url: #{upload.url}")
else
Rails.logger.error("Failed to create optimized image #{width}x#{height} for #{upload.url}")
# create a temp file with the same extension as the original
extension = File.extname(original_path)
temp_file = Tempfile.new(["discourse-thumbnail", extension])
temp_path = temp_file.path
original_path += "[0]" unless opts[:allow_animation]
if resize(original_path, temp_path, width, height)
thumbnail = OptimizedImage.create!(
upload_id: upload.id,
sha1: Digest::SHA1.file(temp_path).hexdigest,
extension: File.extname(temp_path),
width: width,
height: height,
url: "",
)
# store the optimized image and update its url
url = Discourse.store.store_optimized_image(temp_file, thumbnail)
if url.present?
thumbnail.url = url
thumbnail.save
else
Rails.logger.error("Failed to store avatar #{size} for #{upload.url} from #{source}")
end
else
Rails.logger.error("Failed to create optimized image #{width}x#{height} for #{upload.url}")
end
# close && remove temp file
temp_file.close!
end
# close && remove temp file
temp_file.close!
# make sure we remove the cached copy from external stores
external_copy.close! if Discourse.store.external?
end