nfm-backup 4.0.1a

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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +24 -0
  3. data/README.md +20 -0
  4. data/bin/backup +5 -0
  5. data/lib/backup.rb +133 -0
  6. data/lib/backup/archive.rb +170 -0
  7. data/lib/backup/binder.rb +22 -0
  8. data/lib/backup/cleaner.rb +116 -0
  9. data/lib/backup/cli.rb +364 -0
  10. data/lib/backup/cloud_io/base.rb +41 -0
  11. data/lib/backup/cloud_io/cloud_files.rb +298 -0
  12. data/lib/backup/cloud_io/s3.rb +260 -0
  13. data/lib/backup/compressor/base.rb +35 -0
  14. data/lib/backup/compressor/bzip2.rb +39 -0
  15. data/lib/backup/compressor/custom.rb +53 -0
  16. data/lib/backup/compressor/gzip.rb +74 -0
  17. data/lib/backup/config.rb +119 -0
  18. data/lib/backup/config/dsl.rb +102 -0
  19. data/lib/backup/config/helpers.rb +143 -0
  20. data/lib/backup/database/base.rb +85 -0
  21. data/lib/backup/database/mongodb.rb +186 -0
  22. data/lib/backup/database/mysql.rb +123 -0
  23. data/lib/backup/database/postgresql.rb +133 -0
  24. data/lib/backup/database/redis.rb +179 -0
  25. data/lib/backup/database/riak.rb +82 -0
  26. data/lib/backup/encryptor/base.rb +29 -0
  27. data/lib/backup/encryptor/gpg.rb +747 -0
  28. data/lib/backup/encryptor/open_ssl.rb +72 -0
  29. data/lib/backup/errors.rb +58 -0
  30. data/lib/backup/logger.rb +199 -0
  31. data/lib/backup/logger/console.rb +51 -0
  32. data/lib/backup/logger/fog_adapter.rb +29 -0
  33. data/lib/backup/logger/logfile.rb +119 -0
  34. data/lib/backup/logger/syslog.rb +116 -0
  35. data/lib/backup/model.rb +454 -0
  36. data/lib/backup/notifier/base.rb +98 -0
  37. data/lib/backup/notifier/campfire.rb +69 -0
  38. data/lib/backup/notifier/hipchat.rb +93 -0
  39. data/lib/backup/notifier/http_post.rb +122 -0
  40. data/lib/backup/notifier/mail.rb +238 -0
  41. data/lib/backup/notifier/nagios.rb +69 -0
  42. data/lib/backup/notifier/prowl.rb +69 -0
  43. data/lib/backup/notifier/pushover.rb +80 -0
  44. data/lib/backup/notifier/slack.rb +149 -0
  45. data/lib/backup/notifier/twitter.rb +65 -0
  46. data/lib/backup/package.rb +51 -0
  47. data/lib/backup/packager.rb +101 -0
  48. data/lib/backup/pipeline.rb +124 -0
  49. data/lib/backup/splitter.rb +76 -0
  50. data/lib/backup/storage/base.rb +57 -0
  51. data/lib/backup/storage/cloud_files.rb +158 -0
  52. data/lib/backup/storage/cycler.rb +65 -0
  53. data/lib/backup/storage/dropbox.rb +236 -0
  54. data/lib/backup/storage/ftp.rb +98 -0
  55. data/lib/backup/storage/local.rb +64 -0
  56. data/lib/backup/storage/ninefold.rb +74 -0
  57. data/lib/backup/storage/rsync.rb +248 -0
  58. data/lib/backup/storage/s3.rb +154 -0
  59. data/lib/backup/storage/scp.rb +67 -0
  60. data/lib/backup/storage/sftp.rb +82 -0
  61. data/lib/backup/syncer/base.rb +70 -0
  62. data/lib/backup/syncer/cloud/base.rb +179 -0
  63. data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
  64. data/lib/backup/syncer/cloud/local_file.rb +100 -0
  65. data/lib/backup/syncer/cloud/s3.rb +110 -0
  66. data/lib/backup/syncer/rsync/base.rb +48 -0
  67. data/lib/backup/syncer/rsync/local.rb +31 -0
  68. data/lib/backup/syncer/rsync/pull.rb +51 -0
  69. data/lib/backup/syncer/rsync/push.rb +205 -0
  70. data/lib/backup/template.rb +46 -0
  71. data/lib/backup/utilities.rb +221 -0
  72. data/lib/backup/version.rb +5 -0
  73. data/templates/cli/archive +28 -0
  74. data/templates/cli/compressor/bzip2 +4 -0
  75. data/templates/cli/compressor/custom +7 -0
  76. data/templates/cli/compressor/gzip +4 -0
  77. data/templates/cli/config +123 -0
  78. data/templates/cli/databases/mongodb +15 -0
  79. data/templates/cli/databases/mysql +18 -0
  80. data/templates/cli/databases/postgresql +16 -0
  81. data/templates/cli/databases/redis +16 -0
  82. data/templates/cli/databases/riak +17 -0
  83. data/templates/cli/encryptor/gpg +27 -0
  84. data/templates/cli/encryptor/openssl +9 -0
  85. data/templates/cli/model +26 -0
  86. data/templates/cli/notifiers/campfire +12 -0
  87. data/templates/cli/notifiers/hipchat +15 -0
  88. data/templates/cli/notifiers/http_post +32 -0
  89. data/templates/cli/notifiers/mail +21 -0
  90. data/templates/cli/notifiers/nagios +13 -0
  91. data/templates/cli/notifiers/prowl +11 -0
  92. data/templates/cli/notifiers/pushover +11 -0
  93. data/templates/cli/notifiers/twitter +13 -0
  94. data/templates/cli/splitter +7 -0
  95. data/templates/cli/storages/cloud_files +11 -0
  96. data/templates/cli/storages/dropbox +19 -0
  97. data/templates/cli/storages/ftp +12 -0
  98. data/templates/cli/storages/local +7 -0
  99. data/templates/cli/storages/ninefold +9 -0
  100. data/templates/cli/storages/rsync +17 -0
  101. data/templates/cli/storages/s3 +14 -0
  102. data/templates/cli/storages/scp +14 -0
  103. data/templates/cli/storages/sftp +14 -0
  104. data/templates/cli/syncers/cloud_files +22 -0
  105. data/templates/cli/syncers/rsync_local +20 -0
  106. data/templates/cli/syncers/rsync_pull +28 -0
  107. data/templates/cli/syncers/rsync_push +28 -0
  108. data/templates/cli/syncers/s3 +27 -0
  109. data/templates/general/links +3 -0
  110. data/templates/general/version.erb +2 -0
  111. data/templates/notifier/mail/failure.erb +16 -0
  112. data/templates/notifier/mail/success.erb +16 -0
  113. data/templates/notifier/mail/warning.erb +16 -0
  114. data/templates/storage/dropbox/authorization_url.erb +6 -0
  115. data/templates/storage/dropbox/authorized.erb +4 -0
  116. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  117. metadata +688 -0
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Notifier
5
+ class Error < Backup::Error; end
6
+
7
+ class Base
8
+ include Utilities::Helpers
9
+ include Config::Helpers
10
+
11
+ ##
12
+ # When set to true, the user will be notified by email
13
+ # when a backup process ends without raising any exceptions
14
+ attr_accessor :on_success
15
+ alias :notify_on_success? :on_success
16
+
17
+ ##
18
+ # When set to true, the user will be notified by email
19
+ # when a backup process is successful, but has warnings
20
+ attr_accessor :on_warning
21
+ alias :notify_on_warning? :on_warning
22
+
23
+ ##
24
+ # When set to true, the user will be notified by email
25
+ # when a backup process raises an exception before finishing
26
+ attr_accessor :on_failure
27
+ alias :notify_on_failure? :on_failure
28
+
29
+ ##
30
+ # Number of times to retry failed attempts to send notification.
31
+ # Default: 10
32
+ attr_accessor :max_retries
33
+
34
+ ##
35
+ # Time in seconds to pause before each retry.
36
+ # Default: 30
37
+ attr_accessor :retry_waitsec
38
+
39
+ attr_reader :model
40
+
41
+ def initialize(model)
42
+ @model = model
43
+ load_defaults!
44
+
45
+ @on_success = true if on_success.nil?
46
+ @on_warning = true if on_warning.nil?
47
+ @on_failure = true if on_failure.nil?
48
+ @max_retries ||= 10
49
+ @retry_waitsec ||= 30
50
+ end
51
+
52
+ # This method is called from an ensure block in Model#perform! and must
53
+ # not raise any exceptions. However, each Notifier's #notify! method
54
+ # should raise an exception if the request fails so it may be retried.
55
+ def perform!
56
+ status = case model.exit_status
57
+ when 0
58
+ :success if notify_on_success?
59
+ when 1
60
+ :warning if notify_on_success? || notify_on_warning?
61
+ else
62
+ :failure if notify_on_failure?
63
+ end
64
+
65
+ if status
66
+ Logger.info "Sending notification using #{ notifier_name }..."
67
+ with_retries { notify!(status) }
68
+ end
69
+
70
+ rescue Exception => err
71
+ Logger.error Error.wrap(err, "#{ notifier_name } Failed!")
72
+ end
73
+
74
+ private
75
+
76
+ def with_retries
77
+ retries = 0
78
+ begin
79
+ yield
80
+ rescue StandardError, Timeout::Error => err
81
+ retries += 1
82
+ raise if retries > max_retries
83
+
84
+ Logger.info Error.wrap(err, "Retry ##{ retries } of #{ max_retries }.")
85
+ sleep(retry_waitsec)
86
+ retry
87
+ end
88
+ end
89
+
90
+ ##
91
+ # Return the notifier name, with Backup namespace removed
92
+ def notifier_name
93
+ self.class.to_s.sub('Backup::', '')
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+ require 'json'
3
+
4
+ module Backup
5
+ module Notifier
6
+ class Campfire < Base
7
+
8
+ ##
9
+ # Campfire api authentication token
10
+ attr_accessor :api_token
11
+
12
+ ##
13
+ # Campfire account's subdomain
14
+ attr_accessor :subdomain
15
+
16
+ ##
17
+ # Campfire account's room id
18
+ attr_accessor :room_id
19
+
20
+ def initialize(model, &block)
21
+ super
22
+ instance_eval(&block) if block_given?
23
+ end
24
+
25
+ private
26
+
27
+ ##
28
+ # Notify the user of the backup operation results.
29
+ #
30
+ # `status` indicates one of the following:
31
+ #
32
+ # `:success`
33
+ # : The backup completed successfully.
34
+ # : Notification will be sent if `on_success` is `true`.
35
+ #
36
+ # `:warning`
37
+ # : The backup completed successfully, but warnings were logged.
38
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
39
+ #
40
+ # `:failure`
41
+ # : The backup operation failed.
42
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
43
+ #
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)
52
+ end
53
+
54
+ def send_message(message)
55
+ uri = "https://#{ subdomain }.campfirenow.com/room/#{ room_id }/speak.json"
56
+ options = {
57
+ :headers => { 'Content-Type' => 'application/json' },
58
+ :body => JSON.dump(
59
+ { :message => { :body => message, :type => 'Textmessage' } }
60
+ )
61
+ }
62
+ options.merge!(:user => api_token, :password => 'x') # Basic Auth
63
+ options.merge!(:expects => 201) # raise error if unsuccessful
64
+ Excon.post(uri, options)
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ require 'hipchat'
3
+
4
+ module Backup
5
+ module Notifier
6
+ class Hipchat < Base
7
+
8
+ ##
9
+ # The Hipchat API token
10
+ attr_accessor :token
11
+
12
+ ##
13
+ # Who the notification should appear from
14
+ attr_accessor :from
15
+
16
+ ##
17
+ # The rooms that should be notified
18
+ attr_accessor :rooms_notified
19
+
20
+ ##
21
+ # Notify users in the room
22
+ attr_accessor :notify_users
23
+
24
+ ##
25
+ # The background color of a success message.
26
+ # One of :yellow, :red, :green, :purple, or :random. (default: yellow)
27
+ attr_accessor :success_color
28
+
29
+ ##
30
+ # The background color of a warning message.
31
+ # One of :yellow, :red, :green, :purple, or :random. (default: yellow)
32
+ attr_accessor :warning_color
33
+
34
+ ##
35
+ # The background color of an error message.
36
+ # One of :yellow, :red, :green, :purple, or :random. (default: yellow)
37
+ attr_accessor :failure_color
38
+
39
+ def initialize(model, &block)
40
+ super
41
+ instance_eval(&block) if block_given?
42
+
43
+ @notify_users ||= false
44
+ @rooms_notified ||= []
45
+ @success_color ||= 'yellow'
46
+ @warning_color ||= 'yellow'
47
+ @failure_color ||= 'yellow'
48
+ end
49
+
50
+ private
51
+
52
+ ##
53
+ # Notify the user of the backup operation results.
54
+ #
55
+ # `status` indicates one of the following:
56
+ #
57
+ # `:success`
58
+ # : The backup completed successfully.
59
+ # : Notification will be sent if `on_success` is `true`.
60
+ #
61
+ # `:warning`
62
+ # : The backup completed successfully, but warnings were logged.
63
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
64
+ #
65
+ # `:failure`
66
+ # : The backup operation failed.
67
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
68
+ #
69
+ 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)
77
+ end
78
+
79
+ # Hipchat::Client will raise an error if unsuccessful.
80
+ def send_message(msg, color)
81
+ client = HipChat::Client.new(token)
82
+ rooms_to_notify.each do |room|
83
+ client[room].send(from, msg, :color => color, :notify => notify_users)
84
+ end
85
+ end
86
+
87
+ def rooms_to_notify
88
+ Array(rooms_notified).map {|r| r.split(',').map(&:strip) }.flatten
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ require 'uri'
3
+
4
+ module Backup
5
+ module Notifier
6
+ class HttpPost < Base
7
+
8
+ ##
9
+ # URI to post notification to.
10
+ #
11
+ # URI scheme may be `http` or `https`.
12
+ #
13
+ # If Basic Authentication is needed, supply the `user:password` in the URI.
14
+ # e.g. 'https://user:pass@www.example.com/path'
15
+ #
16
+ # Port may also be supplied.
17
+ # e.g. 'http://www.example.com:8080/path'
18
+ attr_accessor :uri
19
+
20
+ ##
21
+ # Hash of additional HTTP headers to send.
22
+ #
23
+ # This notifier sets the following headers:
24
+ # { 'User-Agent' => "Backup/#{ Backup::VERSION }",
25
+ # 'Content-Type' => 'x-www-form-urlencoded' }
26
+ #
27
+ # 'Content-Type' may not be changed.
28
+ # 'User-Agent' may be overridden or omitted by setting it to +nil+.
29
+ # e.g. { 'Authorization' => 'my_auth_info', 'User-Agent' => nil }
30
+ attr_accessor :headers
31
+
32
+ ##
33
+ # Hash of additional POST parameters to send.
34
+ #
35
+ # This notifier will set two parameters:
36
+ # { 'status' => 'success|warning|failure',
37
+ # 'message' => '[Backup::(Success|Warning|Failure)] label (trigger)' }
38
+ #
39
+ # 'status' may not be changed.
40
+ # 'message' may be overridden or omitted by setting a +nil+ value.
41
+ # e.g. { 'auth_token' => 'my_token', 'message' => nil }
42
+ attr_accessor :params
43
+
44
+ ##
45
+ # Successful HTTP Status Code(s) that should be returned.
46
+ #
47
+ # This may be a single code or an Array of acceptable codes.
48
+ # e.g. [200, 201, 204]
49
+ #
50
+ # If any other response code is returned, the request will be retried
51
+ # using `max_retries` and `retry_waitsec`.
52
+ #
53
+ # Default: 200
54
+ attr_accessor :success_codes
55
+
56
+ ##
57
+ # Verify the server's certificate when using SSL.
58
+ #
59
+ # This will default to +true+ for most systems.
60
+ # It may be forced by setting to +true+, or disabled by setting to +false+.
61
+ attr_accessor :ssl_verify_peer
62
+
63
+ ##
64
+ # Path to a +cacert.pem+ file to use for +ssl_verify_peer+.
65
+ #
66
+ # This is provided (via Excon), but may be specified if needed.
67
+ attr_accessor :ssl_ca_file
68
+
69
+ def initialize(model, &block)
70
+ super
71
+ instance_eval(&block) if block_given?
72
+
73
+ @headers ||= {}
74
+ @params ||= {}
75
+ @success_codes ||= 200
76
+ end
77
+
78
+ private
79
+
80
+ ##
81
+ # Notify the user of the backup operation results.
82
+ #
83
+ # `status` indicates one of the following:
84
+ #
85
+ # `:success`
86
+ # : The backup completed successfully.
87
+ # : Notification will be sent if `on_success` is `true`.
88
+ #
89
+ # `:warning`
90
+ # : The backup completed successfully, but warnings were logged.
91
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
92
+ #
93
+ # `:failure`
94
+ # : The backup operation failed.
95
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
96
+ #
97
+ def notify!(status)
98
+ tag = case status
99
+ when :success then '[Backup::Success]'
100
+ when :failure then '[Backup::Failure]'
101
+ when :warning then '[Backup::Warning]'
102
+ end
103
+ message = "#{ tag } #{ model.label } (#{ model.trigger })"
104
+
105
+ opts = {
106
+ :headers => { 'User-Agent' => "Backup/#{ VERSION }" }.
107
+ merge(headers).reject {|k,v| v.nil? }.
108
+ merge('Content-Type' => 'application/x-www-form-urlencoded'),
109
+ :body => URI.encode_www_form({ 'message' => message }.
110
+ merge(params).reject {|k,v| v.nil? }.
111
+ merge('status' => status.to_s)),
112
+ :expects => success_codes # raise error if unsuccessful
113
+ }
114
+ opts.merge!(:ssl_verify_peer => ssl_verify_peer) unless ssl_verify_peer.nil?
115
+ opts.merge!(:ssl_ca_file => ssl_ca_file) if ssl_ca_file
116
+
117
+ Excon.post(uri, opts)
118
+ end
119
+
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,238 @@
1
+ # encoding: utf-8
2
+ require 'mail'
3
+
4
+ module Backup
5
+ module Notifier
6
+ class Mail < Base
7
+
8
+ ##
9
+ # Mail delivery method to be used by the Mail gem.
10
+ #
11
+ # Supported methods:
12
+ #
13
+ # [:smtp - ::Mail::SMTP (default)]
14
+ # Settings used by this method:
15
+ # {#address}, {#port}, {#domain}, {#user_name}, {#password},
16
+ # {#authentication}, {#encryption}, {#openssl_verify_mode}
17
+ #
18
+ # [:sendmail - ::Mail::Sendmail]
19
+ # Settings used by this method:
20
+ # {#sendmail_args}
21
+ #
22
+ # [:exim - ::Mail::Exim]
23
+ # Settings used by this method:
24
+ # {#exim_args}
25
+ #
26
+ # [:file - ::Mail::FileDelivery]
27
+ # Settings used by this method:
28
+ # {#mail_folder}
29
+ #
30
+ attr_accessor :delivery_method
31
+
32
+ ##
33
+ # Sender Email Address
34
+ attr_accessor :from
35
+
36
+ ##
37
+ # Receiver Email Address
38
+ attr_accessor :to
39
+
40
+ ##
41
+ # SMTP Server Address
42
+ attr_accessor :address
43
+
44
+ ##
45
+ # SMTP Server Port
46
+ attr_accessor :port
47
+
48
+ ##
49
+ # Your domain (if applicable)
50
+ attr_accessor :domain
51
+
52
+ ##
53
+ # SMTP Server Username (sender email's credentials)
54
+ attr_accessor :user_name
55
+
56
+ ##
57
+ # SMTP Server Password (sender email's credentials)
58
+ attr_accessor :password
59
+
60
+ ##
61
+ # Authentication type
62
+ #
63
+ # Acceptable values: +:plain+, +:login+, +:cram_md5+
64
+ attr_accessor :authentication
65
+
66
+ ##
67
+ # Set the method of encryption to be used for the +SMTP+ connection.
68
+ #
69
+ # [:starttls (default)]
70
+ # Use +STARTTLS+ to upgrade the connection to a +SSL/TLS+ connection.
71
+ #
72
+ # [:tls or :ssl]
73
+ # Use a +SSL/TLS+ connection.
74
+ #
75
+ # [:none]
76
+ # No encryption will be used.
77
+ attr_accessor :encryption
78
+
79
+ ##
80
+ # OpenSSL Verify Mode
81
+ #
82
+ # Valid modes: +:none+, +:peer+, +:client_once+, +:fail_if_no_peer_cert+
83
+ # See +OpenSSL::SSL+ for details.
84
+ #
85
+ # Use +:none+ for a self-signed and/or wildcard certificate
86
+ attr_accessor :openssl_verify_mode
87
+
88
+ ##
89
+ # Optional arguments to pass to `sendmail`
90
+ #
91
+ # Note that this will override the defaults set by the Mail gem
92
+ # (currently: '-i'). So, if set here, be sure to set all the arguments
93
+ # you require.
94
+ #
95
+ # Example: '-i -X/tmp/traffic.log'
96
+ attr_accessor :sendmail_args
97
+
98
+ ##
99
+ # Optional arguments to pass to `exim`
100
+ #
101
+ # Note that this will override the defaults set by the Mail gem
102
+ # (currently: '-i -t') So, if set here, be sure to set all the arguments
103
+ # you require.
104
+ #
105
+ # Example: '-i -t -X/tmp/traffic.log'
106
+ attr_accessor :exim_args
107
+
108
+ ##
109
+ # Folder where mail will be kept when using the `:file` `delivery_method`.
110
+ #
111
+ # Default location is '$HOME/Backup/emails'
112
+ attr_accessor :mail_folder
113
+
114
+ ##
115
+ # Array of statuses for which the log file should be attached.
116
+ #
117
+ # Available statuses are: `:success`, `:warning` and `:failure`.
118
+ # Default: [:warning, :failure]
119
+ attr_accessor :send_log_on
120
+
121
+ def initialize(model, &block)
122
+ super
123
+ instance_eval(&block) if block_given?
124
+
125
+ @send_log_on ||= [:warning, :failure]
126
+ @encryption ||= :starttls
127
+ end
128
+
129
+ private
130
+
131
+ ##
132
+ # Notify the user of the backup operation results.
133
+ #
134
+ # `status` indicates one of the following:
135
+ #
136
+ # `:success`
137
+ # : The backup completed successfully.
138
+ # : Notification will be sent if `on_success` is `true`.
139
+ #
140
+ # `:warning`
141
+ # : The backup completed successfully, but warnings were logged.
142
+ # : Notification will be sent, including a copy of the current
143
+ # : backup log, if `on_warning` or `on_success` is `true`.
144
+ #
145
+ # `:failure`
146
+ # : The backup operation failed.
147
+ # : Notification will be sent, including a copy of the current
148
+ # : backup log, if `on_failure` is `true`.
149
+ #
150
+ def notify!(status)
151
+ tag = case status
152
+ when :success then '[Backup::Success]'
153
+ when :warning then '[Backup::Warning]'
154
+ when :failure then '[Backup::Failure]'
155
+ end
156
+
157
+ email = new_email
158
+ email.subject = "#{ tag } #{ model.label } (#{ model.trigger })"
159
+
160
+ send_log = send_log_on.include?(status)
161
+ template = Backup::Template.new({ :model => model, :send_log => send_log })
162
+ email.body = template.result('notifier/mail/%s.erb' % status.to_s)
163
+
164
+ if send_log
165
+ email.convert_to_multipart
166
+ email.attachments["#{ model.time }.#{ model.trigger }.log"] = {
167
+ :mime_type => 'text/plain;',
168
+ :content => Logger.messages.map(&:formatted_lines).flatten.join("\n")
169
+ }
170
+ end
171
+
172
+ email.deliver! # raise error if unsuccessful
173
+ end
174
+
175
+ ##
176
+ # Configures the Mail gem by setting the defaults.
177
+ # Creates and returns a new email, based on the @delivery_method used.
178
+ def new_email
179
+ method = %w{ smtp sendmail exim file test }.
180
+ index(@delivery_method.to_s) ? @delivery_method.to_s : 'smtp'
181
+
182
+ options =
183
+ case method
184
+ when 'smtp'
185
+ { :address => @address,
186
+ :port => @port,
187
+ :domain => @domain,
188
+ :user_name => @user_name,
189
+ :password => @password,
190
+ :authentication => @authentication,
191
+ :enable_starttls_auto => @encryption == :starttls,
192
+ :openssl_verify_mode => @openssl_verify_mode,
193
+ :ssl => @encryption == :ssl,
194
+ :tls => @encryption == :tls
195
+ }
196
+ when 'sendmail'
197
+ opts = {}
198
+ opts.merge!(:location => utility(:sendmail))
199
+ opts.merge!(:arguments => @sendmail_args) if @sendmail_args
200
+ opts
201
+ when 'exim'
202
+ opts = {}
203
+ opts.merge!(:location => utility(:exim))
204
+ opts.merge!(:arguments => @exim_args) if @exim_args
205
+ opts
206
+ when 'file'
207
+ @mail_folder ||= File.join(Config.root_path, 'emails')
208
+ { :location => File.expand_path(@mail_folder) }
209
+ when 'test' then {}
210
+ end
211
+
212
+ ::Mail.defaults do
213
+ delivery_method method.to_sym, options
214
+ end
215
+
216
+ email = ::Mail.new
217
+ email.to = @to
218
+ email.from = @from
219
+ email
220
+ end
221
+
222
+ end
223
+ end
224
+ end
225
+
226
+ # Patch mail v2.5.4 Exim delivery method
227
+ # https://github.com/meskyanichi/backup/issues/446
228
+ # https://github.com/mikel/mail/pull/546
229
+ module Mail
230
+ class Exim
231
+ def self.call(path, arguments, destinations, encoded_message)
232
+ popen "#{path} #{arguments}" do |io|
233
+ io.puts encoded_message.to_lf
234
+ io.flush
235
+ end
236
+ end
237
+ end
238
+ end