dmitryv-backup 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/CHANGELOG +125 -0
  2. data/LICENSE +20 -0
  3. data/README.md +180 -0
  4. data/VERSION +1 -0
  5. data/bin/backup +108 -0
  6. data/generators/backup/backup_generator.rb +69 -0
  7. data/generators/backup/templates/backup.rake +56 -0
  8. data/generators/backup/templates/backup.rb +229 -0
  9. data/generators/backup/templates/create_backup_tables.rb +18 -0
  10. data/generators/backup_update/backup_update_generator.rb +50 -0
  11. data/generators/backup_update/templates/migrations/update_backup_tables.rb +27 -0
  12. data/lib/backup.rb +131 -0
  13. data/lib/backup/adapters/archive.rb +34 -0
  14. data/lib/backup/adapters/base.rb +138 -0
  15. data/lib/backup/adapters/custom.rb +41 -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 +11 -0
  20. data/lib/backup/compressors/base.rb +7 -0
  21. data/lib/backup/compressors/gzip.rb +9 -0
  22. data/lib/backup/compressors/seven_zip.rb +9 -0
  23. data/lib/backup/configuration/adapter.rb +21 -0
  24. data/lib/backup/configuration/adapter_options.rb +8 -0
  25. data/lib/backup/configuration/attributes.rb +19 -0
  26. data/lib/backup/configuration/base.rb +77 -0
  27. data/lib/backup/configuration/helpers.rb +24 -0
  28. data/lib/backup/configuration/mail.rb +20 -0
  29. data/lib/backup/configuration/smtp.rb +8 -0
  30. data/lib/backup/configuration/storage.rb +8 -0
  31. data/lib/backup/connection/cloudfiles.rb +75 -0
  32. data/lib/backup/connection/s3.rb +85 -0
  33. data/lib/backup/environment/base.rb +12 -0
  34. data/lib/backup/environment/rails_configuration.rb +15 -0
  35. data/lib/backup/environment/unix_configuration.rb +109 -0
  36. data/lib/backup/mail/base.rb +97 -0
  37. data/lib/backup/mail/mail.txt +7 -0
  38. data/lib/backup/record/base.rb +65 -0
  39. data/lib/backup/record/cloudfiles.rb +28 -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 +26 -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/ftp.rb +38 -0
  48. data/lib/backup/storage/local.rb +22 -0
  49. data/lib/backup/storage/s3.rb +17 -0
  50. data/lib/backup/storage/scp.rb +30 -0
  51. data/lib/backup/storage/sftp.rb +31 -0
  52. data/lib/generators/backup/USAGE +10 -0
  53. data/lib/generators/backup/backup_generator.rb +47 -0
  54. data/lib/generators/backup/templates/backup.rake +56 -0
  55. data/lib/generators/backup/templates/backup.rb +229 -0
  56. data/lib/generators/backup/templates/create_backup_tables.rb +18 -0
  57. data/setup/backup.rb +231 -0
  58. data/setup/backup.sqlite3 +0 -0
  59. metadata +271 -0
@@ -0,0 +1,77 @@
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
8
+
9
+ def initialize(trigger)
10
+ @trigger = trigger
11
+ @adapter_configuration = Backup::Configuration::Adapter.new
12
+ @storage_configuration = Backup::Configuration::Storage.new
13
+ @compressor = :gzip
14
+ end
15
+
16
+ def adapter(adapter, &block)
17
+ @adapter_name = adapter
18
+ @adapter_configuration.instance_eval &block
19
+ end
20
+
21
+ def storage(storage, &block)
22
+ @storage_name = storage
23
+ @storage_configuration.instance_eval &block
24
+ end
25
+
26
+ def compressor(compressor)
27
+ @compressor = compressor
28
+ end
29
+
30
+ def storage_class
31
+ case @storage_name.to_sym
32
+ when :cloudfiles then Backup::Storage::CloudFiles
33
+ when :s3 then Backup::Storage::S3
34
+ when :scp then Backup::Storage::SCP
35
+ when :ftp then Backup::Storage::FTP
36
+ when :sftp then Backup::Storage::SFTP
37
+ when :local then Backup::Storage::Local
38
+ end
39
+ end
40
+
41
+ def record_class
42
+ case @storage_name.to_sym
43
+ when :cloudfiles then Backup::Record::CloudFiles
44
+ when :s3 then Backup::Record::S3
45
+ when :scp then Backup::Record::SCP
46
+ when :ftp then Backup::Record::FTP
47
+ when :sftp then Backup::Record::SFTP
48
+ when :local then Backup::Record::Local
49
+ end
50
+ end
51
+
52
+ def compressor_class
53
+ case @compressor.to_sym
54
+ when :gzip then Backup::Compressors::Gzip
55
+ when :seven_zip then Backup::Compressors::SevenZip
56
+ end
57
+ end
58
+
59
+ # Initializes the storing process depending on the store settings
60
+ def initialize_storage(adapter)
61
+ storage_class.new(adapter)
62
+ end
63
+
64
+ def initialize_record
65
+ record_class.new
66
+ end
67
+
68
+ def get_adapter_configuration
69
+ @adapter_configuration
70
+ end
71
+
72
+ def get_storage_configuration
73
+ @storage_configuration
74
+ end
75
+ end
76
+ end
77
+ 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 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,85 @@
1
+ require 's3'
2
+
3
+ module Backup
4
+ module Connection
5
+ class S3
6
+
7
+ attr_accessor :adapter, :procedure, :access_key_id, :secret_access_key, :s3_bucket, :use_ssl, :final_file, :tmp_path
8
+
9
+ # Initializes the S3 connection, setting the values using the S3 adapter
10
+ def initialize(adapter = false)
11
+ if adapter
12
+ self.adapter = adapter
13
+ self.procedure = adapter.procedure
14
+ self.final_file = adapter.final_file
15
+ self.tmp_path = adapter.tmp_path.gsub('\ ', ' ')
16
+ load_storage_configuration_attributes
17
+ end
18
+ end
19
+
20
+ # Sets values from a procedure, rather than from the adapter object
21
+ def static_initialize(procedure)
22
+ self.procedure = procedure
23
+ load_storage_configuration_attributes(true)
24
+ end
25
+
26
+ # Establishes a connection with Amazon S3 using the credentials provided by the user
27
+ def connect
28
+ service
29
+ end
30
+
31
+ # Wrapper for the Service object
32
+ def service
33
+ ::S3::Service.new(:access_key_id => access_key_id,
34
+ :secret_access_key => secret_access_key,
35
+ :use_ssl => use_ssl)
36
+ end
37
+
38
+ # Wrapper for the Bucket object
39
+ def bucket
40
+ begin
41
+ # Find existing bucket:
42
+ bucket = service.buckets.find(s3_bucket)
43
+ rescue ::S3::Error::NoSuchBucket => e
44
+ # Apparently the bucket doesn't exist yet, so create a new one:
45
+ bucket = service.buckets.build(s3_bucket)
46
+ bucket.save
47
+ end
48
+ bucket.retrieve
49
+ end
50
+
51
+ # Initializes the file transfer to Amazon S3
52
+ # This can only run after a connection has been made using the #connect method
53
+ def store
54
+ object = bucket.objects.build(final_file)
55
+ object.content = open(File.join(tmp_path, final_file))
56
+ object.save
57
+ end
58
+
59
+ # Destroys file from a bucket on Amazon S3
60
+ def destroy(file, bucket_as_string)
61
+ object = bucket.objects.find(file)
62
+ object.destroy
63
+ end
64
+
65
+ private
66
+
67
+ def load_storage_configuration_attributes(static = false)
68
+ %w(access_key_id secret_access_key use_ssl).each do |attribute|
69
+ if static
70
+ send("#{attribute}=", procedure.get_storage_configuration.attributes[attribute])
71
+ else
72
+ send("#{attribute}=", adapter.procedure.get_storage_configuration.attributes[attribute])
73
+ end
74
+ end
75
+
76
+ if static
77
+ self.s3_bucket = procedure.get_storage_configuration.attributes['bucket']
78
+ else
79
+ self.s3_bucket = adapter.procedure.get_storage_configuration.attributes['bucket']
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,12 @@
1
+ module Backup
2
+ module Environment
3
+ module Base
4
+
5
+ def current_environment
6
+ return :rails if defined?(Rails.root)
7
+ return :unix
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Backup
2
+ module Environment
3
+ module RailsConfiguration
4
+
5
+ if defined?(Rails.root)
6
+ # Sets BACKUP_PATH equal to Rails.root
7
+ BACKUP_PATH = Rails.root.to_s
8
+
9
+ # Sets DB_CONNECTION_SETTINGS to false
10
+ DB_CONNECTION_SETTINGS = false
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,109 @@
1
+ module Backup
2
+ module Environment
3
+ module UnixConfiguration
4
+
5
+ require 'active_record'
6
+
7
+ # Sets BACKUP_PATH
8
+ BACKUP_PATH = ENV['BACKUP_PATH'] || "/opt/backup"
9
+
10
+ # Sets DB_CONNECTION_SETTINGS
11
+ DB_CONNECTION_SETTINGS = {
12
+ :adapter => "sqlite3",
13
+ :database => "#{BACKUP_PATH}/backup.sqlite3",
14
+ :pool => 5,
15
+ :timeout => 5000
16
+ }
17
+
18
+ module Commands
19
+
20
+ def setup
21
+ unless File.directory?(BACKUP_PATH)
22
+ puts "Installing Backup in #{BACKUP_PATH}.."
23
+ %x{ #{sudo} mkdir -p #{File.join(BACKUP_PATH, 'config')} }
24
+ %x{ #{sudo} cp #{File.join(File.dirname(__FILE__), '..', '..', '..', 'setup', 'backup.sqlite3')} #{BACKUP_PATH} }
25
+ %x{ #{sudo} cp #{File.join(File.dirname(__FILE__), '..', '..', '..', 'setup', 'backup.rb')} #{File.join(BACKUP_PATH, 'config')} }
26
+ puts <<-MESSAGE
27
+
28
+ ==============================================================
29
+ Backup has been set up!
30
+ ==============================================================
31
+
32
+ 1: Set up some "Backup Settings" inside the configuration file!
33
+
34
+ #{BACKUP_PATH}/config/backup.rb
35
+
36
+
37
+ 2: Run the backups!
38
+
39
+ sudo backup --run [trigger]
40
+
41
+
42
+ For a list of Backup commands:
43
+
44
+ sudo backup --help
45
+
46
+
47
+ For More Information:
48
+
49
+ http://github.com/meskyanichi/backup
50
+
51
+ ==============================================================
52
+
53
+ MESSAGE
54
+ else
55
+ puts "\nBackup is already installed in #{BACKUP_PATH}..\n"
56
+ puts "If you want to reset it, run:\n\nbackup --reset\n\n"
57
+ puts "This will reinstall it."
58
+ puts "Warning: All configuration will be lost!\n\n"
59
+ end
60
+ end
61
+
62
+ def reset
63
+ if File.directory?(BACKUP_PATH)
64
+ remove
65
+ setup
66
+ else
67
+ puts "Backup is not installed.\n"
68
+ puts "Run the following command to install it:\n\nbackup --setup"
69
+ end
70
+ end
71
+
72
+ def remove
73
+ puts "Removing Backup..\n"
74
+ %x{ #{sudo} rm -rf #{BACKUP_PATH} }
75
+ end
76
+ end
77
+
78
+ module Helpers
79
+
80
+ def confirm_configuration_file_existence
81
+ unless File.exist?(File.join(BACKUP_PATH, 'config', 'backup.rb'))
82
+ puts "\nBackup could not find the Backup Configuration File."
83
+ puts "Did you set up Backup? Do so if you haven't yet:"
84
+ puts "\nbackup --setup\n "
85
+ exit
86
+ end
87
+ end
88
+
89
+ def sudo
90
+ if writable?(BACKUP_PATH)
91
+ ""
92
+ else
93
+ "sudo"
94
+ end
95
+ end
96
+
97
+ private
98
+ def writable?(f)
99
+ unless File.exists?(f)
100
+ writable?(File.dirname(f))
101
+ else
102
+ File.writable?(f)
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,97 @@
1
+ module Backup
2
+ module Mail
3
+ class Base
4
+
5
+ # Sets up the Mail Configuration for the Backup::Mail::Base class.
6
+ # This must be set in order to send emails
7
+ # It will dynamically add class methods (configuration) for each email that will be sent
8
+ def self.setup(config)
9
+ if config
10
+ (class << self; self; end).instance_eval do
11
+ config.attributes.each do |method, value|
12
+ define_method method do
13
+ value
14
+ end
15
+ end
16
+ config.get_smtp_configuration.attributes.each do |method, value|
17
+ define_method method do
18
+ value
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Returns true if the "to" and "from" attributes are set
26
+ def self.setup?
27
+ return true if defined?(from) and defined?(to)
28
+ false
29
+ end
30
+
31
+ # Delivers the backup details by email to the recipient
32
+ # Requires the Backup Object
33
+ def self.notify!(backup)
34
+ if self.setup? and backup.procedure.attributes['notify'].eql?(true)
35
+ require 'pony'
36
+
37
+ @backup = backup
38
+ self.parse_body
39
+ Pony.mail({
40
+ :subject => "Backup for \"#{@backup.trigger}\" was successfully created!",
41
+ :body => @content
42
+ }.merge(self.smtp_configuration))
43
+ puts "Sending notification to #{self.to}."
44
+ end
45
+ end
46
+
47
+ # Retrieves SMTP configuration
48
+ def self.smtp_configuration
49
+ { :to => self.to,
50
+ :from => self.from,
51
+ :via => :smtp,
52
+ :smtp => {
53
+ :host => self.host,
54
+ :port => self.port,
55
+ :user => self.username,
56
+ :password => self.password,
57
+ :auth => self.authentication,
58
+ :domain => self.domain,
59
+ :tls => self.tls
60
+ }}
61
+ end
62
+
63
+ def self.parse_body
64
+ File.open(File.join(File.dirname(__FILE__), 'mail.txt'), 'r') do |file|
65
+ self.gsub_content(file.readlines)
66
+ end
67
+ end
68
+
69
+ def self.gsub_content(lines)
70
+ container = @backup.procedure.get_storage_configuration.attributes['container']
71
+ bucket = @backup.procedure.get_storage_configuration.attributes['bucket']
72
+ path = @backup.procedure.get_storage_configuration.attributes['path']
73
+ ip = @backup.procedure.get_storage_configuration.attributes['ip']
74
+
75
+ lines.each do |line|
76
+ line.gsub!(':trigger', @backup.trigger)
77
+ line.gsub!(':day', Time.now.strftime("%A (%d)"))
78
+ line.gsub!(':month', Time.now.strftime("%B"))
79
+ line.gsub!(':year', Time.now.strftime("%Y"))
80
+ line.gsub!(':time', Time.now.strftime("%r"))
81
+ line.gsub!(':adapter', @backup.procedure.adapter_name.to_s)
82
+ line.gsub!(':location', container || bucket || path)
83
+ line.gsub!(':backup', @backup.final_file)
84
+ case @backup.procedure.storage_name.to_sym
85
+ when :cloudfiles then line.gsub!(':remote', "on Rackspace Cloudfiles")
86
+ when :s3 then line.gsub!(':remote', "on Amazon S3")
87
+ when :local then line.gsub!(':remote', "on the local server")
88
+ when :scp, :sftp, :ftp then line.gsub!(':remote', "on the remote server (#{ip})")
89
+ end
90
+ @content ||= String.new
91
+ @content << line
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ end