backup 3.0.19 → 3.0.20
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 +4 -0
- data/Gemfile +9 -8
- data/Gemfile.lock +19 -1
- data/Guardfile +13 -9
- data/README.md +93 -31
- data/backup.gemspec +3 -3
- data/bin/backup +6 -283
- data/lib/backup.rb +101 -72
- data/lib/backup/archive.rb +21 -9
- data/lib/backup/binder.rb +22 -0
- data/lib/backup/cleaner.rb +36 -0
- data/lib/backup/cli/helpers.rb +103 -0
- data/lib/backup/cli/utility.rb +308 -0
- data/lib/backup/compressor/base.rb +2 -2
- data/lib/backup/compressor/pbzip2.rb +76 -0
- data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
- data/lib/backup/configuration/database/riak.rb +25 -0
- data/lib/backup/configuration/encryptor/open_ssl.rb +6 -0
- data/lib/backup/configuration/helpers.rb +5 -18
- data/lib/backup/configuration/notifier/base.rb +13 -0
- data/lib/backup/configuration/notifier/hipchat.rb +41 -0
- data/lib/backup/configuration/notifier/mail.rb +38 -0
- data/lib/backup/configuration/notifier/prowl.rb +23 -0
- data/lib/backup/configuration/storage/cloudfiles.rb +4 -0
- data/lib/backup/configuration/storage/dropbox.rb +8 -4
- data/lib/backup/database/base.rb +10 -2
- data/lib/backup/database/mongodb.rb +16 -19
- data/lib/backup/database/mysql.rb +2 -2
- data/lib/backup/database/postgresql.rb +2 -2
- data/lib/backup/database/redis.rb +15 -7
- data/lib/backup/database/riak.rb +45 -0
- data/lib/backup/dependency.rb +21 -7
- data/lib/backup/encryptor/base.rb +1 -1
- data/lib/backup/encryptor/open_ssl.rb +20 -5
- data/lib/backup/errors.rb +124 -0
- data/lib/backup/finder.rb +11 -3
- data/lib/backup/logger.rb +121 -82
- data/lib/backup/model.rb +103 -44
- data/lib/backup/notifier/base.rb +50 -0
- data/lib/backup/notifier/campfire.rb +32 -52
- data/lib/backup/notifier/hipchat.rb +99 -0
- data/lib/backup/notifier/mail.rb +100 -61
- data/lib/backup/notifier/presently.rb +31 -40
- data/lib/backup/notifier/prowl.rb +73 -0
- data/lib/backup/notifier/twitter.rb +29 -39
- data/lib/backup/packager.rb +25 -0
- data/lib/backup/splitter.rb +62 -0
- data/lib/backup/storage/base.rb +178 -18
- data/lib/backup/storage/cloudfiles.rb +34 -28
- data/lib/backup/storage/dropbox.rb +64 -67
- data/lib/backup/storage/ftp.rb +48 -40
- data/lib/backup/storage/local.rb +33 -28
- data/lib/backup/storage/ninefold.rb +40 -26
- data/lib/backup/storage/object.rb +8 -6
- data/lib/backup/storage/rsync.rb +61 -51
- data/lib/backup/storage/s3.rb +29 -27
- data/lib/backup/storage/scp.rb +56 -36
- data/lib/backup/storage/sftp.rb +49 -33
- data/lib/backup/syncer/base.rb +1 -1
- data/lib/backup/syncer/rsync.rb +1 -1
- data/lib/backup/template.rb +46 -0
- data/lib/backup/version.rb +1 -1
- data/spec/archive_spec.rb +34 -9
- data/spec/backup_spec.rb +1 -1
- data/spec/cli/helpers_spec.rb +35 -0
- data/spec/cli/utility_spec.rb +38 -0
- data/spec/compressor/bzip2_spec.rb +1 -1
- data/spec/compressor/gzip_spec.rb +1 -1
- data/spec/compressor/lzma_spec.rb +1 -1
- data/spec/compressor/pbzip2_spec.rb +63 -0
- data/spec/configuration/base_spec.rb +1 -1
- data/spec/configuration/compressor/bzip2_spec.rb +1 -1
- data/spec/configuration/compressor/gzip_spec.rb +1 -1
- data/spec/configuration/compressor/lzma_spec.rb +1 -1
- data/spec/configuration/database/base_spec.rb +1 -1
- data/spec/configuration/database/mongodb_spec.rb +1 -1
- data/spec/configuration/database/mysql_spec.rb +1 -1
- data/spec/configuration/database/postgresql_spec.rb +1 -1
- data/spec/configuration/database/redis_spec.rb +1 -1
- data/spec/configuration/database/riak_spec.rb +31 -0
- data/spec/configuration/encryptor/gpg_spec.rb +1 -1
- data/spec/configuration/encryptor/open_ssl_spec.rb +4 -1
- data/spec/configuration/notifier/campfire_spec.rb +1 -1
- data/spec/configuration/notifier/hipchat_spec.rb +43 -0
- data/spec/configuration/notifier/mail_spec.rb +34 -22
- data/spec/configuration/notifier/presently_spec.rb +1 -1
- data/spec/configuration/notifier/prowl_spec.rb +28 -0
- data/spec/configuration/notifier/twitter_spec.rb +1 -1
- data/spec/configuration/storage/cloudfiles_spec.rb +19 -16
- data/spec/configuration/storage/dropbox_spec.rb +1 -1
- data/spec/configuration/storage/ftp_spec.rb +1 -1
- data/spec/configuration/storage/local_spec.rb +1 -1
- data/spec/configuration/storage/ninefold_spec.rb +1 -1
- data/spec/configuration/storage/rsync_spec.rb +1 -1
- data/spec/configuration/storage/s3_spec.rb +1 -1
- data/spec/configuration/storage/scp_spec.rb +1 -1
- data/spec/configuration/storage/sftp_spec.rb +1 -1
- data/spec/configuration/syncer/rsync_spec.rb +1 -1
- data/spec/configuration/syncer/s3_spec.rb +1 -1
- data/spec/database/base_spec.rb +10 -1
- data/spec/database/mongodb_spec.rb +34 -7
- data/spec/database/mysql_spec.rb +8 -7
- data/spec/database/postgresql_spec.rb +8 -7
- data/spec/database/redis_spec.rb +39 -9
- data/spec/database/riak_spec.rb +50 -0
- data/spec/encryptor/gpg_spec.rb +1 -1
- data/spec/encryptor/open_ssl_spec.rb +77 -20
- data/spec/errors_spec.rb +306 -0
- data/spec/finder_spec.rb +91 -0
- data/spec/logger_spec.rb +254 -33
- data/spec/model_spec.rb +120 -15
- data/spec/notifier/campfire_spec.rb +127 -52
- data/spec/notifier/hipchat_spec.rb +193 -0
- data/spec/notifier/mail_spec.rb +290 -74
- data/spec/notifier/presently_spec.rb +290 -73
- data/spec/notifier/prowl_spec.rb +149 -0
- data/spec/notifier/twitter_spec.rb +106 -41
- data/spec/spec_helper.rb +8 -2
- data/spec/splitter_spec.rb +71 -0
- data/spec/storage/base_spec.rb +280 -19
- data/spec/storage/cloudfiles_spec.rb +38 -22
- data/spec/storage/dropbox_spec.rb +17 -13
- data/spec/storage/ftp_spec.rb +145 -55
- data/spec/storage/local_spec.rb +6 -6
- data/spec/storage/ninefold_spec.rb +70 -29
- data/spec/storage/object_spec.rb +44 -44
- data/spec/storage/rsync_spec.rb +186 -63
- data/spec/storage/s3_spec.rb +23 -24
- data/spec/storage/scp_spec.rb +116 -41
- data/spec/storage/sftp_spec.rb +124 -46
- data/spec/syncer/rsync_spec.rb +3 -3
- data/spec/syncer/s3_spec.rb +1 -1
- data/spec/version_spec.rb +1 -1
- data/templates/cli/utility/archive +13 -0
- data/{lib/templates → templates/cli/utility}/compressor/bzip2 +1 -1
- data/{lib/templates → templates/cli/utility}/compressor/gzip +1 -1
- data/{lib/templates → templates/cli/utility}/compressor/lzma +0 -0
- data/templates/cli/utility/compressor/pbzip2 +7 -0
- data/templates/cli/utility/config +31 -0
- data/{lib/templates → templates/cli/utility}/database/mongodb +1 -1
- data/{lib/templates → templates/cli/utility}/database/mysql +1 -1
- data/{lib/templates → templates/cli/utility}/database/postgresql +1 -1
- data/{lib/templates → templates/cli/utility}/database/redis +1 -1
- data/templates/cli/utility/database/riak +8 -0
- data/{lib/templates → templates/cli/utility}/encryptor/gpg +1 -1
- data/templates/cli/utility/encryptor/openssl +9 -0
- data/templates/cli/utility/model.erb +23 -0
- data/{lib/templates → templates/cli/utility}/notifier/campfire +2 -1
- data/templates/cli/utility/notifier/hipchat +15 -0
- data/{lib/templates → templates/cli/utility}/notifier/mail +6 -1
- data/{lib/templates → templates/cli/utility}/notifier/presently +1 -0
- data/templates/cli/utility/notifier/prowl +11 -0
- data/{lib/templates → templates/cli/utility}/notifier/twitter +2 -1
- data/templates/cli/utility/splitter +7 -0
- data/templates/cli/utility/storage/cloudfiles +12 -0
- data/{lib/templates → templates/cli/utility}/storage/dropbox +1 -1
- data/{lib/templates → templates/cli/utility}/storage/ftp +0 -0
- data/templates/cli/utility/storage/local +7 -0
- data/{lib/templates → templates/cli/utility}/storage/ninefold +1 -1
- data/templates/cli/utility/storage/rsync +11 -0
- data/{lib/templates → templates/cli/utility}/storage/s3 +0 -2
- data/templates/cli/utility/storage/scp +11 -0
- data/templates/cli/utility/storage/sftp +11 -0
- data/{lib/templates → templates/cli/utility}/syncer/rsync +1 -1
- data/{lib/templates → templates/cli/utility}/syncer/s3 +1 -1
- data/templates/general/links +11 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +9 -0
- data/templates/notifier/mail/success.erb +7 -0
- data/templates/notifier/mail/warning.erb +9 -0
- data/templates/storage/dropbox/authorization_url.erb +6 -0
- data/templates/storage/dropbox/authorized.erb +4 -0
- data/templates/storage/dropbox/cache_file_written.erb +10 -0
- metadata +81 -45
- data/lib/backup/cli.rb +0 -110
- data/lib/backup/exception/command_failed.rb +0 -8
- data/lib/backup/exception/command_not_found.rb +0 -8
- data/lib/backup/notifier/binder.rb +0 -32
- data/lib/backup/notifier/templates/notify_failure.erb +0 -33
- data/lib/backup/notifier/templates/notify_success.erb +0 -16
- data/lib/templates/archive +0 -7
- data/lib/templates/encryptor/openssl +0 -8
- data/lib/templates/readme +0 -15
- data/lib/templates/storage/cloudfiles +0 -11
- data/lib/templates/storage/local +0 -7
- data/lib/templates/storage/rsync +0 -11
- data/lib/templates/storage/scp +0 -11
- data/lib/templates/storage/sftp +0 -11
|
@@ -38,7 +38,6 @@ module Backup
|
|
|
38
38
|
@additional_options ||= Array.new
|
|
39
39
|
|
|
40
40
|
instance_eval(&block)
|
|
41
|
-
prepare!
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
##
|
|
@@ -95,7 +94,8 @@ module Backup
|
|
|
95
94
|
# Performs the mysqldump command and outputs the
|
|
96
95
|
# data to the specified path based on the 'trigger'
|
|
97
96
|
def perform!
|
|
98
|
-
|
|
97
|
+
super
|
|
98
|
+
|
|
99
99
|
run("#{mysqldump} > '#{File.join(dump_path, name)}.sql'")
|
|
100
100
|
end
|
|
101
101
|
|
|
@@ -40,7 +40,6 @@ module Backup
|
|
|
40
40
|
@additional_options ||= Array.new
|
|
41
41
|
|
|
42
42
|
instance_eval(&block)
|
|
43
|
-
prepare!
|
|
44
43
|
ENV['PGPASSWORD'] = password
|
|
45
44
|
end
|
|
46
45
|
|
|
@@ -110,7 +109,8 @@ module Backup
|
|
|
110
109
|
# data to the specified path based on the 'trigger'
|
|
111
110
|
# and resets the 'PGPASSWORD' environment variable to nil
|
|
112
111
|
def perform!
|
|
113
|
-
|
|
112
|
+
super
|
|
113
|
+
|
|
114
114
|
run("#{pgdump} > '#{File.join(dump_path, name)}.sql'")
|
|
115
115
|
ENV['PGPASSWORD'] = nil
|
|
116
116
|
end
|
|
@@ -34,7 +34,6 @@ module Backup
|
|
|
34
34
|
@additional_options ||= Array.new
|
|
35
35
|
|
|
36
36
|
instance_eval(&block)
|
|
37
|
-
prepare!
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
##
|
|
@@ -73,7 +72,7 @@ module Backup
|
|
|
73
72
|
# the Redis server to persist the current state to the dump file
|
|
74
73
|
# before copying the dump to get the most recent updates in to the backup
|
|
75
74
|
def perform!
|
|
76
|
-
|
|
75
|
+
super
|
|
77
76
|
|
|
78
77
|
invoke_save! if invoke_save
|
|
79
78
|
copy!
|
|
@@ -83,10 +82,17 @@ module Backup
|
|
|
83
82
|
# Tells Redis to persist the current state of the
|
|
84
83
|
# in-memory database to the persisted dump file
|
|
85
84
|
def invoke_save!
|
|
86
|
-
response = run("#{ utility('redis-cli') } #{ credential_options }
|
|
85
|
+
response = run("#{ utility('redis-cli') } #{ credential_options } " +
|
|
86
|
+
"#{ connectivity_options } #{ additional_options } SAVE")
|
|
87
87
|
unless response =~ /OK/
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
raise Errors::Database::Redis::CommandError, <<-EOS
|
|
89
|
+
Could not invoke the Redis SAVE command.
|
|
90
|
+
The #{ database } file might not contain the most recent data.
|
|
91
|
+
Please check if the server is running, the credentials (if any) are correct,
|
|
92
|
+
and the host/port/socket are correct.
|
|
93
|
+
|
|
94
|
+
Redis CLI response: #{ response }
|
|
95
|
+
EOS
|
|
90
96
|
end
|
|
91
97
|
end
|
|
92
98
|
|
|
@@ -94,8 +100,10 @@ module Backup
|
|
|
94
100
|
# Performs the copy command to copy over the Redis dump file to the Backup archive
|
|
95
101
|
def copy!
|
|
96
102
|
unless File.exist?(File.join(path, database))
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
raise Errors::Database::Redis::NotFoundError, <<-EOS
|
|
104
|
+
Redis database dump not found
|
|
105
|
+
File path was #{ File.join(path, database) }
|
|
106
|
+
EOS
|
|
99
107
|
end
|
|
100
108
|
|
|
101
109
|
# Temporarily remove a custom `utility_path` setting so that the system
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class Riak < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Name is the name of the backup
|
|
9
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Node is the node from which to perform the backup.
|
|
13
|
+
attr_accessor :node
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Cookie is the Erlang cookie/shared secret used to connect to the node.
|
|
17
|
+
attr_accessor :cookie
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Creates a new instance of the Riak adapter object
|
|
21
|
+
def initialize(&block)
|
|
22
|
+
load_defaults!
|
|
23
|
+
|
|
24
|
+
instance_eval(&block)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Builds the full riak-admin string based on all attributes
|
|
29
|
+
def riakadmin
|
|
30
|
+
"riak-admin backup #{node} #{cookie}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Performs the riak-admin command and outputs the
|
|
35
|
+
# data to the specified path based on the 'trigger'
|
|
36
|
+
def perform!
|
|
37
|
+
super
|
|
38
|
+
# have to make riak the owner since the riak-admin tool runs as the riak user in a default setup.
|
|
39
|
+
run("chown -R riak.riak #{dump_path}")
|
|
40
|
+
run("#{riakadmin} #{File.join(dump_path, name)} node")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/backup/dependency.rb
CHANGED
|
@@ -48,7 +48,7 @@ module Backup
|
|
|
48
48
|
|
|
49
49
|
'mail' => {
|
|
50
50
|
:require => 'mail',
|
|
51
|
-
:version => '
|
|
51
|
+
:version => '>= 2.2.15',
|
|
52
52
|
:for => 'Sending Emails (Mail Notifier)'
|
|
53
53
|
},
|
|
54
54
|
|
|
@@ -69,6 +69,18 @@ module Backup
|
|
|
69
69
|
:version => '~> 1.5.1',
|
|
70
70
|
:for => 'Parsing JSON for HTTParty'
|
|
71
71
|
},
|
|
72
|
+
|
|
73
|
+
'prowler' => {
|
|
74
|
+
:require => 'prowler',
|
|
75
|
+
:version => '>= 1.3.1',
|
|
76
|
+
:for => 'Sending iOS push notifications (Prowl Notifier)'
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
'hipchat' => {
|
|
80
|
+
:require => 'hipchat',
|
|
81
|
+
:version => '~> 0.4.1',
|
|
82
|
+
:for => 'Sending notifications to Hipchat'
|
|
83
|
+
}
|
|
72
84
|
}
|
|
73
85
|
end
|
|
74
86
|
|
|
@@ -81,12 +93,14 @@ module Backup
|
|
|
81
93
|
gem(name, all[name][:version])
|
|
82
94
|
require(all[name][:require])
|
|
83
95
|
rescue LoadError
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
Logger.error Errors::Dependency::LoadError.new(<<-EOS)
|
|
97
|
+
Dependency missing
|
|
98
|
+
Dependency required for:
|
|
99
|
+
#{all[name][:for]}
|
|
100
|
+
To install the gem, issue the following command:
|
|
101
|
+
> gem install #{name} -v '#{all[name][:version]}'
|
|
102
|
+
Please try again after installing the missing dependency.
|
|
103
|
+
EOS
|
|
90
104
|
exit
|
|
91
105
|
end
|
|
92
106
|
end
|
|
@@ -9,6 +9,10 @@ module Backup
|
|
|
9
9
|
# password will be required to decrypt the backup later on.
|
|
10
10
|
attr_accessor :password
|
|
11
11
|
|
|
12
|
+
##
|
|
13
|
+
# The password file to use to encrypt the backup.
|
|
14
|
+
attr_accessor :password_file
|
|
15
|
+
|
|
12
16
|
##
|
|
13
17
|
# Determines whether the 'base64' should be used or not
|
|
14
18
|
attr_writer :base64
|
|
@@ -23,8 +27,9 @@ module Backup
|
|
|
23
27
|
def initialize(&block)
|
|
24
28
|
load_defaults!
|
|
25
29
|
|
|
26
|
-
@base64
|
|
27
|
-
@salt
|
|
30
|
+
@base64 ||= false
|
|
31
|
+
@salt ||= false
|
|
32
|
+
@password_file ||= nil
|
|
28
33
|
|
|
29
34
|
instance_eval(&block) if block_given?
|
|
30
35
|
end
|
|
@@ -33,7 +38,7 @@ module Backup
|
|
|
33
38
|
# Performs the encryption of the backup file
|
|
34
39
|
def perform!
|
|
35
40
|
log!
|
|
36
|
-
run("#{ utility(:openssl) } #{ options } -in '#{ Backup::Model.file }' -out '#{ Backup::Model.file }.enc'
|
|
41
|
+
run("#{ utility(:openssl) } #{ options } -in '#{ Backup::Model.file }' -out '#{ Backup::Model.file }.enc'")
|
|
37
42
|
rm(Backup::Model.file)
|
|
38
43
|
Backup::Model.extension += '.enc'
|
|
39
44
|
end
|
|
@@ -44,11 +49,11 @@ module Backup
|
|
|
44
49
|
# Backup::Encryptor::OpenSSL uses the 256bit AES encryption cipher.
|
|
45
50
|
# 256bit AES is what the US Government uses to encrypt information at the "Top Secret" level.
|
|
46
51
|
def options
|
|
47
|
-
(['aes-256-cbc'] + base64 + salt).join("\s")
|
|
52
|
+
(['aes-256-cbc'] + base64 + salt + pass).join("\s")
|
|
48
53
|
end
|
|
49
54
|
|
|
50
55
|
##
|
|
51
|
-
# Returns '-
|
|
56
|
+
# Returns '-base64' if @base64 is set to 'true'.
|
|
52
57
|
# This option will make the encrypted output base64 encoded,
|
|
53
58
|
# this makes the encrypted file readable using text editors
|
|
54
59
|
def base64
|
|
@@ -62,6 +67,16 @@ module Backup
|
|
|
62
67
|
return ['-salt'] if @salt; []
|
|
63
68
|
end
|
|
64
69
|
|
|
70
|
+
##
|
|
71
|
+
# Returns '-pass file:<password file>' when @password_file has been set.
|
|
72
|
+
def pass
|
|
73
|
+
if @password_file
|
|
74
|
+
["-pass file:#{@password_file}"]
|
|
75
|
+
else
|
|
76
|
+
["-k '#{@password}'"]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
65
80
|
end
|
|
66
81
|
end
|
|
67
82
|
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
##
|
|
5
|
+
# - automatically defines module namespaces referenced under Backup::Errors
|
|
6
|
+
# - any constant name referenced that ends with 'Error' will be created
|
|
7
|
+
# as a subclass of Backup::Errors::Error
|
|
8
|
+
# e.g.
|
|
9
|
+
# err = Backup::Errors::Foo::Bar::FooError.new('error message')
|
|
10
|
+
# err.message => "Foo::Bar::FooError: error message"
|
|
11
|
+
#
|
|
12
|
+
module ErrorsHelper
|
|
13
|
+
def const_missing(const)
|
|
14
|
+
if const.to_s.end_with?('Error')
|
|
15
|
+
module_eval("class #{const} < Backup::Errors::Error; end")
|
|
16
|
+
else
|
|
17
|
+
module_eval("module #{const}; extend Backup::ErrorsHelper; end")
|
|
18
|
+
end
|
|
19
|
+
const_get(const)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# provides cascading errors with formatted messages
|
|
25
|
+
# see the specs for details
|
|
26
|
+
#
|
|
27
|
+
# e.g.
|
|
28
|
+
# module Backup
|
|
29
|
+
# begin
|
|
30
|
+
# begin
|
|
31
|
+
# begin
|
|
32
|
+
# raise Errors::ZoneAError, 'an error occurred in Zone A'
|
|
33
|
+
# rescue => err
|
|
34
|
+
# raise Errors::ZoneBError.wrap(err, <<-EOS)
|
|
35
|
+
# an error occurred in Zone B
|
|
36
|
+
#
|
|
37
|
+
# the following error should give a reason
|
|
38
|
+
# EOS
|
|
39
|
+
# end
|
|
40
|
+
# rescue => err
|
|
41
|
+
# raise Errors::ZoneCError.wrap(err)
|
|
42
|
+
# end
|
|
43
|
+
# rescue => err
|
|
44
|
+
# puts Errors::ZoneDError.wrap(err, 'an error occurred in Zone D')
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
#
|
|
48
|
+
# Outputs:
|
|
49
|
+
# ZoneDError: an error occurred in Zone D
|
|
50
|
+
# Reason: ZoneCError
|
|
51
|
+
# ZoneBError: an error occurred in Zone B
|
|
52
|
+
#
|
|
53
|
+
# the following error should give a reason
|
|
54
|
+
# Reason: ZoneAError
|
|
55
|
+
# an error occurred in Zone A
|
|
56
|
+
#
|
|
57
|
+
module Errors
|
|
58
|
+
extend ErrorsHelper
|
|
59
|
+
|
|
60
|
+
class Error < StandardError
|
|
61
|
+
|
|
62
|
+
def self.wrap(orig_err, msg = nil)
|
|
63
|
+
new(msg, orig_err)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def initialize(msg = nil, orig_err = nil)
|
|
67
|
+
super(msg)
|
|
68
|
+
set_backtrace(orig_err.backtrace) if @orig_err = orig_err
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_s
|
|
72
|
+
return @to_s if @to_s
|
|
73
|
+
orig_to_s = super()
|
|
74
|
+
|
|
75
|
+
if orig_to_s == self.class.to_s
|
|
76
|
+
msg = orig_err_msg ?
|
|
77
|
+
"#{orig_err_class}: #{orig_err_msg}" : orig_err_class
|
|
78
|
+
else
|
|
79
|
+
msg = format_msg(orig_to_s)
|
|
80
|
+
msg << "\n Reason: #{orig_err_class}" + (orig_err_msg ?
|
|
81
|
+
"\n #{orig_err_msg}" : ' (no message given)') if @orig_err
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
@to_s = msg ? msg_prefix + msg : class_name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def msg_prefix
|
|
90
|
+
@msg_prefix ||= class_name + ': '
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def orig_msg
|
|
94
|
+
@orig_msg ||= to_s.sub(msg_prefix, '')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def class_name
|
|
98
|
+
@class_name ||= self.class.to_s.sub('Backup::Errors::', '')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def orig_err_class
|
|
102
|
+
return unless @orig_err
|
|
103
|
+
|
|
104
|
+
@orig_err_class ||= @orig_err.is_a?(Errors::Error) ?
|
|
105
|
+
@orig_err.send(:class_name) : @orig_err.class.to_s
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def orig_err_msg
|
|
109
|
+
return unless @orig_err
|
|
110
|
+
return @orig_err_msg unless @orig_err_msg.nil?
|
|
111
|
+
|
|
112
|
+
msg = @orig_err.is_a?(Errors::Error) ?
|
|
113
|
+
@orig_err.send(:orig_msg) : @orig_err.to_s
|
|
114
|
+
@orig_err_msg = (msg == orig_err_class) ?
|
|
115
|
+
false : format_msg(msg)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def format_msg(msg)
|
|
119
|
+
msg.gsub(/^ */, ' ').strip
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/backup/finder.rb
CHANGED
|
@@ -32,7 +32,8 @@ module Backup
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
raise Errors::Finder::MissingTriggerError,
|
|
36
|
+
"Could not find trigger '#{trigger}' in '#{config}'."
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
##
|
|
@@ -68,12 +69,19 @@ module Backup
|
|
|
68
69
|
# Tries to find and load the configuration file
|
|
69
70
|
def load_config!
|
|
70
71
|
unless File.exist?(config)
|
|
71
|
-
|
|
72
|
+
raise Errors::Finder::MissingConfigError,
|
|
73
|
+
"Could not find configuration file: '#{config}'."
|
|
72
74
|
end
|
|
73
75
|
|
|
76
|
+
##
|
|
77
|
+
# Reset the Backup::Model.all to an empty array since this will be
|
|
78
|
+
# re-filled during the next Backup::Finder.new(arg1, arg2).find
|
|
79
|
+
# or Backup::Finder.new(arg).matching call
|
|
80
|
+
Backup::Model.all = Array.new
|
|
81
|
+
|
|
74
82
|
##
|
|
75
83
|
# Loads the backup configuration file
|
|
76
|
-
|
|
84
|
+
Backup.module_eval(File.read(config), config, 1)
|
|
77
85
|
end
|
|
78
86
|
end
|
|
79
87
|
end
|
data/lib/backup/logger.rb
CHANGED
|
@@ -1,102 +1,141 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
3
|
module Backup
|
|
4
|
-
|
|
4
|
+
module Logger
|
|
5
|
+
class << self
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
##
|
|
8
|
+
# Outputs a messages to the console and writes it to the backup.log
|
|
9
|
+
def message(string)
|
|
10
|
+
to_console loggify(string, :message, :green)
|
|
11
|
+
to_file loggify(string, :message)
|
|
12
|
+
end
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
##
|
|
15
|
+
# Outputs an error to the console and writes it to the backup.log
|
|
16
|
+
# Called when an Exception has caused the backup process to abort.
|
|
17
|
+
def error(string)
|
|
18
|
+
to_console loggify(string, :error, :red), true
|
|
19
|
+
to_file loggify(string, :error)
|
|
20
|
+
end
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
##
|
|
23
|
+
# Outputs a notice to the console and writes it to the backup.log
|
|
24
|
+
# Sets #has_warnings? true so :on_warning notifications will be sent
|
|
25
|
+
def warn(string)
|
|
26
|
+
@has_warnings = true
|
|
27
|
+
to_console loggify(string, :warning, :yellow), true
|
|
28
|
+
to_file loggify(string, :warning)
|
|
29
|
+
end
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
31
|
+
# Outputs the data as if it were a regular 'puts' command,
|
|
32
|
+
# but also logs it to the backup.log
|
|
33
|
+
def normal(string)
|
|
34
|
+
to_console loggify(string)
|
|
35
|
+
to_file loggify(string)
|
|
36
|
+
end
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
##
|
|
39
|
+
# Silently logs data to the log file
|
|
40
|
+
def silent(string)
|
|
41
|
+
to_file loggify(string, :silent)
|
|
42
|
+
end
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
##
|
|
45
|
+
# Returns an Array of all messages written to the log file for this session
|
|
46
|
+
def messages
|
|
47
|
+
@messages ||= []
|
|
48
|
+
end
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def self.loggify(type, string, color = false)
|
|
53
|
-
return "[#{time}][#{type}] #{string}" unless color
|
|
54
|
-
"[#{time}][#{send(color, type)}] #{string}"
|
|
55
|
-
end
|
|
50
|
+
##
|
|
51
|
+
# Returns true if any warnings have been issued
|
|
52
|
+
def has_warnings?
|
|
53
|
+
@has_warnings ||= false
|
|
54
|
+
end
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
File.open(File.join(LOG_PATH, 'backup.log'), 'a') do |file|
|
|
61
|
-
file.write("#{string}\n")
|
|
56
|
+
def clear!
|
|
57
|
+
messages.clear
|
|
58
|
+
@has_warnings = false
|
|
62
59
|
end
|
|
63
|
-
end
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
# Invokes the #colorize method with the provided string
|
|
67
|
-
# and the color code "32" (for green)
|
|
68
|
-
def self.green(string)
|
|
69
|
-
colorize(string, 32)
|
|
70
|
-
end
|
|
61
|
+
private
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
63
|
+
##
|
|
64
|
+
# Returns the time in [YYYY/MM/DD HH:MM:SS] format
|
|
65
|
+
def time
|
|
66
|
+
Time.now.strftime("%Y/%m/%d %H:%M:%S")
|
|
67
|
+
end
|
|
78
68
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
69
|
+
##
|
|
70
|
+
# Receives a String, or an Object that responds to #to_s (e.g. an
|
|
71
|
+
# Exception), from one of the messaging methods and converts it into an
|
|
72
|
+
# Array of Strings, split on newline separators. Each line is then
|
|
73
|
+
# formatted into a log format based on the given options, and the Array
|
|
74
|
+
# returned to be passed to to_console() and/or to_file().
|
|
75
|
+
def loggify(string, type = false, color = false)
|
|
76
|
+
lines = string.to_s.split("\n")
|
|
77
|
+
if type
|
|
78
|
+
type = send(color, type) if color
|
|
79
|
+
time_now = time
|
|
80
|
+
lines.map {|line| "[#{time_now}][#{type}] #{line}" }
|
|
81
|
+
else
|
|
82
|
+
lines
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
##
|
|
87
|
+
# Receives an Array of Strings to be written to the console.
|
|
88
|
+
def to_console(lines, stderr = false)
|
|
89
|
+
return if quiet?
|
|
90
|
+
lines.each {|line| stderr ? Kernel.warn(line) : puts(line) }
|
|
91
|
+
end
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
##
|
|
94
|
+
# Receives an Array of Strings to be written to the log file.
|
|
95
|
+
def to_file(lines)
|
|
96
|
+
File.open(File.join(LOG_PATH, 'backup.log'), 'a') do |file|
|
|
97
|
+
lines.each {|line| file.puts line }
|
|
98
|
+
end
|
|
99
|
+
messages.push(*lines)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Invokes the #colorize method with the provided string
|
|
104
|
+
# and the color code "32" (for green)
|
|
105
|
+
def green(string)
|
|
106
|
+
colorize(string, 32)
|
|
107
|
+
end
|
|
100
108
|
|
|
109
|
+
##
|
|
110
|
+
# Invokes the #colorize method with the provided string
|
|
111
|
+
# and the color code "33" (for yellow)
|
|
112
|
+
def yellow(string)
|
|
113
|
+
colorize(string, 33)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
##
|
|
117
|
+
# Invokes the #colorize method the with provided string
|
|
118
|
+
# and the color code "31" (for red)
|
|
119
|
+
def red(string)
|
|
120
|
+
colorize(string, 31)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
# Wraps the provided string in colorizing tags to provide
|
|
125
|
+
# easier to view output to the client
|
|
126
|
+
def colorize(string, code)
|
|
127
|
+
"\e[#{code}m#{string}\e[0m"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
##
|
|
131
|
+
# Returns 'true' (boolean) if the QUIET constant is defined
|
|
132
|
+
# By default it isn't defined, only when initializing Backup using
|
|
133
|
+
# the '--quiet' (or '-q') option in the CLI
|
|
134
|
+
# (e.g. backup perform -t my_backup --quiet)
|
|
135
|
+
def quiet?
|
|
136
|
+
const_defined?(:QUIET) && QUIET
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
101
140
|
end
|
|
102
141
|
end
|