backup_checksum 3.0.23

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 (244) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +28 -0
  4. data/Gemfile.lock +130 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.md +24 -0
  7. data/README.md +476 -0
  8. data/backup_checksum.gemspec +32 -0
  9. data/bin/backup +11 -0
  10. data/lib/backup.rb +217 -0
  11. data/lib/backup/archive.rb +117 -0
  12. data/lib/backup/binder.rb +22 -0
  13. data/lib/backup/checksum/base.rb +44 -0
  14. data/lib/backup/checksum/shasum.rb +16 -0
  15. data/lib/backup/cleaner.rb +121 -0
  16. data/lib/backup/cli/helpers.rb +88 -0
  17. data/lib/backup/cli/utility.rb +247 -0
  18. data/lib/backup/compressor/base.rb +29 -0
  19. data/lib/backup/compressor/bzip2.rb +50 -0
  20. data/lib/backup/compressor/gzip.rb +47 -0
  21. data/lib/backup/compressor/lzma.rb +50 -0
  22. data/lib/backup/compressor/pbzip2.rb +56 -0
  23. data/lib/backup/config.rb +173 -0
  24. data/lib/backup/configuration/base.rb +15 -0
  25. data/lib/backup/configuration/checksum/base.rb +9 -0
  26. data/lib/backup/configuration/checksum/shasum.rb +9 -0
  27. data/lib/backup/configuration/compressor/base.rb +9 -0
  28. data/lib/backup/configuration/compressor/bzip2.rb +23 -0
  29. data/lib/backup/configuration/compressor/gzip.rb +23 -0
  30. data/lib/backup/configuration/compressor/lzma.rb +23 -0
  31. data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
  32. data/lib/backup/configuration/database/base.rb +19 -0
  33. data/lib/backup/configuration/database/mongodb.rb +49 -0
  34. data/lib/backup/configuration/database/mysql.rb +42 -0
  35. data/lib/backup/configuration/database/postgresql.rb +41 -0
  36. data/lib/backup/configuration/database/redis.rb +39 -0
  37. data/lib/backup/configuration/database/riak.rb +29 -0
  38. data/lib/backup/configuration/encryptor/base.rb +9 -0
  39. data/lib/backup/configuration/encryptor/gpg.rb +17 -0
  40. data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
  41. data/lib/backup/configuration/helpers.rb +52 -0
  42. data/lib/backup/configuration/notifier/base.rb +28 -0
  43. data/lib/backup/configuration/notifier/campfire.rb +25 -0
  44. data/lib/backup/configuration/notifier/hipchat.rb +41 -0
  45. data/lib/backup/configuration/notifier/mail.rb +112 -0
  46. data/lib/backup/configuration/notifier/presently.rb +25 -0
  47. data/lib/backup/configuration/notifier/prowl.rb +23 -0
  48. data/lib/backup/configuration/notifier/twitter.rb +21 -0
  49. data/lib/backup/configuration/storage/base.rb +18 -0
  50. data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
  51. data/lib/backup/configuration/storage/dropbox.rb +58 -0
  52. data/lib/backup/configuration/storage/ftp.rb +29 -0
  53. data/lib/backup/configuration/storage/local.rb +17 -0
  54. data/lib/backup/configuration/storage/ninefold.rb +20 -0
  55. data/lib/backup/configuration/storage/rsync.rb +29 -0
  56. data/lib/backup/configuration/storage/s3.rb +25 -0
  57. data/lib/backup/configuration/storage/scp.rb +25 -0
  58. data/lib/backup/configuration/storage/sftp.rb +25 -0
  59. data/lib/backup/configuration/syncer/base.rb +10 -0
  60. data/lib/backup/configuration/syncer/cloud.rb +23 -0
  61. data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
  62. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  63. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  64. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  65. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  66. data/lib/backup/configuration/syncer/s3.rb +23 -0
  67. data/lib/backup/database/base.rb +59 -0
  68. data/lib/backup/database/mongodb.rb +232 -0
  69. data/lib/backup/database/mysql.rb +163 -0
  70. data/lib/backup/database/postgresql.rb +146 -0
  71. data/lib/backup/database/redis.rb +139 -0
  72. data/lib/backup/database/riak.rb +69 -0
  73. data/lib/backup/dependency.rb +114 -0
  74. data/lib/backup/encryptor/base.rb +29 -0
  75. data/lib/backup/encryptor/gpg.rb +80 -0
  76. data/lib/backup/encryptor/open_ssl.rb +72 -0
  77. data/lib/backup/errors.rb +124 -0
  78. data/lib/backup/logger.rb +152 -0
  79. data/lib/backup/model.rb +386 -0
  80. data/lib/backup/notifier/base.rb +81 -0
  81. data/lib/backup/notifier/campfire.rb +168 -0
  82. data/lib/backup/notifier/hipchat.rb +99 -0
  83. data/lib/backup/notifier/mail.rb +206 -0
  84. data/lib/backup/notifier/presently.rb +88 -0
  85. data/lib/backup/notifier/prowl.rb +65 -0
  86. data/lib/backup/notifier/twitter.rb +70 -0
  87. data/lib/backup/package.rb +51 -0
  88. data/lib/backup/packager.rb +108 -0
  89. data/lib/backup/pipeline.rb +107 -0
  90. data/lib/backup/splitter.rb +75 -0
  91. data/lib/backup/storage/base.rb +119 -0
  92. data/lib/backup/storage/cloudfiles.rb +87 -0
  93. data/lib/backup/storage/cycler.rb +117 -0
  94. data/lib/backup/storage/dropbox.rb +181 -0
  95. data/lib/backup/storage/ftp.rb +119 -0
  96. data/lib/backup/storage/local.rb +82 -0
  97. data/lib/backup/storage/ninefold.rb +116 -0
  98. data/lib/backup/storage/rsync.rb +149 -0
  99. data/lib/backup/storage/s3.rb +94 -0
  100. data/lib/backup/storage/scp.rb +99 -0
  101. data/lib/backup/storage/sftp.rb +108 -0
  102. data/lib/backup/syncer/base.rb +42 -0
  103. data/lib/backup/syncer/cloud.rb +190 -0
  104. data/lib/backup/syncer/cloud_files.rb +56 -0
  105. data/lib/backup/syncer/rsync/base.rb +52 -0
  106. data/lib/backup/syncer/rsync/local.rb +53 -0
  107. data/lib/backup/syncer/rsync/pull.rb +38 -0
  108. data/lib/backup/syncer/rsync/push.rb +113 -0
  109. data/lib/backup/syncer/s3.rb +47 -0
  110. data/lib/backup/template.rb +46 -0
  111. data/lib/backup/version.rb +43 -0
  112. data/spec/archive_spec.rb +335 -0
  113. data/spec/cleaner_spec.rb +304 -0
  114. data/spec/cli/helpers_spec.rb +176 -0
  115. data/spec/cli/utility_spec.rb +363 -0
  116. data/spec/compressor/base_spec.rb +31 -0
  117. data/spec/compressor/bzip2_spec.rb +83 -0
  118. data/spec/compressor/gzip_spec.rb +83 -0
  119. data/spec/compressor/lzma_spec.rb +83 -0
  120. data/spec/compressor/pbzip2_spec.rb +124 -0
  121. data/spec/config_spec.rb +321 -0
  122. data/spec/configuration/base_spec.rb +35 -0
  123. data/spec/configuration/compressor/bzip2_spec.rb +29 -0
  124. data/spec/configuration/compressor/gzip_spec.rb +29 -0
  125. data/spec/configuration/compressor/lzma_spec.rb +29 -0
  126. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  127. data/spec/configuration/database/base_spec.rb +17 -0
  128. data/spec/configuration/database/mongodb_spec.rb +56 -0
  129. data/spec/configuration/database/mysql_spec.rb +53 -0
  130. data/spec/configuration/database/postgresql_spec.rb +53 -0
  131. data/spec/configuration/database/redis_spec.rb +50 -0
  132. data/spec/configuration/database/riak_spec.rb +35 -0
  133. data/spec/configuration/encryptor/gpg_spec.rb +26 -0
  134. data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
  135. data/spec/configuration/notifier/base_spec.rb +32 -0
  136. data/spec/configuration/notifier/campfire_spec.rb +32 -0
  137. data/spec/configuration/notifier/hipchat_spec.rb +44 -0
  138. data/spec/configuration/notifier/mail_spec.rb +71 -0
  139. data/spec/configuration/notifier/presently_spec.rb +35 -0
  140. data/spec/configuration/notifier/prowl_spec.rb +29 -0
  141. data/spec/configuration/notifier/twitter_spec.rb +35 -0
  142. data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
  143. data/spec/configuration/storage/dropbox_spec.rb +38 -0
  144. data/spec/configuration/storage/ftp_spec.rb +44 -0
  145. data/spec/configuration/storage/local_spec.rb +29 -0
  146. data/spec/configuration/storage/ninefold_spec.rb +32 -0
  147. data/spec/configuration/storage/rsync_spec.rb +41 -0
  148. data/spec/configuration/storage/s3_spec.rb +38 -0
  149. data/spec/configuration/storage/scp_spec.rb +41 -0
  150. data/spec/configuration/storage/sftp_spec.rb +41 -0
  151. data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
  152. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  153. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  154. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  155. data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
  156. data/spec/configuration/syncer/s3_spec.rb +38 -0
  157. data/spec/database/base_spec.rb +54 -0
  158. data/spec/database/mongodb_spec.rb +428 -0
  159. data/spec/database/mysql_spec.rb +335 -0
  160. data/spec/database/postgresql_spec.rb +278 -0
  161. data/spec/database/redis_spec.rb +260 -0
  162. data/spec/database/riak_spec.rb +108 -0
  163. data/spec/dependency_spec.rb +49 -0
  164. data/spec/encryptor/base_spec.rb +30 -0
  165. data/spec/encryptor/gpg_spec.rb +134 -0
  166. data/spec/encryptor/open_ssl_spec.rb +129 -0
  167. data/spec/errors_spec.rb +306 -0
  168. data/spec/logger_spec.rb +363 -0
  169. data/spec/model_spec.rb +649 -0
  170. data/spec/notifier/base_spec.rb +89 -0
  171. data/spec/notifier/campfire_spec.rb +199 -0
  172. data/spec/notifier/hipchat_spec.rb +188 -0
  173. data/spec/notifier/mail_spec.rb +280 -0
  174. data/spec/notifier/presently_spec.rb +181 -0
  175. data/spec/notifier/prowl_spec.rb +117 -0
  176. data/spec/notifier/twitter_spec.rb +132 -0
  177. data/spec/package_spec.rb +61 -0
  178. data/spec/packager_spec.rb +225 -0
  179. data/spec/pipeline_spec.rb +257 -0
  180. data/spec/spec_helper.rb +59 -0
  181. data/spec/splitter_spec.rb +120 -0
  182. data/spec/storage/base_spec.rb +160 -0
  183. data/spec/storage/cloudfiles_spec.rb +230 -0
  184. data/spec/storage/cycler_spec.rb +239 -0
  185. data/spec/storage/dropbox_spec.rb +370 -0
  186. data/spec/storage/ftp_spec.rb +247 -0
  187. data/spec/storage/local_spec.rb +235 -0
  188. data/spec/storage/ninefold_spec.rb +319 -0
  189. data/spec/storage/rsync_spec.rb +345 -0
  190. data/spec/storage/s3_spec.rb +221 -0
  191. data/spec/storage/scp_spec.rb +209 -0
  192. data/spec/storage/sftp_spec.rb +220 -0
  193. data/spec/syncer/base_spec.rb +22 -0
  194. data/spec/syncer/cloud_files_spec.rb +192 -0
  195. data/spec/syncer/rsync/base_spec.rb +118 -0
  196. data/spec/syncer/rsync/local_spec.rb +121 -0
  197. data/spec/syncer/rsync/pull_spec.rb +90 -0
  198. data/spec/syncer/rsync/push_spec.rb +327 -0
  199. data/spec/syncer/s3_spec.rb +192 -0
  200. data/spec/version_spec.rb +21 -0
  201. data/templates/cli/utility/archive +25 -0
  202. data/templates/cli/utility/compressor/bzip2 +7 -0
  203. data/templates/cli/utility/compressor/gzip +7 -0
  204. data/templates/cli/utility/compressor/lzma +7 -0
  205. data/templates/cli/utility/compressor/pbzip2 +7 -0
  206. data/templates/cli/utility/config +31 -0
  207. data/templates/cli/utility/database/mongodb +18 -0
  208. data/templates/cli/utility/database/mysql +21 -0
  209. data/templates/cli/utility/database/postgresql +17 -0
  210. data/templates/cli/utility/database/redis +16 -0
  211. data/templates/cli/utility/database/riak +11 -0
  212. data/templates/cli/utility/encryptor/gpg +12 -0
  213. data/templates/cli/utility/encryptor/openssl +9 -0
  214. data/templates/cli/utility/model.erb +23 -0
  215. data/templates/cli/utility/notifier/campfire +12 -0
  216. data/templates/cli/utility/notifier/hipchat +15 -0
  217. data/templates/cli/utility/notifier/mail +22 -0
  218. data/templates/cli/utility/notifier/presently +13 -0
  219. data/templates/cli/utility/notifier/prowl +11 -0
  220. data/templates/cli/utility/notifier/twitter +13 -0
  221. data/templates/cli/utility/splitter +7 -0
  222. data/templates/cli/utility/storage/cloud_files +22 -0
  223. data/templates/cli/utility/storage/dropbox +20 -0
  224. data/templates/cli/utility/storage/ftp +12 -0
  225. data/templates/cli/utility/storage/local +7 -0
  226. data/templates/cli/utility/storage/ninefold +9 -0
  227. data/templates/cli/utility/storage/rsync +11 -0
  228. data/templates/cli/utility/storage/s3 +19 -0
  229. data/templates/cli/utility/storage/scp +11 -0
  230. data/templates/cli/utility/storage/sftp +11 -0
  231. data/templates/cli/utility/syncer/cloud_files +48 -0
  232. data/templates/cli/utility/syncer/rsync_local +12 -0
  233. data/templates/cli/utility/syncer/rsync_pull +17 -0
  234. data/templates/cli/utility/syncer/rsync_push +17 -0
  235. data/templates/cli/utility/syncer/s3 +45 -0
  236. data/templates/general/links +11 -0
  237. data/templates/general/version.erb +2 -0
  238. data/templates/notifier/mail/failure.erb +9 -0
  239. data/templates/notifier/mail/success.erb +7 -0
  240. data/templates/notifier/mail/warning.erb +9 -0
  241. data/templates/storage/dropbox/authorization_url.erb +6 -0
  242. data/templates/storage/dropbox/authorized.erb +4 -0
  243. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  244. metadata +311 -0
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Checksum
5
+ class Shasum < Base
6
+
7
+
8
+ def checksum_with(outfile)
9
+ log!
10
+ yield "shasum '#{outfile}' >> '#{outfile}.sum'"
11
+ end
12
+
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,121 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Cleaner
5
+ class << self
6
+
7
+ ##
8
+ # Logs warnings if any temporary files still exist
9
+ # from the last time this model/trigger was run,
10
+ # then removes the files.
11
+ def prepare(model)
12
+ @model = model
13
+
14
+ messages = []
15
+ if packaging_folder_dirty?
16
+ messages << <<-EOS
17
+ The temporary backup folder still contains files!
18
+ '#{ File.join(Config.tmp_path, @model.trigger) }'
19
+ These files will now be removed.
20
+ EOS
21
+ FileUtils.rm_rf(File.join(Config.tmp_path, @model.trigger))
22
+ end
23
+
24
+ package_files = tmp_path_package_files
25
+ unless package_files.empty?
26
+ # the chances that tmp_path would be dirty
27
+ # AND package files exist are practically nil
28
+ messages << ('-' * 74) unless messages.empty?
29
+
30
+ messages << <<-EOS
31
+ The temporary backup folder '#{ Config.tmp_path }'
32
+ appears to contain the package files from the previous backup!
33
+ #{ package_files.join("\n") }
34
+ These files will now be removed.
35
+ EOS
36
+ package_files.each {|file| FileUtils.rm_f(file) }
37
+ end
38
+
39
+ unless messages.empty?
40
+ Logger.warn Errors::CleanerError.new(<<-EOS)
41
+ Cleanup Warning
42
+ #{ messages.join("\n") }
43
+ Please check the log for messages and/or your notifications
44
+ concerning this backup: '#{ @model.label } (#{ @model.trigger })'
45
+ The temporary files which had to be removed should not have existed.
46
+ EOS
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Remove the temporary folder used during packaging
52
+ def remove_packaging(model)
53
+ Logger.message "Cleaning up the temporary files..."
54
+ FileUtils.rm_rf(File.join(Config.tmp_path, model.trigger))
55
+ end
56
+
57
+ ##
58
+ # Remove the final package files from tmp_path
59
+ # Note: 'force' is used, since a Local Storage may *move* these files.
60
+ def remove_package(package)
61
+ Logger.message "Cleaning up the package files..."
62
+ package.filenames.each do |file|
63
+ FileUtils.rm_f(File.join(Config.tmp_path, file))
64
+ end
65
+ end
66
+
67
+ ##
68
+ # Logs warnings if any temporary files still exist
69
+ # when errors occur during the backup
70
+ def warnings(model)
71
+ @model = model
72
+
73
+ messages = []
74
+ if packaging_folder_dirty?
75
+ messages << <<-EOS
76
+ The temporary backup folder still contains files!
77
+ '#{ File.join(Config.tmp_path, @model.trigger) }'
78
+ This folder may contain completed Archives and/or Database backups.
79
+ EOS
80
+ end
81
+
82
+ package_files = tmp_path_package_files
83
+ unless package_files.empty?
84
+ # the chances that tmp_path would be dirty
85
+ # AND package files exist are practically nil
86
+ messages << ('-' * 74) unless messages.empty?
87
+
88
+ messages << <<-EOS
89
+ The temporary backup folder '#{ Config.tmp_path }'
90
+ appears to contain the backup files which were to be stored:
91
+ #{ package_files.join("\n") }
92
+ EOS
93
+ end
94
+
95
+ unless messages.empty?
96
+ Logger.warn Errors::CleanerError.new(<<-EOS)
97
+ Cleanup Warning
98
+ #{ messages.join("\n") }
99
+ Make sure you check these files before the next scheduled backup for
100
+ '#{ @model.label } (#{ @model.trigger })'
101
+ These files will be removed at that time!
102
+ EOS
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def packaging_folder_dirty?
109
+ !Dir[File.join(Config.tmp_path, @model.trigger, '*')].empty?
110
+ end
111
+
112
+ def tmp_path_package_files
113
+ Dir[File.join(
114
+ Config.tmp_path,
115
+ "????.??.??.??.??.??.#{ @model.trigger }.tar{,[.-]*}"
116
+ )]
117
+ end
118
+
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module CLI
5
+ module Helpers
6
+ UTILITY = {}
7
+
8
+ ##
9
+ # Runs a given command in an isolated (sub) process using POpen4.
10
+ # The STDOUT, STDERR and the returned exit code of the utility will be stored in the process_data Hash.
11
+ #
12
+ # If a command returns an exit code other than 0, an exception will raise and the backup process will abort.
13
+ # Some utilities return exit codes other than 0 which aren't an issue in Backup's context. If this is the case,
14
+ # you can pass in an array of exit codes to ignore (whitelist), for example:
15
+ #
16
+ # run("tar -cf /output.tar /some/folder", :ignore_exit_codes => [1])
17
+ #
18
+ # So if the `tar` utility returns in this case 1, Backup will consider it an acceptable return code.
19
+ #
20
+ # Note: Exit code 0 is always automatically added to the :ignore_exit_codes array, regardless of whether you specify an
21
+ # array to ignore or not.
22
+ def run(command, options = {})
23
+ command.gsub!(/^\s+/, "")
24
+
25
+ process_data = Hash.new
26
+ pid, stdin, stdout, stderr = Open4::popen4(command)
27
+ ignored, process_data[:status] = Process::waitpid2(pid)
28
+ process_data[:stdout] = stdout.read
29
+ process_data[:stderr] = stderr.read
30
+ process_data[:ignore_exit_codes] = ((options[:ignore_exit_codes] || Array.new) << 0).uniq
31
+
32
+ raise_if_command_failed!(command_name(command), process_data)
33
+ process_data[:stdout]
34
+ end
35
+
36
+ ##
37
+ # Returns the full path to the specified utility.
38
+ # Raises an error if utility can not be found in the system's $PATH
39
+ def utility(name)
40
+ path = UTILITY[name] || %x[which #{name} 2>/dev/null].chomp
41
+ if path.empty?
42
+ raise Errors::CLI::UtilityNotFoundError, <<-EOS
43
+ Path to '#{ name }' could not be found.
44
+ Make sure the specified utility is installed
45
+ and available in your system's $PATH.
46
+ If this is a database utility, you may need to specify the full path
47
+ using the Database's '<utility_name>_utility' configuration setting.
48
+ EOS
49
+ end
50
+ UTILITY[name] = path
51
+ end
52
+
53
+ ##
54
+ # Returns the name of the command name from the given command line
55
+ def command_name(command)
56
+ i = command =~ /\s/
57
+ command = command.slice(0, i) if i
58
+ command.split('/')[-1]
59
+ end
60
+
61
+ ##
62
+ # Inspects the exit code returned from the POpen4 child process. If the exit code isn't listed
63
+ # in the process_data[:ignore_exit_codes] array, an exception will be raised, aborting the backup process.
64
+ #
65
+ # Information regarding the error ( EXIT CODE and STDERR ) will be returned to the shell so the user can
66
+ # investigate the issue.
67
+ #
68
+ # raises Backup::Errors::CLI::SystemCallError
69
+ def raise_if_command_failed!(utility, process_data)
70
+ unless process_data[:ignore_exit_codes].include?(process_data[:status].to_i)
71
+
72
+ stderr = process_data[:stderr].empty? ?
73
+ nil : "STDERR:\n#{process_data[:stderr]}\n"
74
+ stdout = process_data[:stdout].empty? ?
75
+ nil : "STDOUT:\n#{process_data[:stdout]}\n"
76
+
77
+ raise Errors::CLI::SystemCallError, <<-EOS
78
+ Failed to run #{utility} on #{RUBY_PLATFORM}
79
+ The following information should help to determine the problem:
80
+ Exit Code: #{process_data[:status]}
81
+ #{stderr}#{stdout}
82
+ EOS
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,247 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Build the Backup Command Line Interface using Thor
5
+ module Backup
6
+ module CLI
7
+ class Utility < Thor
8
+ include Thor::Actions
9
+
10
+ ##
11
+ # [Perform]
12
+ # Performs the backup process. The only required option is the --trigger [-t].
13
+ # If the other options (--config-file, --data-path, --cache--path, --tmp-path) aren't specified
14
+ # they will fallback to the (good) defaults
15
+ #
16
+ # If --root-path is given, it will be used as the base path for our defaults,
17
+ # as well as the base path for any option specified as a relative path.
18
+ # Any option given as an absolute path will be used "as-is".
19
+ method_option :trigger, :type => :string, :required => true, :aliases => ['-t', '--triggers']
20
+ method_option :config_file, :type => :string, :default => '', :aliases => '-c'
21
+ method_option :root_path, :type => :string, :default => '', :aliases => '-r'
22
+ method_option :data_path, :type => :string, :default => '', :aliases => '-d'
23
+ method_option :log_path, :type => :string, :default => '', :aliases => '-l'
24
+ method_option :cache_path, :type => :string, :default => ''
25
+ method_option :tmp_path, :type => :string, :default => ''
26
+ method_option :quiet, :type => :boolean, :default => false, :aliases => '-q'
27
+ desc 'perform', "Performs the backup for the specified trigger.\n" +
28
+ "You may perform multiple backups by providing multiple triggers, separated by commas.\n\n" +
29
+ "Example:\n\s\s$ backup perform --triggers backup1,backup2,backup3,backup4\n\n" +
30
+ "This will invoke 4 backups, and they will run in the order specified (not asynchronous)."
31
+ def perform
32
+ ##
33
+ # Silence Backup::Logger from printing to STDOUT, if --quiet was specified
34
+ Logger.quiet = options[:quiet]
35
+
36
+ ##
37
+ # Update Config variables based on the given options
38
+ Config.update(options)
39
+
40
+ ##
41
+ # Load the configuration file
42
+ Config.load_config!
43
+
44
+ ##
45
+ # Ensure the :log_path, :cache_path and :tmp_path are created
46
+ # if they do not yet exist
47
+ [Config.log_path, Config.cache_path, Config.tmp_path].each do |path|
48
+ FileUtils.mkdir_p(path)
49
+ end
50
+
51
+ ##
52
+ # Truncate log file if needed
53
+ Logger.truncate!
54
+
55
+ ##
56
+ # Prepare all trigger names by splitting them by ','
57
+ # and finding trigger names matching wildcard
58
+ triggers = options[:trigger].split(",")
59
+ triggers.map!(&:strip).map! {|t|
60
+ t.include?('*') ? Model.find_matching(t) : t
61
+ }.flatten!
62
+
63
+ ##
64
+ # Process each trigger
65
+ triggers.each do |trigger|
66
+ ##
67
+ # Find the model for this trigger
68
+ # Will raise an error if not found
69
+ model = Model.find(trigger)
70
+
71
+ ##
72
+ # Prepare and Perform the backup
73
+ model.prepare!
74
+ model.perform!
75
+
76
+ ##
77
+ # Clear the Log Messages for the next potential run
78
+ Logger.clear!
79
+ end
80
+
81
+ rescue => err
82
+ Logger.error Errors::CLIError.wrap(err)
83
+ exit(1)
84
+ end
85
+
86
+ ##
87
+ # [Generate:Model]
88
+ # Generates a model configuration file based on the arguments passed in.
89
+ # For example:
90
+ # $ backup generate:model --trigger my_backup --databases='mongodb'
91
+ # will generate a pre-populated model with a base MongoDB setup
92
+ desc 'generate:model', "Generates a Backup model file\n\n" +
93
+ "Note:\n" +
94
+ "\s\s'--config-path' is the path to the directory where 'config.rb' is located.\n" +
95
+ "\s\sThe model file will be created as '<config_path>/models/<trigger>.rb'\n" +
96
+ "\s\sDefault: #{Config.root_path}\n"
97
+
98
+ method_option :trigger, :type => :string, :required => true
99
+ method_option :config_path, :type => :string,
100
+ :desc => 'Path to your Backup configuration directory'
101
+
102
+ # options with their available values
103
+ %w{ databases storages syncers
104
+ encryptors compressors notifiers }.map(&:to_sym).each do |name|
105
+ path = File.join(Backup::TEMPLATE_PATH, 'cli', 'utility', name.to_s[0..-2])
106
+ method_option name, :type => :string, :desc =>
107
+ "(#{Dir[path + '/*'].sort.map {|p| File.basename(p) }.join(', ')})"
108
+ end
109
+
110
+ method_option :archives, :type => :boolean
111
+ method_option :splitter, :type => :boolean, :default => true,
112
+ :desc => "use `--no-splitter` to disable"
113
+
114
+ define_method "generate:model" do
115
+ opts = options.merge(
116
+ :trigger => options[:trigger].gsub(/[\W\s]/, '_'),
117
+ :config_path => options[:config_path] ?
118
+ File.expand_path(options[:config_path]) : nil
119
+ )
120
+ config_path = opts[:config_path] || Config.root_path
121
+ models_path = File.join(config_path, "models")
122
+ config = File.join(config_path, "config.rb")
123
+ model = File.join(models_path, "#{opts[:trigger]}.rb")
124
+
125
+ FileUtils.mkdir_p(models_path)
126
+ if overwrite?(model)
127
+ File.open(model, 'w') do |file|
128
+ file.write(Backup::Template.new({:options => opts}).
129
+ result("cli/utility/model.erb"))
130
+ end
131
+ puts "Generated model file: '#{ model }'."
132
+ end
133
+
134
+ if not File.exist?(config)
135
+ File.open(config, "w") do |file|
136
+ file.write(Backup::Template.new.result("cli/utility/config"))
137
+ end
138
+ puts "Generated configuration file: '#{ config }'."
139
+ end
140
+ end
141
+
142
+ ##
143
+ # [Generate:Config]
144
+ # Generates the main configuration file
145
+ desc 'generate:config', 'Generates the main Backup bootstrap/configuration file'
146
+ method_option :config_path, :type => :string,
147
+ :desc => 'Path to your Backup configuration directory'
148
+ define_method 'generate:config' do
149
+ config_path = options[:config_path] ?
150
+ File.expand_path(options[:config_path]) : Config.root_path
151
+ config = File.join(config_path, "config.rb")
152
+
153
+ FileUtils.mkdir_p(config_path)
154
+ if overwrite?(config)
155
+ File.open(config, "w") do |file|
156
+ file.write(Backup::Template.new.result("cli/utility/config"))
157
+ end
158
+ puts "Generated configuration file: '#{ config }'."
159
+ end
160
+ end
161
+
162
+ ##
163
+ # [Decrypt]
164
+ # Shorthand for decrypting encrypted files
165
+ desc 'decrypt', 'Decrypts encrypted files'
166
+ method_option :encryptor, :type => :string, :required => true
167
+ method_option :in, :type => :string, :required => true
168
+ method_option :out, :type => :string, :required => true
169
+ method_option :base64, :type => :boolean, :default => false
170
+ method_option :password_file, :type => :string, :default => ''
171
+ method_option :salt, :type => :boolean, :default => false
172
+ def decrypt
173
+ case options[:encryptor].downcase
174
+ when 'openssl'
175
+ base64 = options[:base64] ? '-base64' : ''
176
+ password = options[:password_file] ? "-pass file:#{options[:password_file]}" : ''
177
+ salt = options[:salt] ? '-salt' : ''
178
+ %x[openssl aes-256-cbc -d #{base64} #{password} #{salt} -in '#{options[:in]}' -out '#{options[:out]}']
179
+ when 'gpg'
180
+ %x[gpg -o '#{options[:out]}' -d '#{options[:in]}']
181
+ else
182
+ puts "Unknown encryptor: #{options[:encryptor]}"
183
+ puts "Use either 'openssl' or 'gpg'."
184
+ end
185
+ end
186
+
187
+ ##
188
+ # [Dependencies]
189
+ # Returns a list of Backup's dependencies
190
+ desc 'dependencies', 'Display the list of dependencies for Backup, or install them through Backup.'
191
+ method_option :install, :type => :string
192
+ method_option :list, :type => :boolean
193
+ def dependencies
194
+ unless options.any?
195
+ puts
196
+ puts "To display a list of available dependencies, run:\n\n"
197
+ puts " backup dependencies --list"
198
+ puts
199
+ puts "To install one of these dependencies (with the correct version), run:\n\n"
200
+ puts " backup dependencies --install <name>"
201
+ exit
202
+ end
203
+
204
+ if options[:list]
205
+ Backup::Dependency.all.each do |name, gemspec|
206
+ puts
207
+ puts name
208
+ puts "--------------------------------------------------"
209
+ puts "version: #{gemspec[:version]}"
210
+ puts "lib required: #{gemspec[:require]}"
211
+ puts "used for: #{gemspec[:for]}"
212
+ end
213
+ end
214
+
215
+ if options[:install]
216
+ puts
217
+ puts "Installing \"#{options[:install]}\" version \"#{Backup::Dependency.all[options[:install]][:version]}\".."
218
+ puts "If this doesn't work, please issue the following command yourself:\n\n"
219
+ puts " gem install #{options[:install]} -v '#{Backup::Dependency.all[options[:install]][:version]}'\n\n"
220
+ puts "Please wait..\n\n"
221
+ puts %x[gem install #{options[:install]} -v '#{Backup::Dependency.all[options[:install]][:version]}']
222
+ end
223
+ end
224
+
225
+ ##
226
+ # [Version]
227
+ # Returns the current version of the Backup gem
228
+ map '-v' => :version
229
+ desc 'version', 'Display installed Backup version'
230
+ def version
231
+ puts "Backup #{Backup::Version.current}"
232
+ end
233
+
234
+ private
235
+
236
+ ##
237
+ # Helper method for asking the user if he/she wants to overwrite the file
238
+ def overwrite?(path)
239
+ if File.exist?(path)
240
+ return yes? "A file already exists at '#{ path }'. Do you want to overwrite? [y/n]"
241
+ end
242
+ true
243
+ end
244
+
245
+ end
246
+ end
247
+ end