backup 3.0.20 → 3.0.21

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -12,6 +12,7 @@ describe Backup::Configuration::Storage::S3 do
12
12
  s3.path = 'my_backups'
13
13
  end
14
14
  end
15
+ after { Backup::Configuration::Storage::S3.clear_defaults! }
15
16
 
16
17
  it 'should set the default S3 configuration' do
17
18
  s3 = Backup::Configuration::Storage::S3
@@ -13,6 +13,7 @@ describe Backup::Configuration::Storage::SCP do
13
13
  scp.keep = 20
14
14
  end
15
15
  end
16
+ after { Backup::Configuration::Storage::SCP.clear_defaults! }
16
17
 
17
18
  it 'should set the default scp configuration' do
18
19
  scp = Backup::Configuration::Storage::SCP
@@ -13,6 +13,7 @@ describe Backup::Configuration::Storage::SFTP do
13
13
  sftp.keep = 20
14
14
  end
15
15
  end
16
+ after { Backup::Configuration::Storage::SFTP.clear_defaults! }
16
17
 
17
18
  it 'should set the default sftp configuration' do
18
19
  sftp = Backup::Configuration::Storage::SFTP
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Configuration::Syncer::RSync::Base do
6
+ before do
7
+ Backup::Configuration::Syncer::RSync::Base.defaults do |rsync|
8
+ #rsync.directories = 'cannot_have_a_default_value'
9
+ rsync.path = '~/backups/'
10
+ rsync.mirror = true
11
+ rsync.additional_options = []
12
+ end
13
+ end
14
+ after { Backup::Configuration::Syncer::RSync::Base.clear_defaults! }
15
+
16
+ it 'should set the default rsync configuration' do
17
+ rsync = Backup::Configuration::Syncer::RSync::Base
18
+ rsync.path.should == '~/backups/'
19
+ rsync.mirror.should == true
20
+ rsync.additional_options.should == []
21
+ end
22
+
23
+ describe '#clear_defaults!' do
24
+ it 'should clear all the defaults, resetting them to nil' do
25
+ Backup::Configuration::Syncer::RSync::Base.clear_defaults!
26
+
27
+ rsync = Backup::Configuration::Syncer::RSync::Base
28
+ rsync.path.should == nil
29
+ rsync.mirror.should == nil
30
+ rsync.additional_options.should == nil
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Configuration::Syncer::RSync::Local do
6
+ it 'should be a subclass of RSync::Base' do
7
+ rsync = Backup::Configuration::Syncer::RSync::Local
8
+ rsync.superclass.should == Backup::Configuration::Syncer::RSync::Base
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Configuration::Syncer::RSync::Pull do
6
+ it 'should be a subclass of RSync::Push' do
7
+ rsync = Backup::Configuration::Syncer::RSync::Pull
8
+ rsync.superclass.should == Backup::Configuration::Syncer::RSync::Push
9
+ end
10
+ end
@@ -1,46 +1,43 @@
1
1
  # encoding: utf-8
2
2
 
3
- require File.expand_path('../../../spec_helper.rb', __FILE__)
3
+ require File.expand_path('../../../../spec_helper.rb', __FILE__)
4
4
 
5
- describe Backup::Configuration::Syncer::RSync do
5
+ describe Backup::Configuration::Syncer::RSync::Push do
6
6
  before do
7
- Backup::Configuration::Syncer::RSync.defaults do |rsync|
7
+ Backup::Configuration::Syncer::RSync::Push.defaults do |rsync|
8
8
  rsync.username = 'my_username'
9
9
  rsync.password = 'my_password'
10
10
  rsync.ip = '123.45.678.90'
11
11
  rsync.port = 22
12
- rsync.path = '~/backups/'
13
- rsync.mirror = true
14
12
  rsync.compress = true
15
- rsync.additional_options = []
16
13
  end
17
14
  end
15
+ after { Backup::Configuration::Syncer::RSync::Push.clear_defaults! }
16
+
17
+ it 'should be a subclass of RSync::Base' do
18
+ rsync = Backup::Configuration::Syncer::RSync::Push
19
+ rsync.superclass.should == Backup::Configuration::Syncer::RSync::Base
20
+ end
18
21
 
19
22
  it 'should set the default rsync configuration' do
20
- rsync = Backup::Configuration::Syncer::RSync
23
+ rsync = Backup::Configuration::Syncer::RSync::Push
21
24
  rsync.username.should == 'my_username'
22
25
  rsync.password.should == 'my_password'
23
26
  rsync.ip.should == '123.45.678.90'
24
27
  rsync.port.should == 22
25
- rsync.path.should == '~/backups/'
26
- rsync.mirror.should == true
27
28
  rsync.compress.should == true
28
- rsync.additional_options.should == []
29
29
  end
30
30
 
31
31
  describe '#clear_defaults!' do
32
32
  it 'should clear all the defaults, resetting them to nil' do
33
- Backup::Configuration::Syncer::RSync.clear_defaults!
33
+ Backup::Configuration::Syncer::RSync::Push.clear_defaults!
34
34
 
35
- rsync = Backup::Configuration::Syncer::RSync
35
+ rsync = Backup::Configuration::Syncer::RSync::Push
36
36
  rsync.username.should == nil
37
37
  rsync.password.should == nil
38
38
  rsync.ip.should == nil
39
39
  rsync.port.should == nil
40
- rsync.path.should == nil
41
- rsync.mirror.should == nil
42
40
  rsync.compress.should == nil
43
- rsync.additional_options.should == nil
44
41
  end
45
42
  end
46
43
  end
@@ -9,11 +9,12 @@ describe Backup::Configuration::Syncer::S3 do
9
9
  s3.secret_access_key = 'my_secret_access_key'
10
10
  s3.bucket = 'my-bucket'
11
11
  s3.path = '/backups/'
12
- s3.directories = '/directories/to/backup/'
12
+ #s3.directories = 'cannot_have_a_default_value'
13
13
  s3.mirror = true
14
14
  s3.additional_options = ['--exclude="*.rb"']
15
15
  end
16
16
  end
17
+ after { Backup::Configuration::Syncer::S3.clear_defaults! }
17
18
 
18
19
  it 'should set the default s3 configuration' do
19
20
  s3 = Backup::Configuration::Syncer::S3
@@ -21,7 +22,6 @@ describe Backup::Configuration::Syncer::S3 do
21
22
  s3.secret_access_key.should == 'my_secret_access_key'
22
23
  s3.bucket.should == 'my-bucket'
23
24
  s3.path.should == '/backups/'
24
- s3.directories.should == '/directories/to/backup/'
25
25
  s3.mirror.should == true
26
26
  s3.additional_options.should == ['--exclude="*.rb"']
27
27
  end
@@ -35,7 +35,6 @@ describe Backup::Configuration::Syncer::S3 do
35
35
  s3.secret_access_key.should == nil
36
36
  s3.bucket.should == nil
37
37
  s3.path.should == nil
38
- s3.directories.should == nil
39
38
  s3.mirror.should == nil
40
39
  s3.additional_options.should == nil
41
40
  end
@@ -3,37 +3,52 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Database::Base do
6
+ let(:model) { Backup::Model.new('foo', 'foo') }
7
+ let(:db) { Backup::Database::Base.new(model) }
6
8
 
7
- before do
8
- class Backup::Database::Base
9
- def initialize(&block)
10
- instance_eval(&block) if block_given?
11
- end
12
- end
9
+ it 'should set #utility_path' do
10
+ db.utility_path.should be_nil
11
+ db.utility_path = 'utility path'
12
+ db.utility_path.should == 'utility path'
13
13
  end
14
14
 
15
- let(:db) do
16
- Backup::Database::Base.new do |db|
17
- db.utility_path = '/var/usr/my_util'
15
+ describe '#perform!' do
16
+ it 'should invoke prepare! and log!' do
17
+ s = sequence ''
18
+ db.expects(:prepare!).in_sequence(s)
19
+ db.expects(:log!).in_sequence(s)
20
+
21
+ db.perform!
18
22
  end
19
23
  end
20
24
 
21
- it 'should return the utility path instead of auto-detecting it' do
22
- db.utility(:my_database_util).should == '/var/usr/my_util'
25
+ context 'since CLI::Helpers are included' do
26
+ it 'should respond to the #utility method' do
27
+ db.respond_to?(:utility).should be_true
28
+ end
23
29
  end
24
30
 
25
- it 'should ignore the utility_path when not defined' do
26
- db = Backup::Database::Base.new
27
- db.utility(:my_database_util).should == :my_database_util
31
+ describe '#prepare!' do
32
+ it 'should set and create #dump_path' do
33
+ model = stub(:trigger => 'test_trigger')
34
+ db.instance_variable_set(:@model, model)
35
+ FileUtils.expects(:mkdir_p).with(
36
+ File.join(Backup::Config.tmp_path, 'test_trigger', 'databases', 'Base')
37
+ )
38
+ db.send(:prepare!)
39
+ db.instance_variable_get(:@dump_path).should ==
40
+ File.join(Backup::Config.tmp_path, 'test_trigger', 'databases', 'Base')
41
+ end
28
42
  end
29
43
 
30
- describe '#perform!' do
31
- it 'should invoke prepare! and log!' do
32
- db.expects(:prepare!)
33
- db.expects(:log!)
44
+ describe '#log!' do
45
+ it 'should use #database_name' do
46
+ db.stubs(:name).returns('database_name')
47
+ Backup::Logger.expects(:message).with(
48
+ "Database::Base started dumping and archiving 'database_name'."
49
+ )
34
50
 
35
- db.perform!
51
+ db.send(:log!)
36
52
  end
37
53
  end
38
-
39
54
  end
@@ -3,13 +3,9 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Database::MongoDB do
6
-
7
- before do
8
- Backup::Database::MongoDB.any_instance.stubs(:load_defaults!)
9
- end
10
-
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
11
7
  let(:db) do
12
- Backup::Database::MongoDB.new do |db|
8
+ Backup::Database::MongoDB.new(model) do |db|
13
9
  db.name = 'mydatabase'
14
10
  db.username = 'someuser'
15
11
  db.password = 'secret'
@@ -18,11 +14,14 @@ describe Backup::Database::MongoDB do
18
14
 
19
15
  db.ipv6 = true
20
16
  db.only_collections = ['users', 'pirates']
21
- db.additional_options = ['--query']
17
+ db.additional_options = ['--query', '--foo']
18
+ db.mongodump_utility = '/path/to/mongodump'
19
+ db.mongo_utility = '/path/to/mongo'
22
20
  end
23
21
  end
24
22
 
25
- describe '#new' do
23
+ describe '#initialize' do
24
+
26
25
  it 'should read the adapter details correctly' do
27
26
  db.name.should == 'mydatabase'
28
27
  db.username.should == 'someuser'
@@ -30,178 +29,358 @@ describe Backup::Database::MongoDB do
30
29
  db.host.should == 'localhost'
31
30
  db.port.should == 123
32
31
 
33
- db.only_collections.should == ['users', 'pirates']
34
- db.additional_options.should == '--query'
32
+ db.ipv6.should == true
33
+ db.only_collections.should == ['users', 'pirates']
34
+ db.additional_options.should == ['--query', '--foo']
35
+ db.mongodump_utility.should == '/path/to/mongodump'
36
+ db.mongo_utility.should == '/path/to/mongo'
37
+ db.lock.should == false
35
38
  end
36
39
 
37
- it 'arrays should default to empty arrays when not specified' do
38
- db = Backup::Database::MongoDB.new do |db|
39
- db.name = 'mydatabase'
40
- db.username = 'someuser'
41
- db.password = 'secret'
40
+ context 'when options are not set' do
41
+ before do
42
+ Backup::Database::MongoDB.any_instance.expects(:utility).
43
+ with(:mongodump).returns('/real/mongodump')
44
+ Backup::Database::MongoDB.any_instance.expects(:utility).
45
+ with(:mongo).returns('/real/mongo')
42
46
  end
43
47
 
44
- db.only_collections.should == []
45
- db.additional_options.should == ""
48
+ it 'should use default values' do
49
+ db = Backup::Database::MongoDB.new(model)
50
+
51
+ db.name.should be_nil
52
+ db.username.should be_nil
53
+ db.password.should be_nil
54
+ db.host.should be_nil
55
+ db.port.should be_nil
56
+
57
+ db.ipv6.should be_false
58
+ db.only_collections.should == []
59
+ db.additional_options.should == []
60
+ db.mongodump_utility.should == '/real/mongodump'
61
+ db.mongo_utility.should == '/real/mongo'
62
+ db.lock.should be_false
63
+ end
46
64
  end
47
- end
48
65
 
49
- describe '#only_collections' do
50
- it 'should return a string for the mongodump selected table to dump option' do
51
- db.collections_to_dump.should == %w[users pirates]
66
+ context 'when configuration defaults have been set' do
67
+ after { Backup::Configuration::Database::MongoDB.clear_defaults! }
68
+
69
+ it 'should use configuration defaults' do
70
+ Backup::Configuration::Database::MongoDB.defaults do |db|
71
+ db.name = 'db_name'
72
+ db.username = 'db_username'
73
+ db.password = 'db_password'
74
+ db.host = 'db_host'
75
+ db.port = 789
76
+
77
+ db.ipv6 = true
78
+ db.only_collections = ['collection']
79
+ db.additional_options = ['--opt']
80
+ db.mongodump_utility = '/default/path/to/mongodump'
81
+ db.mongo_utility = '/default/path/to/mongo'
82
+ db.lock = true
83
+ end
84
+
85
+ db = Backup::Database::MongoDB.new(model)
86
+ db.name.should == 'db_name'
87
+ db.username.should == 'db_username'
88
+ db.password.should == 'db_password'
89
+ db.host.should == 'db_host'
90
+ db.port.should == 789
91
+
92
+ db.ipv6.should be_true
93
+ db.only_collections.should == ['collection']
94
+ db.additional_options.should == ['--opt']
95
+ db.mongodump_utility.should == '/default/path/to/mongodump'
96
+ db.mongo_utility.should == '/default/path/to/mongo'
97
+ db.lock.should be_true
98
+ end
52
99
  end
53
- end
100
+ end # describe '#initialize'
54
101
 
55
- describe '#credential_options' do
56
- it 'should return the mongo syntax for the credential options' do
57
- db.credential_options.should == "--username='someuser' --password='secret'"
102
+ describe '#perform!' do
103
+ let(:s) { sequence '' }
104
+
105
+ before do
106
+ # superclass actions
107
+ db.expects(:prepare!).in_sequence(s)
108
+ db.expects(:log!).in_sequence(s)
58
109
  end
59
110
 
60
- it 'should only return the mongo syntax for the user' do
61
- db = Backup::Database::MongoDB.new do |db|
62
- db.username = 'someuser'
111
+ context 'when #lock is set to false' do
112
+
113
+ context 'when #only_collections has not been specified' do
114
+ before { db.only_collections = [] }
115
+ it 'should dump everything without locking' do
116
+ db.expects(:lock_database).never
117
+ db.expects(:unlock_database).never
118
+ db.expects(:specific_collection_dump!).never
119
+
120
+ db.expects(:dump!).in_sequence(s)
121
+ db.expects(:package!).in_sequence(s)
122
+ db.perform!
123
+ end
63
124
  end
64
125
 
65
- db.credential_options.should == "--username='someuser'"
66
- end
67
- end
126
+ context 'when #only_collections has been specified' do
127
+ it 'should dump specific collections without locking' do
128
+ db.expects(:lock_database).never
129
+ db.expects(:unlock_database).never
130
+ db.expects(:dump!).never
68
131
 
69
- describe '#connectivity_options' do
70
- it 'should return the mongo syntax for the connectivity options' do
71
- db.connectivity_options.should == "--host='localhost' --port='123'"
72
- end
132
+ db.expects(:specific_collection_dump!).in_sequence(s)
133
+ db.expects(:package!).in_sequence(s)
134
+ db.perform!
135
+ end
136
+ end
137
+
138
+ end # context 'when #lock is set to false'
73
139
 
74
- it 'should return only the socket' do
75
- db = Backup::Database::MongoDB.new do |db|
76
- db.host = ''
77
- db.port = 123
140
+ context 'when #lock is set to true' do
141
+ before { db.lock = true }
142
+
143
+ context 'when #only_collections has not been specified' do
144
+ before { db.only_collections = [] }
145
+ it 'should dump everything while locking the database' do
146
+ db.expects(:specific_collection_dump!).never
147
+
148
+ db.expects(:lock_database).in_sequence(s)
149
+ db.expects(:dump!).in_sequence(s)
150
+ db.expects(:unlock_database).in_sequence(s)
151
+ db.expects(:package!).in_sequence(s)
152
+ db.perform!
153
+ end
78
154
  end
79
155
 
80
- db.connectivity_options.should == "--port='123'"
81
- end
82
- end
156
+ context 'when #only_collections has been specified' do
157
+ it 'should dump specific collections without locking' do
158
+ db.expects(:lock_database).never
159
+ db.expects(:unlock_database).never
160
+ db.expects(:dump!).never
161
+
162
+ db.expects(:lock_database).in_sequence(s)
163
+ db.expects(:specific_collection_dump!).in_sequence(s)
164
+ db.expects(:unlock_database).in_sequence(s)
165
+ db.expects(:package!).in_sequence(s)
166
+ db.perform!
167
+ end
168
+ end
169
+
170
+ end # context 'when #lock is set to true'
171
+
172
+ context 'when errors occur' do
173
+ it 'should re-raise error and skip package!' do
174
+ db.expects(:specific_collection_dump!).in_sequence(s).
175
+ raises('Test Error Message')
176
+ db.expects(:package!).never
177
+
178
+ expect do
179
+ db.perform!
180
+ end.to raise_error(
181
+ Backup::Errors::Database::MongoDBError,
182
+ "Database::MongoDBError: Database Dump Failed!\n" +
183
+ " Reason: RuntimeError\n" +
184
+ " Test Error Message"
185
+ )
186
+ end
83
187
 
84
- describe '#ipv6' do
85
- it 'should return a mongodb syntax compatible ipv6 flag' do
86
- db.ipv6 = true
87
- db.ipv6.should == '--ipv6'
188
+ it 'should ensure database is unlocked' do
189
+ db.lock = true
190
+
191
+ db.expects(:lock_database).in_sequence(s)
192
+ db.expects(:specific_collection_dump!).in_sequence(s).
193
+ raises('Test Error Message')
194
+ db.expects(:unlock_database).in_sequence(s)
195
+ db.expects(:package!).never
196
+
197
+ expect do
198
+ db.perform!
199
+ end.to raise_error(
200
+ Backup::Errors::Database::MongoDBError,
201
+ "Database::MongoDBError: Database Dump Failed!\n" +
202
+ " Reason: RuntimeError\n" +
203
+ " Test Error Message"
204
+ )
205
+ end
88
206
  end
89
207
 
90
- it 'should return an empty string' do
91
- db.ipv6 = nil
92
- db.ipv6.should == ''
208
+ end # describe '#perform!'
209
+
210
+ describe '#dump!' do
211
+ it 'should run the mongodb dump command' do
212
+ db.expects(:mongodump).returns(:dump_command)
213
+ db.expects(:run).with(:dump_command)
214
+ db.send(:dump!)
93
215
  end
94
216
  end
95
217
 
96
- describe '#mongodump_string' do
97
- it 'should return the full mongodump string' do
98
- db.expects(:utility).with(:mongodump).returns('mongodump')
99
- db.prepare!
100
- db.mongodump.should ==
101
- "mongodump --db='mydatabase' --username='someuser' --password='secret' " +
102
- "--host='localhost' --port='123' --ipv6 --query --out='#{ File.join(Backup::TMP_PATH, Backup::TRIGGER, 'MongoDB') }'"
218
+ describe '#specific_collection_dump!' do
219
+ it 'should run the mongodb dump command for each collection' do
220
+ db.expects(:mongodump).twice.returns('dump_command')
221
+ db.expects(:run).with("dump_command --collection='users'")
222
+ db.expects(:run).with("dump_command --collection='pirates'")
223
+ db.send(:specific_collection_dump!)
103
224
  end
104
225
  end
105
226
 
106
- describe '#perform!' do
227
+ describe '#mongodump' do
107
228
  before do
108
- db.stubs(:utility).returns('mongodump')
109
- db.stubs(:mkdir)
110
- db.stubs(:run)
229
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
111
230
  end
112
231
 
113
- it 'should ensure the directory is available' do
114
- db.expects(:mkdir).with(File.join(Backup::TMP_PATH, "myapp", "MongoDB"))
115
- db.perform!
232
+ it 'should return the mongodb dump command string' do
233
+ db.send(:mongodump).should == "/path/to/mongodump " +
234
+ "--db='mydatabase' --username='someuser' --password='secret' " +
235
+ "--host='localhost' --port='123' --ipv6 " +
236
+ "--query --foo --out='/path/to/dump/folder'"
116
237
  end
238
+ end
117
239
 
118
- it 'should run the mongodump command and dump all collections' do
119
- db.only_collections = []
120
- db.expects(:dump!)
240
+ describe '#package!' do
241
+ let(:compressor) { mock }
121
242
 
122
- db.perform!
123
- end
243
+ context 'when a compressor is configured' do
244
+ before do
245
+ Timecop.freeze(Time.now)
246
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
247
+ db.expects(:utility).with(:tar).returns('tar')
248
+ model.expects(:compressor).twice.returns(compressor)
249
+ compressor.expects(:compress_with).yields('compressor_command', '.gz')
250
+ end
124
251
 
125
- it 'should run the mongodump command and dump all collections' do
126
- db.only_collections = nil
127
- db.expects(:dump!)
252
+ it 'should package the dump directory, then remove it' do
253
+ timestamp = Time.now.to_i.to_s[-5, 5]
254
+ db.expects(:run).with(
255
+ "tar -cf - -C '/path/to/dump' 'folder' | compressor_command" +
256
+ " > /path/to/dump/folder-#{ timestamp }.tar.gz"
257
+ )
258
+ FileUtils.expects(:rm_rf).with('/path/to/dump/folder')
128
259
 
129
- db.perform!
260
+ db.send(:package!)
261
+ end
130
262
  end
131
263
 
132
- it 'should lock database before dump if lock mode is enabled' do
133
- db.lock = true
134
- db.expects(:lock_database)
264
+ context 'when a compressor is not configured' do
265
+ before do
266
+ model.expects(:compressor).returns(nil)
267
+ end
135
268
 
136
- db.perform!
269
+ it 'should return nil' do
270
+ db.expects(:run).never
271
+ db.send(:package!).should be_nil
272
+ end
137
273
  end
274
+ end
138
275
 
139
- it 'should not lock database before dump if lock mode is disabled' do
140
- db.lock = false
141
- db.expects(:lock_database).never
142
-
143
- db.perform!
276
+ describe '#database' do
277
+ context 'when a database name is given' do
278
+ it 'should return the command string for the database' do
279
+ db.send(:database).should == "--db='mydatabase'"
280
+ end
144
281
  end
145
282
 
146
- it 'should unlock database after dump if lock mode is enabled' do
147
- db.lock = true
148
- db.expects(:unlock_database)
283
+ context 'when no database name is given' do
284
+ it 'should return nil' do
285
+ db.name = nil
286
+ db.send(:database).should be_nil
287
+ end
288
+ end
289
+ end
149
290
 
150
- db.perform!
291
+ describe '#credential_options' do
292
+ it 'should return the command string for the user credentials' do
293
+ db.send(:credential_options).should ==
294
+ "--username='someuser' --password='secret'"
151
295
  end
296
+ end
152
297
 
153
- it 'should unlock the database if an exception is raised after it was locked' do
154
- db.lock = true
155
- db.expects(:unlock_database)
156
- db.expects(:lock_database).raises(RuntimeError, 'something went wrong')
157
- db.expects(:raise)
298
+ describe '#connectivity_options' do
299
+ it 'should return the command string for the connectivity options' do
300
+ db.send(:connectivity_options).should == "--host='localhost' --port='123'"
301
+ end
302
+ end
158
303
 
159
- db.perform!
304
+ describe '#ipv6_option' do
305
+ context 'when #ipv6 is set true' do
306
+ it 'should return the command string for the ipv6 option' do
307
+ db.send(:ipv6_option).should == '--ipv6'
308
+ end
160
309
  end
161
310
 
162
- it 'should not unlock database after dump if lock mode is disabled' do
163
- db.lock = false
164
- db.expects(:unlock_database).never
311
+ context 'when #ipv6 is set false' do
312
+ it 'should return and empty string' do
313
+ db.ipv6 = false
314
+ db.send(:ipv6_option).should == ''
315
+ end
316
+ end
317
+ end
165
318
 
166
- db.perform!
319
+ describe '#user_options' do
320
+ context 'when #additional_options are set' do
321
+ it 'should return the command string for the options' do
322
+ db.send(:user_options).should == '--query --foo'
323
+ end
167
324
  end
168
325
 
169
- it 'should dump only the provided collections' do
170
- db.only_collections = %w[users admins profiles]
171
- db.expects(:specific_collection_dump!)
326
+ context 'when #additional_options are not set' do
327
+ it 'should return an empty string' do
328
+ db.additional_options = []
329
+ db.send(:user_options).should == ''
330
+ end
331
+ end
332
+ end
172
333
 
173
- db.perform!
334
+ describe '#dump_directory' do
335
+ it 'should return the command string for the dump path' do
336
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
337
+ db.send(:dump_directory).should == "--out='/path/to/dump/folder'"
174
338
  end
339
+ end
175
340
 
176
- it do
177
- Backup::Logger.expects(:message).
178
- with("Backup::Database::MongoDB started dumping and archiving 'mydatabase'.")
179
- db.perform!
341
+ describe '#lock_database' do
342
+ it 'should return the command to lock the database' do
343
+ db.stubs(:mongo_uri).returns(:mongo_uri_output)
344
+ db.expects(:run).with(
345
+ " echo 'use admin\n" +
346
+ ' db.runCommand({"fsync" : 1, "lock" : 1})\' | /path/to/mongo mongo_uri_output' +
347
+ "\n"
348
+ )
349
+ db.send(:lock_database)
180
350
  end
181
351
  end
182
352
 
183
- describe "#mongo_uri" do
184
- before do
185
- db.host = "flame.mongohq.com"
186
- db.port = 12345
187
- db.username = "sample_username"
188
- db.password = "sample_password"
189
- db.ipv6 = nil
353
+ describe '#unlock_database' do
354
+ it 'should return the command to unlock the database' do
355
+ db.stubs(:mongo_uri).returns(:mongo_uri_output)
356
+ db.expects(:run).with(
357
+ " echo 'use admin\n" +
358
+ ' db.$cmd.sys.unlock.findOne()\' | /path/to/mongo mongo_uri_output' +
359
+ "\n"
360
+ )
361
+ db.send(:unlock_database)
190
362
  end
363
+ end
191
364
 
192
- it "should return URI without database" do
193
- db.name = nil
194
- db.mongo_uri.should == "flame.mongohq.com:12345 --username='sample_username' --password='sample_password'"
365
+ describe '#mongo_uri' do
366
+ before do
367
+ db.stubs(:credential_options).returns(:credential_options_output)
368
+ db.stubs(:ipv6_option).returns(:ipv6_option_output)
195
369
  end
196
370
 
197
- it "should return URI without database" do
198
- db.name = ""
199
- db.mongo_uri.should == "flame.mongohq.com:12345 --username='sample_username' --password='sample_password'"
371
+ context 'when a database name is given' do
372
+ it 'should return the URI specifying the database' do
373
+ db.send(:mongo_uri).should ==
374
+ "localhost:123/mydatabase credential_options_output ipv6_option_output"
375
+ end
200
376
  end
201
377
 
202
- it "should return URI without database" do
203
- db.name = "sample_db"
204
- db.mongo_uri.should == "flame.mongohq.com:12345/sample_db --username='sample_username' --password='sample_password'"
378
+ context 'when no database name is given' do
379
+ it 'should return the URI without specifying the database' do
380
+ db.name = nil
381
+ db.send(:mongo_uri).should ==
382
+ "localhost:123 credential_options_output ipv6_option_output"
383
+ end
205
384
  end
206
385
  end
207
386
  end