backup-agoddard 3.0.27

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of backup-agoddard might be problematic. Click here for more details.

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