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,370 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Storage::Dropbox do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:storage) do
8
+ Backup::Storage::Dropbox.new(model) do |db|
9
+ db.api_key = 'my_api_key'
10
+ db.api_secret = 'my_api_secret'
11
+ db.keep = 5
12
+ end
13
+ end
14
+
15
+ describe '#initialize' do
16
+ it 'should set the correct values' do
17
+ storage.api_key.should == 'my_api_key'
18
+ storage.api_secret.should == 'my_api_secret'
19
+ storage.access_type.should == :app_folder
20
+ storage.path.should == 'backups'
21
+
22
+ storage.storage_id.should be_nil
23
+ storage.keep.should == 5
24
+ end
25
+
26
+ it 'should set a storage_id if given' do
27
+ db = Backup::Storage::Dropbox.new(model, 'my storage_id')
28
+ db.storage_id.should == 'my storage_id'
29
+ end
30
+
31
+ context 'when setting configuration defaults' do
32
+ after { Backup::Configuration::Storage::Dropbox.clear_defaults! }
33
+
34
+ it 'should use the configured defaults' do
35
+ Backup::Configuration::Storage::Dropbox.defaults do |db|
36
+ db.api_key = 'some_api_key'
37
+ db.api_secret = 'some_api_secret'
38
+ db.access_type = 'some_access_type'
39
+ db.path = 'some_path'
40
+ db.keep = 15
41
+ end
42
+ storage = Backup::Storage::Dropbox.new(model)
43
+ storage.api_key.should == 'some_api_key'
44
+ storage.api_secret.should == 'some_api_secret'
45
+ storage.access_type.should == 'some_access_type'
46
+ storage.path.should == 'some_path'
47
+
48
+ storage.storage_id.should be_nil
49
+ storage.keep.should == 15
50
+ end
51
+
52
+ it 'should override the configured defaults' do
53
+ Backup::Configuration::Storage::Dropbox.defaults do |db|
54
+ db.api_key = 'old_api_key'
55
+ db.api_secret = 'old_api_secret'
56
+ db.access_type = 'old_access_type'
57
+ db.path = 'old_path'
58
+ db.keep = 15
59
+ end
60
+ storage = Backup::Storage::Dropbox.new(model) do |db|
61
+ db.api_key = 'new_api_key'
62
+ db.api_secret = 'new_api_secret'
63
+ db.access_type = 'new_access_type'
64
+ db.path = 'new_path'
65
+ db.keep = 10
66
+ end
67
+
68
+ storage.api_key.should == 'new_api_key'
69
+ storage.api_secret.should == 'new_api_secret'
70
+ storage.access_type.should == 'new_access_type'
71
+ storage.path.should == 'new_path'
72
+
73
+ storage.storage_id.should be_nil
74
+ storage.keep.should == 10
75
+ end
76
+ end # context 'when setting configuration defaults'
77
+
78
+ end # describe '#initialize'
79
+
80
+ describe '#connection' do
81
+ let(:session) { mock }
82
+ let(:client) { mock }
83
+ let(:s) { sequence '' }
84
+
85
+ context 'when a cached session exists' do
86
+ before do
87
+ storage.expects(:cached_session).in_sequence(s).returns(session)
88
+ storage.expects(:create_write_and_return_new_session!).never
89
+ DropboxClient.expects(:new).in_sequence(s).
90
+ with(session, :app_folder).returns(client)
91
+ end
92
+
93
+ it 'should use the cached session to create the client' do
94
+ storage.send(:connection).should be(client)
95
+ end
96
+
97
+ it 'should return an already existing client' do
98
+ storage.send(:connection).should be(client)
99
+ storage.send(:connection).should be(client)
100
+ end
101
+ end
102
+
103
+ context 'when a cached session does not exist' do
104
+ before do
105
+ storage.expects(:cached_session).in_sequence(s).returns(false)
106
+ Backup::Logger.expects(:message).in_sequence(s).with(
107
+ 'Creating a new session!'
108
+ )
109
+ storage.expects(:create_write_and_return_new_session!).in_sequence(s).
110
+ returns(session)
111
+ DropboxClient.expects(:new).in_sequence(s).
112
+ with(session, :app_folder).returns(client)
113
+ end
114
+
115
+ it 'should create a new session and return the client' do
116
+ storage.send(:connection).should be(client)
117
+ end
118
+
119
+ it 'should return an already existing client' do
120
+ storage.send(:connection).should be(client)
121
+ storage.send(:connection).should be(client)
122
+ end
123
+ end
124
+
125
+ context 'when an error is raised creating a client for the session' do
126
+ it 'should wrap and raise the error' do
127
+ storage.stubs(:cached_session).returns(true)
128
+ DropboxClient.expects(:new).raises('error')
129
+
130
+ expect do
131
+ storage.send(:connection)
132
+ end.to raise_error {|err|
133
+ err.should be_an_instance_of(
134
+ Backup::Errors::Storage::Dropbox::ConnectionError
135
+ )
136
+ err.message.should ==
137
+ 'Storage::Dropbox::ConnectionError: RuntimeError: error'
138
+ }
139
+ end
140
+ end
141
+
142
+ end # describe '#connection'
143
+
144
+ describe '#cached_session' do
145
+ let(:session) { mock }
146
+
147
+ context 'when a cached session file exists' do
148
+ before do
149
+ storage.expects(:cache_exists?).returns(true)
150
+ storage.expects(:cached_file).returns('cached_file')
151
+ File.expects(:read).with('cached_file').returns('yaml_data')
152
+ end
153
+
154
+ context 'when the cached session is successfully loaded' do
155
+ it 'should return the sesssion' do
156
+ DropboxSession.expects(:deserialize).with('yaml_data').
157
+ returns(session)
158
+ Backup::Logger.expects(:message).with(
159
+ 'Session data loaded from cache!'
160
+ )
161
+
162
+ storage.send(:cached_session).should be(session)
163
+ end
164
+ end
165
+
166
+ context 'when errors occur loading the session' do
167
+ it 'should log a warning and return false' do
168
+ DropboxSession.expects(:deserialize).with('yaml_data').
169
+ raises('error message')
170
+ Backup::Logger.expects(:warn).with do |err|
171
+ err.should be_an_instance_of(
172
+ Backup::Errors::Storage::Dropbox::CacheError
173
+ )
174
+ err.message.should == 'Storage::Dropbox::CacheError: ' +
175
+ "Could not read session data from cache.\n" +
176
+ " Cache data might be corrupt.\n" +
177
+ " Reason: RuntimeError\n" +
178
+ " error message"
179
+ end
180
+
181
+ expect do
182
+ storage.send(:cached_session).should be_false
183
+ end.not_to raise_error
184
+ end
185
+ end
186
+ end
187
+
188
+ context 'when a cached session file does not exist' do
189
+ before { storage.stubs(:cache_exists?).returns(false) }
190
+ it 'should return false' do
191
+ storage.send(:cached_session).should be_false
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '#transfer!' do
197
+ let(:connection) { mock }
198
+ let(:package) { mock }
199
+ let(:file) { mock }
200
+ let(:s) { sequence '' }
201
+
202
+ before do
203
+ storage.instance_variable_set(:@package, package)
204
+ storage.stubs(:storage_name).returns('Storage::Dropbox')
205
+ storage.stubs(:local_path).returns('/local/path')
206
+ storage.stubs(:connection).returns(connection)
207
+ end
208
+
209
+ it 'should transfer the package files' do
210
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
211
+ returns('remote/path')
212
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
213
+ multiple_yields(
214
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
215
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
216
+ )
217
+ # first yield
218
+ Backup::Logger.expects(:message).in_sequence(s).with(
219
+ "Storage::Dropbox started transferring " +
220
+ "'2011.12.31.11.00.02.backup.tar.enc-aa'."
221
+ )
222
+ File.expects(:open).in_sequence(s).with(
223
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'), 'r'
224
+ ).yields(file)
225
+ connection.expects(:put_file).in_sequence(s).with(
226
+ File.join('remote/path', 'backup.tar.enc-aa'), file
227
+ )
228
+ # second yield
229
+ Backup::Logger.expects(:message).in_sequence(s).with(
230
+ "Storage::Dropbox started transferring " +
231
+ "'2011.12.31.11.00.02.backup.tar.enc-ab'."
232
+ )
233
+ File.expects(:open).in_sequence(s).with(
234
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'), 'r'
235
+ ).yields(file)
236
+ connection.expects(:put_file).in_sequence(s).with(
237
+ File.join('remote/path', 'backup.tar.enc-ab'), file
238
+ )
239
+
240
+ storage.send(:transfer!)
241
+ end
242
+ end # describe '#transfer!'
243
+
244
+ describe '#remove!' do
245
+ let(:package) { mock }
246
+ let(:connection) { mock }
247
+ let(:s) { sequence '' }
248
+
249
+ before do
250
+ storage.stubs(:storage_name).returns('Storage::Dropbox')
251
+ storage.stubs(:connection).returns(connection)
252
+ end
253
+
254
+ it 'should remove the package files' do
255
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
256
+ returns('remote/path')
257
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
258
+ multiple_yields(
259
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
260
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
261
+ )
262
+ # after both yields
263
+ Backup::Logger.expects(:message).in_sequence(s).with(
264
+ "Storage::Dropbox started removing " +
265
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' from Dropbox.\n" +
266
+ "Storage::Dropbox started removing " +
267
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' from Dropbox."
268
+ )
269
+ connection.expects(:file_delete).in_sequence(s).with('remote/path')
270
+
271
+ storage.send(:remove!, package)
272
+ end
273
+ end # describe '#remove!'
274
+
275
+ describe '#cached_file' do
276
+ it 'should return the path to the cache file' do
277
+ storage.send(:cached_file).should ==
278
+ File.join(Backup::Config.cache_path, 'my_api_keymy_api_secret')
279
+ end
280
+ end
281
+
282
+ describe '#cache_exists?' do
283
+ it 'should check if #cached_file exists' do
284
+ storage.expects(:cached_file).returns('/path/to/cache_file')
285
+ File.expects(:exist?).with('/path/to/cache_file')
286
+
287
+ storage.send(:cache_exists?)
288
+ end
289
+ end
290
+
291
+ describe '#write_cache!' do
292
+ let(:session) { mock }
293
+ let(:cache_file) { mock }
294
+
295
+ it 'should write a serialized session to file' do
296
+ storage.expects(:cached_file).returns('/path/to/cache_file')
297
+ session.expects(:serialize).returns('serialized_data')
298
+
299
+ File.expects(:open).with('/path/to/cache_file', 'w').yields(cache_file)
300
+ cache_file.expects(:write).with('serialized_data')
301
+
302
+ storage.send(:write_cache!, session)
303
+ end
304
+ end
305
+
306
+ describe '#create_write_and_return_new_session!' do
307
+ let(:session) { mock }
308
+ let(:template) { mock }
309
+ let(:s) { sequence '' }
310
+
311
+ before do
312
+ storage.stubs(:cached_file).returns('/path/to/cache_file')
313
+
314
+ DropboxSession.expects(:new).in_sequence(s).
315
+ with('my_api_key', 'my_api_secret').returns(session)
316
+ session.expects(:get_request_token).in_sequence(s)
317
+ Backup::Template.expects(:new).in_sequence(s).with(
318
+ {:session => session, :cached_file => '/path/to/cache_file'}
319
+ ).returns(template)
320
+ template.expects(:render).in_sequence(s).with(
321
+ 'storage/dropbox/authorization_url.erb'
322
+ )
323
+ Timeout.expects(:timeout).in_sequence(s).with(180).yields
324
+ STDIN.expects(:gets).in_sequence(s)
325
+ end
326
+
327
+ context 'when session is authenticated' do
328
+ before do
329
+ session.expects(:get_access_token).in_sequence(s)
330
+ end
331
+
332
+ it 'should cache and return the new session' do
333
+ template.expects(:render).in_sequence(s).with(
334
+ 'storage/dropbox/authorized.erb'
335
+ )
336
+ storage.expects(:write_cache!).in_sequence(s).with(session)
337
+ template.expects(:render).in_sequence(s).with(
338
+ 'storage/dropbox/cache_file_written.erb'
339
+ )
340
+
341
+ storage.send(:create_write_and_return_new_session!).should be(session)
342
+ end
343
+ end
344
+
345
+ context 'when session is not authenticated' do
346
+ before do
347
+ session.expects(:get_access_token).in_sequence(s).raises('error message')
348
+ end
349
+
350
+ it 'should wrap and re-raise the error' do
351
+ template.expects(:render).with('storage/dropbox/authorized.erb').never
352
+ storage.expects(:write_cache!).never
353
+ template.expects(:render).with('storage/dropbox/cache_file_written.erb').never
354
+
355
+ expect do
356
+ storage.send(:create_write_and_return_new_session!)
357
+ end.to raise_error {|err|
358
+ err.should be_an_instance_of(
359
+ Backup::Errors::Storage::Dropbox::AuthenticationError
360
+ )
361
+ err.message.should == 'Storage::Dropbox::AuthenticationError: ' +
362
+ "Could not create or authenticate a new session\n" +
363
+ " Reason: RuntimeError\n" +
364
+ " error message"
365
+ }
366
+ end
367
+ end
368
+ end
369
+
370
+ end
@@ -0,0 +1,247 @@
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
+ describe '#initialize' do
17
+ it 'should set the correct values' do
18
+ storage.username.should == 'my_username'
19
+ storage.password.should == 'my_password'
20
+ storage.ip.should == '123.45.678.90'
21
+ storage.port.should == 21
22
+ storage.path.should == 'backups'
23
+ storage.passive_mode.should == false
24
+
25
+ storage.storage_id.should be_nil
26
+ storage.keep.should == 5
27
+ end
28
+
29
+ it 'should set a storage_id if given' do
30
+ ftp = Backup::Storage::FTP.new(model, 'my storage_id')
31
+ ftp.storage_id.should == 'my storage_id'
32
+ end
33
+
34
+ it 'should remove any preceeding tilde and slash from the path' do
35
+ storage = Backup::Storage::FTP.new(model) do |ftp|
36
+ ftp.path = '~/my_backups/path'
37
+ end
38
+ storage.path.should == 'my_backups/path'
39
+ end
40
+
41
+ context 'when setting configuration defaults' do
42
+ after { Backup::Configuration::Storage::FTP.clear_defaults! }
43
+
44
+ it 'should use the configured defaults' do
45
+ Backup::Configuration::Storage::FTP.defaults do |ftp|
46
+ ftp.username = 'some_username'
47
+ ftp.password = 'some_password'
48
+ ftp.ip = 'some_ip'
49
+ ftp.port = 'some_port'
50
+ ftp.path = 'some_path'
51
+ ftp.passive_mode = 'some_passive_mode'
52
+ ftp.keep = 'some_keep'
53
+ end
54
+ storage = Backup::Storage::FTP.new(model)
55
+ storage.username.should == 'some_username'
56
+ storage.password.should == 'some_password'
57
+ storage.ip.should == 'some_ip'
58
+ storage.port.should == 'some_port'
59
+ storage.path.should == 'some_path'
60
+ storage.passive_mode.should == 'some_passive_mode'
61
+
62
+ storage.storage_id.should be_nil
63
+ storage.keep.should == 'some_keep'
64
+ end
65
+
66
+ it 'should override the configured defaults' do
67
+ Backup::Configuration::Storage::FTP.defaults do |ftp|
68
+ ftp.username = 'old_username'
69
+ ftp.password = 'old_password'
70
+ ftp.ip = 'old_ip'
71
+ ftp.port = 'old_port'
72
+ ftp.path = 'old_path'
73
+ ftp.passive_mode = 'old_passive_mode'
74
+ ftp.keep = 'old_keep'
75
+ end
76
+ storage = Backup::Storage::FTP.new(model) do |ftp|
77
+ ftp.username = 'new_username'
78
+ ftp.password = 'new_password'
79
+ ftp.ip = 'new_ip'
80
+ ftp.port = 'new_port'
81
+ ftp.path = 'new_path'
82
+ ftp.passive_mode = 'new_passive_mode'
83
+ ftp.keep = 'new_keep'
84
+ end
85
+
86
+ storage.username.should == 'new_username'
87
+ storage.password.should == 'new_password'
88
+ storage.ip.should == 'new_ip'
89
+ storage.port.should == 'new_port'
90
+ storage.path.should == 'new_path'
91
+ storage.passive_mode.should == 'new_passive_mode'
92
+
93
+ storage.storage_id.should be_nil
94
+ storage.keep.should == 'new_keep'
95
+ end
96
+ end # context 'when setting configuration defaults'
97
+
98
+ end # describe '#initialize'
99
+
100
+ describe '#connection' do
101
+ let(:connection) { mock }
102
+
103
+ it 'should yield a connection to the remote server' do
104
+ Net::FTP.expects(:open).with(
105
+ '123.45.678.90', 'my_username', 'my_password'
106
+ ).yields(connection)
107
+
108
+ storage.send(:connection) do |ftp|
109
+ ftp.should be(connection)
110
+ end
111
+ end
112
+
113
+ it 'should set passive mode if @passive_mode is true' do
114
+ storage.passive_mode = true
115
+ Net::FTP.expects(:open).with(
116
+ '123.45.678.90', 'my_username', 'my_password'
117
+ ).yields(connection)
118
+ connection.expects(:passive=).with(true)
119
+
120
+ storage.send(:connection) do |ftp|
121
+ ftp.should be(connection)
122
+ end
123
+ end
124
+
125
+ it 'should set the Net::FTP_PORT constant' do
126
+ storage.port = 40
127
+ Net::FTP.expects(:const_defined?).with(:FTP_PORT).returns(true)
128
+ Net::FTP.expects(:send).with(:remove_const, :FTP_PORT)
129
+ Net::FTP.expects(:send).with(:const_set, :FTP_PORT, 40)
130
+
131
+ Net::FTP.expects(:open)
132
+ storage.send(:connection)
133
+ end
134
+
135
+ end # describe '#connection'
136
+
137
+ describe '#transfer!' do
138
+ let(:connection) { mock }
139
+ let(:package) { mock }
140
+ let(:s) { sequence '' }
141
+
142
+ before do
143
+ storage.instance_variable_set(:@package, package)
144
+ storage.stubs(:storage_name).returns('Storage::FTP')
145
+ storage.stubs(:local_path).returns('/local/path')
146
+ storage.stubs(:connection).yields(connection)
147
+ end
148
+
149
+ it 'should transfer the package files' do
150
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
151
+ returns('remote/path')
152
+ storage.expects(:create_remote_path).in_sequence(s).with(
153
+ 'remote/path', connection
154
+ )
155
+
156
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
157
+ multiple_yields(
158
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
159
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
160
+ )
161
+ # first yield
162
+ Backup::Logger.expects(:message).in_sequence(s).with(
163
+ "Storage::FTP started transferring " +
164
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' to '123.45.678.90'."
165
+ )
166
+ connection.expects(:put).in_sequence(s).with(
167
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'),
168
+ File.join('remote/path', 'backup.tar.enc-aa')
169
+ )
170
+ # second yield
171
+ Backup::Logger.expects(:message).in_sequence(s).with(
172
+ "Storage::FTP started transferring " +
173
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' to '123.45.678.90'."
174
+ )
175
+ connection.expects(:put).in_sequence(s).with(
176
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'),
177
+ File.join('remote/path', 'backup.tar.enc-ab')
178
+ )
179
+
180
+ storage.send(:transfer!)
181
+ end
182
+ end # describe '#transfer!'
183
+
184
+ describe '#remove!' do
185
+ let(:package) { mock }
186
+ let(:connection) { mock }
187
+ let(:s) { sequence '' }
188
+
189
+ before do
190
+ storage.stubs(:storage_name).returns('Storage::FTP')
191
+ storage.stubs(:connection).yields(connection)
192
+ end
193
+
194
+ it 'should remove the package files' do
195
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
196
+ returns('remote/path')
197
+
198
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
199
+ multiple_yields(
200
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
201
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
202
+ )
203
+ # first yield
204
+ Backup::Logger.expects(:message).in_sequence(s).with(
205
+ "Storage::FTP started removing " +
206
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' from '123.45.678.90'."
207
+ )
208
+ connection.expects(:delete).in_sequence(s).with(
209
+ File.join('remote/path', 'backup.tar.enc-aa')
210
+ )
211
+ # second yield
212
+ Backup::Logger.expects(:message).in_sequence(s).with(
213
+ "Storage::FTP started removing " +
214
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' from '123.45.678.90'."
215
+ )
216
+ connection.expects(:delete).in_sequence(s).with(
217
+ File.join('remote/path', 'backup.tar.enc-ab')
218
+ )
219
+
220
+ connection.expects(:rmdir).with('remote/path').in_sequence(s)
221
+
222
+ storage.send(:remove!, package)
223
+ end
224
+ end # describe '#remove!'
225
+
226
+ describe '#create_remote_path' do
227
+ let(:connection) { mock }
228
+ let(:remote_path) { 'backups/folder/another_folder' }
229
+ let(:s) { sequence '' }
230
+
231
+ context 'while properly creating remote directories one by one' do
232
+ it 'should rescue any FTPPermErrors and continue' do
233
+ connection.expects(:mkdir).in_sequence(s).
234
+ with("backups").raises(Net::FTPPermError)
235
+ connection.expects(:mkdir).in_sequence(s).
236
+ with("backups/folder")
237
+ connection.expects(:mkdir).in_sequence(s).
238
+ with("backups/folder/another_folder")
239
+
240
+ expect do
241
+ storage.send(:create_remote_path, remote_path, connection)
242
+ end.not_to raise_error
243
+ end
244
+ end
245
+ end
246
+
247
+ end