FEATURE: Upload backups to S3 when complete.
This commit is contained in:
parent
3175c85fa6
commit
085f7997a2
|
@ -25,6 +25,25 @@ class Backup
|
||||||
|
|
||||||
def remove
|
def remove
|
||||||
File.delete(@path) if File.exists?(path)
|
File.delete(@path) if File.exists?(path)
|
||||||
|
after_remove_hook
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_create_hook
|
||||||
|
upload_to_s3 if SiteSetting.enable_s3_backups?
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_remove_hook
|
||||||
|
remove_from_s3 if SiteSetting.enable_s3_backups?
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload_to_s3
|
||||||
|
return unless fog_directory
|
||||||
|
fog_directory.files.create(key: @filename, public: false, body: File.read(@path))
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_from_s3
|
||||||
|
return unless fog
|
||||||
|
fog.delete_object(SiteSetting.s3_backup_bucket, @filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.base_directory
|
def self.base_directory
|
||||||
|
@ -49,4 +68,23 @@ class Backup
|
||||||
all_backups[SiteSetting.maximum_backups..-1].each {|b| b.remove}
|
all_backups[SiteSetting.maximum_backups..-1].each {|b| b.remove}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def fog
|
||||||
|
return @fog if @fog
|
||||||
|
return unless SiteSetting.s3_access_key_id.present? &&
|
||||||
|
SiteSetting.s3_secret_access_key.present? &&
|
||||||
|
SiteSetting.s3_backup_bucket.present?
|
||||||
|
require 'fog'
|
||||||
|
@fog = Fog::Storage.new(provider: 'AWS',
|
||||||
|
aws_access_key_id: SiteSetting.s3_access_key_id,
|
||||||
|
aws_secret_access_key: SiteSetting.s3_secret_access_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fog_directory
|
||||||
|
return @fog_directory if @fog_directory
|
||||||
|
return unless fog
|
||||||
|
@fog_directory ||= fog.directories.get(SiteSetting.s3_backup_bucket)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -714,6 +714,8 @@ en:
|
||||||
allow_restore: "Allow restore, which can replace ALL site data! Leave false unless you plan to do restore a backup"
|
allow_restore: "Allow restore, which can replace ALL site data! Leave false unless you plan to do restore a backup"
|
||||||
maximum_backups: "The maximum amount of backups to keep on disk. Older backups are automatically deleted"
|
maximum_backups: "The maximum amount of backups to keep on disk. Older backups are automatically deleted"
|
||||||
backup_daily: "Automatically create a site backup once a day"
|
backup_daily: "Automatically create a site backup once a day"
|
||||||
|
enable_s3_backups: "Upload backups to S3 when complete. Make sure you have filled in your s3 credentials."
|
||||||
|
s3_backup_bucket: "The remote bucket to hold backups. WARNING: Make sure it is a private bucket."
|
||||||
|
|
||||||
active_user_rate_limit_secs: "How frequently we update the 'last_seen_at' field, in seconds"
|
active_user_rate_limit_secs: "How frequently we update the 'last_seen_at' field, in seconds"
|
||||||
previous_visit_timeout_hours: "How long a visit lasts before we consider it the 'previous' visit, in hours"
|
previous_visit_timeout_hours: "How long a visit lasts before we consider it the 'previous' visit, in hours"
|
||||||
|
|
|
@ -419,6 +419,11 @@ backups:
|
||||||
backup_daily:
|
backup_daily:
|
||||||
client: false
|
client: false
|
||||||
default: false
|
default: false
|
||||||
|
enable_s3_backups:
|
||||||
|
client: false
|
||||||
|
default: false
|
||||||
|
s3_backup_bucket:
|
||||||
|
client: false
|
||||||
|
|
||||||
uncategorized:
|
uncategorized:
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ module Export
|
||||||
|
|
||||||
create_archive
|
create_archive
|
||||||
|
|
||||||
|
after_create_hook
|
||||||
|
|
||||||
remove_old
|
remove_old
|
||||||
|
|
||||||
notify_user
|
notify_user
|
||||||
|
@ -236,6 +238,12 @@ module Export
|
||||||
`gzip --best #{tar_filename}`
|
`gzip --best #{tar_filename}`
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_create_hook
|
||||||
|
log "Executing the after_create_hook for the backup"
|
||||||
|
backup = Backup.create_from_filename("#{File.basename(@archive_basename)}.tar.gz")
|
||||||
|
backup.after_create_hook
|
||||||
|
end
|
||||||
|
|
||||||
def notify_user
|
def notify_user
|
||||||
log "Notifying '#{@user.username}' of the success of the backup..."
|
log "Notifying '#{@user.username}' of the success of the backup..."
|
||||||
# NOTE: will only notify if @user != Discourse.site_contact_user
|
# NOTE: will only notify if @user != Discourse.site_contact_user
|
||||||
|
|
|
@ -27,5 +27,34 @@ describe Backup do
|
||||||
Backup.remove_old
|
Backup.remove_old
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context ".after_create_hook" do
|
||||||
|
it "calls upload_to_s3 if the SiteSetting is true" do
|
||||||
|
SiteSetting.stubs(:enable_s3_backups?).returns(true)
|
||||||
|
b1.expects(:upload_to_s3).once
|
||||||
|
b1.after_create_hook
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls upload_to_s3 if the SiteSetting is false" do
|
||||||
|
SiteSetting.stubs(:enable_s3_backups?).returns(false)
|
||||||
|
b1.expects(:upload_to_s3).never
|
||||||
|
b1.after_create_hook
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context ".after_remove_hook" do
|
||||||
|
it "calls remove_from_s3 if the SiteSetting is true" do
|
||||||
|
SiteSetting.stubs(:enable_s3_backups?).returns(true)
|
||||||
|
b1.expects(:remove_from_s3).once
|
||||||
|
b1.after_remove_hook
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls remove_from_s3 if the SiteSetting is false" do
|
||||||
|
SiteSetting.stubs(:enable_s3_backups?).returns(false)
|
||||||
|
b1.expects(:remove_from_s3).never
|
||||||
|
b1.after_remove_hook
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue