backup-ssh 4.1.10 → 4.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 (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