backup 3.5.1 → 3.6.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.
- checksums.yaml +4 -4
- data/lib/backup/cli.rb +29 -6
- data/lib/backup/errors.rb +46 -81
- data/lib/backup/model.rb +184 -143
- data/lib/backup/notifier/base.rb +60 -29
- data/lib/backup/notifier/campfire.rb +23 -105
- data/lib/backup/notifier/hipchat.rb +19 -17
- data/lib/backup/notifier/mail.rb +64 -59
- data/lib/backup/notifier/prowl.rb +27 -19
- data/lib/backup/notifier/pushover.rb +26 -36
- data/lib/backup/notifier/twitter.rb +13 -15
- data/lib/backup/pipeline.rb +1 -3
- data/lib/backup/storage/s3.rb +0 -3
- data/lib/backup/utilities.rb +9 -8
- data/lib/backup/version.rb +1 -1
- data/templates/notifier/mail/failure.erb +2 -0
- data/templates/notifier/mail/success.erb +4 -0
- data/templates/notifier/mail/warning.erb +2 -0
- metadata +16 -30
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require '
|
2
|
+
require 'excon'
|
3
|
+
require 'uri'
|
3
4
|
|
4
5
|
module Backup
|
5
6
|
module Notifier
|
@@ -16,8 +17,7 @@ module Backup
|
|
16
17
|
attr_accessor :api_key
|
17
18
|
|
18
19
|
def initialize(model, &block)
|
19
|
-
super
|
20
|
-
|
20
|
+
super
|
21
21
|
instance_eval(&block) if block_given?
|
22
22
|
end
|
23
23
|
|
@@ -25,36 +25,44 @@ module Backup
|
|
25
25
|
|
26
26
|
##
|
27
27
|
# Notify the user of the backup operation results.
|
28
|
+
#
|
28
29
|
# `status` indicates one of the following:
|
29
30
|
#
|
30
31
|
# `:success`
|
31
32
|
# : The backup completed successfully.
|
32
|
-
# : Notification will be sent if `on_success`
|
33
|
+
# : Notification will be sent if `on_success` is `true`.
|
33
34
|
#
|
34
35
|
# `:warning`
|
35
|
-
# : The backup completed successfully, but warnings were logged
|
36
|
-
# : Notification will be sent
|
37
|
-
# : backup log, if `on_warning` was set to `true`
|
36
|
+
# : The backup completed successfully, but warnings were logged.
|
37
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
38
38
|
#
|
39
39
|
# `:failure`
|
40
40
|
# : The backup operation failed.
|
41
|
-
# : Notification will be sent
|
42
|
-
# : the failure, the Exception's backtrace, a copy of the current
|
43
|
-
# : backup log and other information if `on_failure` was set to `true`
|
41
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
44
42
|
#
|
45
43
|
def notify!(status)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
send_message(message)
|
44
|
+
tag = case status
|
45
|
+
when :success then '[Backup::Success]'
|
46
|
+
when :warning then '[Backup::Warning]'
|
47
|
+
when :failure then '[Backup::Failure]'
|
48
|
+
end
|
49
|
+
send_message(tag)
|
53
50
|
end
|
54
51
|
|
55
52
|
def send_message(message)
|
56
|
-
|
57
|
-
|
53
|
+
uri = 'https://api.prowlapp.com/publicapi/add'
|
54
|
+
data = {
|
55
|
+
:application => application,
|
56
|
+
:apikey => api_key,
|
57
|
+
:event => message,
|
58
|
+
:description => "#{ model.label } (#{ model.trigger })"
|
59
|
+
}
|
60
|
+
options = {
|
61
|
+
:headers => { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
62
|
+
:body => encode_www_form(data)
|
63
|
+
}
|
64
|
+
options.merge!(:expects => 200) # raise error if unsuccessful
|
65
|
+
Excon.post(uri, options)
|
58
66
|
end
|
59
67
|
|
60
68
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require '
|
2
|
+
require 'excon'
|
3
|
+
require 'uri'
|
3
4
|
|
4
5
|
module Backup
|
5
6
|
module Notifier
|
@@ -27,8 +28,7 @@ module Backup
|
|
27
28
|
attr_accessor :priority
|
28
29
|
|
29
30
|
def initialize(model, &block)
|
30
|
-
super
|
31
|
-
|
31
|
+
super
|
32
32
|
instance_eval(&block) if block_given?
|
33
33
|
end
|
34
34
|
|
@@ -36,56 +36,46 @@ module Backup
|
|
36
36
|
|
37
37
|
##
|
38
38
|
# Notify the user of the backup operation results.
|
39
|
+
#
|
39
40
|
# `status` indicates one of the following:
|
40
41
|
#
|
41
42
|
# `:success`
|
42
43
|
# : The backup completed successfully.
|
43
|
-
# : Notification will be sent if `on_success`
|
44
|
+
# : Notification will be sent if `on_success` is `true`.
|
44
45
|
#
|
45
46
|
# `:warning`
|
46
|
-
# : The backup completed successfully, but warnings were logged
|
47
|
-
# : Notification will be sent
|
48
|
-
# : backup log, if `on_warning` was set to `true`
|
47
|
+
# : The backup completed successfully, but warnings were logged.
|
48
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
49
49
|
#
|
50
50
|
# `:failure`
|
51
51
|
# : The backup operation failed.
|
52
|
-
# : Notification will be sent
|
53
|
-
# : the failure, the Exception's backtrace, a copy of the current
|
54
|
-
# : backup log and other information if `on_failure` was set to `true`
|
52
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
55
53
|
#
|
56
54
|
def notify!(status)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
message = "
|
63
|
-
|
55
|
+
tag = case status
|
56
|
+
when :success then '[Backup::Success]'
|
57
|
+
when :failure then '[Backup::Failure]'
|
58
|
+
when :warning then '[Backup::Warning]'
|
59
|
+
end
|
60
|
+
message = "#{ tag } #{ model.label } (#{ model.trigger })"
|
64
61
|
send_message(message)
|
65
62
|
end
|
66
63
|
|
67
|
-
# Push a message via the Pushover API
|
68
64
|
def send_message(message)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
response.use_ssl = true
|
76
|
-
response.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
77
|
-
|
78
|
-
response.start {|http| http.request(request) }
|
79
|
-
end
|
80
|
-
|
81
|
-
# List available parameters
|
82
|
-
def parameters
|
83
|
-
@values = {}
|
84
|
-
[:token, :user, :message, :title, :priority, :device].each do |k|
|
85
|
-
@values.merge! k => self.instance_variable_get("@#{k}")
|
65
|
+
uri = 'https://api.pushover.net/1/messages.json'
|
66
|
+
data = { :user => user, :token => token, :message => message }
|
67
|
+
[:device, :title, :priority].each do |param|
|
68
|
+
val = send(param)
|
69
|
+
data.merge!(param => val) if val
|
86
70
|
end
|
87
|
-
|
71
|
+
options = {
|
72
|
+
:headers => { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
73
|
+
:body => encode_www_form(data)
|
74
|
+
}
|
75
|
+
options.merge!(:expects => 200) # raise error if unsuccessful
|
76
|
+
Excon.post(uri, options)
|
88
77
|
end
|
78
|
+
|
89
79
|
end
|
90
80
|
end
|
91
81
|
end
|
@@ -14,8 +14,7 @@ module Backup
|
|
14
14
|
attr_accessor :oauth_token, :oauth_token_secret
|
15
15
|
|
16
16
|
def initialize(model, &block)
|
17
|
-
super
|
18
|
-
|
17
|
+
super
|
19
18
|
instance_eval(&block) if block_given?
|
20
19
|
end
|
21
20
|
|
@@ -23,33 +22,32 @@ module Backup
|
|
23
22
|
|
24
23
|
##
|
25
24
|
# Notify the user of the backup operation results.
|
25
|
+
#
|
26
26
|
# `status` indicates one of the following:
|
27
27
|
#
|
28
28
|
# `:success`
|
29
29
|
# : The backup completed successfully.
|
30
|
-
# : Notification will be sent if `on_success`
|
30
|
+
# : Notification will be sent if `on_success` is `true`.
|
31
31
|
#
|
32
32
|
# `:warning`
|
33
|
-
# : The backup completed successfully, but warnings were logged
|
34
|
-
# : Notification will be sent
|
35
|
-
# : backup log, if `on_warning` was set to `true`
|
33
|
+
# : The backup completed successfully, but warnings were logged.
|
34
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
36
35
|
#
|
37
36
|
# `:failure`
|
38
37
|
# : The backup operation failed.
|
39
|
-
# : Notification will be sent
|
40
|
-
# : the failure, the Exception's backtrace, a copy of the current
|
41
|
-
# : backup log and other information if `on_failure` was set to `true`
|
38
|
+
# : Notification will be sent if `on_warning` or `on_success` is `true`.
|
42
39
|
#
|
43
40
|
def notify!(status)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
message = "
|
41
|
+
tag = case status
|
42
|
+
when :success then '[Backup::Success]'
|
43
|
+
when :warning then '[Backup::Warning]'
|
44
|
+
when :failure then '[Backup::Failure]'
|
45
|
+
end
|
46
|
+
message = "#{ tag } #{ model.label } (#{ model.trigger }) (@ #{ model.time })"
|
50
47
|
send_message(message)
|
51
48
|
end
|
52
49
|
|
50
|
+
# Twitter::Client will raise an error if unsuccessful.
|
53
51
|
def send_message(message)
|
54
52
|
::Twitter.configure do |config|
|
55
53
|
config.consumer_key = @consumer_key
|
data/lib/backup/pipeline.rb
CHANGED
@@ -75,12 +75,10 @@ module Backup
|
|
75
75
|
# Returns a multi-line String, reporting all STDERR messages received
|
76
76
|
# from the commands in the pipeline (if any), along with the SystemCallError
|
77
77
|
# (Errno) message for each command which had a non-zero exit status.
|
78
|
-
#
|
79
|
-
# Each error is wrapped by Backup::Errors to provide formatting.
|
80
78
|
def error_messages
|
81
79
|
@error_messages ||= (stderr_messages || '') +
|
82
80
|
"The following system errors were returned:\n" +
|
83
|
-
@errors.map {|err|
|
81
|
+
@errors.map {|err| "#{ err.class }: #{ err.message }" }.join("\n")
|
84
82
|
end
|
85
83
|
|
86
84
|
private
|
data/lib/backup/storage/s3.rb
CHANGED
@@ -233,9 +233,6 @@ module Backup
|
|
233
233
|
end
|
234
234
|
end
|
235
235
|
|
236
|
-
# Avoid wrapping Excon::Errors::HTTPStatusError since it's message
|
237
|
-
# includes `request.inspect`. For multipart uploads, this includes
|
238
|
-
# the String#inspect output of `file.read(chunk_size)`.
|
239
236
|
def error_with(err, msg)
|
240
237
|
if err.is_a? Excon::Errors::HTTPStatusError
|
241
238
|
Errors::Storage::S3::UploaderError.new(<<-EOS)
|
data/lib/backup/utilities.rb
CHANGED
@@ -9,6 +9,7 @@ module Backup
|
|
9
9
|
mongo mongodump mysqldump pg_dump pg_dumpall redis-cli riak-admin
|
10
10
|
gpg openssl
|
11
11
|
rsync ssh
|
12
|
+
sendmail exim
|
12
13
|
}
|
13
14
|
|
14
15
|
module DSL
|
@@ -88,6 +89,10 @@ module Backup
|
|
88
89
|
# # Syncer and Storage
|
89
90
|
# rsync '/path/to/rsync'
|
90
91
|
# ssh '/path/to/ssh'
|
92
|
+
#
|
93
|
+
# # Notifiers
|
94
|
+
# sendmail '/path/to/sendmail'
|
95
|
+
# exim '/path/to/exim'
|
91
96
|
# end
|
92
97
|
#
|
93
98
|
# These paths may be set using absolute paths, or relative to the
|
@@ -144,6 +149,7 @@ module Backup
|
|
144
149
|
def command_name(command)
|
145
150
|
parts = []
|
146
151
|
command = command.split(' ')
|
152
|
+
command.shift while command[0].to_s.include?('=')
|
147
153
|
parts << command.shift.split('/')[-1]
|
148
154
|
if parts[0] == 'sudo'
|
149
155
|
until command.empty?
|
@@ -184,10 +190,8 @@ module Backup
|
|
184
190
|
out, err = stdout.read.strip, stderr.read.strip
|
185
191
|
end
|
186
192
|
rescue Exception => e
|
187
|
-
raise Errors::Utilities::SystemCallError.wrap(
|
188
|
-
|
189
|
-
Command was: #{ command }
|
190
|
-
EOS
|
193
|
+
raise Errors::Utilities::SystemCallError.wrap(
|
194
|
+
e, "Failed to execute '#{ name }'")
|
191
195
|
ensure
|
192
196
|
GC.enable if RUBY_VERSION < '1.9'
|
193
197
|
end
|
@@ -208,10 +212,7 @@ module Backup
|
|
208
212
|
return out
|
209
213
|
else
|
210
214
|
raise Errors::Utilities::SystemCallError, <<-EOS
|
211
|
-
'#{ name }'
|
212
|
-
The following information should help to determine the problem:
|
213
|
-
Command was: #{ command }
|
214
|
-
Exit Status: #{ ps.exitstatus }
|
215
|
+
'#{ name }' failed with exit status: #{ ps.exitstatus }
|
215
216
|
STDOUT Messages: #{ out.empty? ? 'None' : "\n#{ out }" }
|
216
217
|
STDERR Messages: #{ err.empty? ? 'None' : "\n#{ err }" }
|
217
218
|
EOS
|
data/lib/backup/version.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
|
2
2
|
Backup <%= @model.label %> (<%= @model.trigger %>) Failed!
|
3
|
+
<% if @send_log %>
|
3
4
|
|
4
5
|
See the attached backup log for details.
|
6
|
+
<% end %>
|
5
7
|
|
6
8
|
===========================================================================
|
7
9
|
<%= Backup::Template.new.result("general/version.erb") %>
|
@@ -1,5 +1,9 @@
|
|
1
1
|
|
2
2
|
Backup <%= @model.label %> (<%= @model.trigger %>) finished without any errors!
|
3
|
+
<% if @send_log %>
|
4
|
+
|
5
|
+
See the attached backup log for details.
|
6
|
+
<% end %>
|
3
7
|
|
4
8
|
===========================================================================
|
5
9
|
<%= Backup::Template.new.result("general/version.erb") %>
|
@@ -1,7 +1,9 @@
|
|
1
1
|
|
2
2
|
Backup <%= @model.label %> (<%= @model.trigger %>) finished with warnings.
|
3
|
+
<% if @send_log %>
|
3
4
|
|
4
5
|
See the attached backup log for details.
|
6
|
+
<% end %>
|
5
7
|
|
6
8
|
===========================================================================
|
7
9
|
<%= Backup::Template.new.result("general/version.erb") %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael van Rooijen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: 0.22.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: 0.22.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: faraday
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - '='
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.9.0
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.9.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: httparty
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - '='
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 1.
|
131
|
+
version: 1.8.0
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - '='
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 1.
|
138
|
+
version: 1.8.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: mail
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - '='
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.7.
|
173
|
+
version: 1.7.3
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - '='
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 1.7.
|
180
|
+
version: 1.7.3
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: multi_xml
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,28 +212,28 @@ dependencies:
|
|
212
212
|
requirements:
|
213
213
|
- - '='
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version: 1.1.
|
215
|
+
version: 1.1.1
|
216
216
|
type: :runtime
|
217
217
|
prerelease: false
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
219
219
|
requirements:
|
220
220
|
- - '='
|
221
221
|
- !ruby/object:Gem::Version
|
222
|
-
version: 1.1.
|
222
|
+
version: 1.1.1
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
224
|
name: net-sftp
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|
226
226
|
requirements:
|
227
227
|
- - '='
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version: 2.1.
|
229
|
+
version: 2.1.2
|
230
230
|
type: :runtime
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
234
|
- - '='
|
235
235
|
- !ruby/object:Gem::Version
|
236
|
-
version: 2.1.
|
236
|
+
version: 2.1.2
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: net-ssh
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
@@ -282,14 +282,14 @@ dependencies:
|
|
282
282
|
requirements:
|
283
283
|
- - '='
|
284
284
|
- !ruby/object:Gem::Version
|
285
|
-
version: 0.6.
|
285
|
+
version: 0.6.5
|
286
286
|
type: :runtime
|
287
287
|
prerelease: false
|
288
288
|
version_requirements: !ruby/object:Gem::Requirement
|
289
289
|
requirements:
|
290
290
|
- - '='
|
291
291
|
- !ruby/object:Gem::Version
|
292
|
-
version: 0.6.
|
292
|
+
version: 0.6.5
|
293
293
|
- !ruby/object:Gem::Dependency
|
294
294
|
name: polyglot
|
295
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,20 +304,6 @@ dependencies:
|
|
304
304
|
- - '='
|
305
305
|
- !ruby/object:Gem::Version
|
306
306
|
version: 0.3.3
|
307
|
-
- !ruby/object:Gem::Dependency
|
308
|
-
name: prowler
|
309
|
-
requirement: !ruby/object:Gem::Requirement
|
310
|
-
requirements:
|
311
|
-
- - '='
|
312
|
-
- !ruby/object:Gem::Version
|
313
|
-
version: 1.3.1
|
314
|
-
type: :runtime
|
315
|
-
prerelease: false
|
316
|
-
version_requirements: !ruby/object:Gem::Requirement
|
317
|
-
requirements:
|
318
|
-
- - '='
|
319
|
-
- !ruby/object:Gem::Version
|
320
|
-
version: 1.3.1
|
321
307
|
- !ruby/object:Gem::Dependency
|
322
308
|
name: ruby-hmac
|
323
309
|
requirement: !ruby/object:Gem::Requirement
|