backup 2.3.1 → 2.3.2.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +16 -1
  2. data/README.textile +42 -177
  3. data/bin/backup +14 -17
  4. data/generators/backup/templates/config/backup.rb +26 -6
  5. data/generators/backup/templates/migrations/create_backup_tables.rb +3 -2
  6. data/generators/backup/templates/tasks/backup.rake +14 -17
  7. data/generators/backup_update/backup_update_generator.rb +50 -0
  8. data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
  9. data/lib/backup.rb +31 -30
  10. data/lib/backup/adapters/archive.rb +19 -54
  11. data/lib/backup/adapters/base.rb +55 -35
  12. data/lib/backup/adapters/custom.rb +15 -53
  13. data/lib/backup/adapters/mysql.rb +24 -55
  14. data/lib/backup/adapters/postgresql.rb +19 -54
  15. data/lib/backup/adapters/sqlite.rb +25 -0
  16. data/lib/backup/command_helper.rb +11 -0
  17. data/lib/backup/configuration/adapter.rb +4 -11
  18. data/lib/backup/configuration/adapter_options.rb +3 -14
  19. data/lib/backup/configuration/attributes.rb +19 -0
  20. data/lib/backup/configuration/base.rb +26 -9
  21. data/lib/backup/configuration/mail.rb +3 -9
  22. data/lib/backup/configuration/smtp.rb +3 -14
  23. data/lib/backup/configuration/storage.rb +3 -12
  24. data/lib/backup/connection/s3.rb +3 -1
  25. data/lib/backup/environment/unix.rb +4 -4
  26. data/lib/backup/mail/base.rb +8 -2
  27. data/lib/backup/mail/mail.txt +3 -3
  28. data/lib/backup/record/base.rb +65 -0
  29. data/lib/backup/record/ftp.rb +10 -69
  30. data/lib/backup/record/local.rb +26 -0
  31. data/lib/backup/record/s3.rb +9 -63
  32. data/lib/backup/record/scp.rb +9 -64
  33. data/lib/backup/record/sftp.rb +10 -68
  34. data/lib/backup/storage/ftp.rb +3 -1
  35. data/lib/backup/storage/local.rb +24 -0
  36. data/lib/backup/storage/s3.rb +3 -1
  37. data/lib/backup/storage/scp.rb +3 -1
  38. data/lib/backup/storage/sftp.rb +3 -1
  39. data/setup/backup.rb +27 -6
  40. data/setup/backup.sqlite3 +0 -0
  41. metadata +130 -60
  42. data/.document +0 -5
  43. data/.gitignore +0 -5
  44. data/Rakefile +0 -70
  45. data/backup.gemspec +0 -111
@@ -1,12 +1,13 @@
1
1
  class CreateBackupTables < ActiveRecord::Migration
2
2
  def self.up
3
3
  create_table :backup do |t|
4
- t.string :storage
5
4
  t.string :trigger
6
5
  t.string :adapter
7
6
  t.string :filename
7
+ t.string :md5sum
8
8
  t.string :path
9
9
  t.string :bucket
10
+ t.string :type
10
11
  t.timestamps
11
12
  end
12
13
  end
@@ -14,4 +15,4 @@ class CreateBackupTables < ActiveRecord::Migration
14
15
  def self.down
15
16
  drop_table :backup
16
17
  end
17
- end
18
+ end
@@ -12,10 +12,11 @@ namespace :backup do
12
12
  backup = Backup::Setup.new(ENV['trigger'], @backup_procedures)
13
13
  records = Array.new
14
14
  case backup.procedure.storage_name.to_sym
15
- when :s3 then records = Backup::Record::S3.all :conditions => {:trigger => ENV['trigger']}
16
- when :scp then records = Backup::Record::SCP.all :conditions => {:trigger => ENV['trigger']}
17
- when :ftp then records = Backup::Record::FTP.all :conditions => {:trigger => ENV['trigger']}
18
- when :sftp then records = Backup::Record::SFTP.all :conditions => {:trigger => ENV['trigger']}
15
+ when :s3 then records = Backup::Record::S3.all :conditions => {:trigger => ENV['trigger']}
16
+ when :scp then records = Backup::Record::SCP.all :conditions => {:trigger => ENV['trigger']}
17
+ when :ftp then records = Backup::Record::FTP.all :conditions => {:trigger => ENV['trigger']}
18
+ when :sftp then records = Backup::Record::SFTP.all :conditions => {:trigger => ENV['trigger']}
19
+ when :local then records = Backup::Record::Local.all :conditions => {:trigger => ENV['trigger']}
19
20
  end
20
21
 
21
22
  if ENV['table'].eql?("true")
@@ -30,19 +31,13 @@ namespace :backup do
30
31
  desc "Truncates all records for the specified \"trigger\", excluding the physical files on s3 or the remote server."
31
32
  task :truncate => :environment do
32
33
  puts "Truncating backup records with trigger: #{ENV['trigger']}."
33
- Backup::Record::S3.destroy_all :trigger => ENV['trigger'], :storage => 's3'
34
- Backup::Record::SCP.destroy_all :trigger => ENV['trigger'], :storage => 'scp'
35
- Backup::Record::FTP.destroy_all :trigger => ENV['trigger'], :storage => 'ftp'
36
- Backup::Record::SFTP.destroy_all :trigger => ENV['trigger'], :storage => 'sftp'
34
+ Backup::Record::Base.destroy_all :trigger => ENV['trigger']
37
35
  end
38
36
 
39
37
  desc "Truncates everything."
40
38
  task :truncate_all => :environment do
41
39
  puts "Truncating all backup records."
42
- Backup::Record::S3.destroy_all
43
- Backup::Record::SCP.destroy_all
44
- Backup::Record::FTP.destroy_all
45
- Backup::Record::SFTP.destroy_all
40
+ Backup::Record::Base.destroy_all
46
41
  end
47
42
 
48
43
  desc "Destroys all records for the specified \"trigger\", including the physical files on s3 or the remote server."
@@ -50,10 +45,11 @@ namespace :backup do
50
45
  puts "Destroying backup records with trigger: #{ENV['trigger']}."
51
46
  backup = Backup::Setup.new(ENV['trigger'], @backup_procedures)
52
47
  case backup.procedure.storage_name.to_sym
53
- when :s3 then Backup::Record::S3.destroy_all_backups backup.procedure, ENV['trigger']
54
- when :scp then Backup::Record::SCP.destroy_all_backups backup.procedure, ENV['trigger']
55
- when :ftp then Backup::Record::FTP.destroy_all_backups backup.procedure, ENV['trigger']
56
- when :sftp then Backup::Record::SFTP.destroy_all_backups backup.procedure, ENV['trigger']
48
+ when :s3 then Backup::Record::S3.destroy_all_backups backup.procedure, ENV['trigger']
49
+ when :scp then Backup::Record::SCP.destroy_all_backups backup.procedure, ENV['trigger']
50
+ when :ftp then Backup::Record::FTP.destroy_all_backups backup.procedure, ENV['trigger']
51
+ when :sftp then Backup::Record::SFTP.destroy_all_backups backup.procedure, ENV['trigger']
52
+ when :local then Backup::Record::Local.destroy_all_backups backup.procedure, ENV['trigger']
57
53
  end
58
54
  end
59
55
 
@@ -67,8 +63,9 @@ namespace :backup do
67
63
  when :scp then Backup::Record::SCP.destroy_all_backups backup_procedure, backup_procedure.trigger
68
64
  when :ftp then Backup::Record::FTP.destroy_all_backups backup_procedure, backup_procedure.trigger
69
65
  when :sftp then Backup::Record::SFTP.destroy_all_backups backup_procedure, backup_procedure.trigger
66
+ when :local then Backup::Record::Local.destroy_all_backups backup_procedure, backup_procedure.trigger
70
67
  end
71
68
  end
72
69
  end
73
70
 
74
- end
71
+ end
@@ -0,0 +1,50 @@
1
+ class BackupUpdateGenerator < Rails::Generator::Base
2
+
3
+ # This method gets initialized when the generator gets run.
4
+ # It will receive an array of arguments inside @args
5
+ def initialize(runtime_args, runtime_options = {})
6
+ super
7
+ end
8
+
9
+ # Processes the file generation/templating
10
+ # This will automatically be run after the initialize method
11
+ def manifest
12
+ record do |m|
13
+
14
+ # Generates the database update migration file
15
+ m.migration_template "migrations/update_backup_tables.rb",
16
+ "db/migrate",
17
+ :migration_file_name => "update_backup_tables"
18
+
19
+ # Outputs the generators message to the terminal
20
+ puts message
21
+ end
22
+ end
23
+
24
+ def message
25
+ <<-MESSAGE
26
+
27
+
28
+
29
+ ==============================================================
30
+ Backup's update files have been generated!
31
+ ==============================================================
32
+
33
+ Please follow these instructions Backup:
34
+
35
+ 1: Please migrate the database to finish the update!
36
+
37
+ rake db:migrate
38
+
39
+
40
+ For More Information:
41
+ http://github.com/meskyanichi/backup
42
+
43
+ ==============================================================
44
+
45
+
46
+
47
+ MESSAGE
48
+ end
49
+
50
+ end
@@ -0,0 +1,27 @@
1
+ class UpdateBackupTables < ActiveRecord::Migration
2
+ def self.up
3
+ change_table :backup do |t|
4
+ t.rename :storage, :type # will use STI from now
5
+ t.string :md5sum
6
+ end
7
+
8
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='Backup::Record::FTP' WHERE type='ftp'"
9
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='Backup::Record::Local' WHERE type='local'"
10
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='Backup::Record::S3' WHERE type='s3'"
11
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='Backup::Record::SCP' WHERE type='scp'"
12
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='Backup::Record::SFTP' WHERE type='sftp'"
13
+ end
14
+
15
+ def self.down
16
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='ftp' WHERE type='Backup::Record::FTP'"
17
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='local' WHERE type='Backup::Record::Local'"
18
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='s3' WHERE type='Backup::Record::S3'"
19
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='scp' WHERE type='Backup::Record::SCP'"
20
+ ActiveRecord::Base.connection.execute "UPDATE backup SET type='sftp' WHERE type='Backup::Record::SFTP'"
21
+
22
+ change_table :backup do |t|
23
+ t.rename :type, :storage
24
+ t.remove :md5sum
25
+ end
26
+ end
27
+ end
data/lib/backup.rb CHANGED
@@ -1,10 +1,4 @@
1
1
  # Load Gems
2
- require 'net/ssh'
3
- require 'net/scp'
4
- require 'net/ftp'
5
- require 'net/sftp'
6
- require 'aws/s3'
7
- require 'pony'
8
2
  require 'hirb'
9
3
 
10
4
  # Load Environments
@@ -13,6 +7,7 @@ require 'backup/environment/unix'
13
7
  require 'backup/environment/rails'
14
8
 
15
9
  # Load Configuration
10
+ require 'backup/configuration/attributes'
16
11
  require 'backup/configuration/base'
17
12
  require 'backup/configuration/adapter'
18
13
  require 'backup/configuration/adapter_options'
@@ -21,7 +16,9 @@ require 'backup/configuration/mail'
21
16
  require 'backup/configuration/smtp'
22
17
  require 'backup/configuration/helpers'
23
18
 
24
- # Include the Configuration adn Environment Helpers
19
+ require 'backup/command_helper'
20
+
21
+ # Include the Configuration and Environment Helpers
25
22
  include Backup::Configuration::Helpers
26
23
  include Backup::Environment::Base
27
24
 
@@ -42,31 +39,34 @@ require 'backup/mail/base'
42
39
  # Set Mail Configuration (extracted from the backup.rb configuration file) inside the Mail Class
43
40
  Backup::Mail::Base.setup(@mail_configuration)
44
41
 
45
- # Load Adapters
46
- require 'backup/adapters/base'
47
- require 'backup/adapters/mysql'
48
- require 'backup/adapters/postgresql'
49
- require 'backup/adapters/archive'
50
- require 'backup/adapters/custom'
51
-
52
- # Load Connectors
53
- require 'backup/connection/s3'
54
-
55
- # Load Storage
56
- require 'backup/storage/s3'
57
- require 'backup/storage/scp'
58
- require 'backup/storage/ftp'
59
- require 'backup/storage/sftp'
42
+ # Backup Module
43
+ module Backup
44
+ module Adapters
45
+ autoload :Base, 'backup/adapters/base'
46
+ autoload :MySQL, 'backup/adapters/mysql'
47
+ autoload :SQLite, 'backup/adapters/sqlite'
48
+ autoload :PostgreSQL, 'backup/adapters/postgresql'
49
+ autoload :Archive, 'backup/adapters/archive'
50
+ autoload :Custom, 'backup/adapters/custom'
51
+ end
60
52
 
61
- # Backup Recorders
62
- require 'backup/record/s3'
63
- require 'backup/record/scp'
64
- require 'backup/record/ftp'
65
- require 'backup/record/sftp'
53
+ module Storage
54
+ autoload :S3, 'backup/storage/s3'
55
+ autoload :SCP, 'backup/storage/scp'
56
+ autoload :FTP, 'backup/storage/ftp'
57
+ autoload :SFTP, 'backup/storage/sftp'
58
+ autoload :Local, 'backup/storage/local'
59
+ end
66
60
 
61
+ module Record
62
+ autoload :Base, 'backup/record/base'
63
+ autoload :S3, 'backup/record/s3'
64
+ autoload :SCP, 'backup/record/scp'
65
+ autoload :FTP, 'backup/record/ftp'
66
+ autoload :SFTP, 'backup/record/sftp'
67
+ autoload :Local, 'backup/record/local'
68
+ end
67
69
 
68
- # Backup Module
69
- module Backup
70
70
  class Setup
71
71
 
72
72
  attr_accessor :trigger, :procedures, :procedure
@@ -83,6 +83,7 @@ module Backup
83
83
  def initialize_adapter
84
84
  case procedure.adapter_name.to_sym
85
85
  when :mysql then Backup::Adapters::MySQL.new trigger, procedure
86
+ when :sqlite then Backup::Adapters::SQLite.new trigger, procedure
86
87
  when :postgresql then Backup::Adapters::PostgreSQL.new trigger, procedure
87
88
  when :archive then Backup::Adapters::Archive.new trigger, procedure
88
89
  when :custom then Backup::Adapters::Custom.new trigger, procedure
@@ -108,4 +109,4 @@ module Backup
108
109
  end
109
110
 
110
111
  end
111
- end
112
+ end
@@ -2,68 +2,33 @@ module Backup
2
2
  module Adapters
3
3
  class Archive < Backup::Adapters::Base
4
4
 
5
- attr_accessor :archived_file, :compressed_file, :encrypted_file
6
-
7
- # Initializes the Backup Process
8
- #
9
- # This will first load in any prefixed settings from the Backup::Adapters::Base
10
- # Then it will add it's own settings.
11
- #
12
- # First it will archive and compress every folder/file
13
- # Then it will optionally encrypt the backed up file
14
- # Then it will store it to the specified storage location
15
- # Then it will record the data to the database
16
- # Once this is all done, all the temporary files will be removed
17
- #
18
- # Wrapped inside of begin/ensure/end block to ensure the deletion of any files in the tmp directory
19
- def initialize(trigger, procedure)
20
- super
21
- load_settings
22
-
23
- begin
24
- targz
25
- encrypt
26
- store
27
- record
28
- notify
29
- ensure
30
- remove_tmp_files
31
- end
32
- end
5
+ attr_accessor :files, :exclude
33
6
 
34
7
  private
35
-
8
+
36
9
  # Archives and Compresses all files
37
- def targz
38
- files = procedure.get_adapter_configuration.attributes['files']
39
- if files.is_a?(Array)
40
- puts system_messages[:archiving]; puts system_messages[:compressing]
41
- %x{ tar -czf #{File.join(tmp_path, compressed_file)} #{files.map{|f| f.gsub(' ', '\ ')}.join(' ')} }
42
- elsif files.is_a?(String)
43
- puts system_messages[:archiving]; puts system_messages[:compressing]
44
- %x{ tar -czf #{File.join(tmp_path, compressed_file)} #{files.gsub(' ', '\ ')} }
45
- end
46
- end
47
-
48
- # Encrypts the Archive
49
- def encrypt
50
- if encrypt_with_password.is_a?(String)
51
- puts system_messages[:encrypting]
52
- %x{ openssl enc -des-cbc -in #{File.join(tmp_path, compressed_file)} -out #{File.join(tmp_path, encrypted_file)} -k #{encrypt_with_password} }
53
- self.final_file = encrypted_file
54
- end
10
+ def perform
11
+ log system_messages[:archiving]; log system_messages[:compressing]
12
+ run "tar -czf #{File.join(tmp_path, compressed_file)} #{exclude_files} #{tar_files}"
55
13
  end
56
14
 
57
- # Loads the initial settings
58
15
  def load_settings
59
- self.trigger = procedure.trigger
16
+ self.files = procedure.get_adapter_configuration.attributes['files']
17
+ self.exclude = procedure.get_adapter_configuration.attributes['exclude']
18
+ end
60
19
 
61
- self.archived_file = "#{timestamp}.#{trigger.gsub(' ', '-')}.tar"
62
- self.compressed_file = "#{archived_file}.gz"
63
- self.encrypted_file = "#{compressed_file}.enc"
64
- self.final_file = compressed_file
20
+ def performed_file_extension
21
+ ".tar"
65
22
  end
66
23
 
24
+ def tar_files
25
+ [*files].map{|f| f.gsub(' ', '\ ')}.join(' ')
26
+ end
27
+
28
+ def exclude_files
29
+ [*exclude].compact.map{|x| "--exclude=#{x}"}.join(' ')
30
+ end
31
+
67
32
  end
68
33
  end
69
- end
34
+ end
@@ -2,6 +2,8 @@ module Backup
2
2
  module Adapters
3
3
  class Base
4
4
 
5
+ include Backup::CommandHelper
6
+
5
7
  attr_accessor :procedure, :timestamp, :options, :tmp_path, :encrypt_with_password, :keep_backups, :trigger
6
8
 
7
9
  # IMPORTANT
@@ -13,8 +15,21 @@ module Backup
13
15
  # myfile.gz.enc
14
16
  #
15
17
  # It is important that, whatever the final filename of the file will be, that :final_file will contain it.
16
- attr_accessor :final_file
18
+ attr_accessor :performed_file, :compressed_file, :encrypted_file, :final_file
17
19
 
20
+ # Initializes the Backup Process
21
+ #
22
+ # This will first load in any prefixed settings from the Backup::Adapters::Base
23
+ # Then it will add it's own settings.
24
+ #
25
+ # First it will call the 'perform' method. This method is concerned with the backup, and must
26
+ # be implemented by derived classes!
27
+ # Then it will optionally encrypt the backed up file
28
+ # Then it will store it to the specified storage location
29
+ # Then it will record the data to the database
30
+ # Once this is all done, all the temporary files will be removed
31
+ #
32
+ # Wrapped inside of begin/ensure/end block to ensure the deletion of any files in the tmp directory
18
33
  def initialize(trigger, procedure)
19
34
  self.trigger = trigger
20
35
  self.procedure = procedure
@@ -22,54 +37,58 @@ module Backup
22
37
  self.tmp_path = File.join(BACKUP_PATH.gsub(' ', '\ '), 'tmp', 'backup', trigger)
23
38
  self.encrypt_with_password = procedure.attributes['encrypt_with_password']
24
39
  self.keep_backups = procedure.attributes['keep_backups']
25
- create_tmp_folder
40
+
41
+ self.performed_file = "#{timestamp}.#{trigger.gsub(' ', '-')}#{performed_file_extension}"
42
+ self.compressed_file = "#{performed_file}.gz"
43
+ self.encrypted_file = "#{compressed_file}.enc"
44
+ self.final_file = compressed_file
45
+
46
+ begin
47
+ create_tmp_folder
48
+ load_settings # if respond_to?(:load_settings)
49
+ perform
50
+ encrypt
51
+ store
52
+ record
53
+ notify
54
+ ensure
55
+ remove_tmp_files
56
+ end
26
57
  end
27
58
 
28
59
  # Creates the temporary folder for the specified adapter
29
60
  def create_tmp_folder
30
- %x{ mkdir -p #{tmp_path} }
61
+ run "mkdir -p #{tmp_path}"
62
+ end
63
+
64
+ # TODO make methods in derived classes public? respond_to cannot identify private methods
65
+ def load_settings
31
66
  end
32
67
 
33
68
  # Removes the files inside the temporary folder
34
69
  def remove_tmp_files
35
- %x{ rm #{File.join(tmp_path, '*')} }
70
+ run "rm #{File.join(tmp_path, '*')}"
36
71
  end
37
72
 
38
- # Initializes the storing process depending on the store settings
39
- # Options:
40
- # Amazon (S3)
41
- # Remote Server (SCP)
42
- # Remote Server (FTP)
43
- # Remote Server (SFTP)
44
- def store
45
- case procedure.storage_name.to_sym
46
- when :s3 then Backup::Storage::S3.new(self)
47
- when :scp then Backup::Storage::SCP.new(self)
48
- when :ftp then Backup::Storage::FTP.new(self)
49
- when :sftp then Backup::Storage::SFTP.new(self)
73
+ # Encrypts the archive file
74
+ def encrypt
75
+ if encrypt_with_password.is_a?(String)
76
+ log system_messages[:encrypting]
77
+ run "openssl enc -des-cbc -in #{File.join(tmp_path, compressed_file)} -out #{File.join(tmp_path, encrypted_file)} -k #{encrypt_with_password}"
78
+ self.final_file = encrypted_file
50
79
  end
51
80
  end
52
81
 
82
+ # Initializes the storing process
83
+ def store
84
+ procedure.initialize_storage(self)
85
+ end
86
+
53
87
  # Records data on every individual file to the database
54
88
  def record
55
- case procedure.storage_name.to_sym
56
- when :s3
57
- record = Backup::Record::S3.new
58
- record.load_adapter(self)
59
- record.save
60
- when :scp
61
- record = Backup::Record::SCP.new
62
- record.load_adapter(self)
63
- record.save
64
- when :ftp
65
- record = Backup::Record::FTP.new
66
- record.load_adapter(self)
67
- record.save
68
- when :sftp
69
- record = Backup::Record::SFTP.new
70
- record.load_adapter(self)
71
- record.save
72
- end
89
+ record = procedure.initialize_record
90
+ record.load_adapter(self)
91
+ record.save
73
92
  end
74
93
 
75
94
  # Delivers a notification by email regarding the successfully stored backup
@@ -85,9 +104,10 @@ module Backup
85
104
  :encrypting => "Encrypting backup..",
86
105
  :mysqldump => "Creating MySQL dump..",
87
106
  :pgdump => "Creating PostgreSQL dump..",
107
+ :sqlite => "Copying and compressing SQLite database..",
88
108
  :commands => "Executing commands.." }
89
109
  end
90
110
 
91
111
  end
92
112
  end
93
- end
113
+ end