backup 3.0.20 → 3.0.21

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 (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. data/spec/syncer/rsync_spec.rb +0 -195
@@ -3,8 +3,7 @@
3
3
  module Backup
4
4
  module Configuration
5
5
  module Compressor
6
- class Base < Backup::Configuration::Base
7
- end
6
+ class Base < Configuration::Base; end
8
7
  end
9
8
  end
10
9
  end
@@ -16,10 +16,10 @@ module Backup
16
16
  # faster (-1) (but not significantly faster)
17
17
  attr_accessor :fast
18
18
 
19
- ##
20
- # Tells Backup::Compressor::Pbzip2 how many processors
21
- # use, by default autodetect is used
22
- attr_writer :processors
19
+ ##
20
+ # Tells Backup::Compressor::Pbzip2 how many processors
21
+ # use, by default autodetect is used
22
+ attr_accessor :processors
23
23
 
24
24
  end
25
25
  end
@@ -3,12 +3,13 @@
3
3
  module Backup
4
4
  module Configuration
5
5
  module Database
6
- class Base < Backup::Configuration::Base
6
+ class Base < Configuration::Base
7
7
  class << self
8
8
 
9
9
  ##
10
10
  # Allows the user to specify the path to a "dump" utility
11
11
  # in case it cannot be auto-detected by Backup
12
+ # [DEPRECATED] - use <utility_name>_utility methods
12
13
  attr_accessor :utility_path
13
14
 
14
15
  end
@@ -30,6 +30,14 @@ module Backup
30
30
  # Additional "mongodump" options
31
31
  attr_accessor :additional_options
32
32
 
33
+ ##
34
+ # Path to the mongodump utility (optional)
35
+ attr_accessor :mongodump_utility
36
+
37
+ ##
38
+ # Path to the mongo utility (optional)
39
+ attr_accessor :mongo_utility
40
+
33
41
  ##
34
42
  # 'lock' dump meaning wrapping mongodump with fsync & lock
35
43
  attr_accessor :lock
@@ -30,6 +30,10 @@ module Backup
30
30
  # Additional "mysqldump" options
31
31
  attr_accessor :additional_options
32
32
 
33
+ ##
34
+ # Path to mysqldump utility (optional)
35
+ attr_accessor :mysqldump_utility
36
+
33
37
  end
34
38
  end
35
39
  end
@@ -30,6 +30,10 @@ module Backup
30
30
  # Additional "pg_dump" options
31
31
  attr_accessor :additional_options
32
32
 
33
+ ##
34
+ # Path to pg_dump utility (optional)
35
+ attr_accessor :pg_dump_utility
36
+
33
37
  end
34
38
  end
35
39
  end
@@ -28,6 +28,10 @@ module Backup
28
28
  # Additional "redis-cli" options
29
29
  attr_accessor :additional_options
30
30
 
31
+ ##
32
+ # Path to the redis-cli utility (optional)
33
+ attr_accessor :redis_cli_utility
34
+
31
35
  end
32
36
  end
33
37
  end
@@ -18,8 +18,12 @@ module Backup
18
18
  # Cookie is the Erlang cookie/shared secret used to connect to the node.
19
19
  attr_accessor :cookie
20
20
 
21
+ ##
22
+ # Path to riak-admin utility (optional)
23
+ attr_accessor :riak_admin_utility
24
+
21
25
  end
22
26
  end
23
27
  end
24
28
  end
25
- end
29
+ end
@@ -3,8 +3,7 @@
3
3
  module Backup
4
4
  module Configuration
5
5
  module Encryptor
6
- class Base < Backup::Configuration::Base
7
- end
6
+ class Base < Configuration::Base; end
8
7
  end
9
8
  end
10
9
  end
@@ -10,7 +10,7 @@ module Backup
10
10
  # The password that'll be used to encrypt the backup. This
11
11
  # password will be required to decrypt the backup later on.
12
12
  attr_accessor :password
13
-
13
+
14
14
  ##
15
15
  # The password file used for encrypting the backup. This
16
16
  # password file will be required to decrypt the backup later
@@ -9,8 +9,11 @@ module Backup
9
9
  # configuration for these methods, if they respond then they will
10
10
  # assign the object's attribute(s) to that particular global configuration's attribute
11
11
  def load_defaults!
12
- c = self.class.name.split('::')
13
- configuration = Backup::Configuration.const_get(c[1]).const_get(c[2])
12
+ module_names = self.class.name.split('::')[1..-1]
13
+ configuration = Backup::Configuration
14
+ module_names.each do |module_name|
15
+ configuration = configuration.const_get(module_name)
16
+ end
14
17
 
15
18
  getter_methods.each do |attribute|
16
19
  if configuration.respond_to?(attribute)
@@ -27,6 +30,8 @@ module Backup
27
30
  end
28
31
  end
29
32
 
33
+ private
34
+
30
35
  ##
31
36
  # Returns an Array of the setter methods (as String)
32
37
  def setter_methods
@@ -3,49 +3,25 @@
3
3
  module Backup
4
4
  module Configuration
5
5
  module Notifier
6
- class Base < Backup::Configuration::Base
6
+ class Base < Configuration::Base
7
7
  class << self
8
8
 
9
9
  ##
10
10
  # When set to true, the user will be notified by email
11
11
  # when a backup process ends without raising any exceptions
12
- attr_writer :on_success
12
+ attr_accessor :on_success
13
13
 
14
14
  ##
15
15
  # When set to true, the user will be notified by email
16
16
  # when a backup process ends successfully, but logged warnings
17
- attr_writer :on_warning
17
+ attr_accessor :on_warning
18
18
 
19
19
  ##
20
20
  # When set to true, the user will be notified by email
21
21
  # when a backup process raises an exception before finishing
22
- attr_writer :on_failure
22
+ attr_accessor :on_failure
23
23
 
24
24
  end
25
-
26
- ##
27
- # When @on_success is nil it means it hasn't been defined
28
- # and will then default to true
29
- def self.on_success
30
- return true if @on_success.nil?
31
- @on_success
32
- end
33
-
34
- ##
35
- # When @on_success is nil it means it hasn't been defined
36
- # and will then default to true
37
- def self.on_warning
38
- return true if @on_warning.nil?
39
- @on_warning
40
- end
41
-
42
- ##
43
- # When @on_failure is nil it means it hasn't been defined
44
- # and will then default to true
45
- def self.on_failure
46
- return true if @on_failure.nil?
47
- @on_failure
48
- end
49
25
  end
50
26
  end
51
27
  end
@@ -3,7 +3,7 @@
3
3
  module Backup
4
4
  module Configuration
5
5
  module Storage
6
- class Base < Backup::Configuration::Base
6
+ class Base < Configuration::Base
7
7
  class << self
8
8
 
9
9
  ##
@@ -11,16 +11,26 @@ module Backup
11
11
  attr_accessor :api_key, :api_secret
12
12
 
13
13
  ##
14
- # Path to where the backups will be stored
15
- attr_accessor :path
14
+ # Dropbox Access Type
15
+ # Valid values are:
16
+ # :app_folder (default)
17
+ # :dropbox (full access)
18
+ attr_accessor :access_type
16
19
 
17
20
  ##
18
- # Dropbox connection timeout
19
- attr_accessor :timeout
21
+ # Path to where the backups will be stored
22
+ attr_accessor :path
20
23
 
21
24
 
22
25
  # DEPRECATED METHODS #############################################
23
26
 
27
+ # Deprecated as of v3.0.21 - for move to official 'dropbox-sdk' gem (v1.1)
28
+ attr_reader :timeout
29
+ def timeout=(value)
30
+ Logger.warn "[DEPRECATED] Backup::Configuration::Storage::Dropbox.timeout=\n" +
31
+ " is deprecated and will be removed at some point."
32
+ end
33
+
24
34
  def email
25
35
  Logger.warn "[DEPRECATED] Backup::Configuration::Storage::Dropbox.email\n" +
26
36
  " is deprecated and will be removed at some point."
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Configuration
5
+ module Syncer
6
+ class Base < Configuration::Base; end
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Configuration
5
+ module Syncer
6
+ module RSync
7
+ class Base < Syncer::Base
8
+ class << self
9
+
10
+ ##
11
+ # Path to store the synced files/directories to
12
+ attr_accessor :path
13
+
14
+ ##
15
+ # Flag for mirroring the files/directories
16
+ attr_accessor :mirror
17
+
18
+ ##
19
+ # Additional options for the rsync cli
20
+ attr_accessor :additional_options
21
+
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Configuration
5
+ module Syncer
6
+ module RSync
7
+ class Local < Base; end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Configuration
5
+ module Syncer
6
+ module RSync
7
+ class Pull < Push; end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Configuration
5
+ module Syncer
6
+ module RSync
7
+ class Push < Base
8
+ class << self
9
+
10
+ ##
11
+ # Server credentials
12
+ attr_accessor :username, :password
13
+
14
+ ##
15
+ # Server IP Address and SSH port
16
+ attr_accessor :ip
17
+
18
+ ##
19
+ # The SSH port to connect to
20
+ attr_accessor :port
21
+
22
+ ##
23
+ # Flag for compressing (only compresses for the transfer)
24
+ attr_accessor :compress
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -14,10 +14,6 @@ module Backup
14
14
  # Amazon S3 bucket name and path to sync to
15
15
  attr_accessor :bucket, :path
16
16
 
17
- ##
18
- # Directories to sync
19
- attr_accessor :directories
20
-
21
17
  ##
22
18
  # Flag to enable mirroring
23
19
  attr_accessor :mirror
@@ -6,15 +6,20 @@ module Backup
6
6
  include Backup::CLI::Helpers
7
7
  include Backup::Configuration::Helpers
8
8
 
9
- ##
10
- # Contains the path to where the database should be dumped
11
- attr_accessor :dump_path
12
-
13
9
  ##
14
10
  # Allows the user to specify the path to a "dump" utility
15
11
  # in case it cannot be auto-detected by Backup
12
+ # [DEPRECATED] - use each subclass' <utility_name>_utility method
16
13
  attr_accessor :utility_path
17
14
 
15
+ ##
16
+ # Creates a new instance of the MongoDB database object
17
+ # * Called using super(model) from subclasses *
18
+ def initialize(model)
19
+ @model = model
20
+ load_defaults!
21
+ end
22
+
18
23
  ##
19
24
  # Super method for all child (database) objects. Every database object's #perform!
20
25
  # method should call #super before anything else to prepare
@@ -23,18 +28,31 @@ module Backup
23
28
  log!
24
29
  end
25
30
 
31
+ private
32
+
26
33
  ##
27
34
  # Defines the @dump_path and ensures it exists by creating it
28
35
  def prepare!
29
- @dump_path = File.join(TMP_PATH, TRIGGER, self.class.name.split('::').last)
30
- mkdir(dump_path)
36
+ @dump_path = File.join(
37
+ Config.tmp_path,
38
+ @model.trigger,
39
+ 'databases',
40
+ self.class.name.split('::').last
41
+ )
42
+ FileUtils.mkdir_p(@dump_path)
43
+ end
44
+
45
+ ##
46
+ # Return the database name, with Backup namespace removed
47
+ def database_name
48
+ self.class.to_s.sub('Backup::', '')
31
49
  end
32
50
 
33
51
  ##
34
52
  # Logs a message to the console and log file to inform
35
53
  # the client that Backup is dumping the database
36
54
  def log!
37
- Logger.message "#{self.class} started dumping and archiving '#{ name }'."
55
+ Logger.message "#{ database_name } started dumping and archiving '#{ name }'."
38
56
  end
39
57
  end
40
58
  end
@@ -28,123 +28,153 @@ module Backup
28
28
  # Additional "mongodump" options
29
29
  attr_accessor :additional_options
30
30
 
31
+ ##
32
+ # Path to the mongodump utility (optional)
33
+ attr_accessor :mongodump_utility
34
+
35
+ ##
36
+ # Path to the mongo utility (optional)
37
+ attr_accessor :mongo_utility
38
+
31
39
  ##
32
40
  # 'lock' dump meaning wrapping mongodump with fsync & lock
33
41
  attr_accessor :lock
34
42
 
35
43
  ##
36
44
  # Creates a new instance of the MongoDB database object
37
- def initialize(&block)
38
- load_defaults!
45
+ def initialize(model, &block)
46
+ super(model)
39
47
 
40
48
  @only_collections ||= Array.new
41
49
  @additional_options ||= Array.new
42
50
  @ipv6 ||= false
43
51
  @lock ||= false
44
52
 
45
- instance_eval(&block)
46
- end
53
+ instance_eval(&block) if block_given?
47
54
 
48
- ##
49
- # Builds the MongoDB credentials syntax to authenticate the user
50
- # to perform the database dumping process
51
- def credential_options
52
- %w[username password].map do |option|
53
- next if send(option).nil? or send(option).empty?
54
- "--#{option}='#{send(option)}'"
55
- end.compact.join("\s")
55
+ if @utility_path
56
+ Logger.warn "[DEPRECATED] " +
57
+ "Database::MongoDB#utility_path has been deprecated.\n" +
58
+ " Use Database::MongoDB#mongodump_utility instead."
59
+ @mongodump_utility ||= @utility_path
60
+ end
61
+ @mongodump_utility ||= utility(:mongodump)
62
+ @mongo_utility ||= utility(:mongo)
56
63
  end
57
64
 
58
65
  ##
59
- # Builds the MongoDB connectivity options syntax to connect the user
60
- # to perform the database dumping process
61
- def connectivity_options
62
- %w[host port].map do |option|
63
- next if send(option).nil? or (send(option).respond_to?(:empty?) and send(option).empty?)
64
- "--#{option}='#{send(option)}'"
65
- end.compact.join("\s")
66
+ # Performs the mongodump command and outputs the data to the
67
+ # specified path based on the 'trigger'. If the user hasn't specified any
68
+ # specific collections to dump, it'll dump everything. If the user has specified
69
+ # collections to dump, it'll loop through the array of collections and invoke the
70
+ # 'mongodump' command once per collection
71
+ def perform!
72
+ super
73
+
74
+ lock_database if @lock
75
+ @only_collections.empty? ? dump! : specific_collection_dump!
76
+
77
+ rescue => err
78
+ raise Errors::Database::MongoDBError.wrap(err, 'Database Dump Failed!')
79
+ ensure
80
+ unlock_database if @lock
81
+ package! unless err
66
82
  end
67
83
 
84
+ private
85
+
68
86
  ##
69
- # Builds a MongoDB compatible string for the
70
- # additional options specified by the user
71
- def additional_options
72
- @additional_options.join("\s")
87
+ # Builds and runs the mongodump command
88
+ def dump!
89
+ run(mongodump)
73
90
  end
74
91
 
75
92
  ##
76
- # Returns an array of collections to dump
77
- def collections_to_dump
78
- @only_collections
93
+ # For each collection in the @only_collections array, it'll
94
+ # build the whole 'mongodump' command, append the '--collection' option,
95
+ # and run the command built command
96
+ def specific_collection_dump!
97
+ @only_collections.each do |collection|
98
+ run("#{mongodump} --collection='#{collection}'")
99
+ end
79
100
  end
80
101
 
81
102
  ##
82
- # Returns the MongoDB database selector syntax
83
- def database
84
- "--db='#{ name }'"
103
+ # Builds the full mongodump string based on all attributes
104
+ def mongodump
105
+ "#{ mongodump_utility } #{ database } #{ credential_options } " +
106
+ "#{ connectivity_options } #{ ipv6_option } #{ user_options } #{ dump_directory }"
85
107
  end
86
108
 
87
109
  ##
88
- # Returns the mongodump syntax for enabling ipv6
89
- def ipv6
90
- @ipv6.eql?(true) ? '--ipv6' : ''
110
+ # If a compressor is configured, packages the dump_path into a
111
+ # single compressed tar archive, then removes the dump_path.
112
+ # e.g.
113
+ # if the database was dumped to:
114
+ # ~/Backup/.tmp/databases/MongoDB/
115
+ # then it will be packaged into:
116
+ # ~/Backup/.tmp/databases/MongoDB-<timestamp>.tar.gz
117
+ def package!
118
+ return unless @model.compressor
119
+
120
+ base_dir = File.dirname(@dump_path)
121
+ dump_dir = File.basename(@dump_path)
122
+ timestamp = Time.now.to_i.to_s[-5, 5]
123
+ outfile = @dump_path + '-' + timestamp + '.tar'
124
+
125
+ @model.compressor.compress_with do |command, ext|
126
+ run("#{ utility(:tar) } -cf - " +
127
+ "-C '#{ base_dir }' '#{ dump_dir }'" +
128
+ " | #{ command } > #{ outfile + ext }")
129
+ end
130
+
131
+ FileUtils.rm_rf(@dump_path)
91
132
  end
92
133
 
93
134
  ##
94
- # Returns the MongoDB syntax for determining where to output all the database dumps,
95
- # e.g. ~/Backup/.tmp/MongoDB/<databases here>/<database collections>
96
- def dump_directory
97
- "--out='#{ dump_path }'"
135
+ # Returns the MongoDB database selector syntax
136
+ def database
137
+ "--db='#{ name }'" if name
98
138
  end
99
139
 
100
140
  ##
101
- # Builds the full mongodump string based on all attributes
102
- def mongodump
103
- "#{ utility(:mongodump) } #{ database } #{ credential_options } " +
104
- "#{ connectivity_options } #{ ipv6 } #{ additional_options } #{ dump_directory }"
141
+ # Builds the MongoDB credentials syntax to authenticate the user
142
+ # to perform the database dumping process
143
+ def credential_options
144
+ %w[username password].map do |option|
145
+ next if send(option).to_s.empty?
146
+ "--#{option}='#{send(option)}'"
147
+ end.compact.join(' ')
105
148
  end
106
149
 
107
150
  ##
108
- # Performs the mongodump command and outputs the data to the
109
- # specified path based on the 'trigger'. If the user hasn't specified any
110
- # specific collections to dump, it'll dump everything. If the user has specified
111
- # collections to dump, it'll loop through the array of collections and invoke the
112
- # 'mongodump' command once per collection
113
- def perform!
114
- super
115
-
116
- lock_database if @lock.eql?(true)
117
- if collections_to_dump.is_a?(Array) and not collections_to_dump.empty?
118
- specific_collection_dump!
119
- else
120
- dump!
121
- end
122
- unlock_database if @lock.eql?(true)
123
- rescue => exception
124
- unlock_database if @lock.eql?(true)
125
- raise exception
151
+ # Builds the MongoDB connectivity options syntax to connect the user
152
+ # to perform the database dumping process
153
+ def connectivity_options
154
+ %w[host port].map do |option|
155
+ next if send(option).to_s.empty?
156
+ "--#{option}='#{send(option)}'"
157
+ end.compact.join(' ')
126
158
  end
127
159
 
128
160
  ##
129
- # Builds and runs the mongodump command
130
- def dump!
131
- run(mongodump)
161
+ # Returns the mongodump syntax for enabling ipv6
162
+ def ipv6_option
163
+ @ipv6 ? '--ipv6' : ''
132
164
  end
133
165
 
134
166
  ##
135
- # For each collection in the @only_collections array, it'll
136
- # build the whole 'mongodump' command, append the '--collection' option,
137
- # and run the command built command
138
- def specific_collection_dump!
139
- collections_to_dump.each do |collection|
140
- run("#{mongodump} --collection='#{collection}'")
141
- end
167
+ # Builds a MongoDB compatible string for the
168
+ # additional options specified by the user
169
+ def user_options
170
+ @additional_options.join(' ')
142
171
  end
143
172
 
144
173
  ##
145
- # Builds a Mongo URI based on the provided attributes
146
- def mongo_uri
147
- ["#{ host }:#{ port }#{ name.is_a?(String) && !name.empty? ? "/#{ name }" : "" }", credential_options, ipv6].join(' ').strip
174
+ # Returns the MongoDB syntax for determining where to output all the database dumps,
175
+ # e.g. ~/Backup/.tmp/databases/MongoDB/<databases here>/<database collections>
176
+ def dump_directory
177
+ "--out='#{ @dump_path }'"
148
178
  end
149
179
 
150
180
  ##
@@ -152,9 +182,9 @@ module Backup
152
182
  # and ensure no 'write operations' are performed during the
153
183
  # dump process
154
184
  def lock_database
155
- lock_command = <<-EOS
185
+ lock_command = <<-EOS.gsub(/^ +/, ' ')
156
186
  echo 'use admin
157
- db.runCommand({"fsync" : 1, "lock" : 1})' | #{ "#{ utility(:mongo) } #{ mongo_uri }" }
187
+ db.runCommand({"fsync" : 1, "lock" : 1})' | #{ "#{ mongo_utility } #{ mongo_uri }" }
158
188
  EOS
159
189
 
160
190
  run(lock_command)
@@ -163,14 +193,21 @@ module Backup
163
193
  ##
164
194
  # Unlocks the (locked) database
165
195
  def unlock_database
166
- unlock_command = <<-EOS
196
+ unlock_command = <<-EOS.gsub(/^ +/, ' ')
167
197
  echo 'use admin
168
- db.$cmd.sys.unlock.findOne()' | #{ "#{ utility(:mongo) } #{ mongo_uri }" }
198
+ db.$cmd.sys.unlock.findOne()' | #{ "#{ mongo_utility } #{ mongo_uri }" }
169
199
  EOS
170
200
 
171
201
  run(unlock_command)
172
202
  end
173
203
 
204
+ ##
205
+ # Builds a Mongo URI based on the provided attributes
206
+ def mongo_uri
207
+ ["#{ host }:#{ port }#{ ('/' + name) if name }",
208
+ credential_options, ipv6_option].join(' ').strip
209
+ end
210
+
174
211
  end
175
212
  end
176
213
  end