namxam-backup 2.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/CHANGELOG +131 -0
  2. data/LICENSE +20 -0
  3. data/README.md +122 -0
  4. data/bin/backup +108 -0
  5. data/generators/backup/backup_generator.rb +69 -0
  6. data/generators/backup/templates/backup.rake +56 -0
  7. data/generators/backup/templates/backup.rb +253 -0
  8. data/generators/backup/templates/create_backup_tables.rb +18 -0
  9. data/generators/backup_update/backup_update_generator.rb +50 -0
  10. data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
  11. data/lib/backup.rb +132 -0
  12. data/lib/backup/adapters/archive.rb +34 -0
  13. data/lib/backup/adapters/base.rb +167 -0
  14. data/lib/backup/adapters/custom.rb +41 -0
  15. data/lib/backup/adapters/mongo_db.rb +139 -0
  16. data/lib/backup/adapters/mysql.rb +60 -0
  17. data/lib/backup/adapters/postgresql.rb +56 -0
  18. data/lib/backup/adapters/sqlite.rb +25 -0
  19. data/lib/backup/command_helper.rb +14 -0
  20. data/lib/backup/configuration/adapter.rb +21 -0
  21. data/lib/backup/configuration/adapter_options.rb +8 -0
  22. data/lib/backup/configuration/attributes.rb +19 -0
  23. data/lib/backup/configuration/base.rb +75 -0
  24. data/lib/backup/configuration/helpers.rb +24 -0
  25. data/lib/backup/configuration/mail.rb +20 -0
  26. data/lib/backup/configuration/smtp.rb +8 -0
  27. data/lib/backup/configuration/storage.rb +8 -0
  28. data/lib/backup/connection/cloudfiles.rb +75 -0
  29. data/lib/backup/connection/dropbox.rb +62 -0
  30. data/lib/backup/connection/s3.rb +88 -0
  31. data/lib/backup/core_ext/object.rb +5 -0
  32. data/lib/backup/environment/base.rb +12 -0
  33. data/lib/backup/environment/rails_configuration.rb +15 -0
  34. data/lib/backup/environment/unix_configuration.rb +109 -0
  35. data/lib/backup/mail/base.rb +97 -0
  36. data/lib/backup/mail/mail.txt +7 -0
  37. data/lib/backup/record/base.rb +65 -0
  38. data/lib/backup/record/cloudfiles.rb +28 -0
  39. data/lib/backup/record/dropbox.rb +27 -0
  40. data/lib/backup/record/ftp.rb +39 -0
  41. data/lib/backup/record/local.rb +26 -0
  42. data/lib/backup/record/s3.rb +25 -0
  43. data/lib/backup/record/scp.rb +33 -0
  44. data/lib/backup/record/sftp.rb +38 -0
  45. data/lib/backup/storage/base.rb +10 -0
  46. data/lib/backup/storage/cloudfiles.rb +16 -0
  47. data/lib/backup/storage/dropbox.rb +12 -0
  48. data/lib/backup/storage/ftp.rb +38 -0
  49. data/lib/backup/storage/local.rb +22 -0
  50. data/lib/backup/storage/s3.rb +15 -0
  51. data/lib/backup/storage/scp.rb +30 -0
  52. data/lib/backup/storage/sftp.rb +31 -0
  53. data/lib/backup/version.rb +3 -0
  54. data/lib/generators/backup/USAGE +10 -0
  55. data/lib/generators/backup/backup_generator.rb +47 -0
  56. data/lib/generators/backup/templates/backup.rake +56 -0
  57. data/lib/generators/backup/templates/backup.rb +236 -0
  58. data/lib/generators/backup/templates/create_backup_tables.rb +18 -0
  59. data/setup/backup.rb +255 -0
  60. data/setup/backup.sqlite3 +0 -0
  61. metadata +278 -0
@@ -0,0 +1,25 @@
1
+ module Backup
2
+ module Adapters
3
+ class SQLite < Base
4
+
5
+ attr_accessor :database
6
+
7
+ private
8
+
9
+ # Compress the sqlite file
10
+ def perform
11
+ log system_messages[:sqlite]
12
+ run "gzip -c --best #{database} > #{File.join(tmp_path, compressed_file)}"
13
+ end
14
+
15
+ def load_settings
16
+ self.database = procedure.get_adapter_configuration.attributes['database']
17
+ end
18
+
19
+ def performed_file_extension
20
+ ""
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module Backup
2
+ module CommandHelper
3
+ def run(command, opts={})
4
+ opts[:exit_on_failure] ||= false
5
+ output = `#{command}`
6
+ exit 1 if opts[:exit_on_failure] && !$?.success?
7
+ output
8
+ end
9
+
10
+ def log(command)
11
+ puts "Backup (#{Time.now.strftime("%Y-%m-%d %H:%M:%S %Z")}) => #{command}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module Backup
2
+ module Configuration
3
+ class Adapter
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(files exclude user password database tables skip_tables commands additional_options backup_method)
6
+
7
+ def initialize
8
+ @options = Backup::Configuration::AdapterOptions.new
9
+ end
10
+
11
+ def options(&block)
12
+ @options.instance_eval &block
13
+ end
14
+
15
+ def get_options
16
+ @options
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ module Backup
2
+ module Configuration
3
+ class AdapterOptions
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(host port socket)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ module Backup
2
+ module Configuration
3
+ module Attributes
4
+
5
+ def generate_attributes(*attrs)
6
+ define_method :attributes do
7
+ @attributes ||= {}
8
+ end
9
+
10
+ attrs.flatten.each do |att|
11
+ define_method att do |value|
12
+ self.attributes[att.to_s] = value
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,75 @@
1
+ module Backup
2
+ module Configuration
3
+ class Base
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(encrypt_with_password encrypt_with_gpg_public_key keep_backups notify)
6
+
7
+ attr_accessor :trigger, :storage_name, :adapter_name, :before_backup_block, :after_backup_block
8
+
9
+ def initialize(trigger)
10
+ @trigger = trigger
11
+ @adapter_configuration = Backup::Configuration::Adapter.new
12
+ @storage_configuration = Backup::Configuration::Storage.new
13
+ end
14
+
15
+ def adapter(adapter, &block)
16
+ @adapter_name = adapter
17
+ @adapter_configuration.instance_eval &block
18
+ end
19
+
20
+ def storage(storage, &block)
21
+ @storage_name = storage
22
+ @storage_configuration.instance_eval &block
23
+ end
24
+
25
+ def before_backup(&block)
26
+ @before_backup_block = block
27
+ end
28
+
29
+ def after_backup(&block)
30
+ @after_backup_block = block
31
+ end
32
+
33
+ def storage_class
34
+ case @storage_name.to_sym
35
+ when :cloudfiles then Backup::Storage::CloudFiles
36
+ when :s3 then Backup::Storage::S3
37
+ when :scp then Backup::Storage::SCP
38
+ when :ftp then Backup::Storage::FTP
39
+ when :sftp then Backup::Storage::SFTP
40
+ when :local then Backup::Storage::Local
41
+ when :dropbox then Backup::Storage::Dropbox
42
+ end
43
+ end
44
+
45
+ def record_class
46
+ case @storage_name.to_sym
47
+ when :cloudfiles then Backup::Record::CloudFiles
48
+ when :s3 then Backup::Record::S3
49
+ when :scp then Backup::Record::SCP
50
+ when :ftp then Backup::Record::FTP
51
+ when :sftp then Backup::Record::SFTP
52
+ when :local then Backup::Record::Local
53
+ when :dropbox then Backup::Record::Dropbox
54
+ end
55
+ end
56
+
57
+ # Initializes the storing process depending on the store settings
58
+ def initialize_storage(adapter)
59
+ storage_class.new(adapter)
60
+ end
61
+
62
+ def initialize_record
63
+ record_class.new
64
+ end
65
+
66
+ def get_adapter_configuration
67
+ @adapter_configuration
68
+ end
69
+
70
+ def get_storage_configuration
71
+ @storage_configuration
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,24 @@
1
+ module Backup
2
+ module Configuration
3
+ module Helpers
4
+
5
+ # A helper method for the config/backup.rb configuration file
6
+ # Expects a trigger in argument one (STRING)
7
+ # Expects a block of settings
8
+ def backup(trigger, &block)
9
+ backup = Backup::Configuration::Base.new(trigger)
10
+ backup.instance_eval &block
11
+ @backup_procedures ||= Array.new
12
+ @backup_procedures << backup
13
+ end
14
+
15
+ # A helper method for the config/mail.rb configuration file
16
+ # Takes a block containing the mail options
17
+ def notifier_settings(&block)
18
+ @mail_configuration = Backup::Configuration::Mail.new
19
+ @mail_configuration.instance_eval &block
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Backup
2
+ module Configuration
3
+ class Mail
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(from to smtp)
6
+
7
+ def initialize
8
+ @smtp_configuration = Backup::Configuration::SMTP.new
9
+ end
10
+
11
+ def smtp(&block)
12
+ @smtp_configuration.instance_eval &block
13
+ end
14
+
15
+ def get_smtp_configuration
16
+ @smtp_configuration
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module Backup
2
+ module Configuration
3
+ class SMTP
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(host port username password authentication domain tls)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Backup
2
+ module Configuration
3
+ class Storage
4
+ extend Backup::Configuration::Attributes
5
+ generate_attributes %w(ip user password path access_key_id secret_access_key host use_ssl bucket username api_key container)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,75 @@
1
+ require 'cloudfiles'
2
+
3
+ module Backup
4
+ module Connection
5
+ class CloudFiles
6
+
7
+ attr_accessor :adapter, :procedure, :api_key, :username, :cf_container, :final_file, :tmp_path
8
+
9
+ # Initializes the Cloud Files connection, setting the values using the
10
+ # Cloud Files adapter
11
+ def initialize(adapter = false)
12
+ if adapter
13
+ self.adapter = adapter
14
+ self.procedure = adapter.procedure
15
+ self.final_file = adapter.final_file
16
+ self.tmp_path = adapter.tmp_path.gsub('\ ', ' ')
17
+ load_storage_configuration_attributes
18
+ end
19
+ end
20
+
21
+ # Sets values from a procedure, rather than from the adapter object
22
+ def static_initialize(procedure)
23
+ self.procedure = procedure
24
+ load_storage_configuration_attributes(true)
25
+ end
26
+
27
+ # Establishes a connection with Rackspace Cloud Files using the
28
+ # credentials provided by the user
29
+ def connect
30
+ connection
31
+ end
32
+
33
+ # Wrapper for the Connection object
34
+ def connection
35
+ ::CloudFiles::Connection.new(username, api_key)
36
+ end
37
+
38
+ # Wrapper for the Container object
39
+ def container
40
+ connection.container(cf_container)
41
+ end
42
+
43
+ # Initializes the file transfer to Rackspace Cloud Files
44
+ # This can only run after a connection has been made using the #connect method
45
+ def store
46
+ object = container.create_object(final_file)
47
+ object.write(open(File.join(tmp_path, final_file)))
48
+ end
49
+
50
+ # Destroys file from a bucket on Amazon S3
51
+ def destroy(file, c)
52
+ c = connection.container(c)
53
+ c.delete_object(file)
54
+ end
55
+
56
+ private
57
+
58
+ def load_storage_configuration_attributes(static = false)
59
+ %w(api_key username).each do |attribute|
60
+ if static
61
+ send("#{attribute}=", procedure.get_storage_configuration.attributes[attribute])
62
+ else
63
+ send("#{attribute}=", adapter.procedure.get_storage_configuration.attributes[attribute])
64
+ end
65
+ end
66
+
67
+ if static
68
+ self.cf_container = procedure.get_storage_configuration.attributes['container']
69
+ else
70
+ self.cf_container = adapter.procedure.get_storage_configuration.attributes['container']
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,62 @@
1
+ require 'dropbox'
2
+
3
+ module Backup
4
+ module Connection
5
+ class Dropbox
6
+
7
+ attr_accessor :adapter, :procedure, :final_file, :tmp_path, :api_key, :secret_access_key, :username, :password, :path
8
+
9
+ def initialize(adapter=false)
10
+ if adapter
11
+ self.adapter = adapter
12
+ self.procedure = adapter.procedure
13
+ self.final_file = adapter.final_file
14
+ self.tmp_path = adapter.tmp_path.gsub('\ ', ' ')
15
+
16
+ load_storage_configuration_attributes
17
+ end
18
+ end
19
+
20
+ def static_initialize(procedure)
21
+ self.procedure = procedure
22
+ load_storage_configuration_attributes(true)
23
+ end
24
+
25
+ def session
26
+ @session ||= ::Dropbox::Session.new(api_key, secret_access_key)
27
+ unless @session.authorized?
28
+ @session.authorizing_user = username
29
+ @session.authorizing_password = password
30
+ @session.authorize!
31
+ end
32
+
33
+ @session
34
+ end
35
+
36
+ def connect
37
+ session
38
+ end
39
+
40
+ def path
41
+ @path || "backups"
42
+ end
43
+
44
+ def store
45
+ path_to_file = File.join(tmp_path, final_file)
46
+ session.upload(path_to_file, path, :mode => :dropbox)
47
+ end
48
+
49
+ private
50
+
51
+ def load_storage_configuration_attributes(static=false)
52
+ %w(api_key secret_access_key username password path).each do |attribute|
53
+ if static
54
+ send("#{attribute}=", procedure.get_storage_configuration.attributes[attribute])
55
+ else
56
+ send("#{attribute}=", adapter.procedure.get_storage_configuration.attributes[attribute])
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,88 @@
1
+ require "fog"
2
+
3
+ module Backup
4
+ module Connection
5
+ class S3
6
+ include Backup::CommandHelper
7
+
8
+ MAX_S3_FILE_SIZE = 5368709120 - 1
9
+
10
+ attr_accessor :adapter, :procedure, :access_key_id, :secret_access_key, :host, :s3_bucket, :use_ssl, :final_file, :tmp_path
11
+
12
+ # Initializes the S3 connection, setting the values using the S3 adapter
13
+ def initialize(adapter = false)
14
+ if adapter
15
+ self.adapter = adapter
16
+ self.procedure = adapter.procedure
17
+ self.final_file = adapter.final_file
18
+ self.tmp_path = adapter.tmp_path.gsub('\ ', ' ')
19
+ load_storage_configuration_attributes
20
+ end
21
+ end
22
+
23
+ # Sets values from a procedure, rather than from the adapter object
24
+ def static_initialize(procedure)
25
+ self.procedure = procedure
26
+ load_storage_configuration_attributes(true)
27
+ end
28
+
29
+ # Establishes a connection with Amazon S3 using the credentials provided by the user
30
+ def connection
31
+ @_connection ||= Fog::AWS::Storage.new(
32
+ :aws_access_key_id => access_key_id,
33
+ :aws_secret_access_key => secret_access_key
34
+ )
35
+ end
36
+
37
+ # Initializes the file transfer to Amazon S3
38
+ # This can only run after a connection has been made using the #connect method
39
+ def store
40
+ #TODO: need to add logic like this to restore: `cat /mnt/backups/part.xx >>restore.tgz`
41
+ tmp_file_path = File.join(tmp_path, final_file)
42
+ store_files = []
43
+ if File.stat(File.join(tmp_path, final_file)).size >= MAX_S3_FILE_SIZE
44
+ #we need to split!
45
+ `split -b #{MAX_S3_FILE_SIZE} #{tmp_file_path} #{tmp_file_path}.`
46
+ store_files += `ls #{tmp_file_path}.*`.split
47
+ log("Splitting '#{final_file}' into #{store_files.length} parts as it is too large for s3.")
48
+ else
49
+ store_files << tmp_file_path
50
+ end
51
+
52
+ #lets make sure it exists
53
+ self.connection.put_bucket(s3_bucket)
54
+
55
+ store_files.each do |tmp_file|
56
+ file_name = File.basename(tmp_file)
57
+ log("Saving '#{file_name}' to s3 bucket '#{s3_bucket}'")
58
+ self.connection.put_object(s3_bucket, file_name, open(tmp_file))
59
+ end
60
+ end
61
+
62
+ # Destroys file from a bucket on Amazon S3
63
+ def destroy(file, bucket_as_string)
64
+ self.connection.put_bucket(s3_bucket)
65
+ connection.delete_object(s3_bucket, file)
66
+ end
67
+
68
+ private
69
+
70
+ def load_storage_configuration_attributes(static = false)
71
+ %w(access_key_id secret_access_key use_ssl host).each do |attribute|
72
+ if static
73
+ send("#{attribute}=", procedure.get_storage_configuration.attributes[attribute])
74
+ else
75
+ send("#{attribute}=", adapter.procedure.get_storage_configuration.attributes[attribute])
76
+ end
77
+ end
78
+
79
+ if static
80
+ self.s3_bucket = procedure.get_storage_configuration.attributes['bucket']
81
+ else
82
+ self.s3_bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end