backup 3.0.23 → 3.0.24

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 (197) hide show
  1. data/Gemfile.lock +42 -45
  2. data/Guardfile +7 -4
  3. data/README.md +10 -7
  4. data/backup.gemspec +2 -2
  5. data/lib/backup.rb +27 -97
  6. data/lib/backup/archive.rb +14 -6
  7. data/lib/backup/cli/helpers.rb +52 -49
  8. data/lib/backup/cli/utility.rb +9 -1
  9. data/lib/backup/compressor/base.rb +10 -4
  10. data/lib/backup/compressor/bzip2.rb +22 -26
  11. data/lib/backup/compressor/custom.rb +53 -0
  12. data/lib/backup/compressor/gzip.rb +22 -23
  13. data/lib/backup/compressor/lzma.rb +15 -13
  14. data/lib/backup/compressor/pbzip2.rb +20 -17
  15. data/lib/backup/config.rb +6 -3
  16. data/lib/backup/configuration.rb +33 -0
  17. data/lib/backup/configuration/helpers.rb +114 -28
  18. data/lib/backup/configuration/store.rb +24 -0
  19. data/lib/backup/database/base.rb +0 -6
  20. data/lib/backup/database/mongodb.rb +27 -11
  21. data/lib/backup/database/mysql.rb +19 -14
  22. data/lib/backup/database/postgresql.rb +16 -11
  23. data/lib/backup/database/redis.rb +7 -11
  24. data/lib/backup/database/riak.rb +3 -6
  25. data/lib/backup/dependency.rb +5 -11
  26. data/lib/backup/model.rb +14 -5
  27. data/lib/backup/notifier/campfire.rb +3 -16
  28. data/lib/backup/notifier/hipchat.rb +1 -7
  29. data/lib/backup/notifier/mail.rb +1 -1
  30. data/lib/backup/packager.rb +29 -19
  31. data/lib/backup/pipeline.rb +110 -0
  32. data/lib/backup/storage/dropbox.rb +4 -7
  33. data/lib/backup/syncer/base.rb +8 -4
  34. data/lib/backup/syncer/cloud/base.rb +247 -0
  35. data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
  36. data/lib/backup/syncer/cloud/s3.rb +68 -0
  37. data/lib/backup/syncer/rsync/base.rb +1 -4
  38. data/lib/backup/syncer/rsync/local.rb +9 -5
  39. data/lib/backup/syncer/rsync/pull.rb +1 -1
  40. data/lib/backup/syncer/rsync/push.rb +10 -5
  41. data/lib/backup/version.rb +1 -1
  42. data/spec-live/.gitignore +6 -0
  43. data/spec-live/README +7 -0
  44. data/spec-live/backups/config.rb +153 -0
  45. data/spec-live/backups/config.yml.template +43 -0
  46. data/spec-live/compressor/custom_spec.rb +30 -0
  47. data/spec-live/compressor/gzip_spec.rb +30 -0
  48. data/spec-live/notifier/mail_spec.rb +85 -0
  49. data/spec-live/spec_helper.rb +85 -0
  50. data/spec-live/storage/dropbox_spec.rb +151 -0
  51. data/spec-live/storage/local_spec.rb +83 -0
  52. data/spec-live/storage/scp_spec.rb +193 -0
  53. data/spec-live/syncer/cloud/s3_spec.rb +124 -0
  54. data/spec/archive_spec.rb +86 -31
  55. data/spec/cleaner_spec.rb +8 -0
  56. data/spec/cli/helpers_spec.rb +200 -75
  57. data/spec/cli/utility_spec.rb +11 -3
  58. data/spec/compressor/base_spec.rb +31 -10
  59. data/spec/compressor/bzip2_spec.rb +212 -57
  60. data/spec/compressor/custom_spec.rb +106 -0
  61. data/spec/compressor/gzip_spec.rb +212 -57
  62. data/spec/compressor/lzma_spec.rb +75 -35
  63. data/spec/compressor/pbzip2_spec.rb +93 -52
  64. data/spec/configuration/helpers_spec.rb +406 -0
  65. data/spec/configuration/store_spec.rb +39 -0
  66. data/spec/configuration_spec.rb +62 -0
  67. data/spec/database/base_spec.rb +19 -10
  68. data/spec/database/mongodb_spec.rb +195 -70
  69. data/spec/database/mysql_spec.rb +183 -64
  70. data/spec/database/postgresql_spec.rb +167 -53
  71. data/spec/database/redis_spec.rb +121 -46
  72. data/spec/database/riak_spec.rb +96 -27
  73. data/spec/dependency_spec.rb +2 -0
  74. data/spec/encryptor/base_spec.rb +10 -0
  75. data/spec/encryptor/gpg_spec.rb +29 -13
  76. data/spec/encryptor/open_ssl_spec.rb +40 -21
  77. data/spec/logger_spec.rb +4 -0
  78. data/spec/model_spec.rb +19 -2
  79. data/spec/notifier/base_spec.rb +32 -17
  80. data/spec/notifier/campfire_spec.rb +63 -45
  81. data/spec/notifier/hipchat_spec.rb +79 -56
  82. data/spec/notifier/mail_spec.rb +82 -46
  83. data/spec/notifier/prowl_spec.rb +53 -32
  84. data/spec/notifier/twitter_spec.rb +62 -41
  85. data/spec/packager_spec.rb +95 -36
  86. data/spec/pipeline_spec.rb +259 -0
  87. data/spec/spec_helper.rb +6 -5
  88. data/spec/storage/base_spec.rb +61 -41
  89. data/spec/storage/cloudfiles_spec.rb +69 -45
  90. data/spec/storage/dropbox_spec.rb +158 -36
  91. data/spec/storage/ftp_spec.rb +69 -45
  92. data/spec/storage/local_spec.rb +47 -23
  93. data/spec/storage/ninefold_spec.rb +55 -31
  94. data/spec/storage/rsync_spec.rb +67 -50
  95. data/spec/storage/s3_spec.rb +65 -41
  96. data/spec/storage/scp_spec.rb +65 -41
  97. data/spec/storage/sftp_spec.rb +65 -41
  98. data/spec/syncer/base_spec.rb +91 -4
  99. data/spec/syncer/cloud/base_spec.rb +511 -0
  100. data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
  101. data/spec/syncer/cloud/s3_spec.rb +174 -0
  102. data/spec/syncer/rsync/base_spec.rb +46 -66
  103. data/spec/syncer/rsync/local_spec.rb +55 -26
  104. data/spec/syncer/rsync/pull_spec.rb +15 -4
  105. data/spec/syncer/rsync/push_spec.rb +59 -52
  106. data/templates/cli/utility/compressor/bzip2 +1 -4
  107. data/templates/cli/utility/compressor/custom +11 -0
  108. data/templates/cli/utility/compressor/gzip +1 -4
  109. data/templates/cli/utility/compressor/lzma +3 -0
  110. data/templates/cli/utility/compressor/pbzip2 +3 -0
  111. data/templates/cli/utility/database/mysql +4 -1
  112. data/templates/cli/utility/syncer/cloud_files +17 -19
  113. data/templates/cli/utility/syncer/s3 +18 -20
  114. metadata +38 -92
  115. data/lib/backup/configuration/base.rb +0 -15
  116. data/lib/backup/configuration/compressor/base.rb +0 -9
  117. data/lib/backup/configuration/compressor/bzip2.rb +0 -23
  118. data/lib/backup/configuration/compressor/gzip.rb +0 -23
  119. data/lib/backup/configuration/compressor/lzma.rb +0 -23
  120. data/lib/backup/configuration/compressor/pbzip2.rb +0 -28
  121. data/lib/backup/configuration/database/base.rb +0 -19
  122. data/lib/backup/configuration/database/mongodb.rb +0 -49
  123. data/lib/backup/configuration/database/mysql.rb +0 -42
  124. data/lib/backup/configuration/database/postgresql.rb +0 -41
  125. data/lib/backup/configuration/database/redis.rb +0 -39
  126. data/lib/backup/configuration/database/riak.rb +0 -29
  127. data/lib/backup/configuration/encryptor/base.rb +0 -9
  128. data/lib/backup/configuration/encryptor/gpg.rb +0 -17
  129. data/lib/backup/configuration/encryptor/open_ssl.rb +0 -32
  130. data/lib/backup/configuration/notifier/base.rb +0 -28
  131. data/lib/backup/configuration/notifier/campfire.rb +0 -25
  132. data/lib/backup/configuration/notifier/hipchat.rb +0 -41
  133. data/lib/backup/configuration/notifier/mail.rb +0 -112
  134. data/lib/backup/configuration/notifier/presently.rb +0 -25
  135. data/lib/backup/configuration/notifier/prowl.rb +0 -23
  136. data/lib/backup/configuration/notifier/twitter.rb +0 -21
  137. data/lib/backup/configuration/storage/base.rb +0 -18
  138. data/lib/backup/configuration/storage/cloudfiles.rb +0 -25
  139. data/lib/backup/configuration/storage/dropbox.rb +0 -58
  140. data/lib/backup/configuration/storage/ftp.rb +0 -29
  141. data/lib/backup/configuration/storage/local.rb +0 -17
  142. data/lib/backup/configuration/storage/ninefold.rb +0 -20
  143. data/lib/backup/configuration/storage/rsync.rb +0 -29
  144. data/lib/backup/configuration/storage/s3.rb +0 -25
  145. data/lib/backup/configuration/storage/scp.rb +0 -25
  146. data/lib/backup/configuration/storage/sftp.rb +0 -25
  147. data/lib/backup/configuration/syncer/base.rb +0 -10
  148. data/lib/backup/configuration/syncer/cloud.rb +0 -23
  149. data/lib/backup/configuration/syncer/cloud_files.rb +0 -30
  150. data/lib/backup/configuration/syncer/rsync/base.rb +0 -28
  151. data/lib/backup/configuration/syncer/rsync/local.rb +0 -11
  152. data/lib/backup/configuration/syncer/rsync/pull.rb +0 -11
  153. data/lib/backup/configuration/syncer/rsync/push.rb +0 -31
  154. data/lib/backup/configuration/syncer/s3.rb +0 -23
  155. data/lib/backup/notifier/presently.rb +0 -88
  156. data/lib/backup/syncer/cloud.rb +0 -187
  157. data/lib/backup/syncer/cloud_files.rb +0 -56
  158. data/lib/backup/syncer/s3.rb +0 -47
  159. data/spec/configuration/base_spec.rb +0 -35
  160. data/spec/configuration/compressor/bzip2_spec.rb +0 -29
  161. data/spec/configuration/compressor/gzip_spec.rb +0 -29
  162. data/spec/configuration/compressor/lzma_spec.rb +0 -29
  163. data/spec/configuration/compressor/pbzip2_spec.rb +0 -32
  164. data/spec/configuration/database/base_spec.rb +0 -17
  165. data/spec/configuration/database/mongodb_spec.rb +0 -56
  166. data/spec/configuration/database/mysql_spec.rb +0 -53
  167. data/spec/configuration/database/postgresql_spec.rb +0 -53
  168. data/spec/configuration/database/redis_spec.rb +0 -50
  169. data/spec/configuration/database/riak_spec.rb +0 -35
  170. data/spec/configuration/encryptor/gpg_spec.rb +0 -26
  171. data/spec/configuration/encryptor/open_ssl_spec.rb +0 -35
  172. data/spec/configuration/notifier/base_spec.rb +0 -32
  173. data/spec/configuration/notifier/campfire_spec.rb +0 -32
  174. data/spec/configuration/notifier/hipchat_spec.rb +0 -44
  175. data/spec/configuration/notifier/mail_spec.rb +0 -71
  176. data/spec/configuration/notifier/presently_spec.rb +0 -35
  177. data/spec/configuration/notifier/prowl_spec.rb +0 -29
  178. data/spec/configuration/notifier/twitter_spec.rb +0 -35
  179. data/spec/configuration/storage/cloudfiles_spec.rb +0 -41
  180. data/spec/configuration/storage/dropbox_spec.rb +0 -38
  181. data/spec/configuration/storage/ftp_spec.rb +0 -44
  182. data/spec/configuration/storage/local_spec.rb +0 -29
  183. data/spec/configuration/storage/ninefold_spec.rb +0 -32
  184. data/spec/configuration/storage/rsync_spec.rb +0 -41
  185. data/spec/configuration/storage/s3_spec.rb +0 -38
  186. data/spec/configuration/storage/scp_spec.rb +0 -41
  187. data/spec/configuration/storage/sftp_spec.rb +0 -41
  188. data/spec/configuration/syncer/cloud_files_spec.rb +0 -44
  189. data/spec/configuration/syncer/rsync/base_spec.rb +0 -33
  190. data/spec/configuration/syncer/rsync/local_spec.rb +0 -10
  191. data/spec/configuration/syncer/rsync/pull_spec.rb +0 -10
  192. data/spec/configuration/syncer/rsync/push_spec.rb +0 -43
  193. data/spec/configuration/syncer/s3_spec.rb +0 -38
  194. data/spec/notifier/presently_spec.rb +0 -181
  195. data/spec/syncer/cloud_files_spec.rb +0 -192
  196. data/spec/syncer/s3_spec.rb +0 -192
  197. data/templates/cli/utility/notifier/presently +0 -13
@@ -6,10 +6,25 @@ describe Backup::Database::Base do
6
6
  let(:model) { Backup::Model.new('foo', 'foo') }
7
7
  let(:db) { Backup::Database::Base.new(model) }
8
8
 
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'
9
+ it 'should include CLI::Helpers' do
10
+ Backup::Database::Base.
11
+ include?(Backup::CLI::Helpers).should be_true
12
+ end
13
+
14
+ it 'should include Configuration::Helpers' do
15
+ Backup::Database::Base.
16
+ include?(Backup::Configuration::Helpers).should be_true
17
+ end
18
+
19
+ describe '#initialize' do
20
+ it 'should load pre-configured defaults' do
21
+ Backup::Database::Base.any_instance.expects(:load_defaults!)
22
+ db
23
+ end
24
+
25
+ it 'should set a reference to the model' do
26
+ db.instance_variable_get(:@model).should == model
27
+ end
13
28
  end
14
29
 
15
30
  describe '#perform!' do
@@ -22,12 +37,6 @@ describe Backup::Database::Base do
22
37
  end
23
38
  end
24
39
 
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
29
- end
30
-
31
40
  describe '#prepare!' do
32
41
  it 'should set and create #dump_path' do
33
42
  model = stub(:trigger => 'test_trigger')
@@ -17,86 +17,127 @@ describe Backup::Database::MongoDB do
17
17
  db.additional_options = ['--query', '--foo']
18
18
  db.mongodump_utility = '/path/to/mongodump'
19
19
  db.mongo_utility = '/path/to/mongo'
20
+ db.lock = true
20
21
  end
21
22
  end
22
23
 
24
+ it 'should be a subclass of Database::Base' do
25
+ Backup::Database::MongoDB.superclass.
26
+ should == Backup::Database::Base
27
+ end
28
+
23
29
  describe '#initialize' do
24
30
 
25
- it 'should read the adapter details correctly' do
26
- db.name.should == 'mydatabase'
27
- db.username.should == 'someuser'
28
- db.password.should == 'secret'
29
- db.host.should == 'localhost'
30
- db.port.should == 123
31
-
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
31
+ it 'should load pre-configured defaults through Base' do
32
+ Backup::Database::MongoDB.any_instance.expects(:load_defaults!)
33
+ db
38
34
  end
39
35
 
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')
46
- end
36
+ it 'should pass the model reference to Base' do
37
+ db.instance_variable_get(:@model).should == model
38
+ end
47
39
 
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
40
+ context 'when no pre-configured defaults have been set' do
41
+ context 'when options are specified' do
42
+ it 'should use the given values' do
43
+ db.name.should == 'mydatabase'
44
+ db.username.should == 'someuser'
45
+ db.password.should == 'secret'
46
+ db.host.should == 'localhost'
47
+ db.port.should == 123
48
+
49
+ db.ipv6.should == true
50
+ db.only_collections.should == ['users', 'pirates']
51
+ db.additional_options.should == ['--query', '--foo']
52
+ db.mongodump_utility.should == '/path/to/mongodump'
53
+ db.mongo_utility.should == '/path/to/mongo'
54
+ db.lock.should == true
55
+ end
63
56
  end
64
- end
65
57
 
66
- context 'when configuration defaults have been set' do
67
- after { Backup::Configuration::Database::MongoDB.clear_defaults! }
58
+ context 'when options are not specified' do
59
+ before do
60
+ Backup::Database::MongoDB.any_instance.expects(:utility).
61
+ with(:mongodump).returns('/real/mongodump')
62
+ Backup::Database::MongoDB.any_instance.expects(:utility).
63
+ with(:mongo).returns('/real/mongo')
64
+ end
65
+
66
+ it 'should provide default values' do
67
+ db = Backup::Database::MongoDB.new(model)
68
+
69
+ db.name.should be_nil
70
+ db.username.should be_nil
71
+ db.password.should be_nil
72
+ db.host.should be_nil
73
+ db.port.should be_nil
74
+
75
+ db.ipv6.should be_false
76
+ db.only_collections.should == []
77
+ db.additional_options.should == []
78
+ db.mongodump_utility.should == '/real/mongodump'
79
+ db.mongo_utility.should == '/real/mongo'
80
+ db.lock.should be_false
81
+ end
82
+ end
83
+ end # context 'when no pre-configured defaults have been set'
68
84
 
69
- it 'should use configuration defaults' do
70
- Backup::Configuration::Database::MongoDB.defaults do |db|
85
+ context 'when pre-configured defaults have been set' do
86
+ before do
87
+ Backup::Database::MongoDB.defaults do |db|
71
88
  db.name = 'db_name'
72
89
  db.username = 'db_username'
73
90
  db.password = 'db_password'
74
91
  db.host = 'db_host'
75
92
  db.port = 789
76
93
 
77
- db.ipv6 = true
94
+ db.ipv6 = 'default_ipv6'
78
95
  db.only_collections = ['collection']
79
96
  db.additional_options = ['--opt']
80
97
  db.mongodump_utility = '/default/path/to/mongodump'
81
98
  db.mongo_utility = '/default/path/to/mongo'
82
- db.lock = true
99
+ db.lock = 'default_lock'
83
100
  end
101
+ end
84
102
 
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
103
+ after { Backup::Database::MongoDB.clear_defaults! }
104
+
105
+ context 'when options are specified' do
106
+ it 'should override the pre-configured defaults' do
107
+ db.name.should == 'mydatabase'
108
+ db.username.should == 'someuser'
109
+ db.password.should == 'secret'
110
+ db.host.should == 'localhost'
111
+ db.port.should == 123
112
+
113
+ db.ipv6.should == true
114
+ db.only_collections.should == ['users', 'pirates']
115
+ db.additional_options.should == ['--query', '--foo']
116
+ db.mongodump_utility.should == '/path/to/mongodump'
117
+ db.mongo_utility.should == '/path/to/mongo'
118
+ db.lock.should == true
119
+ end
98
120
  end
99
- end
121
+
122
+ context 'when options are not specified' do
123
+ it 'should use the pre-configured defaults' do
124
+ db = Backup::Database::MongoDB.new(model)
125
+
126
+ db.name.should == 'db_name'
127
+ db.username.should == 'db_username'
128
+ db.password.should == 'db_password'
129
+ db.host.should == 'db_host'
130
+ db.port.should == 789
131
+
132
+ db.ipv6.should == 'default_ipv6'
133
+ db.only_collections.should == ['collection']
134
+ db.additional_options.should == ['--opt']
135
+ db.mongodump_utility.should == '/default/path/to/mongodump'
136
+ db.mongo_utility.should == '/default/path/to/mongo'
137
+ db.lock.should == 'default_lock'
138
+ end
139
+ end
140
+ end # context 'when no pre-configured defaults have been set'
100
141
  end # describe '#initialize'
101
142
 
102
143
  describe '#perform!' do
@@ -109,6 +150,7 @@ describe Backup::Database::MongoDB do
109
150
  end
110
151
 
111
152
  context 'when #lock is set to false' do
153
+ before { db.lock = false }
112
154
 
113
155
  context 'when #only_collections has not been specified' do
114
156
  before { db.only_collections = [] }
@@ -138,7 +180,6 @@ describe Backup::Database::MongoDB do
138
180
  end # context 'when #lock is set to false'
139
181
 
140
182
  context 'when #lock is set to true' do
141
- before { db.lock = true }
142
183
 
143
184
  context 'when #only_collections has not been specified' do
144
185
  before { db.only_collections = [] }
@@ -171,6 +212,8 @@ describe Backup::Database::MongoDB do
171
212
 
172
213
  context 'when errors occur' do
173
214
  it 'should re-raise error and skip package!' do
215
+ db.lock = false
216
+
174
217
  db.expects(:specific_collection_dump!).in_sequence(s).
175
218
  raises('Test Error Message')
176
219
  db.expects(:package!).never
@@ -186,8 +229,6 @@ describe Backup::Database::MongoDB do
186
229
  end
187
230
 
188
231
  it 'should ensure database is unlocked' do
189
- db.lock = true
190
-
191
232
  db.expects(:lock_database).in_sequence(s)
192
233
  db.expects(:specific_collection_dump!).in_sequence(s).
193
234
  raises('Test Error Message')
@@ -239,6 +280,9 @@ describe Backup::Database::MongoDB do
239
280
 
240
281
  describe '#package!' do
241
282
  let(:compressor) { mock }
283
+ let(:pipeline) { mock }
284
+ let(:timestamp) { Time.now.to_i.to_s[-5, 5] }
285
+ let(:s) { sequence '' }
242
286
 
243
287
  context 'when a compressor is configured' do
244
288
  before do
@@ -247,18 +291,62 @@ describe Backup::Database::MongoDB do
247
291
  db.expects(:utility).with(:tar).returns('tar')
248
292
  model.expects(:compressor).twice.returns(compressor)
249
293
  compressor.expects(:compress_with).yields('compressor_command', '.gz')
294
+ Backup::Pipeline.expects(:new).returns(pipeline)
250
295
  end
251
296
 
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')
297
+ context 'when pipeline command succeeds' do
298
+ it 'should package the dump directory, then remove it' do
299
+
300
+ Backup::Logger.expects(:message).in_sequence(s).with(
301
+ "Database::MongoDB started compressing and packaging:\n" +
302
+ " '/path/to/dump/folder'"
303
+ )
304
+
305
+ pipeline.expects(:<<).in_sequence(s).with(
306
+ "tar -cf - -C '/path/to/dump' 'folder'"
307
+ )
308
+ pipeline.expects(:<<).in_sequence(s).with('compressor_command')
309
+ pipeline.expects(:<<).in_sequence(s).with(
310
+ "cat > /path/to/dump/folder-#{ timestamp }.tar.gz"
311
+ )
312
+
313
+ pipeline.expects(:run).in_sequence(s)
314
+ pipeline.expects(:success?).in_sequence(s).returns(true)
315
+ Backup::Logger.expects(:message).in_sequence(s).with(
316
+ "Database::MongoDB completed compressing and packaging:\n" +
317
+ " '/path/to/dump/folder-#{ timestamp }.tar.gz'"
318
+ )
319
+ FileUtils.expects(:rm_rf).in_sequence(s).with('/path/to/dump/folder')
320
+
321
+ db.send(:package!)
322
+ end
323
+ end #context 'when pipeline command succeeds'
324
+
325
+ context 'when pipeline command fails' do
326
+ before do
327
+ pipeline.stubs(:<<)
328
+ pipeline.expects(:run)
329
+ pipeline.expects(:success?).returns(false)
330
+ pipeline.expects(:error_messages).returns('pipeline_errors')
331
+ end
259
332
 
260
- db.send(:package!)
261
- end
333
+ it 'should raise an error' do
334
+ Backup::Logger.expects(:message).with(
335
+ "Database::MongoDB started compressing and packaging:\n" +
336
+ " '/path/to/dump/folder'"
337
+ )
338
+
339
+ expect do
340
+ db.send(:package!)
341
+ end.to raise_error(
342
+ Backup::Errors::Database::PipelineError,
343
+ "Database::PipelineError: Database::MongoDB " +
344
+ "Failed to create compressed dump package:\n" +
345
+ " '/path/to/dump/folder-#{ timestamp }.tar.gz'\n" +
346
+ " pipeline_errors"
347
+ )
348
+ end
349
+ end # context 'when pipeline command fails'
262
350
  end
263
351
 
264
352
  context 'when a compressor is not configured' do
@@ -267,11 +355,11 @@ describe Backup::Database::MongoDB do
267
355
  end
268
356
 
269
357
  it 'should return nil' do
270
- db.expects(:run).never
358
+ Backup::Pipeline.expects(:new).never
271
359
  db.send(:package!).should be_nil
272
360
  end
273
361
  end
274
- end
362
+ end # describe '#package!'
275
363
 
276
364
  describe '#database' do
277
365
  context 'when a database name is given' do
@@ -383,4 +471,41 @@ describe Backup::Database::MongoDB do
383
471
  end
384
472
  end
385
473
  end
474
+
475
+ describe 'deprecations' do
476
+ after do
477
+ Backup::Database::MongoDB.clear_defaults!
478
+ end
479
+
480
+ describe '#utility_path' do
481
+ before do
482
+ Backup::Database::MongoDB.any_instance.stubs(:utility)
483
+ Backup::Logger.expects(:warn).with(
484
+ instance_of(Backup::Errors::ConfigurationError)
485
+ )
486
+ Backup::Logger.expects(:warn).with(
487
+ "Backup::Database::MongoDB.mongodump_utility is being set to 'foo'"
488
+ )
489
+ end
490
+
491
+ context 'when set directly' do
492
+ it 'should issue a deprecation warning and set the replacement value' do
493
+ mongodb = Backup::Database::MongoDB.new(model) do |db|
494
+ db.utility_path = 'foo'
495
+ end
496
+ mongodb.mongodump_utility.should == 'foo'
497
+ end
498
+ end
499
+
500
+ context 'when set as a default' do
501
+ it 'should issue a deprecation warning and set the replacement value' do
502
+ mongodb = Backup::Database::MongoDB.defaults do |db|
503
+ db.utility_path = 'foo'
504
+ end
505
+ mongodb = Backup::Database::MongoDB.new(model)
506
+ mongodb.mongodump_utility.should == 'foo'
507
+ end
508
+ end
509
+ end # describe '#utility_path'
510
+ end
386
511
  end
@@ -20,49 +20,66 @@ describe Backup::Database::MySQL do
20
20
  end
21
21
  end
22
22
 
23
+ it 'should be a subclass of Database::Base' do
24
+ Backup::Database::MySQL.superclass.
25
+ should == Backup::Database::Base
26
+ end
27
+
23
28
  describe '#initialize' do
24
- it 'should read the adapter details correctly' do
25
- db.name.should == 'mydatabase'
26
- db.username.should == 'someuser'
27
- db.password.should == 'secret'
28
- db.host.should == 'localhost'
29
- db.port.should == '123'
30
- db.socket.should == '/mysql.sock'
31
-
32
- db.skip_tables.should == ['logs', 'profiles']
33
- db.only_tables.should == ['users', 'pirates']
34
- db.additional_options.should == ['--single-transaction', '--quick']
35
- db.mysqldump_utility.should == '/path/to/mysqldump'
29
+
30
+ it 'should load pre-configured defaults through Base' do
31
+ Backup::Database::MySQL.any_instance.expects(:load_defaults!)
32
+ db
36
33
  end
37
34
 
38
- context 'when options are not set' do
39
- before do
40
- Backup::Database::MySQL.any_instance.expects(:utility).
41
- with(:mysqldump).returns('/real/mysqldump')
35
+ it 'should pass the model reference to Base' do
36
+ db.instance_variable_get(:@model).should == model
37
+ end
38
+
39
+ context 'when no pre-configured defaults have been set' do
40
+ context 'when options are specified' do
41
+ it 'should use the given values' do
42
+ db.name.should == 'mydatabase'
43
+ db.username.should == 'someuser'
44
+ db.password.should == 'secret'
45
+ db.host.should == 'localhost'
46
+ db.port.should == '123'
47
+ db.socket.should == '/mysql.sock'
48
+
49
+ db.skip_tables.should == ['logs', 'profiles']
50
+ db.only_tables.should == ['users', 'pirates']
51
+ db.additional_options.should == ['--single-transaction', '--quick']
52
+ db.mysqldump_utility.should == '/path/to/mysqldump'
53
+ end
42
54
  end
43
55
 
44
- it 'should use default values' do
45
- db = Backup::Database::MySQL.new(model)
56
+ context 'when options are not specified' do
57
+ before do
58
+ Backup::Database::MySQL.any_instance.expects(:utility).
59
+ with(:mysqldump).returns('/real/mysqldump')
60
+ end
46
61
 
47
- db.name.should == :all
48
- db.username.should be_nil
49
- db.password.should be_nil
50
- db.host.should be_nil
51
- db.port.should be_nil
52
- db.socket.should be_nil
62
+ it 'should provide default values' do
63
+ db = Backup::Database::MySQL.new(model)
53
64
 
54
- db.skip_tables.should == []
55
- db.only_tables.should == []
56
- db.additional_options.should == []
57
- db.mysqldump_utility.should == '/real/mysqldump'
58
- end
59
- end
65
+ db.name.should == :all
66
+ db.username.should be_nil
67
+ db.password.should be_nil
68
+ db.host.should be_nil
69
+ db.port.should be_nil
70
+ db.socket.should be_nil
60
71
 
61
- context 'when configuration defaults have been set' do
62
- after { Backup::Configuration::Database::MySQL.clear_defaults! }
72
+ db.skip_tables.should == []
73
+ db.only_tables.should == []
74
+ db.additional_options.should == []
75
+ db.mysqldump_utility.should == '/real/mysqldump'
76
+ end
77
+ end
78
+ end # context 'when no pre-configured defaults have been set'
63
79
 
64
- it 'should use configuration defaults' do
65
- Backup::Configuration::Database::MySQL.defaults do |db|
80
+ context 'when pre-configured defaults have been set' do
81
+ before do
82
+ Backup::Database::MySQL.defaults do |db|
66
83
  db.name = 'db_name'
67
84
  db.username = 'db_username'
68
85
  db.password = 'db_password'
@@ -75,25 +92,50 @@ describe Backup::Database::MySQL do
75
92
  db.additional_options = ['--add', '--opts']
76
93
  db.mysqldump_utility = '/default/path/to/mysqldump'
77
94
  end
95
+ end
78
96
 
79
- db = Backup::Database::MySQL.new(model)
80
- db.name.should == 'db_name'
81
- db.username.should == 'db_username'
82
- db.password.should == 'db_password'
83
- db.host.should == 'db_host'
84
- db.port.should == 789
85
- db.socket.should == '/foo.sock'
86
-
87
- db.skip_tables.should == ['skip', 'tables']
88
- db.only_tables.should == ['only', 'tables']
89
- db.additional_options.should == ['--add', '--opts']
90
- db.mysqldump_utility.should == '/default/path/to/mysqldump'
97
+ after { Backup::Database::MySQL.clear_defaults! }
98
+
99
+ context 'when options are specified' do
100
+ it 'should override the pre-configured defaults' do
101
+ db.name.should == 'mydatabase'
102
+ db.username.should == 'someuser'
103
+ db.password.should == 'secret'
104
+ db.host.should == 'localhost'
105
+ db.port.should == '123'
106
+ db.socket.should == '/mysql.sock'
107
+
108
+ db.skip_tables.should == ['logs', 'profiles']
109
+ db.only_tables.should == ['users', 'pirates']
110
+ db.additional_options.should == ['--single-transaction', '--quick']
111
+ db.mysqldump_utility.should == '/path/to/mysqldump'
112
+ end
91
113
  end
92
- end
114
+
115
+ context 'when options are not specified' do
116
+ it 'should use the pre-configured defaults' do
117
+ db = Backup::Database::MySQL.new(model)
118
+
119
+ db.name.should == 'db_name'
120
+ db.username.should == 'db_username'
121
+ db.password.should == 'db_password'
122
+ db.host.should == 'db_host'
123
+ db.port.should == 789
124
+ db.socket.should == '/foo.sock'
125
+
126
+ db.skip_tables.should == ['skip', 'tables']
127
+ db.only_tables.should == ['only', 'tables']
128
+ db.additional_options.should == ['--add', '--opts']
129
+ db.mysqldump_utility.should == '/default/path/to/mysqldump'
130
+ end
131
+ end
132
+ end # context 'when no pre-configured defaults have been set'
93
133
  end # describe '#initialize'
94
134
 
95
135
  describe '#perform!' do
96
136
  let(:s) { sequence '' }
137
+ let(:pipeline) { mock }
138
+
97
139
  before do
98
140
  # superclass actions
99
141
  db.expects(:prepare!).in_sequence(s)
@@ -102,17 +144,25 @@ describe Backup::Database::MySQL do
102
144
 
103
145
  db.stubs(:mysqldump).returns('mysqldump_command')
104
146
  db.stubs(:dump_filename).returns('dump_filename')
147
+ Backup::Pipeline.expects(:new).returns(pipeline)
105
148
  end
106
149
 
107
150
  context 'when no compressor is configured' do
108
151
  before do
109
- model.expects(:compressor).in_sequence(s).returns(nil)
152
+ model.expects(:compressor).returns(nil)
110
153
  end
111
154
 
112
155
  it 'should run mysqldump without compression' do
113
- db.expects(:run).in_sequence(s).with(
114
- "mysqldump_command > '/dump/path/dump_filename.sql'"
156
+ pipeline.expects(:<<).in_sequence(s).with('mysqldump_command')
157
+ pipeline.expects(:<<).in_sequence(s).with(
158
+ "cat > '/dump/path/dump_filename.sql'"
159
+ )
160
+ pipeline.expects(:run).in_sequence(s)
161
+ pipeline.expects(:success?).in_sequence(s).returns(true)
162
+ Backup::Logger.expects(:message).in_sequence(s).with(
163
+ 'Database::MySQL Complete!'
115
164
  )
165
+
116
166
  db.perform!
117
167
  end
118
168
  end
@@ -120,18 +170,46 @@ describe Backup::Database::MySQL do
120
170
  context 'when a compressor is configured' do
121
171
  before do
122
172
  compressor = mock
123
- model.expects(:compressor).twice.in_sequence(s).returns(compressor)
124
- compressor.expects(:compress_with).in_sequence(s).yields('gzip', '.gz')
173
+ model.expects(:compressor).twice.returns(compressor)
174
+ compressor.expects(:compress_with).yields('gzip', '.gz')
125
175
  end
126
176
 
127
177
  it 'should run mysqldump with compression' do
128
- db.expects(:run).in_sequence(s).with(
129
- "mysqldump_command | gzip > '/dump/path/dump_filename.sql.gz'"
178
+ pipeline.expects(:<<).in_sequence(s).with('mysqldump_command')
179
+ pipeline.expects(:<<).in_sequence(s).with('gzip')
180
+ pipeline.expects(:<<).in_sequence(s).with(
181
+ "cat > '/dump/path/dump_filename.sql.gz'"
182
+ )
183
+ pipeline.expects(:run).in_sequence(s)
184
+ pipeline.expects(:success?).in_sequence(s).returns(true)
185
+ Backup::Logger.expects(:message).in_sequence(s).with(
186
+ 'Database::MySQL Complete!'
130
187
  )
188
+
131
189
  db.perform!
132
190
  end
133
191
  end
134
192
 
193
+ context 'when pipeline command fails' do
194
+ before do
195
+ model.expects(:compressor).returns(nil)
196
+ pipeline.stubs(:<<)
197
+ pipeline.expects(:run)
198
+ pipeline.expects(:success?).returns(false)
199
+ pipeline.expects(:error_messages).returns('pipeline_errors')
200
+ end
201
+
202
+ it 'should raise an error' do
203
+ expect do
204
+ db.perform!
205
+ end.to raise_error(
206
+ Backup::Errors::Database::PipelineError,
207
+ "Database::PipelineError: Database::MySQL Dump Failed!\n" +
208
+ " pipeline_errors"
209
+ )
210
+ end
211
+ end # context 'when pipeline command fails'
212
+
135
213
  end # describe '#perform!'
136
214
 
137
215
  describe '#mysqldump' do
@@ -261,18 +339,22 @@ describe Backup::Database::MySQL do
261
339
  "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
262
340
  end
263
341
 
264
- context 'when #skip_tables is not set' do
265
- before { db.skip_tables = [] }
266
- it 'should return an empty string' do
267
- db.send(:tables_to_skip).should == ''
268
- end
342
+ it 'should return an empty string if #skip_tables is empty' do
343
+ db.skip_tables = []
344
+ db.send(:tables_to_skip).should == ''
269
345
  end
270
346
 
271
- context 'when dump_all? is true' do
272
- before { db.stubs(:dump_all?).returns(true) }
273
- it 'should return nil' do
274
- db.send(:tables_to_skip).should be_nil
275
- end
347
+ it 'should accept table names prefixed with the database name' do
348
+ db.skip_tables = ['table_name', 'db_name.table_name']
349
+ db.send(:tables_to_skip).should ==
350
+ "--ignore-table='mydatabase.table_name' --ignore-table='db_name.table_name'"
351
+ end
352
+
353
+ it 'should not prefix table name if dump_all? is true' do
354
+ db.name = :all
355
+ db.skip_tables = ['table_name', 'db_name.table_name']
356
+ db.send(:tables_to_skip).should ==
357
+ "--ignore-table='table_name' --ignore-table='db_name.table_name'"
276
358
  end
277
359
  end
278
360
 
@@ -290,4 +372,41 @@ describe Backup::Database::MySQL do
290
372
  end
291
373
  end
292
374
  end
375
+
376
+ describe 'deprecations' do
377
+ after do
378
+ Backup::Database::MySQL.clear_defaults!
379
+ end
380
+
381
+ describe '#utility_path' do
382
+ before do
383
+ Backup::Database::MySQL.any_instance.stubs(:utility)
384
+ Backup::Logger.expects(:warn).with(
385
+ instance_of(Backup::Errors::ConfigurationError)
386
+ )
387
+ Backup::Logger.expects(:warn).with(
388
+ "Backup::Database::MySQL.mysqldump_utility is being set to 'foo'"
389
+ )
390
+ end
391
+
392
+ context 'when set directly' do
393
+ it 'should issue a deprecation warning and set the replacement value' do
394
+ mysql = Backup::Database::MySQL.new(model) do |db|
395
+ db.utility_path = 'foo'
396
+ end
397
+ mysql.mysqldump_utility.should == 'foo'
398
+ end
399
+ end
400
+
401
+ context 'when set as a default' do
402
+ it 'should issue a deprecation warning and set the replacement value' do
403
+ mysql = Backup::Database::MySQL.defaults do |db|
404
+ db.utility_path = 'foo'
405
+ end
406
+ mysql = Backup::Database::MySQL.new(model)
407
+ mysql.mysqldump_utility.should == 'foo'
408
+ end
409
+ end
410
+ end # describe '#utility_path'
411
+ end
293
412
  end