backup 3.0.3.build.0 → 3.0.3
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.
- data/.gitignore +2 -0
- data/.infinity_test +7 -0
- data/.rspec +3 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +88 -0
- data/LICENSE.md +24 -0
- data/README.md +236 -0
- data/backup.gemspec +41 -0
- data/bin/backup +191 -12
- data/lib/backup.rb +162 -0
- data/lib/backup/archive.rb +54 -0
- data/lib/backup/cli.rb +50 -0
- data/lib/backup/compressor/base.rb +17 -0
- data/lib/backup/compressor/gzip.rb +61 -0
- data/lib/backup/configuration/base.rb +15 -0
- data/lib/backup/configuration/compressor/base.rb +10 -0
- data/lib/backup/configuration/compressor/gzip.rb +23 -0
- data/lib/backup/configuration/database/base.rb +18 -0
- data/lib/backup/configuration/database/mongodb.rb +37 -0
- data/lib/backup/configuration/database/mysql.rb +37 -0
- data/lib/backup/configuration/database/postgresql.rb +37 -0
- data/lib/backup/configuration/database/redis.rb +35 -0
- data/lib/backup/configuration/encryptor/base.rb +10 -0
- data/lib/backup/configuration/encryptor/gpg.rb +17 -0
- data/lib/backup/configuration/encryptor/open_ssl.rb +26 -0
- data/lib/backup/configuration/helpers.rb +54 -0
- data/lib/backup/configuration/notifier/base.rb +39 -0
- data/lib/backup/configuration/notifier/mail.rb +52 -0
- data/lib/backup/configuration/storage/base.rb +18 -0
- data/lib/backup/configuration/storage/cloudfiles.rb +21 -0
- data/lib/backup/configuration/storage/dropbox.rb +25 -0
- data/lib/backup/configuration/storage/ftp.rb +25 -0
- data/lib/backup/configuration/storage/rsync.rb +25 -0
- data/lib/backup/configuration/storage/s3.rb +25 -0
- data/lib/backup/configuration/storage/scp.rb +25 -0
- data/lib/backup/configuration/storage/sftp.rb +25 -0
- data/lib/backup/configuration/syncer/rsync.rb +45 -0
- data/lib/backup/database/base.rb +33 -0
- data/lib/backup/database/mongodb.rb +137 -0
- data/lib/backup/database/mysql.rb +104 -0
- data/lib/backup/database/postgresql.rb +111 -0
- data/lib/backup/database/redis.rb +105 -0
- data/lib/backup/encryptor/base.rb +17 -0
- data/lib/backup/encryptor/gpg.rb +78 -0
- data/lib/backup/encryptor/open_ssl.rb +67 -0
- data/lib/backup/finder.rb +39 -0
- data/lib/backup/logger.rb +86 -0
- data/lib/backup/model.rb +272 -0
- data/lib/backup/notifier/base.rb +29 -0
- data/lib/backup/notifier/binder.rb +32 -0
- data/lib/backup/notifier/mail.rb +141 -0
- data/lib/backup/notifier/templates/notify_failure.erb +31 -0
- data/lib/backup/notifier/templates/notify_success.erb +16 -0
- data/lib/backup/storage/base.rb +67 -0
- data/lib/backup/storage/cloudfiles.rb +95 -0
- data/lib/backup/storage/dropbox.rb +82 -0
- data/lib/backup/storage/ftp.rb +114 -0
- data/lib/backup/storage/object.rb +45 -0
- data/lib/backup/storage/rsync.rb +99 -0
- data/lib/backup/storage/s3.rb +108 -0
- data/lib/backup/storage/scp.rb +105 -0
- data/lib/backup/storage/sftp.rb +106 -0
- data/lib/backup/syncer/rsync.rb +119 -0
- data/lib/backup/version.rb +72 -0
- data/lib/templates/archive +4 -0
- data/lib/templates/compressor/gzip +4 -0
- data/lib/templates/database/mongodb +10 -0
- data/lib/templates/database/mysql +11 -0
- data/lib/templates/database/postgresql +11 -0
- data/lib/templates/database/redis +10 -0
- data/lib/templates/encryptor/gpg +9 -0
- data/lib/templates/encryptor/openssl +5 -0
- data/lib/templates/notifier/mail +14 -0
- data/lib/templates/readme +15 -0
- data/lib/templates/storage/cloudfiles +7 -0
- data/lib/templates/storage/dropbox +8 -0
- data/lib/templates/storage/ftp +8 -0
- data/lib/templates/storage/rsync +7 -0
- data/lib/templates/storage/s3 +8 -0
- data/lib/templates/storage/scp +8 -0
- data/lib/templates/storage/sftp +8 -0
- data/lib/templates/syncer/rsync +14 -0
- data/spec/archive_spec.rb +53 -0
- data/spec/backup_spec.rb +11 -0
- data/spec/compressor/gzip_spec.rb +59 -0
- data/spec/configuration/base_spec.rb +35 -0
- data/spec/configuration/compressor/gzip_spec.rb +28 -0
- data/spec/configuration/database/base_spec.rb +16 -0
- data/spec/configuration/database/mongodb_spec.rb +30 -0
- data/spec/configuration/database/mysql_spec.rb +32 -0
- data/spec/configuration/database/postgresql_spec.rb +32 -0
- data/spec/configuration/database/redis_spec.rb +30 -0
- data/spec/configuration/encryptor/gpg_spec.rb +25 -0
- data/spec/configuration/encryptor/open_ssl_spec.rb +31 -0
- data/spec/configuration/notifier/mail_spec.rb +32 -0
- data/spec/configuration/storage/cloudfiles_spec.rb +34 -0
- data/spec/configuration/storage/dropbox_spec.rb +40 -0
- data/spec/configuration/storage/ftp_spec.rb +40 -0
- data/spec/configuration/storage/rsync_spec.rb +37 -0
- data/spec/configuration/storage/s3_spec.rb +37 -0
- data/spec/configuration/storage/scp_spec.rb +40 -0
- data/spec/configuration/storage/sftp_spec.rb +40 -0
- data/spec/configuration/syncer/rsync_spec.rb +46 -0
- data/spec/database/base_spec.rb +30 -0
- data/spec/database/mongodb_spec.rb +144 -0
- data/spec/database/mysql_spec.rb +150 -0
- data/spec/database/postgresql_spec.rb +164 -0
- data/spec/database/redis_spec.rb +122 -0
- data/spec/encryptor/gpg_spec.rb +57 -0
- data/spec/encryptor/open_ssl_spec.rb +102 -0
- data/spec/logger_spec.rb +46 -0
- data/spec/model_spec.rb +236 -0
- data/spec/notifier/mail_spec.rb +97 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/storage/base_spec.rb +33 -0
- data/spec/storage/cloudfiles_spec.rb +102 -0
- data/spec/storage/dropbox_spec.rb +89 -0
- data/spec/storage/ftp_spec.rb +133 -0
- data/spec/storage/object_spec.rb +74 -0
- data/spec/storage/rsync_spec.rb +115 -0
- data/spec/storage/s3_spec.rb +110 -0
- data/spec/storage/scp_spec.rb +129 -0
- data/spec/storage/sftp_spec.rb +125 -0
- data/spec/syncer/rsync_spec.rb +156 -0
- data/spec/version_spec.rb +32 -0
- metadata +195 -6
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Only load the Net::SFTP library/gem when the Backup::Storage::SFTP class is loaded
|
|
5
|
+
require 'net/sftp'
|
|
6
|
+
|
|
7
|
+
module Backup
|
|
8
|
+
module Storage
|
|
9
|
+
class SFTP < Base
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Server credentials
|
|
13
|
+
attr_accessor :username, :password
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Server IP Address and SFTP port
|
|
17
|
+
attr_accessor :ip, :port
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Path to store backups to
|
|
21
|
+
attr_accessor :path
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Creates a new instance of the SFTP storage object
|
|
25
|
+
# First it sets the defaults (if any exist) and then evaluates
|
|
26
|
+
# the configuration block which may overwrite these defaults
|
|
27
|
+
def initialize(&block)
|
|
28
|
+
load_defaults!
|
|
29
|
+
|
|
30
|
+
@port ||= 22
|
|
31
|
+
@path ||= 'backups'
|
|
32
|
+
|
|
33
|
+
instance_eval(&block) if block_given?
|
|
34
|
+
|
|
35
|
+
@time = TIME
|
|
36
|
+
@path = path.sub(/^\~\//, '')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# This is the remote path to where the backup files will be stored
|
|
41
|
+
def remote_path
|
|
42
|
+
File.join(path, TRIGGER)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Performs the backup transfer
|
|
47
|
+
def perform!
|
|
48
|
+
transfer!
|
|
49
|
+
cycle!
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Establishes a connection to the remote server and returns the Net::SFTP object.
|
|
56
|
+
# Not doing any instance variable caching because this object gets persisted in YAML
|
|
57
|
+
# format to a file and will issues. This, however has no impact on performance since it only
|
|
58
|
+
# gets invoked once per object for a #transfer! and once for a remove! Backups run in the
|
|
59
|
+
# background anyway so even if it were a bit slower it shouldn't matter.
|
|
60
|
+
def connection
|
|
61
|
+
Net::SFTP.start(ip, username, :password => password, :port => port)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Transfers the archived file to the specified remote server
|
|
66
|
+
def transfer!
|
|
67
|
+
Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
|
|
68
|
+
create_remote_directories!
|
|
69
|
+
connection.upload!(
|
|
70
|
+
File.join(local_path, local_file),
|
|
71
|
+
File.join(remote_path, remote_file)
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Removes the transferred archive file from the server
|
|
77
|
+
def remove!
|
|
78
|
+
begin
|
|
79
|
+
connection.remove!(
|
|
80
|
+
File.join(remote_path, remote_file)
|
|
81
|
+
)
|
|
82
|
+
rescue Net::SFTP::StatusException
|
|
83
|
+
Logger.warn "Could not remove file \"#{ File.join(remote_path, remote_file) }\"."
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# Creates (if they don't exist yet) all the directories on the remote
|
|
89
|
+
# server in order to upload the backup file. Net::SFTP does not support
|
|
90
|
+
# paths to directories that don't yet exist when creating new directories.
|
|
91
|
+
# Instead, we split the parts up in to an array (for each '/') and loop through
|
|
92
|
+
# that to create the directories one by one. Net::SFTP raises an exception when
|
|
93
|
+
# the directory it's trying ot create already exists, so we have rescue it
|
|
94
|
+
def create_remote_directories!
|
|
95
|
+
path_parts = Array.new
|
|
96
|
+
remote_path.split('/').each do |path_part|
|
|
97
|
+
path_parts << path_part
|
|
98
|
+
begin
|
|
99
|
+
connection.mkdir!(path_parts.join('/'))
|
|
100
|
+
rescue Net::SFTP::StatusException; end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Syncer
|
|
5
|
+
class RSync
|
|
6
|
+
include Backup::CLI
|
|
7
|
+
include Backup::Configuration::Helpers
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Server credentials
|
|
11
|
+
attr_accessor :username, :password
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
# Server IP Address and SSH port
|
|
15
|
+
attr_accessor :ip
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# The SSH port to connect to
|
|
19
|
+
attr_writer :port
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Files/Folders to Sync
|
|
23
|
+
attr_writer :folders
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Path to store the synced files/folders to
|
|
27
|
+
attr_accessor :path
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Flag for mirroring the files/folders
|
|
31
|
+
attr_writer :mirror
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Flag for compressing (only compresses for the transfer)
|
|
35
|
+
attr_writer :compress
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Additional options for the rsync cli
|
|
39
|
+
attr_accessor :additional_options
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Instantiates a new RSync Syncer object and sets the default configuration
|
|
43
|
+
# specified in the Backup::Configuration::Syncer::RSync. Then it sets the object
|
|
44
|
+
# defaults if particular properties weren't set. Finally it'll evaluate the users
|
|
45
|
+
# configuration file and overwrite anything that's been defined
|
|
46
|
+
def initialize(&block)
|
|
47
|
+
load_defaults!
|
|
48
|
+
|
|
49
|
+
@folders = Array.new
|
|
50
|
+
@additional_options ||= Array.new
|
|
51
|
+
@path ||= 'backups'
|
|
52
|
+
@port ||= 22
|
|
53
|
+
@mirror ||= false
|
|
54
|
+
@compress ||= false
|
|
55
|
+
|
|
56
|
+
instance_eval(&block) if block_given?
|
|
57
|
+
|
|
58
|
+
@path = path.sub(/^\~\//, '')
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# Performs the RSync operation
|
|
63
|
+
# debug options: -vhP
|
|
64
|
+
def perform!
|
|
65
|
+
Logger.message("#{ self.class } started syncing #{ folders }.")
|
|
66
|
+
Logger.silent( run("#{ utility(:rsync) } -vhP #{ options } #{ folders } '#{ username }@#{ ip }:#{ path }'") )
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Returns all the specified Rsync options, concatenated, ready for the CLI
|
|
71
|
+
def options
|
|
72
|
+
([archive, mirror, compress, port] + additional_options).compact.join("\s")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Returns Rsync syntax for specifying the --delete option (to enable mirroring)
|
|
77
|
+
def mirror
|
|
78
|
+
'--delete' if @mirror
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# Returns Rsync syntax for specifying the the 'compress' option
|
|
83
|
+
def compress
|
|
84
|
+
'-z' if @compress
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# Returns Rsync syntax for specifying the --archive option
|
|
89
|
+
def archive
|
|
90
|
+
'--archive'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Returns Rsync syntax for specifying a port to connect to
|
|
95
|
+
def port
|
|
96
|
+
"--port='#{@port}'"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# If no block has been provided, it'll return the array of @folders.
|
|
101
|
+
# If a block has been provided, it'll evaluate it and add the defined paths to the @folders
|
|
102
|
+
def folders(&block)
|
|
103
|
+
unless block_given?
|
|
104
|
+
return @folders.map do |folder|
|
|
105
|
+
"'#{folder}'"
|
|
106
|
+
end.join("\s")
|
|
107
|
+
end
|
|
108
|
+
instance_eval(&block)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Adds a path to the @folder array
|
|
113
|
+
def add(path)
|
|
114
|
+
@folders << path
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Usage:
|
|
7
|
+
#
|
|
8
|
+
# # Returns the current backup version based on the defined constants
|
|
9
|
+
# Backup::Version.current
|
|
10
|
+
#
|
|
11
|
+
# # Returns a gemspec compatible version number based on the defined constants
|
|
12
|
+
# Backup::Version.gemspec
|
|
13
|
+
#
|
|
14
|
+
class Version
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# MAJOR:
|
|
18
|
+
# Defines the major version
|
|
19
|
+
# MINOR:
|
|
20
|
+
# Defines the minor version
|
|
21
|
+
# PATCH:
|
|
22
|
+
# Defines the patch version
|
|
23
|
+
# BUILD:
|
|
24
|
+
# Defines the build version ( use 'false' if no build )
|
|
25
|
+
MAJOR, MINOR, PATCH, BUILD = 3, 0, 3, false
|
|
26
|
+
|
|
27
|
+
# ========================================================= #
|
|
28
|
+
# ADJUST THE CONSTANTS ABOVE TO CHANGE THE BACKUP VERSION #
|
|
29
|
+
# ========================================================= #
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Returns the major version ( big release based off of multiple minor releases )
|
|
33
|
+
def self.major
|
|
34
|
+
MAJOR
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Returns the minor version ( small release based off of multiple patches )
|
|
39
|
+
def self.minor
|
|
40
|
+
MINOR
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Returns the patch version ( updates, features and (crucial) bug fixes based off of multiple builds )
|
|
45
|
+
def self.patch
|
|
46
|
+
PATCH
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# Returns the build version ( improvements, small additions, frequent releases )
|
|
51
|
+
def self.build
|
|
52
|
+
BUILD
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Returns the current version ( not for gemspec / rubygems )
|
|
57
|
+
def self.current
|
|
58
|
+
"#{major}.#{minor}.#{patch} / build #{build or 0}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# Returns the (gemspec qualified) current version
|
|
63
|
+
def self.gemspec
|
|
64
|
+
if build.eql?(false)
|
|
65
|
+
"#{major}.#{minor}.#{patch}"
|
|
66
|
+
else
|
|
67
|
+
"#{major}.#{minor}.#{patch}.build.#{build}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
database MongoDB do |db|
|
|
2
|
+
db.name = "my_database_name"
|
|
3
|
+
db.username = "my_username"
|
|
4
|
+
db.password = "my_password"
|
|
5
|
+
db.host = "localhost"
|
|
6
|
+
db.port = 5432
|
|
7
|
+
db.ipv6 = false
|
|
8
|
+
db.only_collections = ['only', 'these' 'collections']
|
|
9
|
+
db.additional_options = []
|
|
10
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
database MySQL do |db|
|
|
2
|
+
db.name = "my_database_name"
|
|
3
|
+
db.username = "my_username"
|
|
4
|
+
db.password = "my_password"
|
|
5
|
+
db.host = "localhost"
|
|
6
|
+
db.port = 3306
|
|
7
|
+
db.socket = "/tmp/mysql.sock"
|
|
8
|
+
db.skip_tables = ['skip', 'these', 'tables']
|
|
9
|
+
db.only_tables = ['only', 'these' 'tables']
|
|
10
|
+
db.additional_options = ['--quick', '--single-transaction']
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
database PostgreSQL do |db|
|
|
2
|
+
db.name = "my_database_name"
|
|
3
|
+
db.username = "my_username"
|
|
4
|
+
db.password = "my_password"
|
|
5
|
+
db.host = "localhost"
|
|
6
|
+
db.port = 5432
|
|
7
|
+
db.socket = "/tmp/pg.sock"
|
|
8
|
+
db.skip_tables = ['skip', 'these', 'tables']
|
|
9
|
+
db.only_tables = ['only', 'these' 'tables']
|
|
10
|
+
db.additional_options = ['--quick', '--single-transaction']
|
|
11
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
notify_by Mail do |mail|
|
|
2
|
+
mail.on_success = true
|
|
3
|
+
mail.on_failure = true
|
|
4
|
+
|
|
5
|
+
mail.from = 'sender@email.com'
|
|
6
|
+
mail.to = 'receiver@email.com'
|
|
7
|
+
mail.address = 'smtp.gmail.com'
|
|
8
|
+
mail.port = 587
|
|
9
|
+
mail.domain = 'your.host.name'
|
|
10
|
+
mail.user_name = 'sender@email.com'
|
|
11
|
+
mail.password = 'my_password'
|
|
12
|
+
mail.authentication = 'plain'
|
|
13
|
+
mail.enable_starttls_auto = true
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Backup
|
|
3
|
+
# Generated Template
|
|
4
|
+
#
|
|
5
|
+
# For more information:
|
|
6
|
+
#
|
|
7
|
+
# View the Git repository at https://github.com/meskyanichi/backup
|
|
8
|
+
# View the Wiki/Documentation at https://github.com/meskyanichi/backup/wiki
|
|
9
|
+
# View the issue log at https://github.com/meskyanichi/backup/issues
|
|
10
|
+
#
|
|
11
|
+
# When you're finished configuring this configuration file,
|
|
12
|
+
# you can run it from the command line by issuing the following command:
|
|
13
|
+
#
|
|
14
|
+
# $ backup -t my_backup [-c <path_to_configuration_file>]
|
|
15
|
+
|