backup-ssh 4.1.10 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -6
  3. data/lib/backup.rb +3 -0
  4. data/lib/backup/config/dsl.rb +2 -2
  5. data/lib/backup/database/mongodb.rb +2 -1
  6. data/lib/backup/database/mysql.rb +2 -2
  7. data/lib/backup/database/postgresql.rb +1 -1
  8. data/lib/backup/model.rb +26 -1
  9. data/lib/backup/notifier/base.rb +30 -0
  10. data/lib/backup/notifier/campfire.rb +1 -7
  11. data/lib/backup/notifier/command.rb +102 -0
  12. data/lib/backup/notifier/datadog.rb +11 -20
  13. data/lib/backup/notifier/flowdock.rb +6 -5
  14. data/lib/backup/notifier/hipchat.rb +33 -8
  15. data/lib/backup/notifier/http_post.rb +2 -7
  16. data/lib/backup/notifier/mail.rb +26 -15
  17. data/lib/backup/notifier/nagios.rb +3 -8
  18. data/lib/backup/notifier/prowl.rb +8 -9
  19. data/lib/backup/notifier/pushover.rb +1 -7
  20. data/lib/backup/notifier/ses.rb +19 -8
  21. data/lib/backup/notifier/slack.rb +4 -10
  22. data/lib/backup/notifier/twitter.rb +1 -7
  23. data/lib/backup/notifier/zabbix.rb +1 -6
  24. data/lib/backup/package.rb +4 -0
  25. data/lib/backup/packager.rb +8 -2
  26. data/lib/backup/storage/base.rb +15 -3
  27. data/lib/backup/storage/cycler.rb +24 -14
  28. data/lib/backup/storage/dropbox.rb +0 -24
  29. data/lib/backup/storage/ftp.rb +15 -1
  30. data/lib/backup/storage/qiniu.rb +65 -0
  31. data/lib/backup/storage/s3.rb +3 -2
  32. data/lib/backup/syncer/rsync/base.rb +7 -1
  33. data/lib/backup/version.rb +1 -1
  34. data/templates/cli/databases/mongodb +1 -1
  35. data/templates/cli/notifiers/command +32 -0
  36. data/templates/cli/notifiers/hipchat +1 -0
  37. data/templates/cli/notifiers/mail +3 -0
  38. data/templates/cli/storages/dropbox +1 -0
  39. data/templates/cli/storages/ftp +1 -0
  40. data/templates/cli/storages/local +1 -0
  41. data/templates/cli/storages/qiniu +12 -0
  42. data/templates/cli/storages/s3 +2 -0
  43. data/templates/cli/storages/scp +1 -0
  44. data/templates/cli/storages/sftp +1 -0
  45. metadata +79 -46
  46. data/LICENSE.md +0 -24
  47. data/lib/backup/storage/ninefold.rb +0 -74
  48. data/templates/cli/storages/ninefold +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ca21e187d62587f721654eb3ae84a84cf5e5f65
4
- data.tar.gz: 359e12d0e6d1e3762207b5cc99ad9cc6584dae0c
3
+ metadata.gz: 4e204b72f3e7d1cde84dc735f73fb5c2b040d8ff
4
+ data.tar.gz: '038ef67371243b75efaf003d2af79b822926e0b7'
5
5
  SHA512:
6
- metadata.gz: ed9a3a6af42428ec67c601d0ecf2a57e3f1e01031d495c7c9d1b00e282eac7e2c66ea36810434321fbb8a02807df5aa8c509df123db4234834609c996aefc9cd
7
- data.tar.gz: c6b399157b606def1740f2108ad947140a77466adb90733564cf97650581e7be0dfe17a645e18408910468af99d04d663e4a53d884bd96719ed00eb7671dc806
6
+ metadata.gz: 1f3a096e09ae0aef5d3be110e99949c4559c3889ba5710ee83273df469c24674e3616e8d5a5082b6a9e9218991c3df9182bf5ab57541889bdfb9a23b7f38eaba
7
+ data.tar.gz: f0b8d4b1134f7616fcb7b89965e0553b4f5718657efc6d97534381ea4104cce6202f3237727d78a213460d2da8cd5cb568f27ee7a06b6255c965f2ff692fd8d7
data/README.md CHANGED
@@ -1,25 +1,29 @@
1
1
  Backup v4.x
2
2
  ===========
3
+
3
4
  [![Code Climate](https://codeclimate.com/github/backup/backup.png)](https://codeclimate.com/github/backup/backup)
4
5
  [![Build Status](https://travis-ci.org/backup/backup.svg?branch=master)](https://travis-ci.org/backup/backup)
6
+ [![Join the chat at https://gitter.im/backup/backup](https://badges.gitter.im/Join%20Chat.svg)][Gitter]
5
7
 
6
8
  Backup is a system utility for Linux and Mac OS X, distributed as a RubyGem, that allows you to easily perform backup
7
9
  operations. It provides an elegant DSL in Ruby for _modeling_ your backups. Backup has built-in support for various
8
10
  databases, storage protocols/services, syncers, compressors, encryptors and notifiers which you can mix and match. It
9
11
  was built with modularity, extensibility and simplicity in mind.
10
12
 
11
- [Installation][] · [Release Notes][] · [Documentation][] · [Issues][] · [Features][]
13
+ [Installation][] · [Release Notes][] · [Documentation][] · [Issues][] · [Features][] · [Chat][Gitter]
12
14
 
13
15
  Please use the Backup features [issue tracker][Features] to suggest new features.
14
16
  Only use the Backup gem [issue tracker][Issues] for bugs and other issues.
17
+ We're also available on [Gitter] for questions and problems.
15
18
 
16
- **Copyright (c) 2009-2015 [Michael van Rooijen][] ( [@meskyanichi][] )**
17
- Released under the **MIT** [License](LICENSE.md).
19
+ **Copyright (c) 2009-2016 [Michael van Rooijen][] ( [@mrrooijen] )**
20
+ Released under the **MIT** [LICENSE](LICENSE).
18
21
 
19
22
  [Installation]: http://backup.github.io/backup/v4/installation
20
23
  [Release Notes]: http://backup.github.io/backup/v4/release-notes
21
24
  [Documentation]: http://backup.github.io/backup/v4
22
25
  [Issues]: https://github.com/backup/backup/issues
23
- [Features]: https://github.com/meskyanichi/backup-features/issues
24
- [Michael van Rooijen]: http://michaelvanrooijen.com
25
- [@meskyanichi]: http://twitter.com/#!/meskyanichi
26
+ [Features]: https://github.com/backup/backup-features/issues
27
+ [Gitter]: https://gitter.im/backup/backup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
28
+ [Michael van Rooijen]: http://github.com/mrrooijen
29
+ [@mrrooijen]: http://twitter.com/mrrooijen
data/lib/backup.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  # Load Ruby Core Libraries
4
+ require 'time'
4
5
  require 'fileutils'
5
6
  require 'tempfile'
6
7
  require 'syslog'
@@ -48,6 +49,7 @@ module Backup
48
49
  autoload :SCP, File.join(STORAGE_PATH, 'scp')
49
50
  autoload :RSync, File.join(STORAGE_PATH, 'rsync')
50
51
  autoload :Local, File.join(STORAGE_PATH, 'local')
52
+ autoload :Qiniu, File.join(STORAGE_PATH, 'qiniu')
51
53
  end
52
54
 
53
55
  ##
@@ -116,6 +118,7 @@ module Backup
116
118
  autoload :Zabbix, File.join(NOTIFIER_PATH, 'zabbix')
117
119
  autoload :DataDog, File.join(NOTIFIER_PATH, 'datadog')
118
120
  autoload :Ses, File.join(NOTIFIER_PATH, 'ses')
121
+ autoload :Command, File.join(NOTIFIER_PATH, 'command')
119
122
  end
120
123
 
121
124
  ##
@@ -30,7 +30,7 @@ module Backup
30
30
  ['MySQL', 'PostgreSQL', 'MongoDB', 'Redis', 'Riak', 'OpenLDAP', 'SQLite'],
31
31
  # Storages
32
32
  ['S3', 'CloudFiles', 'Ninefold', 'Dropbox', 'FTP',
33
- 'SFTP', 'SCP', 'RSync', 'Local'],
33
+ 'SFTP', 'SCP', 'RSync', 'Local', 'Qiniu'],
34
34
  # Compressors
35
35
  ['Gzip', 'Bzip2', 'Custom', 'Pbzip2', 'Lzma'],
36
36
  # Encryptors
@@ -43,7 +43,7 @@ module Backup
43
43
  # Notifiers
44
44
  ['Mail', 'Twitter', 'Campfire', 'Prowl',
45
45
  'Hipchat', 'PagerDuty', 'Pushover', 'HttpPost', 'Nagios',
46
- 'Slack', 'FlowDock', 'Zabbix', 'Ses', 'DataDog']
46
+ 'Slack', 'FlowDock', 'Zabbix', 'Ses', 'DataDog', 'Command']
47
47
  ]
48
48
  )
49
49
  end
@@ -11,7 +11,7 @@ module Backup
11
11
 
12
12
  ##
13
13
  # Credentials for the specified database
14
- attr_accessor :username, :password
14
+ attr_accessor :username, :password, :authdb
15
15
 
16
16
  ##
17
17
  # Connectivity options
@@ -132,6 +132,7 @@ module Backup
132
132
  opts = []
133
133
  opts << "--username='#{ username }'" if username
134
134
  opts << "--password='#{ password }'" if password
135
+ opts << "--authenticationDatabase='#{ authdb }'" if authdb
135
136
  opts.join(' ')
136
137
  end
137
138
 
@@ -105,8 +105,8 @@ module Backup
105
105
  private
106
106
 
107
107
  def mysqldump
108
- "#{ ssh_option } #{ utility(:mysqldump) } #{ credential_options } " +
109
- "#{ connectivity_options } #{ user_options } #{ name_option } " +
108
+ "#{ ssh_option } #{ utility(:mysqldump) } #{ user_options } #{ credential_options } " +
109
+ "#{ connectivity_options } #{ name_option } " +
110
110
  "#{ tables_to_dump } #{ tables_to_skip }"
111
111
  end
112
112
 
@@ -92,7 +92,7 @@ module Backup
92
92
  end
93
93
 
94
94
  def sudo_option
95
- "#{ utility(:sudo) } -n -u #{ sudo_user } " if sudo_user
95
+ "#{ utility(:sudo) } -n -H -u #{ sudo_user } " if sudo_user
96
96
  end
97
97
 
98
98
  def username_option
data/lib/backup/model.rb CHANGED
@@ -303,7 +303,7 @@ module Backup
303
303
  return [] unless databases.any? || archives.any?
304
304
 
305
305
  [lambda { prepare! }, databases, archives,
306
- lambda { package! }, storages, lambda { clean! }]
306
+ lambda { package! }, lambda { store! }, lambda { clean! }]
307
307
  end
308
308
 
309
309
  ##
@@ -325,6 +325,31 @@ module Backup
325
325
  Cleaner.remove_packaging(self)
326
326
  end
327
327
 
328
+ ##
329
+ # Attempts to use all configured Storages, even if some of them result in exceptions.
330
+ # Returns true or raises first encountered exception.
331
+ def store!
332
+ storage_results = storages.map do |storage|
333
+ begin
334
+ storage.perform!
335
+ rescue => ex
336
+ ex
337
+ end
338
+ end
339
+
340
+ first_exception, *other_exceptions = storage_results.select { |result| result.is_a? Exception }
341
+
342
+ if first_exception
343
+ other_exceptions.each do |exception|
344
+ Logger.error exception.to_s
345
+ Logger.error exception.backtrace.join('\n')
346
+ end
347
+ raise first_exception
348
+ else
349
+ true
350
+ end
351
+ end
352
+
328
353
  ##
329
354
  # Removes the final package file(s) once all configured Storages have run.
330
355
  def clean!
@@ -36,6 +36,15 @@ module Backup
36
36
  # Default: 30
37
37
  attr_accessor :retry_waitsec
38
38
 
39
+ ##
40
+ # Message to send. Depends on notifier implementation if this is used.
41
+ # Default: lambda returning:
42
+ # "#{ message } #{ model.label } (#{ model.trigger })"
43
+ #
44
+ # @yieldparam [model] Backup::Model
45
+ # @yieldparam [data] Hash containing `message` and `key` values.
46
+ attr_accessor :message
47
+
39
48
  attr_reader :model
40
49
 
41
50
  def initialize(model)
@@ -47,6 +56,9 @@ module Backup
47
56
  @on_failure = true if on_failure.nil?
48
57
  @max_retries ||= 10
49
58
  @retry_waitsec ||= 30
59
+ @message ||= lambda do |model, data|
60
+ "[#{ data[:status][:message] }] #{ model.label } (#{ model.trigger })"
61
+ end
50
62
  end
51
63
 
52
64
  # This method is called from an ensure block in Model#perform! and must
@@ -93,6 +105,24 @@ module Backup
93
105
  self.class.to_s.sub('Backup::', '')
94
106
  end
95
107
 
108
+ ##
109
+ # Return status data for message creation
110
+ def status_data_for(status)
111
+ {
112
+ :success => {
113
+ :message => 'Backup::Success',
114
+ :key => :success
115
+ },
116
+ :warning => {
117
+ :message => 'Backup::Warning',
118
+ :key => :warning
119
+ },
120
+ :failure => {
121
+ :message => 'Backup::Failure',
122
+ :key => :failure
123
+ }
124
+ }[status]
125
+ end
96
126
  end
97
127
  end
98
128
  end
@@ -42,13 +42,7 @@ module Backup
42
42
  # : Notification will be sent if `on_warning` or `on_success` is `true`.
43
43
  #
44
44
  def notify!(status)
45
- tag = case status
46
- when :success then '[Backup::Success]'
47
- when :warning then '[Backup::Warning]'
48
- when :failure then '[Backup::Failure]'
49
- end
50
- message = "#{ tag } #{ model.label } (#{ model.trigger })"
51
- send_message(message)
45
+ send_message(message.call(model, :status => status_data_for(status)))
52
46
  end
53
47
 
54
48
  def send_message(message)
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Notifier
5
+ class Command < Base
6
+
7
+ ##
8
+ # Command to execute.
9
+ #
10
+ # Make sure it is accessible from your $PATH, or provide
11
+ # the absolute path to the command.
12
+ attr_accessor :command
13
+
14
+ ##
15
+ # Arguments to pass to the command.
16
+ #
17
+ # Must be an array of strings or callable objects.
18
+ #
19
+ # Callables will be invoked with #call(model, status),
20
+ # and the return value used as the argument.
21
+ #
22
+ # In strings you can use the following placeholders:
23
+ #
24
+ # %l - Model label
25
+ # %t - Model trigger
26
+ # %d - Backup duration (HH:MM:SS)
27
+ # %s - Status (success/failure/warning)
28
+ # %v - Status verb (succeeded/failed/succeeded with warnings)
29
+ #
30
+ # All placeholders can be used with uppercase letters to capitalize
31
+ # the value.
32
+ #
33
+ # Defaults to ["%L %v"]
34
+ attr_accessor :args
35
+
36
+ def initialize(model, &block)
37
+ super
38
+ instance_eval(&block) if block_given?
39
+
40
+ @args ||= ["%L %v"]
41
+ end
42
+
43
+ private
44
+
45
+ ##
46
+ # Notify the user of the backup operation results.
47
+ #
48
+ # `status` indicates one of the following:
49
+ #
50
+ # `:success`
51
+ # : The backup completed successfully.
52
+ # : Notification will be sent if `on_success` is `true`.
53
+ #
54
+ # `:warning`
55
+ # : The backup completed successfully, but warnings were logged.
56
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
57
+ #
58
+ # `:failure`
59
+ # : The backup operation failed.
60
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
61
+ #
62
+ def notify!(status)
63
+ IO.popen([@command] + args.map { |arg| format_arg(arg, status) })
64
+ end
65
+
66
+ def format_arg(arg, status)
67
+ if arg.respond_to?(:call)
68
+ arg.call(model, status)
69
+ else
70
+ arg.gsub(/%(\w)/) do |match|
71
+ ph = match[1]
72
+ val = case ph.downcase
73
+ when "l"
74
+ model.label
75
+ when "t"
76
+ model.trigger.to_s
77
+ when "d"
78
+ model.duration
79
+ when "v"
80
+ status_verb(status)
81
+ when "s"
82
+ status.to_s
83
+ end
84
+ val.capitalize! if ph == ph.upcase
85
+ val
86
+ end
87
+ end
88
+ end
89
+
90
+ def status_verb(status)
91
+ case status
92
+ when :success
93
+ "succeeded"
94
+ when :failure
95
+ "failed"
96
+ when :warning
97
+ "succeeded with warnings"
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -13,9 +13,10 @@ module Backup
13
13
  # The title of the event
14
14
  attr_accessor :title
15
15
 
16
- ##
17
- # The text information for the event
18
- attr_accessor :text
16
+ attr_deprecate :text,
17
+ :version => '4.2',
18
+ :message => 'Please use the `message` attribute. For more information '\
19
+ 'see https://github.com/backup/backup/pull/698'
19
20
 
20
21
  ##
21
22
  # The timestamp for the event
@@ -48,9 +49,7 @@ module Backup
48
49
  def initialize(model, &block)
49
50
  super
50
51
  instance_eval(&block) if block_given?
51
-
52
- @title ||= default_title
53
- @text ||= default_text
52
+ @title ||= "Backup #{ model.label }"
54
53
  end
55
54
 
56
55
  private
@@ -73,7 +72,9 @@ module Backup
73
72
  # : Notification will be sent if `on_warning` or `on_success` is `true`.
74
73
  #
75
74
  def notify!(status)
76
- hash = {alert_type: default_alert_type(status)}
75
+ msg = message.call(model, :status => status_data_for(status))
76
+
77
+ hash = { alert_type: default_alert_type(status) }
77
78
  hash.store(:msg_title, @title)
78
79
  hash.store(:date_happened, @date_happened) if @date_happened
79
80
  hash.store(:priority, @priority) if @priority
@@ -82,13 +83,13 @@ module Backup
82
83
  hash.store(:aggregation_key, @aggregation_key) if @aggregation_key
83
84
  hash.store(:source_type_name, @source_type_name) if @source_type_name
84
85
  hash.store(:alert_type, @alert_type) if @alert_type
85
- send_event(hash)
86
+ send_event(msg, hash)
86
87
  end
87
88
 
88
89
  # Dogapi::Client will raise an error if unsuccessful.
89
- def send_event(hash)
90
+ def send_event(msg, hash)
90
91
  client = Dogapi::Client.new(@api_key)
91
- event = Dogapi::Event.new(@text, hash)
92
+ event = Dogapi::Event.new(msg, hash)
92
93
  client.emit_event(event)
93
94
  end
94
95
 
@@ -101,16 +102,6 @@ module Backup
101
102
  end
102
103
  end
103
104
 
104
- # set default title
105
- def default_title
106
- "Backup #{ model.label }"
107
- end
108
-
109
- # set default text
110
- def default_text
111
- "Backup Notification for #{ model.label }"
112
- end
113
-
114
105
  end
115
106
  end
116
107
  end
@@ -61,15 +61,16 @@ module Backup
61
61
  # : Notification will be sent if `on_warning` or `on_success` is `true`.
62
62
  #
63
63
  def notify!(status)
64
- @tags += default_tags(status)
65
- message = "#{ model.label } (#{ model.trigger })"
66
- send_message(message)
64
+ @tags += default_tags(status)
65
+ send_message(message.call(model, status: status_data_for(status)))
67
66
  end
68
67
 
69
68
  # Flowdock::Client will raise an error if unsuccessful.
70
69
  def send_message(msg)
71
- client = Flowdock::Flow.new(:api_token => token, :source => source,
72
- :from => {:name => from_name, :address => from_email })
70
+ client = Flowdock::Flow.new(
71
+ :api_token => token, :source => source,
72
+ :from => {:name => from_name, :address => from_email }
73
+ )
73
74
 
74
75
  client.push_to_team_inbox(:subject => subject,
75
76
  :content => msg,
@@ -9,10 +9,19 @@ module Backup
9
9
  # The Hipchat API token
10
10
  attr_accessor :token
11
11
 
12
+ ##
13
+ # The Hipchat API version
14
+ # Either 'v1' or 'v2' (default is 'v1')
15
+ attr_accessor :api_version
16
+
12
17
  ##
13
18
  # Who the notification should appear from
14
19
  attr_accessor :from
15
20
 
21
+ ##
22
+ # Custom server URL
23
+ attr_accessor :server_url
24
+
16
25
  ##
17
26
  # The rooms that should be notified
18
27
  attr_accessor :rooms_notified
@@ -45,6 +54,7 @@ module Backup
45
54
  @success_color ||= 'yellow'
46
55
  @warning_color ||= 'yellow'
47
56
  @failure_color ||= 'yellow'
57
+ @api_version ||= 'v1'
48
58
  end
49
59
 
50
60
  private
@@ -67,18 +77,20 @@ module Backup
67
77
  # : Notification will be sent if `on_warning` or `on_success` is `true`.
68
78
  #
69
79
  def notify!(status)
70
- tag, color = case status
71
- when :success then ['[Backup::Success]', success_color]
72
- when :warning then ['[Backup::Warning]', warning_color]
73
- when :failure then ['[Backup::Failure]', failure_color]
74
- end
75
- message = "#{ tag } #{ model.label } (#{ model.trigger })"
76
- send_message(message, color)
80
+ status_data = status_data_for(status)
81
+ msg = message.call(model, :status => status_data)
82
+ send_message(msg, status_data[:color])
83
+ end
84
+
85
+ def client_options
86
+ { api_version: @api_version }.tap do |h|
87
+ h[:server_url] = server_url if server_url
88
+ end
77
89
  end
78
90
 
79
91
  # Hipchat::Client will raise an error if unsuccessful.
80
92
  def send_message(msg, color)
81
- client = HipChat::Client.new(token)
93
+ client = HipChat::Client.new(token, client_options)
82
94
  rooms_to_notify.each do |room|
83
95
  client[room].send(from, msg, :color => color, :notify => notify_users)
84
96
  end
@@ -88,6 +100,19 @@ module Backup
88
100
  Array(rooms_notified).map {|r| r.split(',').map(&:strip) }.flatten
89
101
  end
90
102
 
103
+ def status_data_for(status)
104
+ data = super(status)
105
+ data[:color] = status_color_for(status)
106
+ data
107
+ end
108
+
109
+ def status_color_for(status)
110
+ {
111
+ :success => success_color,
112
+ :warning => warning_color,
113
+ :failure => failure_color
114
+ }[status]
115
+ end
91
116
  end
92
117
  end
93
118
  end