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
data/lib/backup/cli.rb ADDED
@@ -0,0 +1,376 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Build the Backup Command Line Interface using Thor
5
+ module Backup
6
+ class CLI < Thor
7
+ class Error < Backup::Error; end
8
+ class FatalError < Backup::FatalError; end
9
+
10
+ ##
11
+ # [Perform]
12
+ #
13
+ # The only required option is the --trigger [-t].
14
+ # If --config-file, --data-path, --tmp-path or --log-path
15
+ # aren't specified they will fallback to defaults.
16
+ # If --root-path is given, it will be used as the base path for our
17
+ # defaults, as well as the base path for any option specified as
18
+ # a relative path.
19
+ # Any option given as an absolute path will be used "as-is".
20
+ #
21
+ # This command will exit with one of the following status codes:
22
+ #
23
+ # 0: All triggers were successful and no warnings were issued.
24
+ # 1: All triggers were successful, but some had warnings.
25
+ # 2: All triggers were processed, but some failed.
26
+ # 3: A fatal error caused Backup to exit.
27
+ # Some triggers may not have been processed.
28
+ #
29
+ # If the --check option is given, `backup check` will be run
30
+ # and no triggers will be performed.
31
+ desc "perform", "Performs the backup for the specified trigger(s)."
32
+
33
+ long_desc <<-EOS.gsub(%r{^ +}, "")
34
+ Performs the backup for the specified trigger(s).
35
+
36
+ You may perform multiple backups by providing multiple triggers,
37
+ separated by commas. Each will run in the order specified.
38
+
39
+ $ backup perform --triggers backup1,backup2,backup3,backup4
40
+
41
+ --root-path may be an absolute path or relative to the current directory.
42
+
43
+ To use the current directory, use: `--root-path .`
44
+
45
+ Relative paths given for --config-file, --data-path, --tmp-path,
46
+ and --log-path will be relative to --root-path.
47
+
48
+ Console log output may be forced using --no-quiet.
49
+
50
+ Logging to file or syslog may be disabled using --no-logfile or --no-syslog
51
+ respectively. This will override logging options set in `config.rb`.
52
+ EOS
53
+
54
+ method_option :trigger,
55
+ aliases: ["-t", "--triggers"],
56
+ required: true,
57
+ type: :string,
58
+ desc: "Triggers to perform. e.g. 'trigger_a,trigger_b'"
59
+
60
+ method_option :config_file,
61
+ aliases: "-c",
62
+ type: :string,
63
+ default: "",
64
+ desc: "Path to your config.rb file."
65
+
66
+ method_option :root_path,
67
+ aliases: "-r",
68
+ type: :string,
69
+ default: "",
70
+ desc: "Root path to base all relative path on."
71
+
72
+ method_option :data_path,
73
+ aliases: "-d",
74
+ type: :string,
75
+ default: "",
76
+ desc: "Path to store storage cycling data."
77
+
78
+ method_option :log_path,
79
+ aliases: "-l",
80
+ type: :string,
81
+ default: "",
82
+ desc: "Path to store Backup's log file."
83
+
84
+ method_option :tmp_path,
85
+ type: :string,
86
+ default: "",
87
+ desc: "Path to store temporary data during the backup."
88
+
89
+ # Note that :quiet, :syslog and :logfile are specified as :string types,
90
+ # so the --no-<option> usage will set the value to nil instead of false.
91
+ method_option :quiet,
92
+ aliases: "-q",
93
+ type: :boolean,
94
+ default: false,
95
+ banner: "",
96
+ desc: "Disable console log output."
97
+
98
+ method_option :syslog,
99
+ type: :boolean,
100
+ default: false,
101
+ banner: "",
102
+ desc: "Enable logging to syslog."
103
+
104
+ method_option :logfile,
105
+ type: :boolean,
106
+ default: true,
107
+ banner: "",
108
+ desc: "Enable Backup's log file."
109
+
110
+ method_option :check,
111
+ type: :boolean,
112
+ default: false,
113
+ desc: "Check configuration for errors or warnings."
114
+
115
+ # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
116
+ def perform
117
+ check if options[:check] # this will exit()
118
+
119
+ models = nil
120
+ begin
121
+ # Set logger options
122
+ opts = options
123
+ Logger.configure do
124
+ console.quiet = opts[:quiet]
125
+ logfile.enabled = opts[:logfile]
126
+ logfile.log_path = opts[:log_path]
127
+ syslog.enabled = opts[:syslog]
128
+ end
129
+
130
+ # Load the user's +config.rb+ file and all their Models
131
+ Config.load(options)
132
+
133
+ # Identify all Models to be run for the given +triggers+.
134
+ triggers = options[:trigger].split(",").map(&:strip)
135
+ models = triggers.uniq.flat_map do |trigger|
136
+ Model.find_by_trigger(trigger)
137
+ end
138
+
139
+ if models.empty?
140
+ raise Error, "No Models found for trigger(s) " \
141
+ "'#{triggers.join(",")}'."
142
+ end
143
+
144
+ # Finalize Logger and begin real-time logging.
145
+ Logger.start!
146
+ rescue Exception => err
147
+ Logger.error Error.wrap(err)
148
+ Logger.error err.backtrace.join("\n") unless Helpers.backup_error? err
149
+
150
+ # Logger configuration will be ignored
151
+ # and messages will be output to the console only.
152
+ Logger.abort!
153
+ exit 3
154
+ end
155
+
156
+ until models.empty?
157
+ model = models.shift
158
+ model.perform!
159
+
160
+ case model.exit_status
161
+ when 1
162
+ warnings = true
163
+ when 2
164
+ errors = true
165
+ unless models.empty?
166
+ Logger.info Error.new(<<-EOS)
167
+ Backup will now continue...
168
+ The following triggers will now be processed:
169
+ (#{models.map(&:trigger).join(", ")})
170
+ EOS
171
+ end
172
+ when 3
173
+ fatal = true
174
+ unless models.empty?
175
+ Logger.error FatalError.new(<<-EOS)
176
+ Backup will now exit.
177
+ The following triggers will not be processed:
178
+ (#{models.map(&:trigger).join(", ")})
179
+ EOS
180
+ end
181
+ end
182
+
183
+ model.notifiers.each(&:perform!)
184
+ exit(3) if fatal
185
+ Logger.clear!
186
+ end
187
+
188
+ exit(errors ? 2 : 1) if errors || warnings
189
+ end
190
+ # rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
191
+ ##
192
+ # [Check]
193
+ #
194
+ # Loads the user's `config.rb` (and all Model files) and reports any Errors
195
+ # or Warnings. This is primarily for checking for syntax errors, missing
196
+ # dependencies and deprecation warnings.
197
+ #
198
+ # This may also be invoked using the `--check` option to `backup perform`.
199
+ #
200
+ # This command only requires `Config.config_file` to be correct.
201
+ # All other Config paths are irrelevant.
202
+ #
203
+ # All output will be sent to the console only.
204
+ # Logger options will be ignored.
205
+ #
206
+ # If successful, this method with exit(0).
207
+ # If there are Errors or Warnings, it will exit(1).
208
+ desc "check", "Check for configuration errors or warnings"
209
+
210
+ long_desc <<-EOS.gsub(%r{^ +}, "")
211
+ Loads your 'config.rb' file and all models and reports any
212
+ errors or warnings with your configuration, including missing
213
+ dependencies and the use of any deprecated settings.
214
+ EOS
215
+
216
+ method_option :config_file,
217
+ aliases: "-c",
218
+ type: :string,
219
+ default: "",
220
+ desc: "Path to your config.rb file."
221
+
222
+ def check
223
+ begin
224
+ Config.load(options)
225
+ rescue Exception => err
226
+ Logger.error Error.wrap(err)
227
+ Logger.error err.backtrace.join("\n") unless Helpers.backup_error? err
228
+ end
229
+
230
+ if Logger.has_warnings? || Logger.has_errors?
231
+ Logger.error "Configuration Check Failed."
232
+ exit_code = 1
233
+ else
234
+ Logger.info "Configuration Check Succeeded."
235
+ exit_code = 0
236
+ end
237
+
238
+ Logger.abort!
239
+ exit(exit_code)
240
+ end
241
+
242
+ ##
243
+ # [Generate:Model]
244
+ # Generates a model configuration file based on the arguments passed in.
245
+ # For example:
246
+ # $ backup generate:model --trigger my_backup --databases='mongodb'
247
+ # will generate a pre-populated model with a base MongoDB setup
248
+ desc "generate:model", "Generates a Backup model file."
249
+
250
+ long_desc <<-EOS.gsub(%r{^ +}, "")
251
+ Generates a Backup model file.
252
+
253
+ If your configuration file is not in the default location at
254
+ #{Config.config_file}
255
+ you must specify it's location using '--config-file'.
256
+ If no configuration file exists at this location, one will be created.
257
+
258
+ The model file will be created as '<config_path>/models/<trigger>.rb'
259
+ Your model file will be created in a 'models/' sub-directory
260
+ where your config file is located. The default location would be:
261
+ #{Config.root_path}/models/<trigger>.rb
262
+ EOS
263
+
264
+ method_option :trigger,
265
+ aliases: "-t",
266
+ required: true,
267
+ type: :string,
268
+ desc: "Trigger name for the Backup model"
269
+
270
+ method_option :config_file,
271
+ type: :string,
272
+ desc: "Path to your Backup configuration file"
273
+
274
+ # options with their available values
275
+ %w[databases storages syncers encryptor compressor notifiers].each do |name|
276
+ path = File.join(Backup::TEMPLATE_PATH, "cli", name)
277
+ opts = Dir[path + "/*"].sort.map { |p| File.basename(p) }.join(", ")
278
+ method_option name, type: :string, desc: "(#{opts})"
279
+ end
280
+
281
+ method_option :archives,
282
+ type: :boolean,
283
+ desc: "Model will include tar archives."
284
+
285
+ method_option :splitter,
286
+ type: :boolean,
287
+ default: false,
288
+ desc: "Add Splitter to the model"
289
+
290
+ define_method "generate:model" do
291
+ opts = options.merge(trigger: options[:trigger].gsub(%r{\W}, "_"))
292
+ config_file = if opts[:config_file]
293
+ File.expand_path(opts.delete(:config_file))
294
+ else
295
+ Config.config_file
296
+ end
297
+ models_path = File.join(File.dirname(config_file), "models")
298
+ model_file = File.join(models_path, "#{opts[:trigger]}.rb")
299
+
300
+ unless File.exist?(config_file)
301
+ invoke "generate:config", [], config_file: config_file
302
+ end
303
+
304
+ FileUtils.mkdir_p(models_path)
305
+ if Helpers.overwrite?(model_file)
306
+ File.open(model_file, "w") do |file|
307
+ file.write(Backup::Template.new(options: opts).result("cli/model"))
308
+ end
309
+ puts "Generated model file: '#{model_file}'."
310
+ end
311
+ end
312
+
313
+ ##
314
+ # [Generate:Config]
315
+ # Generates the main configuration file
316
+ desc "generate:config", "Generates the main Backup configuration file"
317
+
318
+ long_desc <<-EOS.gsub(%r{^ +}, "")
319
+ Path to the Backup configuration file to generate.
320
+
321
+ Defaults to:
322
+
323
+ #{Config.config_file}
324
+ EOS
325
+
326
+ method_option :config_file,
327
+ type: :string,
328
+ desc: "Path to the Backup configuration file to generate."
329
+
330
+ define_method "generate:config" do
331
+ config_file = if options[:config_file]
332
+ File.expand_path(options[:config_file])
333
+ else
334
+ Config.config_file
335
+ end
336
+ FileUtils.mkdir_p(File.dirname(config_file))
337
+ if Helpers.overwrite?(config_file)
338
+ File.open(config_file, "w") do |file|
339
+ file.write(Backup::Template.new.result("cli/config"))
340
+ end
341
+ puts "Generated configuration file: '#{config_file}'."
342
+ end
343
+ end
344
+
345
+ ##
346
+ # [Version]
347
+ # Returns the current version of the Backup gem
348
+ map "-v" => :version
349
+ desc "version", "Display installed Backup version"
350
+ def version
351
+ puts "Backup #{Backup::VERSION}"
352
+ end
353
+
354
+ # This is to avoid Thor's warnings when stubbing methods on the Thor class.
355
+ module Helpers
356
+ class << self
357
+ def overwrite?(path)
358
+ return true unless File.exist?(path)
359
+
360
+ $stderr.print "A file already exists at '#{path}'.\n" \
361
+ "Do you want to overwrite? [y/n] "
362
+ %r{^[Yy]} =~ $stdin.gets
363
+ end
364
+
365
+ def exec!(cmd)
366
+ puts "Launching: #{cmd}"
367
+ exec(cmd)
368
+ end
369
+
370
+ def backup_error?(error)
371
+ error.class.ancestors.include? Backup::Error
372
+ end
373
+ end
374
+ end
375
+ end
376
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Backup
4
+ module CloudIO
5
+ class Error < Backup::Error; end
6
+ class FileSizeError < Backup::Error; end
7
+
8
+ class Base
9
+ attr_reader :max_retries, :retry_waitsec
10
+
11
+ def initialize(options = {})
12
+ @max_retries = options[:max_retries]
13
+ @retry_waitsec = options[:retry_waitsec]
14
+ end
15
+
16
+ private
17
+
18
+ def with_retries(operation)
19
+ retries = 0
20
+ begin
21
+ yield
22
+ rescue => err
23
+ retries += 1
24
+ raise Error.wrap(err, <<-EOS) if retries > max_retries
25
+ Max Retries (#{max_retries}) Exceeded!
26
+ Operation: #{operation}
27
+ Be sure to check the log messages for each retry attempt.
28
+ EOS
29
+
30
+ Logger.info Error.wrap(err, <<-EOS)
31
+ Retry ##{retries} of #{max_retries}
32
+ Operation: #{operation}
33
+ EOS
34
+ sleep(retry_waitsec)
35
+ retry
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end