backup_checksum 3.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +28 -0
  4. data/Gemfile.lock +130 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.md +24 -0
  7. data/README.md +476 -0
  8. data/backup_checksum.gemspec +32 -0
  9. data/bin/backup +11 -0
  10. data/lib/backup.rb +217 -0
  11. data/lib/backup/archive.rb +117 -0
  12. data/lib/backup/binder.rb +22 -0
  13. data/lib/backup/checksum/base.rb +44 -0
  14. data/lib/backup/checksum/shasum.rb +16 -0
  15. data/lib/backup/cleaner.rb +121 -0
  16. data/lib/backup/cli/helpers.rb +88 -0
  17. data/lib/backup/cli/utility.rb +247 -0
  18. data/lib/backup/compressor/base.rb +29 -0
  19. data/lib/backup/compressor/bzip2.rb +50 -0
  20. data/lib/backup/compressor/gzip.rb +47 -0
  21. data/lib/backup/compressor/lzma.rb +50 -0
  22. data/lib/backup/compressor/pbzip2.rb +56 -0
  23. data/lib/backup/config.rb +173 -0
  24. data/lib/backup/configuration/base.rb +15 -0
  25. data/lib/backup/configuration/checksum/base.rb +9 -0
  26. data/lib/backup/configuration/checksum/shasum.rb +9 -0
  27. data/lib/backup/configuration/compressor/base.rb +9 -0
  28. data/lib/backup/configuration/compressor/bzip2.rb +23 -0
  29. data/lib/backup/configuration/compressor/gzip.rb +23 -0
  30. data/lib/backup/configuration/compressor/lzma.rb +23 -0
  31. data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
  32. data/lib/backup/configuration/database/base.rb +19 -0
  33. data/lib/backup/configuration/database/mongodb.rb +49 -0
  34. data/lib/backup/configuration/database/mysql.rb +42 -0
  35. data/lib/backup/configuration/database/postgresql.rb +41 -0
  36. data/lib/backup/configuration/database/redis.rb +39 -0
  37. data/lib/backup/configuration/database/riak.rb +29 -0
  38. data/lib/backup/configuration/encryptor/base.rb +9 -0
  39. data/lib/backup/configuration/encryptor/gpg.rb +17 -0
  40. data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
  41. data/lib/backup/configuration/helpers.rb +52 -0
  42. data/lib/backup/configuration/notifier/base.rb +28 -0
  43. data/lib/backup/configuration/notifier/campfire.rb +25 -0
  44. data/lib/backup/configuration/notifier/hipchat.rb +41 -0
  45. data/lib/backup/configuration/notifier/mail.rb +112 -0
  46. data/lib/backup/configuration/notifier/presently.rb +25 -0
  47. data/lib/backup/configuration/notifier/prowl.rb +23 -0
  48. data/lib/backup/configuration/notifier/twitter.rb +21 -0
  49. data/lib/backup/configuration/storage/base.rb +18 -0
  50. data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
  51. data/lib/backup/configuration/storage/dropbox.rb +58 -0
  52. data/lib/backup/configuration/storage/ftp.rb +29 -0
  53. data/lib/backup/configuration/storage/local.rb +17 -0
  54. data/lib/backup/configuration/storage/ninefold.rb +20 -0
  55. data/lib/backup/configuration/storage/rsync.rb +29 -0
  56. data/lib/backup/configuration/storage/s3.rb +25 -0
  57. data/lib/backup/configuration/storage/scp.rb +25 -0
  58. data/lib/backup/configuration/storage/sftp.rb +25 -0
  59. data/lib/backup/configuration/syncer/base.rb +10 -0
  60. data/lib/backup/configuration/syncer/cloud.rb +23 -0
  61. data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
  62. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  63. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  64. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  65. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  66. data/lib/backup/configuration/syncer/s3.rb +23 -0
  67. data/lib/backup/database/base.rb +59 -0
  68. data/lib/backup/database/mongodb.rb +232 -0
  69. data/lib/backup/database/mysql.rb +163 -0
  70. data/lib/backup/database/postgresql.rb +146 -0
  71. data/lib/backup/database/redis.rb +139 -0
  72. data/lib/backup/database/riak.rb +69 -0
  73. data/lib/backup/dependency.rb +114 -0
  74. data/lib/backup/encryptor/base.rb +29 -0
  75. data/lib/backup/encryptor/gpg.rb +80 -0
  76. data/lib/backup/encryptor/open_ssl.rb +72 -0
  77. data/lib/backup/errors.rb +124 -0
  78. data/lib/backup/logger.rb +152 -0
  79. data/lib/backup/model.rb +386 -0
  80. data/lib/backup/notifier/base.rb +81 -0
  81. data/lib/backup/notifier/campfire.rb +168 -0
  82. data/lib/backup/notifier/hipchat.rb +99 -0
  83. data/lib/backup/notifier/mail.rb +206 -0
  84. data/lib/backup/notifier/presently.rb +88 -0
  85. data/lib/backup/notifier/prowl.rb +65 -0
  86. data/lib/backup/notifier/twitter.rb +70 -0
  87. data/lib/backup/package.rb +51 -0
  88. data/lib/backup/packager.rb +108 -0
  89. data/lib/backup/pipeline.rb +107 -0
  90. data/lib/backup/splitter.rb +75 -0
  91. data/lib/backup/storage/base.rb +119 -0
  92. data/lib/backup/storage/cloudfiles.rb +87 -0
  93. data/lib/backup/storage/cycler.rb +117 -0
  94. data/lib/backup/storage/dropbox.rb +181 -0
  95. data/lib/backup/storage/ftp.rb +119 -0
  96. data/lib/backup/storage/local.rb +82 -0
  97. data/lib/backup/storage/ninefold.rb +116 -0
  98. data/lib/backup/storage/rsync.rb +149 -0
  99. data/lib/backup/storage/s3.rb +94 -0
  100. data/lib/backup/storage/scp.rb +99 -0
  101. data/lib/backup/storage/sftp.rb +108 -0
  102. data/lib/backup/syncer/base.rb +42 -0
  103. data/lib/backup/syncer/cloud.rb +190 -0
  104. data/lib/backup/syncer/cloud_files.rb +56 -0
  105. data/lib/backup/syncer/rsync/base.rb +52 -0
  106. data/lib/backup/syncer/rsync/local.rb +53 -0
  107. data/lib/backup/syncer/rsync/pull.rb +38 -0
  108. data/lib/backup/syncer/rsync/push.rb +113 -0
  109. data/lib/backup/syncer/s3.rb +47 -0
  110. data/lib/backup/template.rb +46 -0
  111. data/lib/backup/version.rb +43 -0
  112. data/spec/archive_spec.rb +335 -0
  113. data/spec/cleaner_spec.rb +304 -0
  114. data/spec/cli/helpers_spec.rb +176 -0
  115. data/spec/cli/utility_spec.rb +363 -0
  116. data/spec/compressor/base_spec.rb +31 -0
  117. data/spec/compressor/bzip2_spec.rb +83 -0
  118. data/spec/compressor/gzip_spec.rb +83 -0
  119. data/spec/compressor/lzma_spec.rb +83 -0
  120. data/spec/compressor/pbzip2_spec.rb +124 -0
  121. data/spec/config_spec.rb +321 -0
  122. data/spec/configuration/base_spec.rb +35 -0
  123. data/spec/configuration/compressor/bzip2_spec.rb +29 -0
  124. data/spec/configuration/compressor/gzip_spec.rb +29 -0
  125. data/spec/configuration/compressor/lzma_spec.rb +29 -0
  126. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  127. data/spec/configuration/database/base_spec.rb +17 -0
  128. data/spec/configuration/database/mongodb_spec.rb +56 -0
  129. data/spec/configuration/database/mysql_spec.rb +53 -0
  130. data/spec/configuration/database/postgresql_spec.rb +53 -0
  131. data/spec/configuration/database/redis_spec.rb +50 -0
  132. data/spec/configuration/database/riak_spec.rb +35 -0
  133. data/spec/configuration/encryptor/gpg_spec.rb +26 -0
  134. data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
  135. data/spec/configuration/notifier/base_spec.rb +32 -0
  136. data/spec/configuration/notifier/campfire_spec.rb +32 -0
  137. data/spec/configuration/notifier/hipchat_spec.rb +44 -0
  138. data/spec/configuration/notifier/mail_spec.rb +71 -0
  139. data/spec/configuration/notifier/presently_spec.rb +35 -0
  140. data/spec/configuration/notifier/prowl_spec.rb +29 -0
  141. data/spec/configuration/notifier/twitter_spec.rb +35 -0
  142. data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
  143. data/spec/configuration/storage/dropbox_spec.rb +38 -0
  144. data/spec/configuration/storage/ftp_spec.rb +44 -0
  145. data/spec/configuration/storage/local_spec.rb +29 -0
  146. data/spec/configuration/storage/ninefold_spec.rb +32 -0
  147. data/spec/configuration/storage/rsync_spec.rb +41 -0
  148. data/spec/configuration/storage/s3_spec.rb +38 -0
  149. data/spec/configuration/storage/scp_spec.rb +41 -0
  150. data/spec/configuration/storage/sftp_spec.rb +41 -0
  151. data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
  152. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  153. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  154. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  155. data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
  156. data/spec/configuration/syncer/s3_spec.rb +38 -0
  157. data/spec/database/base_spec.rb +54 -0
  158. data/spec/database/mongodb_spec.rb +428 -0
  159. data/spec/database/mysql_spec.rb +335 -0
  160. data/spec/database/postgresql_spec.rb +278 -0
  161. data/spec/database/redis_spec.rb +260 -0
  162. data/spec/database/riak_spec.rb +108 -0
  163. data/spec/dependency_spec.rb +49 -0
  164. data/spec/encryptor/base_spec.rb +30 -0
  165. data/spec/encryptor/gpg_spec.rb +134 -0
  166. data/spec/encryptor/open_ssl_spec.rb +129 -0
  167. data/spec/errors_spec.rb +306 -0
  168. data/spec/logger_spec.rb +363 -0
  169. data/spec/model_spec.rb +649 -0
  170. data/spec/notifier/base_spec.rb +89 -0
  171. data/spec/notifier/campfire_spec.rb +199 -0
  172. data/spec/notifier/hipchat_spec.rb +188 -0
  173. data/spec/notifier/mail_spec.rb +280 -0
  174. data/spec/notifier/presently_spec.rb +181 -0
  175. data/spec/notifier/prowl_spec.rb +117 -0
  176. data/spec/notifier/twitter_spec.rb +132 -0
  177. data/spec/package_spec.rb +61 -0
  178. data/spec/packager_spec.rb +225 -0
  179. data/spec/pipeline_spec.rb +257 -0
  180. data/spec/spec_helper.rb +59 -0
  181. data/spec/splitter_spec.rb +120 -0
  182. data/spec/storage/base_spec.rb +160 -0
  183. data/spec/storage/cloudfiles_spec.rb +230 -0
  184. data/spec/storage/cycler_spec.rb +239 -0
  185. data/spec/storage/dropbox_spec.rb +370 -0
  186. data/spec/storage/ftp_spec.rb +247 -0
  187. data/spec/storage/local_spec.rb +235 -0
  188. data/spec/storage/ninefold_spec.rb +319 -0
  189. data/spec/storage/rsync_spec.rb +345 -0
  190. data/spec/storage/s3_spec.rb +221 -0
  191. data/spec/storage/scp_spec.rb +209 -0
  192. data/spec/storage/sftp_spec.rb +220 -0
  193. data/spec/syncer/base_spec.rb +22 -0
  194. data/spec/syncer/cloud_files_spec.rb +192 -0
  195. data/spec/syncer/rsync/base_spec.rb +118 -0
  196. data/spec/syncer/rsync/local_spec.rb +121 -0
  197. data/spec/syncer/rsync/pull_spec.rb +90 -0
  198. data/spec/syncer/rsync/push_spec.rb +327 -0
  199. data/spec/syncer/s3_spec.rb +192 -0
  200. data/spec/version_spec.rb +21 -0
  201. data/templates/cli/utility/archive +25 -0
  202. data/templates/cli/utility/compressor/bzip2 +7 -0
  203. data/templates/cli/utility/compressor/gzip +7 -0
  204. data/templates/cli/utility/compressor/lzma +7 -0
  205. data/templates/cli/utility/compressor/pbzip2 +7 -0
  206. data/templates/cli/utility/config +31 -0
  207. data/templates/cli/utility/database/mongodb +18 -0
  208. data/templates/cli/utility/database/mysql +21 -0
  209. data/templates/cli/utility/database/postgresql +17 -0
  210. data/templates/cli/utility/database/redis +16 -0
  211. data/templates/cli/utility/database/riak +11 -0
  212. data/templates/cli/utility/encryptor/gpg +12 -0
  213. data/templates/cli/utility/encryptor/openssl +9 -0
  214. data/templates/cli/utility/model.erb +23 -0
  215. data/templates/cli/utility/notifier/campfire +12 -0
  216. data/templates/cli/utility/notifier/hipchat +15 -0
  217. data/templates/cli/utility/notifier/mail +22 -0
  218. data/templates/cli/utility/notifier/presently +13 -0
  219. data/templates/cli/utility/notifier/prowl +11 -0
  220. data/templates/cli/utility/notifier/twitter +13 -0
  221. data/templates/cli/utility/splitter +7 -0
  222. data/templates/cli/utility/storage/cloud_files +22 -0
  223. data/templates/cli/utility/storage/dropbox +20 -0
  224. data/templates/cli/utility/storage/ftp +12 -0
  225. data/templates/cli/utility/storage/local +7 -0
  226. data/templates/cli/utility/storage/ninefold +9 -0
  227. data/templates/cli/utility/storage/rsync +11 -0
  228. data/templates/cli/utility/storage/s3 +19 -0
  229. data/templates/cli/utility/storage/scp +11 -0
  230. data/templates/cli/utility/storage/sftp +11 -0
  231. data/templates/cli/utility/syncer/cloud_files +48 -0
  232. data/templates/cli/utility/syncer/rsync_local +12 -0
  233. data/templates/cli/utility/syncer/rsync_pull +17 -0
  234. data/templates/cli/utility/syncer/rsync_push +17 -0
  235. data/templates/cli/utility/syncer/s3 +45 -0
  236. data/templates/general/links +11 -0
  237. data/templates/general/version.erb +2 -0
  238. data/templates/notifier/mail/failure.erb +9 -0
  239. data/templates/notifier/mail/success.erb +7 -0
  240. data/templates/notifier/mail/warning.erb +9 -0
  241. data/templates/storage/dropbox/authorization_url.erb +6 -0
  242. data/templates/storage/dropbox/authorized.erb +4 -0
  243. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  244. metadata +311 -0
@@ -0,0 +1,428 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Database::MongoDB do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:db) do
8
+ Backup::Database::MongoDB.new(model) do |db|
9
+ db.name = 'mydatabase'
10
+ db.username = 'someuser'
11
+ db.password = 'secret'
12
+ db.host = 'localhost'
13
+ db.port = 123
14
+
15
+ db.ipv6 = true
16
+ db.only_collections = ['users', 'pirates']
17
+ db.additional_options = ['--query', '--foo']
18
+ db.mongodump_utility = '/path/to/mongodump'
19
+ db.mongo_utility = '/path/to/mongo'
20
+ end
21
+ end
22
+
23
+ describe '#initialize' do
24
+
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
38
+ end
39
+
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
47
+
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
64
+ end
65
+
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
99
+ end
100
+ end # describe '#initialize'
101
+
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)
109
+ end
110
+
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
124
+ end
125
+
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
131
+
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'
139
+
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
154
+ end
155
+
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
187
+
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
206
+ end
207
+
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!)
215
+ end
216
+ end
217
+
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!)
224
+ end
225
+ end
226
+
227
+ describe '#mongodump' do
228
+ before do
229
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
230
+ end
231
+
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'"
237
+ end
238
+ end
239
+
240
+ describe '#package!' do
241
+ let(:compressor) { mock }
242
+ let(:pipeline) { mock }
243
+ let(:timestamp) { Time.now.to_i.to_s[-5, 5] }
244
+ let(:s) { sequence '' }
245
+
246
+ context 'when a compressor is configured' do
247
+ before do
248
+ Timecop.freeze(Time.now)
249
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
250
+ db.expects(:utility).with(:tar).returns('tar')
251
+ model.expects(:compressor).twice.returns(compressor)
252
+ compressor.expects(:compress_with).yields('compressor_command', '.gz')
253
+ Backup::Pipeline.expects(:new).returns(pipeline)
254
+ end
255
+
256
+ context 'when pipeline command succeeds' do
257
+ it 'should package the dump directory, then remove it' do
258
+
259
+ Backup::Logger.expects(:message).in_sequence(s).with(
260
+ "Database::MongoDB started compressing and packaging:\n" +
261
+ " '/path/to/dump/folder'"
262
+ )
263
+
264
+ pipeline.expects(:<<).in_sequence(s).with(
265
+ "tar -cf - -C '/path/to/dump' 'folder'"
266
+ )
267
+ pipeline.expects(:<<).in_sequence(s).with('compressor_command')
268
+ pipeline.expects(:<<).in_sequence(s).with(
269
+ "cat > /path/to/dump/folder-#{ timestamp }.tar.gz"
270
+ )
271
+
272
+ pipeline.expects(:run).in_sequence(s)
273
+ pipeline.expects(:success?).in_sequence(s).returns(true)
274
+ Backup::Logger.expects(:message).in_sequence(s).with(
275
+ "Database::MongoDB completed compressing and packaging:\n" +
276
+ " '/path/to/dump/folder-#{ timestamp }.tar.gz'"
277
+ )
278
+ FileUtils.expects(:rm_rf).in_sequence(s).with('/path/to/dump/folder')
279
+
280
+ db.send(:package!)
281
+ end
282
+ end #context 'when pipeline command succeeds'
283
+
284
+ context 'when pipeline command fails' do
285
+ before do
286
+ pipeline.stubs(:<<)
287
+ pipeline.expects(:run)
288
+ pipeline.expects(:success?).returns(false)
289
+ pipeline.expects(:error_messages).returns('pipeline_errors')
290
+ end
291
+
292
+ it 'should raise an error' do
293
+ expect do
294
+ db.send(:package!)
295
+ end.to raise_error(
296
+ Backup::Errors::Database::PipelineError,
297
+ "Database::PipelineError: Database::MongoDB " +
298
+ "Failed to create compressed dump package:\n" +
299
+ " '/path/to/dump/folder-#{ timestamp }.tar.gz'\n" +
300
+ " pipeline_errors"
301
+ )
302
+ end
303
+ end # context 'when pipeline command fails'
304
+ end
305
+
306
+ context 'when a compressor is not configured' do
307
+ before do
308
+ model.expects(:compressor).returns(nil)
309
+ end
310
+
311
+ it 'should return nil' do
312
+ Backup::Pipeline.expects(:new).never
313
+ db.send(:package!).should be_nil
314
+ end
315
+ end
316
+ end # describe '#package!'
317
+
318
+ describe '#database' do
319
+ context 'when a database name is given' do
320
+ it 'should return the command string for the database' do
321
+ db.send(:database).should == "--db='mydatabase'"
322
+ end
323
+ end
324
+
325
+ context 'when no database name is given' do
326
+ it 'should return nil' do
327
+ db.name = nil
328
+ db.send(:database).should be_nil
329
+ end
330
+ end
331
+ end
332
+
333
+ describe '#credential_options' do
334
+ it 'should return the command string for the user credentials' do
335
+ db.send(:credential_options).should ==
336
+ "--username='someuser' --password='secret'"
337
+ end
338
+ end
339
+
340
+ describe '#connectivity_options' do
341
+ it 'should return the command string for the connectivity options' do
342
+ db.send(:connectivity_options).should == "--host='localhost' --port='123'"
343
+ end
344
+ end
345
+
346
+ describe '#ipv6_option' do
347
+ context 'when #ipv6 is set true' do
348
+ it 'should return the command string for the ipv6 option' do
349
+ db.send(:ipv6_option).should == '--ipv6'
350
+ end
351
+ end
352
+
353
+ context 'when #ipv6 is set false' do
354
+ it 'should return and empty string' do
355
+ db.ipv6 = false
356
+ db.send(:ipv6_option).should == ''
357
+ end
358
+ end
359
+ end
360
+
361
+ describe '#user_options' do
362
+ context 'when #additional_options are set' do
363
+ it 'should return the command string for the options' do
364
+ db.send(:user_options).should == '--query --foo'
365
+ end
366
+ end
367
+
368
+ context 'when #additional_options are not set' do
369
+ it 'should return an empty string' do
370
+ db.additional_options = []
371
+ db.send(:user_options).should == ''
372
+ end
373
+ end
374
+ end
375
+
376
+ describe '#dump_directory' do
377
+ it 'should return the command string for the dump path' do
378
+ db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
379
+ db.send(:dump_directory).should == "--out='/path/to/dump/folder'"
380
+ end
381
+ end
382
+
383
+ describe '#lock_database' do
384
+ it 'should return the command to lock the database' do
385
+ db.stubs(:mongo_uri).returns(:mongo_uri_output)
386
+ db.expects(:run).with(
387
+ " echo 'use admin\n" +
388
+ ' db.runCommand({"fsync" : 1, "lock" : 1})\' | /path/to/mongo mongo_uri_output' +
389
+ "\n"
390
+ )
391
+ db.send(:lock_database)
392
+ end
393
+ end
394
+
395
+ describe '#unlock_database' do
396
+ it 'should return the command to unlock the database' do
397
+ db.stubs(:mongo_uri).returns(:mongo_uri_output)
398
+ db.expects(:run).with(
399
+ " echo 'use admin\n" +
400
+ ' db.$cmd.sys.unlock.findOne()\' | /path/to/mongo mongo_uri_output' +
401
+ "\n"
402
+ )
403
+ db.send(:unlock_database)
404
+ end
405
+ end
406
+
407
+ describe '#mongo_uri' do
408
+ before do
409
+ db.stubs(:credential_options).returns(:credential_options_output)
410
+ db.stubs(:ipv6_option).returns(:ipv6_option_output)
411
+ end
412
+
413
+ context 'when a database name is given' do
414
+ it 'should return the URI specifying the database' do
415
+ db.send(:mongo_uri).should ==
416
+ "localhost:123/mydatabase credential_options_output ipv6_option_output"
417
+ end
418
+ end
419
+
420
+ context 'when no database name is given' do
421
+ it 'should return the URI without specifying the database' do
422
+ db.name = nil
423
+ db.send(:mongo_uri).should ==
424
+ "localhost:123 credential_options_output ipv6_option_output"
425
+ end
426
+ end
427
+ end
428
+ end
@@ -0,0 +1,335 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Database::MySQL do
6
+ let(:model) { Backup::Model.new('foo', 'foo') }
7
+ let(:db) do
8
+ Backup::Database::MySQL.new(model) do |db|
9
+ db.name = 'mydatabase'
10
+ db.username = 'someuser'
11
+ db.password = 'secret'
12
+ db.host = 'localhost'
13
+ db.port = '123'
14
+ db.socket = '/mysql.sock'
15
+
16
+ db.skip_tables = ['logs', 'profiles']
17
+ db.only_tables = ['users', 'pirates']
18
+ db.additional_options = ['--single-transaction', '--quick']
19
+ db.mysqldump_utility = '/path/to/mysqldump'
20
+ end
21
+ end
22
+
23
+ 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'
36
+ end
37
+
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')
42
+ end
43
+
44
+ it 'should use default values' do
45
+ db = Backup::Database::MySQL.new(model)
46
+
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
53
+
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
60
+
61
+ context 'when configuration defaults have been set' do
62
+ after { Backup::Configuration::Database::MySQL.clear_defaults! }
63
+
64
+ it 'should use configuration defaults' do
65
+ Backup::Configuration::Database::MySQL.defaults do |db|
66
+ db.name = 'db_name'
67
+ db.username = 'db_username'
68
+ db.password = 'db_password'
69
+ db.host = 'db_host'
70
+ db.port = 789
71
+ db.socket = '/foo.sock'
72
+
73
+ db.skip_tables = ['skip', 'tables']
74
+ db.only_tables = ['only', 'tables']
75
+ db.additional_options = ['--add', '--opts']
76
+ db.mysqldump_utility = '/default/path/to/mysqldump'
77
+ end
78
+
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'
91
+ end
92
+ end
93
+ end # describe '#initialize'
94
+
95
+ describe '#perform!' do
96
+ let(:s) { sequence '' }
97
+ let(:pipeline) { mock }
98
+
99
+ before do
100
+ # superclass actions
101
+ db.expects(:prepare!).in_sequence(s)
102
+ db.expects(:log!).in_sequence(s)
103
+ db.instance_variable_set(:@dump_path, '/dump/path')
104
+
105
+ db.stubs(:mysqldump).returns('mysqldump_command')
106
+ db.stubs(:dump_filename).returns('dump_filename')
107
+ Backup::Pipeline.expects(:new).returns(pipeline)
108
+ end
109
+
110
+ context 'when no compressor is configured' do
111
+ before do
112
+ model.expects(:compressor).returns(nil)
113
+ end
114
+
115
+ it 'should run mysqldump without compression' do
116
+ pipeline.expects(:<<).in_sequence(s).with('mysqldump_command')
117
+ pipeline.expects(:<<).in_sequence(s).with(
118
+ "cat > '/dump/path/dump_filename.sql'"
119
+ )
120
+ pipeline.expects(:run).in_sequence(s)
121
+ pipeline.expects(:success?).in_sequence(s).returns(true)
122
+ Backup::Logger.expects(:message).in_sequence(s).with(
123
+ 'Database::MySQL Complete!'
124
+ )
125
+
126
+ db.perform!
127
+ end
128
+ end
129
+
130
+ context 'when a compressor is configured' do
131
+ before do
132
+ compressor = mock
133
+ model.expects(:compressor).twice.returns(compressor)
134
+ compressor.expects(:compress_with).yields('gzip', '.gz')
135
+ end
136
+
137
+ it 'should run mysqldump with compression' do
138
+ pipeline.expects(:<<).in_sequence(s).with('mysqldump_command')
139
+ pipeline.expects(:<<).in_sequence(s).with('gzip')
140
+ pipeline.expects(:<<).in_sequence(s).with(
141
+ "cat > '/dump/path/dump_filename.sql.gz'"
142
+ )
143
+ pipeline.expects(:run).in_sequence(s)
144
+ pipeline.expects(:success?).in_sequence(s).returns(true)
145
+ Backup::Logger.expects(:message).in_sequence(s).with(
146
+ 'Database::MySQL Complete!'
147
+ )
148
+
149
+ db.perform!
150
+ end
151
+ end
152
+
153
+ context 'when pipeline command fails' do
154
+ before do
155
+ model.expects(:compressor).returns(nil)
156
+ pipeline.stubs(:<<)
157
+ pipeline.expects(:run)
158
+ pipeline.expects(:success?).returns(false)
159
+ pipeline.expects(:error_messages).returns('pipeline_errors')
160
+ end
161
+
162
+ it 'should raise an error' do
163
+ expect do
164
+ db.perform!
165
+ end.to raise_error(
166
+ Backup::Errors::Database::PipelineError,
167
+ "Database::PipelineError: Database::MySQL Dump Failed!\n" +
168
+ " pipeline_errors"
169
+ )
170
+ end
171
+ end # context 'when pipeline command fails'
172
+
173
+ end # describe '#perform!'
174
+
175
+ describe '#mysqldump' do
176
+ before do
177
+ db.stubs(:mysqldump_utility).returns(:mysqldump_utility)
178
+ db.stubs(:credential_options).returns(:credential_options)
179
+ db.stubs(:connectivity_options).returns(:connectivity_options)
180
+ db.stubs(:user_options).returns(:user_options)
181
+ db.stubs(:db_name).returns(:db_name)
182
+ db.stubs(:tables_to_dump).returns(:tables_to_dump)
183
+ db.stubs(:tables_to_skip).returns(:tables_to_skip)
184
+ end
185
+
186
+ it 'should return the mysqldump command string' do
187
+ db.send(:mysqldump).should ==
188
+ "mysqldump_utility credential_options connectivity_options " +
189
+ "user_options db_name tables_to_dump tables_to_skip"
190
+ end
191
+ end
192
+
193
+ describe '#dump_filename' do
194
+ context 'when @name is set to :all' do
195
+ before { db.name = :all }
196
+ it 'should set the filename to "all-databases"' do
197
+ db.send(:dump_filename).should == 'all-databases'
198
+ end
199
+ end
200
+
201
+ context 'when @name is not set to :all' do
202
+ it 'should return @name' do
203
+ db.send(:dump_filename).should == 'mydatabase'
204
+ end
205
+ end
206
+ end
207
+
208
+ describe '#credential_options' do
209
+ context 'when a password is set' do
210
+ it 'should return the command string for the user credentials' do
211
+ db.send(:credential_options).should ==
212
+ "--user='someuser' --password='secret'"
213
+ end
214
+ end
215
+
216
+ context 'when no password is set' do
217
+ before { db.password = nil }
218
+ it 'should return the command string for the user credentials' do
219
+ db.send(:credential_options).should ==
220
+ "--user='someuser'"
221
+ end
222
+ end
223
+ end
224
+
225
+ describe '#connectivity_options' do
226
+ it 'should return the mysql syntax for the connectivity options' do
227
+ db.send(:connectivity_options).should ==
228
+ "--host='localhost' --port='123' --socket='/mysql.sock'"
229
+ end
230
+
231
+ context 'when only the socket is set' do
232
+ it 'should return only the socket' do
233
+ db.host = ''
234
+ db.port = nil
235
+ db.send(:connectivity_options).should == "--socket='/mysql.sock'"
236
+ end
237
+ end
238
+
239
+ context 'when only the host and port are set' do
240
+ it 'should return only the host and port' do
241
+ db.socket = nil
242
+ db.send(:connectivity_options).should ==
243
+ "--host='localhost' --port='123'"
244
+ end
245
+ end
246
+ end
247
+
248
+ describe '#user_options' do
249
+ it 'should return a string of additional options specified by the user' do
250
+ db.send(:user_options).should == '--single-transaction --quick'
251
+ end
252
+
253
+ context 'when #additional_options is not set' do
254
+ before { db.additional_options = [] }
255
+ it 'should return an empty string' do
256
+ db.send(:user_options).should == ''
257
+ end
258
+ end
259
+ end
260
+
261
+ describe '#db_name' do
262
+ context 'when @name is set to :all' do
263
+ before { db.name = :all }
264
+ it 'should return the mysqldump flag to dump all databases' do
265
+ db.send(:db_name).should == '--all-databases'
266
+ end
267
+ end
268
+
269
+ context 'when @name is not set to :all' do
270
+ it 'should return @name' do
271
+ db.send(:db_name).should == 'mydatabase'
272
+ end
273
+ end
274
+ end
275
+
276
+ describe '#tables_to_dump' do
277
+ it 'should return a string for the mysqldump selected table to dump option' do
278
+ db.send(:tables_to_dump).should == 'users pirates'
279
+ end
280
+
281
+ context 'when #only_tables is not set' do
282
+ before { db.only_tables = [] }
283
+ it 'should return an empty string' do
284
+ db.send(:tables_to_dump).should == ''
285
+ end
286
+ end
287
+
288
+ context 'when dump_all? is true' do
289
+ before { db.stubs(:dump_all?).returns(true) }
290
+ it 'should return nil' do
291
+ db.send(:tables_to_dump).should be_nil
292
+ end
293
+ end
294
+ end
295
+
296
+ describe '#tables_to_skip' do
297
+ it 'should return a string for the mysqldump --ignore-tables option' do
298
+ db.send(:tables_to_skip).should ==
299
+ "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
300
+ end
301
+
302
+ it 'should return an empty string if #skip_tables is empty' do
303
+ db.skip_tables = []
304
+ db.send(:tables_to_skip).should == ''
305
+ end
306
+
307
+ it 'should accept table names prefixed with the database name' do
308
+ db.skip_tables = ['table_name', 'db_name.table_name']
309
+ db.send(:tables_to_skip).should ==
310
+ "--ignore-table='mydatabase.table_name' --ignore-table='db_name.table_name'"
311
+ end
312
+
313
+ it 'should not prefix table name if dump_all? is true' do
314
+ db.name = :all
315
+ db.skip_tables = ['table_name', 'db_name.table_name']
316
+ db.send(:tables_to_skip).should ==
317
+ "--ignore-table='table_name' --ignore-table='db_name.table_name'"
318
+ end
319
+ end
320
+
321
+ describe '#dump_all?' do
322
+ context 'when @name is set to :all' do
323
+ before { db.name = :all }
324
+ it 'should return true' do
325
+ db.send(:dump_all?).should be_true
326
+ end
327
+ end
328
+
329
+ context 'when @name is not set to :all' do
330
+ it 'should return false' do
331
+ db.send(:dump_all?).should be_false
332
+ end
333
+ end
334
+ end
335
+ end