backupii 0.1.0.pre.alpha.1

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 (135) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +19 -0
  3. data/README.md +37 -0
  4. data/bin/backupii +5 -0
  5. data/bin/docker_test +24 -0
  6. data/lib/backup/archive.rb +171 -0
  7. data/lib/backup/binder.rb +23 -0
  8. data/lib/backup/cleaner.rb +114 -0
  9. data/lib/backup/cli.rb +376 -0
  10. data/lib/backup/cloud_io/base.rb +40 -0
  11. data/lib/backup/cloud_io/cloud_files.rb +301 -0
  12. data/lib/backup/cloud_io/s3.rb +256 -0
  13. data/lib/backup/compressor/base.rb +34 -0
  14. data/lib/backup/compressor/bzip2.rb +37 -0
  15. data/lib/backup/compressor/custom.rb +51 -0
  16. data/lib/backup/compressor/gzip.rb +76 -0
  17. data/lib/backup/config/dsl.rb +103 -0
  18. data/lib/backup/config/helpers.rb +139 -0
  19. data/lib/backup/config.rb +122 -0
  20. data/lib/backup/database/base.rb +89 -0
  21. data/lib/backup/database/mongodb.rb +189 -0
  22. data/lib/backup/database/mysql.rb +194 -0
  23. data/lib/backup/database/openldap.rb +97 -0
  24. data/lib/backup/database/postgresql.rb +134 -0
  25. data/lib/backup/database/redis.rb +179 -0
  26. data/lib/backup/database/riak.rb +82 -0
  27. data/lib/backup/database/sqlite.rb +57 -0
  28. data/lib/backup/encryptor/base.rb +29 -0
  29. data/lib/backup/encryptor/gpg.rb +745 -0
  30. data/lib/backup/encryptor/open_ssl.rb +76 -0
  31. data/lib/backup/errors.rb +55 -0
  32. data/lib/backup/logger/console.rb +50 -0
  33. data/lib/backup/logger/fog_adapter.rb +27 -0
  34. data/lib/backup/logger/logfile.rb +134 -0
  35. data/lib/backup/logger/syslog.rb +116 -0
  36. data/lib/backup/logger.rb +199 -0
  37. data/lib/backup/model.rb +478 -0
  38. data/lib/backup/notifier/base.rb +128 -0
  39. data/lib/backup/notifier/campfire.rb +63 -0
  40. data/lib/backup/notifier/command.rb +101 -0
  41. data/lib/backup/notifier/datadog.rb +107 -0
  42. data/lib/backup/notifier/flowdock.rb +101 -0
  43. data/lib/backup/notifier/hipchat.rb +118 -0
  44. data/lib/backup/notifier/http_post.rb +116 -0
  45. data/lib/backup/notifier/mail.rb +235 -0
  46. data/lib/backup/notifier/nagios.rb +67 -0
  47. data/lib/backup/notifier/pagerduty.rb +82 -0
  48. data/lib/backup/notifier/prowl.rb +70 -0
  49. data/lib/backup/notifier/pushover.rb +73 -0
  50. data/lib/backup/notifier/ses.rb +126 -0
  51. data/lib/backup/notifier/slack.rb +149 -0
  52. data/lib/backup/notifier/twitter.rb +57 -0
  53. data/lib/backup/notifier/zabbix.rb +62 -0
  54. data/lib/backup/package.rb +53 -0
  55. data/lib/backup/packager.rb +108 -0
  56. data/lib/backup/pipeline.rb +122 -0
  57. data/lib/backup/splitter.rb +75 -0
  58. data/lib/backup/storage/base.rb +72 -0
  59. data/lib/backup/storage/cloud_files.rb +158 -0
  60. data/lib/backup/storage/cycler.rb +73 -0
  61. data/lib/backup/storage/dropbox.rb +208 -0
  62. data/lib/backup/storage/ftp.rb +118 -0
  63. data/lib/backup/storage/local.rb +63 -0
  64. data/lib/backup/storage/qiniu.rb +68 -0
  65. data/lib/backup/storage/rsync.rb +251 -0
  66. data/lib/backup/storage/s3.rb +157 -0
  67. data/lib/backup/storage/scp.rb +67 -0
  68. data/lib/backup/storage/sftp.rb +82 -0
  69. data/lib/backup/syncer/base.rb +70 -0
  70. data/lib/backup/syncer/cloud/base.rb +180 -0
  71. data/lib/backup/syncer/cloud/cloud_files.rb +83 -0
  72. data/lib/backup/syncer/cloud/local_file.rb +99 -0
  73. data/lib/backup/syncer/cloud/s3.rb +118 -0
  74. data/lib/backup/syncer/rsync/base.rb +55 -0
  75. data/lib/backup/syncer/rsync/local.rb +29 -0
  76. data/lib/backup/syncer/rsync/pull.rb +49 -0
  77. data/lib/backup/syncer/rsync/push.rb +206 -0
  78. data/lib/backup/template.rb +45 -0
  79. data/lib/backup/utilities.rb +235 -0
  80. data/lib/backup/version.rb +5 -0
  81. data/lib/backup.rb +141 -0
  82. data/templates/cli/archive +28 -0
  83. data/templates/cli/compressor/bzip2 +4 -0
  84. data/templates/cli/compressor/custom +7 -0
  85. data/templates/cli/compressor/gzip +4 -0
  86. data/templates/cli/config +123 -0
  87. data/templates/cli/databases/mongodb +15 -0
  88. data/templates/cli/databases/mysql +18 -0
  89. data/templates/cli/databases/openldap +24 -0
  90. data/templates/cli/databases/postgresql +16 -0
  91. data/templates/cli/databases/redis +16 -0
  92. data/templates/cli/databases/riak +17 -0
  93. data/templates/cli/databases/sqlite +11 -0
  94. data/templates/cli/encryptor/gpg +27 -0
  95. data/templates/cli/encryptor/openssl +9 -0
  96. data/templates/cli/model +26 -0
  97. data/templates/cli/notifier/zabbix +15 -0
  98. data/templates/cli/notifiers/campfire +12 -0
  99. data/templates/cli/notifiers/command +32 -0
  100. data/templates/cli/notifiers/datadog +57 -0
  101. data/templates/cli/notifiers/flowdock +16 -0
  102. data/templates/cli/notifiers/hipchat +16 -0
  103. data/templates/cli/notifiers/http_post +32 -0
  104. data/templates/cli/notifiers/mail +24 -0
  105. data/templates/cli/notifiers/nagios +13 -0
  106. data/templates/cli/notifiers/pagerduty +12 -0
  107. data/templates/cli/notifiers/prowl +11 -0
  108. data/templates/cli/notifiers/pushover +11 -0
  109. data/templates/cli/notifiers/ses +15 -0
  110. data/templates/cli/notifiers/slack +22 -0
  111. data/templates/cli/notifiers/twitter +13 -0
  112. data/templates/cli/splitter +7 -0
  113. data/templates/cli/storages/cloud_files +11 -0
  114. data/templates/cli/storages/dropbox +20 -0
  115. data/templates/cli/storages/ftp +13 -0
  116. data/templates/cli/storages/local +8 -0
  117. data/templates/cli/storages/qiniu +12 -0
  118. data/templates/cli/storages/rsync +17 -0
  119. data/templates/cli/storages/s3 +16 -0
  120. data/templates/cli/storages/scp +15 -0
  121. data/templates/cli/storages/sftp +15 -0
  122. data/templates/cli/syncers/cloud_files +22 -0
  123. data/templates/cli/syncers/rsync_local +20 -0
  124. data/templates/cli/syncers/rsync_pull +28 -0
  125. data/templates/cli/syncers/rsync_push +28 -0
  126. data/templates/cli/syncers/s3 +27 -0
  127. data/templates/general/links +3 -0
  128. data/templates/general/version.erb +2 -0
  129. data/templates/notifier/mail/failure.erb +16 -0
  130. data/templates/notifier/mail/success.erb +16 -0
  131. data/templates/notifier/mail/warning.erb +16 -0
  132. data/templates/storage/dropbox/authorization_url.erb +6 -0
  133. data/templates/storage/dropbox/authorized.erb +4 -0
  134. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  135. metadata +507 -0
@@ -0,0 +1,235 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mail"
4
+
5
+ module Backup
6
+ module Notifier
7
+ class Mail < Base
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
+ # CC receiver Email Address
42
+ attr_accessor :cc
43
+
44
+ ##
45
+ # BCC receiver Email Address
46
+ attr_accessor :bcc
47
+
48
+ ##
49
+ # Set reply to email address
50
+ attr_accessor :reply_to
51
+
52
+ ##
53
+ # SMTP Server Address
54
+ attr_accessor :address
55
+
56
+ ##
57
+ # SMTP Server Port
58
+ attr_accessor :port
59
+
60
+ ##
61
+ # Your domain (if applicable)
62
+ attr_accessor :domain
63
+
64
+ ##
65
+ # SMTP Server Username (sender email's credentials)
66
+ attr_accessor :user_name
67
+
68
+ ##
69
+ # SMTP Server Password (sender email's credentials)
70
+ attr_accessor :password
71
+
72
+ ##
73
+ # Authentication type
74
+ #
75
+ # Acceptable values: +:plain+, +:login+, +:cram_md5+
76
+ attr_accessor :authentication
77
+
78
+ ##
79
+ # Set the method of encryption to be used for the +SMTP+ connection.
80
+ #
81
+ # [:starttls (default)]
82
+ # Use +STARTTLS+ to upgrade the connection to a +SSL/TLS+ connection.
83
+ #
84
+ # [:tls or :ssl]
85
+ # Use a +SSL/TLS+ connection.
86
+ #
87
+ # [:none]
88
+ # No encryption will be used.
89
+ attr_accessor :encryption
90
+
91
+ ##
92
+ # OpenSSL Verify Mode
93
+ #
94
+ # Valid modes: +:none+, +:peer+, +:client_once+, +:fail_if_no_peer_cert+
95
+ # See +OpenSSL::SSL+ for details.
96
+ #
97
+ # Use +:none+ for a self-signed and/or wildcard certificate
98
+ attr_accessor :openssl_verify_mode
99
+
100
+ ##
101
+ # Optional arguments to pass to `sendmail`
102
+ #
103
+ # Note that this will override the defaults set by the Mail gem
104
+ # (currently: '-i'). So, if set here, be sure to set all the arguments
105
+ # you require.
106
+ #
107
+ # Example: '-i -X/tmp/traffic.log'
108
+ attr_accessor :sendmail_args
109
+
110
+ ##
111
+ # Optional arguments to pass to `exim`
112
+ #
113
+ # Note that this will override the defaults set by the Mail gem
114
+ # (currently: '-i -t') So, if set here, be sure to set all the arguments
115
+ # you require.
116
+ #
117
+ # Example: '-i -t -X/tmp/traffic.log'
118
+ attr_accessor :exim_args
119
+
120
+ ##
121
+ # Folder where mail will be kept when using the `:file` `delivery_method`.
122
+ #
123
+ # Default location is '$HOME/Backup/emails'
124
+ attr_accessor :mail_folder
125
+
126
+ ##
127
+ # Array of statuses for which the log file should be attached.
128
+ #
129
+ # Available statuses are: `:success`, `:warning` and `:failure`.
130
+ # Default: [:warning, :failure]
131
+ attr_accessor :send_log_on
132
+
133
+ def initialize(model, &block)
134
+ super
135
+ instance_eval(&block) if block_given?
136
+
137
+ @send_log_on ||= [:warning, :failure]
138
+ @encryption ||= :starttls
139
+ end
140
+
141
+ private
142
+
143
+ ##
144
+ # Notify the user of the backup operation results.
145
+ #
146
+ # `status` indicates one of the following:
147
+ #
148
+ # `:success`
149
+ # : The backup completed successfully.
150
+ # : Notification will be sent if `on_success` is `true`.
151
+ #
152
+ # `:warning`
153
+ # : The backup completed successfully, but warnings were logged.
154
+ # : Notification will be sent, including a copy of the current
155
+ # : backup log, if `on_warning` or `on_success` is `true`.
156
+ #
157
+ # `:failure`
158
+ # : The backup operation failed.
159
+ # : Notification will be sent, including a copy of the current
160
+ # : backup log, if `on_failure` is `true`.
161
+ #
162
+ def notify!(status)
163
+ email = new_email
164
+ email.subject = message.call(model, status: status_data_for(status))
165
+
166
+ send_log = send_log_on.include?(status)
167
+ template = Backup::Template.new(model: model, send_log: send_log)
168
+ email.body = template.result(sprintf("notifier/mail/%s.erb",
169
+ status.to_s))
170
+
171
+ if send_log
172
+ email.convert_to_multipart
173
+ email.attachments["#{model.time}.#{model.trigger}.log"] = {
174
+ mime_type: "text/plain;",
175
+ content: Logger.messages.map(&:formatted_lines).flatten.join("\n")
176
+ }
177
+ end
178
+
179
+ email.deliver! # raise error if unsuccessful
180
+ end
181
+
182
+ ##
183
+ # Configures the Mail gem by setting the defaults.
184
+ # Creates and returns a new email, based on the @delivery_method used.
185
+ def new_email
186
+ method = %w[smtp sendmail exim file test]
187
+ .index(@delivery_method.to_s) ? @delivery_method.to_s : "smtp"
188
+
189
+ options =
190
+ case method
191
+ when "smtp"
192
+ opts = {
193
+ address: @address,
194
+ port: @port,
195
+ user_name: @user_name,
196
+ password: @password,
197
+ authentication: @authentication,
198
+ enable_starttls_auto: @encryption == :starttls,
199
+ openssl_verify_mode: @openssl_verify_mode,
200
+ ssl: @encryption == :ssl,
201
+ tls: @encryption == :tls
202
+ }
203
+
204
+ # Don't override default domain setting if domain not applicable.
205
+ # ref https://github.com/mikel/mail/blob/2.6.3/lib/mail/network/delivery_methods/smtp.rb#L82
206
+ opts[:domain] = @domain if @domain
207
+ opts
208
+ when "sendmail"
209
+ opts = {}
210
+ opts[:location] = utility(:sendmail)
211
+ opts[:arguments] = @sendmail_args if @sendmail_args
212
+ opts
213
+ when "exim"
214
+ opts = {}
215
+ opts[:location] = utility(:exim)
216
+ opts[:arguments] = @exim_args if @exim_args
217
+ opts
218
+ when "file"
219
+ @mail_folder ||= File.join(Config.root_path, "emails")
220
+ { location: File.expand_path(@mail_folder) }
221
+ when "test" then {}
222
+ end
223
+
224
+ email = ::Mail.new
225
+ email.delivery_method method.to_sym, options
226
+ email.to = to
227
+ email.from = from
228
+ email.cc = cc
229
+ email.bcc = bcc
230
+ email.reply_to = reply_to
231
+ email
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Backup
4
+ module Notifier
5
+ class Nagios < Base
6
+ ##
7
+ # Host of Nagios server to notify on backup completion.
8
+ attr_accessor :nagios_host
9
+
10
+ ##
11
+ # Port of Nagios server to notify on backup completion.
12
+ attr_accessor :nagios_port
13
+
14
+ ##
15
+ # Nagios nrpe configuration file.
16
+ attr_accessor :send_nsca_cfg
17
+
18
+ ##
19
+ # Name of the Nagios service for the backup check.
20
+ attr_accessor :service_name
21
+
22
+ ##
23
+ # Host name in Nagios for the backup check.
24
+ attr_accessor :service_host
25
+
26
+ def initialize(model, &block)
27
+ super
28
+ instance_eval(&block) if block_given?
29
+
30
+ @nagios_host ||= Config.hostname
31
+ @nagios_port ||= 5667
32
+ @send_nsca_cfg ||= "/etc/nagios/send_nsca.cfg"
33
+ @service_name ||= "Backup #{model.trigger}"
34
+ @service_host ||= Config.hostname
35
+ end
36
+
37
+ private
38
+
39
+ ##
40
+ # Notify the user of the backup operation results.
41
+ #
42
+ # `status` indicates one of the following:
43
+ #
44
+ # `:success`
45
+ # : The backup completed successfully.
46
+ # : Notification will be sent if `on_success` is `true`.
47
+ #
48
+ # `:warning`
49
+ # : The backup completed successfully, but warnings were logged.
50
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
51
+ #
52
+ # `:failure`
53
+ # : The backup operation failed.
54
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
55
+ #
56
+ def notify!(status)
57
+ send_message(message.call(model, status: status_data_for(status)))
58
+ end
59
+
60
+ def send_message(message)
61
+ cmd = "#{utility(:send_nsca)} -H '#{nagios_host}' -p '#{nagios_port}' -c '#{send_nsca_cfg}'"
62
+ msg = [service_host, service_name, model.exit_status, message].join("\t")
63
+ run("echo '#{msg}' | #{cmd}")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pagerduty"
4
+
5
+ module Backup
6
+ module Notifier
7
+ class PagerDuty < Base
8
+ ##
9
+ # PagerDuty Service API Key. Should be a 32 character hex string.
10
+ attr_accessor :service_key
11
+
12
+ ##
13
+ # Determines if a backup with a warning should resolve an incident rather
14
+ # than trigger one.
15
+ #
16
+ # Defaults to false.
17
+ attr_accessor :resolve_on_warning
18
+
19
+ def initialize(mode, &block)
20
+ super
21
+ instance_eval(&block) if block_given?
22
+
23
+ @resolve_on_warning ||= false
24
+ end
25
+
26
+ private
27
+
28
+ ##
29
+ # Trigger or resolve a PagerDuty incident for this model
30
+ #
31
+ # `status` indicates one of the following:
32
+ #
33
+ # `:success`
34
+ # : The backup completed successfully.
35
+ # : The incident will be resolved if `on_success` is `true`.
36
+ #
37
+ # `:warning`
38
+ # : The backup completed successfully, but warnings were logged.
39
+ # : An incident will be triggered if `on_warning` or `on_success`
40
+ # is `true`.
41
+ #
42
+ # `:failure`
43
+ # : The backup operation failed.
44
+ # : An incident will be triggered if `on_failure` is `true`.
45
+ #
46
+ def notify!(status)
47
+ incident_description = "Backup - #{model.label}"
48
+ incident_key = "backup/#{model.trigger}"
49
+ incident_details = {
50
+ incident_key: incident_key,
51
+ details: {
52
+ trigger: model.trigger,
53
+ label: model.label,
54
+ started_at: model.started_at,
55
+ finished_at: model.finished_at,
56
+ duration: model.duration,
57
+ status: status,
58
+ exception: model.exception
59
+ }
60
+ }
61
+
62
+ event_type = case status
63
+ when :success then :resolve
64
+ when :warning then resolve_on_warning ? :resolve : :trigger
65
+ when :failure then :trigger
66
+ end
67
+
68
+ case event_type
69
+ when :trigger
70
+ pagerduty.trigger(incident_description, incident_details)
71
+ when :resolve
72
+ incident = pagerduty.get_incident(incident_key)
73
+ incident.resolve(incident_description, incident_details)
74
+ end
75
+ end
76
+
77
+ def pagerduty
78
+ @pagerduty ||= Pagerduty.new(service_key)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Backup
6
+ module Notifier
7
+ class Prowl < Base
8
+ ##
9
+ # Application name
10
+ # Tell something like your server name. Example: "Server1 Backup"
11
+ attr_accessor :application
12
+
13
+ ##
14
+ # API-Key
15
+ # Create a Prowl account and request an API key on prowlapp.com.
16
+ attr_accessor :api_key
17
+
18
+ def initialize(model, &block)
19
+ @message =
20
+ lambda do |m, _|
21
+ "#{m.label} (#{m.trigger})"
22
+ end
23
+
24
+ super
25
+
26
+ instance_eval(&block) if block_given?
27
+ end
28
+
29
+ private
30
+
31
+ ##
32
+ # Notify the user of the backup operation results.
33
+ #
34
+ # `status` indicates one of the following:
35
+ #
36
+ # `:success`
37
+ # : The backup completed successfully.
38
+ # : Notification will be sent if `on_success` is `true`.
39
+ #
40
+ # `:warning`
41
+ # : The backup completed successfully, but warnings were logged.
42
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
43
+ #
44
+ # `:failure`
45
+ # : The backup operation failed.
46
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
47
+ #
48
+ def notify!(status)
49
+ send_message(status)
50
+ end
51
+
52
+ def send_message(status)
53
+ uri = "https://api.prowlapp.com/publicapi/add"
54
+ status_data = status_data_for(status)
55
+ data = {
56
+ application: application,
57
+ apikey: api_key,
58
+ event: status_data[:message],
59
+ description: message.call(model, status: status_data)
60
+ }
61
+ options = {
62
+ headers: { "Content-Type" => "application/x-www-form-urlencoded" },
63
+ body: URI.encode_www_form(data)
64
+ }
65
+ options[:expects] = 200 # raise error if unsuccessful
66
+ Excon.post(uri, options)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Backup
6
+ module Notifier
7
+ class Pushover < Base
8
+ ##
9
+ # The API User Token
10
+ attr_accessor :user
11
+
12
+ ##
13
+ # The API Application Token
14
+ attr_accessor :token
15
+
16
+ ##
17
+ # The user's device identifier to sent the message directly to,
18
+ # rather than all of the user's devices
19
+ attr_accessor :device
20
+
21
+ ##
22
+ # The message title
23
+ attr_accessor :title
24
+
25
+ ##
26
+ # The priority of the notification
27
+ attr_accessor :priority
28
+
29
+ def initialize(model, &block)
30
+ super
31
+ instance_eval(&block) if block_given?
32
+ end
33
+
34
+ private
35
+
36
+ ##
37
+ # Notify the user of the backup operation results.
38
+ #
39
+ # `status` indicates one of the following:
40
+ #
41
+ # `:success`
42
+ # : The backup completed successfully.
43
+ # : Notification will be sent if `on_success` is `true`.
44
+ #
45
+ # `:warning`
46
+ # : The backup completed successfully, but warnings were logged.
47
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
48
+ #
49
+ # `:failure`
50
+ # : The backup operation failed.
51
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
52
+ #
53
+ def notify!(status)
54
+ send_message(message.call(model, status: status_data_for(status)))
55
+ end
56
+
57
+ def send_message(message)
58
+ uri = "https://api.pushover.net/1/messages.json"
59
+ data = { user: user, token: token, message: message }
60
+ [:device, :title, :priority].each do |param|
61
+ val = send(param)
62
+ data.merge!(param => val) if val
63
+ end
64
+ options = {
65
+ headers: { "Content-Type" => "application/x-www-form-urlencoded" },
66
+ body: URI.encode_www_form(data)
67
+ }
68
+ options[:expects] = 200 # raise error if unsuccessful
69
+ Excon.post(uri, options)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "aws-sdk"
4
+ require "mail"
5
+
6
+ module Backup
7
+ module Notifier
8
+ class Ses < Base
9
+ ##
10
+ # Amazon Simple Email Service (SES) Credentials
11
+ attr_accessor :access_key_id, :secret_access_key, :use_iam_profile
12
+
13
+ ##
14
+ # SES Region
15
+ attr_accessor :region
16
+
17
+ ##
18
+ # Sender Email Address
19
+ attr_accessor :from
20
+
21
+ ##
22
+ # Receiver Email Address
23
+ attr_accessor :to
24
+
25
+ ##
26
+ # CC receiver Email Address
27
+ attr_accessor :cc
28
+
29
+ ##
30
+ # BCC receiver Email Address
31
+ attr_accessor :bcc
32
+
33
+ ##
34
+ # Set reply to email address
35
+ attr_accessor :reply_to
36
+
37
+ def initialize(model, &block)
38
+ super
39
+ instance_eval(&block) if block_given?
40
+
41
+ @region ||= "eu-west-1"
42
+ @send_log_on ||= [:warning, :failure]
43
+ end
44
+
45
+ ##
46
+ # Array of statuses for which the log file should be attached.
47
+ #
48
+ # Available statuses are: `:success`, `:warning` and `:failure`.
49
+ # Default: [:warning, :failure]
50
+ attr_accessor :send_log_on
51
+
52
+ private
53
+
54
+ def client
55
+ credentials = if use_iam_profile
56
+ Aws::InstanceProfileCredentials.new
57
+ else
58
+ Aws::Credentials.new(access_key_id, secret_access_key)
59
+ end
60
+
61
+ Aws::SES::Client.new(
62
+ region: region,
63
+ credentials: credentials
64
+ )
65
+ end
66
+
67
+ ##
68
+ # Notify the user of the backup operation results.
69
+ #
70
+ # `status` indicates one of the following:
71
+ #
72
+ # `:success`
73
+ # : The backup completed successfully.
74
+ # : Notification will be sent if `on_success` is `true`.
75
+ #
76
+ # `:warning`
77
+ # : The backup completed successfully, but warnings were logged.
78
+ # : Notification will be sent, including a copy of the current
79
+ # : backup log, if `on_warning` or `on_success` is `true`.
80
+ #
81
+ # `:failure`
82
+ # : The backup operation failed.
83
+ # : Notification will be sent, including a copy of the current
84
+ # : backup log, if `on_failure` is `true`.
85
+ #
86
+ def notify!(status)
87
+ email = ::Mail.new
88
+ email.to = to
89
+ email.from = from
90
+ email.cc = cc
91
+ email.bcc = bcc
92
+ email.reply_to = reply_to
93
+ email.subject = message.call(model, status: status_data_for(status))
94
+
95
+ # By default, the `mail` gem doesn't include BCC in raw output, which is
96
+ # needed for SES to send to those addresses.
97
+ email[:bcc].include_in_headers = true
98
+
99
+ send_log = send_log_on.include?(status)
100
+ template = Backup::Template.new(model: model, send_log: send_log)
101
+ email.body = template.result(sprintf("notifier/mail/%s.erb",
102
+ status.to_s))
103
+
104
+ if send_log
105
+ email.convert_to_multipart
106
+ email.attachments["#{model.time}.#{model.trigger}.log"] = {
107
+ mime_type: "text/plain;",
108
+ content: Logger.messages.map(&:formatted_lines).flatten.join("\n")
109
+ }
110
+ end
111
+
112
+ send_opts = {
113
+ raw_message: {
114
+ data: email.to_s
115
+ }
116
+ }
117
+
118
+ if email.respond_to?(:destinations)
119
+ send_opts[:destinations] = email.destinations
120
+ end
121
+
122
+ client.send_raw_email(send_opts)
123
+ end
124
+ end
125
+ end
126
+ end