backup-agoddard 3.0.27

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 (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,271 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Storage::FTP do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:storage) do
8
+ Backup::Storage::FTP.new(model) do |ftp|
9
+ ftp.username = 'my_username'
10
+ ftp.password = 'my_password'
11
+ ftp.ip = '123.45.678.90'
12
+ ftp.keep = 5
13
+ end
14
+ end
15
+
16
+ it 'should be a subclass of Storage::Base' do
17
+ Backup::Storage::FTP.
18
+ superclass.should == Backup::Storage::Base
19
+ end
20
+
21
+ describe '#initialize' do
22
+ after { Backup::Storage::FTP.clear_defaults! }
23
+
24
+ it 'should load pre-configured defaults through Base' do
25
+ Backup::Storage::FTP.any_instance.expects(:load_defaults!)
26
+ storage
27
+ end
28
+
29
+ it 'should pass the model reference to Base' do
30
+ storage.instance_variable_get(:@model).should == model
31
+ end
32
+
33
+ it 'should pass the storage_id to Base' do
34
+ storage = Backup::Storage::FTP.new(model, 'my_storage_id')
35
+ storage.storage_id.should == 'my_storage_id'
36
+ end
37
+
38
+ it 'should remove any preceeding tilde and slash from the path' do
39
+ storage = Backup::Storage::FTP.new(model) do |ftp|
40
+ ftp.path = '~/my_backups/path'
41
+ end
42
+ storage.path.should == 'my_backups/path'
43
+ end
44
+
45
+ context 'when no pre-configured defaults have been set' do
46
+ it 'should use the values given' do
47
+ storage.username.should == 'my_username'
48
+ storage.password.should == 'my_password'
49
+ storage.ip.should == '123.45.678.90'
50
+ storage.port.should == 21
51
+ storage.path.should == 'backups'
52
+ storage.passive_mode.should == false
53
+
54
+ storage.storage_id.should be_nil
55
+ storage.keep.should == 5
56
+ end
57
+
58
+ it 'should use default values if none are given' do
59
+ storage = Backup::Storage::FTP.new(model)
60
+
61
+ storage.username.should be_nil
62
+ storage.password.should be_nil
63
+ storage.ip.should be_nil
64
+ storage.port.should == 21
65
+ storage.path.should == 'backups'
66
+ storage.passive_mode.should == false
67
+
68
+ storage.storage_id.should be_nil
69
+ storage.keep.should be_nil
70
+ end
71
+ end # context 'when no pre-configured defaults have been set'
72
+
73
+ context 'when pre-configured defaults have been set' do
74
+ before do
75
+ Backup::Storage::FTP.defaults do |s|
76
+ s.username = 'some_username'
77
+ s.password = 'some_password'
78
+ s.ip = 'some_ip'
79
+ s.port = 'some_port'
80
+ s.path = 'some_path'
81
+ s.passive_mode = 'some_passive_mode'
82
+ s.keep = 'some_keep'
83
+ end
84
+ end
85
+
86
+ it 'should use pre-configured defaults' do
87
+ storage = Backup::Storage::FTP.new(model)
88
+
89
+ storage.username.should == 'some_username'
90
+ storage.password.should == 'some_password'
91
+ storage.ip.should == 'some_ip'
92
+ storage.port.should == 'some_port'
93
+ storage.path.should == 'some_path'
94
+ storage.passive_mode.should == 'some_passive_mode'
95
+
96
+ storage.storage_id.should be_nil
97
+ storage.keep.should == 'some_keep'
98
+ end
99
+
100
+ it 'should override pre-configured defaults' do
101
+ storage = Backup::Storage::FTP.new(model) do |s|
102
+ s.username = 'new_username'
103
+ s.password = 'new_password'
104
+ s.ip = 'new_ip'
105
+ s.port = 'new_port'
106
+ s.path = 'new_path'
107
+ s.passive_mode = 'new_passive_mode'
108
+ s.keep = 'new_keep'
109
+ end
110
+
111
+ storage.username.should == 'new_username'
112
+ storage.password.should == 'new_password'
113
+ storage.ip.should == 'new_ip'
114
+ storage.port.should == 'new_port'
115
+ storage.path.should == 'new_path'
116
+ storage.passive_mode.should == 'new_passive_mode'
117
+
118
+ storage.storage_id.should be_nil
119
+ storage.keep.should == 'new_keep'
120
+ end
121
+ end # context 'when pre-configured defaults have been set'
122
+ end # describe '#initialize'
123
+
124
+ describe '#connection' do
125
+ let(:connection) { mock }
126
+
127
+ it 'should yield a connection to the remote server' do
128
+ Net::FTP.expects(:open).with(
129
+ '123.45.678.90', 'my_username', 'my_password'
130
+ ).yields(connection)
131
+
132
+ storage.send(:connection) do |ftp|
133
+ ftp.should be(connection)
134
+ end
135
+ end
136
+
137
+ it 'should set passive mode if @passive_mode is true' do
138
+ storage.passive_mode = true
139
+ Net::FTP.expects(:open).with(
140
+ '123.45.678.90', 'my_username', 'my_password'
141
+ ).yields(connection)
142
+ connection.expects(:passive=).with(true)
143
+
144
+ storage.send(:connection) do |ftp|
145
+ ftp.should be(connection)
146
+ end
147
+ end
148
+
149
+ it 'should set the Net::FTP_PORT constant' do
150
+ storage.port = 40
151
+ Net::FTP.expects(:const_defined?).with(:FTP_PORT).returns(true)
152
+ Net::FTP.expects(:send).with(:remove_const, :FTP_PORT)
153
+ Net::FTP.expects(:send).with(:const_set, :FTP_PORT, 40)
154
+
155
+ Net::FTP.expects(:open)
156
+ storage.send(:connection)
157
+ end
158
+
159
+ end # describe '#connection'
160
+
161
+ describe '#transfer!' do
162
+ let(:connection) { mock }
163
+ let(:package) { mock }
164
+ let(:s) { sequence '' }
165
+
166
+ before do
167
+ storage.instance_variable_set(:@package, package)
168
+ storage.stubs(:storage_name).returns('Storage::FTP')
169
+ storage.stubs(:local_path).returns('/local/path')
170
+ storage.stubs(:connection).yields(connection)
171
+ end
172
+
173
+ it 'should transfer the package files' do
174
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
175
+ returns('remote/path')
176
+ storage.expects(:create_remote_path).in_sequence(s).with(
177
+ 'remote/path', connection
178
+ )
179
+
180
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
181
+ multiple_yields(
182
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
183
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
184
+ )
185
+ # first yield
186
+ Backup::Logger.expects(:message).in_sequence(s).with(
187
+ "Storage::FTP started transferring " +
188
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' to '123.45.678.90'."
189
+ )
190
+ connection.expects(:put).in_sequence(s).with(
191
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'),
192
+ File.join('remote/path', 'backup.tar.enc-aa')
193
+ )
194
+ # second yield
195
+ Backup::Logger.expects(:message).in_sequence(s).with(
196
+ "Storage::FTP started transferring " +
197
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' to '123.45.678.90'."
198
+ )
199
+ connection.expects(:put).in_sequence(s).with(
200
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'),
201
+ File.join('remote/path', 'backup.tar.enc-ab')
202
+ )
203
+
204
+ storage.send(:transfer!)
205
+ end
206
+ end # describe '#transfer!'
207
+
208
+ describe '#remove!' do
209
+ let(:package) { mock }
210
+ let(:connection) { mock }
211
+ let(:s) { sequence '' }
212
+
213
+ before do
214
+ storage.stubs(:storage_name).returns('Storage::FTP')
215
+ storage.stubs(:connection).yields(connection)
216
+ end
217
+
218
+ it 'should remove the package files' do
219
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
220
+ returns('remote/path')
221
+
222
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
223
+ multiple_yields(
224
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
225
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
226
+ )
227
+ # first yield
228
+ Backup::Logger.expects(:message).in_sequence(s).with(
229
+ "Storage::FTP started removing " +
230
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' from '123.45.678.90'."
231
+ )
232
+ connection.expects(:delete).in_sequence(s).with(
233
+ File.join('remote/path', 'backup.tar.enc-aa')
234
+ )
235
+ # second yield
236
+ Backup::Logger.expects(:message).in_sequence(s).with(
237
+ "Storage::FTP started removing " +
238
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' from '123.45.678.90'."
239
+ )
240
+ connection.expects(:delete).in_sequence(s).with(
241
+ File.join('remote/path', 'backup.tar.enc-ab')
242
+ )
243
+
244
+ connection.expects(:rmdir).with('remote/path').in_sequence(s)
245
+
246
+ storage.send(:remove!, package)
247
+ end
248
+ end # describe '#remove!'
249
+
250
+ describe '#create_remote_path' do
251
+ let(:connection) { mock }
252
+ let(:remote_path) { 'backups/folder/another_folder' }
253
+ let(:s) { sequence '' }
254
+
255
+ context 'while properly creating remote directories one by one' do
256
+ it 'should rescue any FTPPermErrors and continue' do
257
+ connection.expects(:mkdir).in_sequence(s).
258
+ with("backups").raises(Net::FTPPermError)
259
+ connection.expects(:mkdir).in_sequence(s).
260
+ with("backups/folder")
261
+ connection.expects(:mkdir).in_sequence(s).
262
+ with("backups/folder/another_folder")
263
+
264
+ expect do
265
+ storage.send(:create_remote_path, remote_path, connection)
266
+ end.not_to raise_error
267
+ end
268
+ end
269
+ end
270
+
271
+ end
@@ -0,0 +1,259 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Storage::Local do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:storage_path) do
8
+ File.join(File.expand_path(ENV['HOME'] || ''), 'backups')
9
+ end
10
+ let(:storage) do
11
+ Backup::Storage::Local.new(model) do |local|
12
+ local.keep = 5
13
+ end
14
+ end
15
+
16
+ it 'should be a subclass of Storage::Base' do
17
+ Backup::Storage::Local.
18
+ superclass.should == Backup::Storage::Base
19
+ end
20
+
21
+ describe '#initialize' do
22
+ after { Backup::Storage::Local.clear_defaults! }
23
+
24
+ it 'should load pre-configured defaults through Base' do
25
+ Backup::Storage::Local.any_instance.expects(:load_defaults!)
26
+ storage
27
+ end
28
+
29
+ it 'should pass the model reference to Base' do
30
+ storage.instance_variable_get(:@model).should == model
31
+ end
32
+
33
+ it 'should pass the storage_id to Base' do
34
+ storage = Backup::Storage::Local.new(model, 'my_storage_id')
35
+ storage.storage_id.should == 'my_storage_id'
36
+ end
37
+
38
+ it 'should expand any path given' do
39
+ storage = Backup::Storage::Local.new(model) do |local|
40
+ local.path = 'my_backups/path'
41
+ end
42
+ storage.path.should == File.expand_path('my_backups/path')
43
+ end
44
+
45
+ context 'when no pre-configured defaults have been set' do
46
+ it 'should use the values given' do
47
+ storage.path.should == storage_path
48
+
49
+ storage.storage_id.should be_nil
50
+ storage.keep.should == 5
51
+ end
52
+
53
+ it 'should use default values if none are given' do
54
+ storage = Backup::Storage::Local.new(model)
55
+
56
+ storage.path.should == storage_path
57
+
58
+ storage.storage_id.should be_nil
59
+ storage.keep.should be_nil
60
+ end
61
+ end # context 'when no pre-configured defaults have been set'
62
+
63
+ context 'when pre-configured defaults have been set' do
64
+ before do
65
+ Backup::Storage::Local.defaults do |s|
66
+ s.path = 'some_path'
67
+ s.keep = 'some_keep'
68
+ end
69
+ end
70
+
71
+ it 'should use pre-configured defaults' do
72
+ storage = Backup::Storage::Local.new(model)
73
+
74
+ storage.path.should == File.expand_path('some_path')
75
+
76
+ storage.storage_id.should be_nil
77
+ storage.keep.should == 'some_keep'
78
+ end
79
+
80
+ it 'should override pre-configured defaults' do
81
+ storage = Backup::Storage::Local.new(model) do |s|
82
+ s.path = 'new_path'
83
+ s.keep = 'new_keep'
84
+ end
85
+
86
+ storage.path.should == File.expand_path('new_path')
87
+
88
+ storage.storage_id.should be_nil
89
+ storage.keep.should == 'new_keep'
90
+ end
91
+ end # context 'when pre-configured defaults have been set'
92
+ end # describe '#initialize'
93
+
94
+ describe '#transfer!' do
95
+ let(:package) { mock }
96
+ let(:s) { sequence '' }
97
+
98
+ before do
99
+ storage.instance_variable_set(:@package, package)
100
+ storage.stubs(:storage_name).returns('Storage::Local')
101
+ storage.stubs(:local_path).returns('/local/path')
102
+ end
103
+
104
+ context 'when transfer_method is :mv' do
105
+ before { storage.stubs(:transfer_method).returns(:mv) }
106
+ it 'should move the package files to their destination' do
107
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
108
+ returns('remote/path')
109
+ FileUtils.expects(:mkdir_p).in_sequence(s).with('remote/path')
110
+
111
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
112
+ multiple_yields(
113
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
114
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
115
+ )
116
+ # first yield
117
+ Backup::Logger.expects(:message).in_sequence(s).with(
118
+ "Storage::Local started transferring " +
119
+ "'2011.12.31.11.00.02.backup.tar.enc-aa'."
120
+ )
121
+ FileUtils.expects(:mv).in_sequence(s).with(
122
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'),
123
+ File.join('remote/path', 'backup.tar.enc-aa')
124
+ )
125
+ # second yield
126
+ Backup::Logger.expects(:message).in_sequence(s).with(
127
+ "Storage::Local started transferring " +
128
+ "'2011.12.31.11.00.02.backup.tar.enc-ab'."
129
+ )
130
+ FileUtils.expects(:mv).in_sequence(s).with(
131
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'),
132
+ File.join('remote/path', 'backup.tar.enc-ab')
133
+ )
134
+
135
+ storage.send(:transfer!)
136
+ end
137
+ end # context 'when transfer_method is :mv'
138
+
139
+ context 'when transfer_method is :cp' do
140
+ before { storage.stubs(:transfer_method).returns(:cp) }
141
+ it 'should copy the package files to their destination' do
142
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
143
+ returns('remote/path')
144
+ FileUtils.expects(:mkdir_p).in_sequence(s).with('remote/path')
145
+
146
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
147
+ multiple_yields(
148
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
149
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
150
+ )
151
+ # first yield
152
+ Backup::Logger.expects(:message).in_sequence(s).with(
153
+ "Storage::Local started transferring " +
154
+ "'2011.12.31.11.00.02.backup.tar.enc-aa'."
155
+ )
156
+ FileUtils.expects(:cp).in_sequence(s).with(
157
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'),
158
+ File.join('remote/path', 'backup.tar.enc-aa')
159
+ )
160
+ # second yield
161
+ Backup::Logger.expects(:message).in_sequence(s).with(
162
+ "Storage::Local started transferring " +
163
+ "'2011.12.31.11.00.02.backup.tar.enc-ab'."
164
+ )
165
+ FileUtils.expects(:cp).in_sequence(s).with(
166
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'),
167
+ File.join('remote/path', 'backup.tar.enc-ab')
168
+ )
169
+
170
+ storage.send(:transfer!)
171
+ end
172
+ end # context 'when transfer_method is :cp'
173
+
174
+ end # describe '#transfer!'
175
+
176
+ describe '#remove!' do
177
+ let(:package) { mock }
178
+ let(:s) { sequence '' }
179
+
180
+ before do
181
+ storage.stubs(:storage_name).returns('Storage::Local')
182
+ end
183
+
184
+ it 'should remove the package files' do
185
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
186
+ returns('remote/path')
187
+
188
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
189
+ multiple_yields(
190
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
191
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
192
+ )
193
+ # after both yields
194
+ Backup::Logger.expects(:message).in_sequence(s).with(
195
+ "Storage::Local started removing " +
196
+ "'2011.12.31.11.00.02.backup.tar.enc-aa'.\n" +
197
+ "Storage::Local started removing " +
198
+ "'2011.12.31.11.00.02.backup.tar.enc-ab'."
199
+ )
200
+ FileUtils.expects(:rm_r).in_sequence(s).with('remote/path')
201
+
202
+ storage.send(:remove!, package)
203
+ end
204
+ end # describe '#remove!'
205
+
206
+ describe '#transfer_method' do
207
+ context 'when the storage is the last for the model' do
208
+ before do
209
+ model.storages << storage
210
+ end
211
+
212
+ it 'should return :mv' do
213
+ storage.send(:transfer_method).should == :mv
214
+ storage.instance_variable_get(:@transfer_method).should == :mv
215
+ end
216
+
217
+ it 'should only check once' do
218
+ storage.instance_variable_set(:@transfer_method, :mv)
219
+ model.expects(:storages).never
220
+ storage.send(:transfer_method).should == :mv
221
+ end
222
+ end # context 'when the storage is the last for the model'
223
+
224
+ context 'when the storage is not the last for the model' do
225
+ let(:package) { mock }
226
+
227
+ before do
228
+ model.storages << storage
229
+ model.storages << Backup::Storage::Local.new(model)
230
+
231
+ storage.instance_variable_set(:@package, package)
232
+ end
233
+
234
+ it 'should log a warning and return :cp' do
235
+ storage.expects(:remote_path_for).with(package).returns('remote_path')
236
+ Backup::Logger.expects(:warn).with do |err|
237
+ err.should be_an_instance_of Backup::Errors::Storage::Local::TransferError
238
+ err.message.should ==
239
+ "Storage::Local::TransferError: Local File Copy Warning!\n" +
240
+ " The final backup file(s) for 'test label' (test_trigger)\n" +
241
+ " will be *copied* to 'remote_path'\n" +
242
+ " To avoid this, when using more than one Storage, the 'Local' Storage\n" +
243
+ " should be added *last* so the files may be *moved* to their destination."
244
+ end
245
+
246
+ storage.send(:transfer_method).should == :cp
247
+ storage.instance_variable_get(:@transfer_method).should == :cp
248
+ end
249
+
250
+ it 'should only check once' do
251
+ storage.instance_variable_set(:@transfer_method, :cp)
252
+ model.expects(:storages).never
253
+ storage.send(:transfer_method).should == :cp
254
+ end
255
+ end # context 'when the storage is not the last for the model'
256
+
257
+ end # describe '#transfer_method'
258
+
259
+ end