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,327 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Syncer::RSync::Push do
6
+ let(:syncer) do
7
+ Backup::Syncer::RSync::Push.new do |rsync|
8
+ rsync.username = 'my_username'
9
+ rsync.password = 'my_password'
10
+ rsync.ip = '123.45.678.90'
11
+ rsync.port = 22
12
+ rsync.compress = true
13
+ rsync.path = "~/my_backups"
14
+
15
+ rsync.directories do |directory|
16
+ directory.add "/some/directory"
17
+ directory.add "~/home/directory"
18
+ end
19
+
20
+ rsync.mirror = true
21
+ rsync.additional_options = ['--opt-a', '--opt-b']
22
+ end
23
+ end
24
+
25
+ it 'should be a subclass of RSync::Base' do
26
+ Backup::Syncer::RSync::Push.superclass.should == Backup::Syncer::RSync::Base
27
+ end
28
+
29
+ describe '#initialize' do
30
+ it 'should have defined the configuration properly' do
31
+ syncer.username.should == 'my_username'
32
+ syncer.password.should == 'my_password'
33
+ syncer.ip.should == '123.45.678.90'
34
+ syncer.port.should == 22
35
+ syncer.compress.should == true
36
+ syncer.path.should == '~/my_backups'
37
+ syncer.directories.should == ["/some/directory", "~/home/directory"]
38
+ syncer.mirror.should == true
39
+ syncer.additional_options.should == ['--opt-a', '--opt-b']
40
+ end
41
+
42
+ context 'when options are not set' do
43
+ it 'should use default values' do
44
+ syncer = Backup::Syncer::RSync::Push.new
45
+ syncer.username.should == nil
46
+ syncer.password.should == nil
47
+ syncer.ip.should == nil
48
+ syncer.port.should == 22
49
+ syncer.compress.should == false
50
+ syncer.path.should == 'backups'
51
+ syncer.directories.should == []
52
+ syncer.mirror.should == false
53
+ syncer.additional_options.should == []
54
+ end
55
+ end
56
+
57
+ context 'when setting configuration defaults' do
58
+ after { Backup::Configuration::Syncer::RSync::Push.clear_defaults! }
59
+
60
+ it 'should use the configured defaults' do
61
+ Backup::Configuration::Syncer::RSync::Push.defaults do |rsync|
62
+ rsync.username = 'some_username'
63
+ rsync.password = 'some_password'
64
+ rsync.ip = 'some_ip'
65
+ rsync.port = 'some_port'
66
+ rsync.compress = 'some_compress'
67
+ rsync.path = 'some_path'
68
+ #rsync.directories = 'cannot_have_a_default_value'
69
+ rsync.mirror = 'some_mirror'
70
+ rsync.additional_options = 'some_additional_options'
71
+ end
72
+ syncer = Backup::Syncer::RSync::Push.new
73
+ syncer.username.should == 'some_username'
74
+ syncer.password.should == 'some_password'
75
+ syncer.ip.should == 'some_ip'
76
+ syncer.port.should == 'some_port'
77
+ syncer.compress.should == 'some_compress'
78
+ syncer.path.should == 'some_path'
79
+ syncer.directories.should == []
80
+ syncer.mirror.should == 'some_mirror'
81
+ syncer.additional_options.should == 'some_additional_options'
82
+ end
83
+
84
+ it 'should override the configured defaults' do
85
+ Backup::Configuration::Syncer::RSync::Push.defaults do |rsync|
86
+ rsync.username = 'old_username'
87
+ rsync.password = 'old_password'
88
+ rsync.ip = 'old_ip'
89
+ rsync.port = 'old_port'
90
+ rsync.compress = 'old_compress'
91
+ rsync.path = 'old_path'
92
+ #rsync.directories = 'cannot_have_a_default_value'
93
+ rsync.mirror = 'old_mirror'
94
+ rsync.additional_options = 'old_additional_options'
95
+ end
96
+ syncer = Backup::Syncer::RSync::Push.new do |rsync|
97
+ rsync.username = 'new_username'
98
+ rsync.password = 'new_password'
99
+ rsync.ip = 'new_ip'
100
+ rsync.port = 'new_port'
101
+ rsync.compress = 'new_compress'
102
+ rsync.path = 'new_path'
103
+ rsync.directories = 'new_directories'
104
+ rsync.mirror = 'new_mirror'
105
+ rsync.additional_options = 'new_additional_options'
106
+ end
107
+
108
+ syncer.username.should == 'new_username'
109
+ syncer.password.should == 'new_password'
110
+ syncer.ip.should == 'new_ip'
111
+ syncer.port.should == 'new_port'
112
+ syncer.compress.should == 'new_compress'
113
+ syncer.path.should == 'new_path'
114
+ syncer.directories.should == 'new_directories'
115
+ syncer.mirror.should == 'new_mirror'
116
+ syncer.additional_options.should == 'new_additional_options'
117
+ end
118
+ end # context 'when setting configuration defaults'
119
+ end # describe '#initialize'
120
+
121
+ describe '#perform!' do
122
+ let(:s) { sequence '' }
123
+
124
+ before do
125
+ syncer.expects(:utility).with(:rsync).returns('rsync')
126
+ syncer.expects(:options).returns('options_output')
127
+ end
128
+
129
+ it 'should sync two directories' do
130
+ syncer.expects(:write_password_file!).in_sequence(s)
131
+
132
+ Backup::Logger.expects(:message).in_sequence(s).with(
133
+ "Syncer::RSync::Push started syncing the following directories:\n" +
134
+ " /some/directory\n" +
135
+ " ~/home/directory"
136
+ )
137
+ syncer.expects(:run).in_sequence(s).with(
138
+ "rsync options_output '/some/directory' " +
139
+ "'#{ File.expand_path('~/home/directory') }' " +
140
+ "'my_username@123.45.678.90:my_backups'"
141
+ ).returns('messages from stdout')
142
+ Backup::Logger.expects(:silent).in_sequence(s).with('messages from stdout')
143
+
144
+ syncer.expects(:remove_password_file!).in_sequence(s)
145
+
146
+ syncer.perform!
147
+ end
148
+
149
+ it 'should ensure passoword file removal' do
150
+ syncer.expects(:write_password_file!).in_sequence(s)
151
+
152
+ Backup::Logger.expects(:message).in_sequence(s)
153
+ syncer.expects(:run).in_sequence(s).raises('error message')
154
+
155
+ syncer.expects(:remove_password_file!).in_sequence(s)
156
+
157
+ expect do
158
+ syncer.perform!
159
+ end.to raise_error(RuntimeError, 'error message')
160
+ end
161
+ end # describe '#perform!'
162
+
163
+ describe '#dest_path' do
164
+ it 'should remove any preceeding "~/" from @path' do
165
+ syncer.send(:dest_path).should == 'my_backups'
166
+ end
167
+
168
+ it 'should set @dest_path' do
169
+ syncer.send(:dest_path)
170
+ syncer.instance_variable_get(:@dest_path).should == 'my_backups'
171
+ end
172
+
173
+ it 'should return @dest_path if already set' do
174
+ syncer.instance_variable_set(:@dest_path, 'foo')
175
+ syncer.send(:dest_path).should == 'foo'
176
+ end
177
+ end
178
+
179
+ describe '#options' do
180
+ let(:pwdfile) { mock }
181
+
182
+ context 'when @compress is true' do
183
+ it 'should return the options string with compression enabled' do
184
+ syncer.send(:options).should ==
185
+ "--archive --delete --compress -e 'ssh -p 22' --opt-a --opt-b"
186
+ end
187
+ end
188
+
189
+ context 'when @compress is false' do
190
+ before { syncer.compress = false }
191
+ it 'should return the options string without compression enabled' do
192
+ syncer.send(:options).should ==
193
+ "--archive --delete -e 'ssh -p 22' --opt-a --opt-b"
194
+ end
195
+ end
196
+
197
+ context 'when a @password_file is set' do
198
+ before do
199
+ syncer.instance_variable_set(:@password_file, pwdfile)
200
+ pwdfile.expects(:path).returns('/path/to/pwdfile')
201
+ end
202
+
203
+ it 'should return the options string with the password_option' do
204
+ syncer.send(:options).should ==
205
+ "--archive --delete --compress -e 'ssh -p 22' " +
206
+ "--password-file='/path/to/pwdfile' --opt-a --opt-b"
207
+ end
208
+ end
209
+
210
+ context 'when no @additional_options are set' do
211
+ before { syncer.additional_options = [] }
212
+
213
+ it 'should return the options string without additional options' do
214
+ syncer.send(:options).should ==
215
+ "--archive --delete --compress -e 'ssh -p 22'"
216
+ end
217
+ end
218
+
219
+ end # describe '#options'
220
+
221
+ describe '#compress_option' do
222
+ context 'when @compress is true' do
223
+ it 'should return the compression flag' do
224
+ syncer.send(:compress_option).should == '--compress'
225
+ end
226
+ end
227
+
228
+ context 'when @compress is false' do
229
+ before { syncer.compress = false }
230
+ it 'should return nil' do
231
+ syncer.send(:compress_option).should be_nil
232
+ end
233
+ end
234
+ end
235
+
236
+ describe '#port_option' do
237
+ before { syncer.port = 40 }
238
+ it 'should return the option string with the defined port' do
239
+ syncer.send(:port_option).should == "-e 'ssh -p 40'"
240
+ end
241
+ end
242
+
243
+ describe '#password_option' do
244
+ let(:pwdfile) { mock }
245
+
246
+ context 'when @password_file is set' do
247
+ before do
248
+ syncer.instance_variable_set(:@password_file, pwdfile)
249
+ pwdfile.expects(:path).returns('/path/to/pwdfile')
250
+ end
251
+
252
+ it 'should return the option string' do
253
+ syncer.send(:password_option).should ==
254
+ "--password-file='/path/to/pwdfile'"
255
+ end
256
+ end
257
+
258
+ context 'when @password_file is not set' do
259
+ it 'should return nil' do
260
+ syncer.send(:password_option).should be_nil
261
+ end
262
+ end
263
+ end
264
+
265
+ describe '#write_password_file!' do
266
+ let(:pwdfile) { mock }
267
+ let(:s) { sequence '' }
268
+
269
+ context 'when a @password is set' do
270
+ it 'should create, write and close a temporary password file' do
271
+ Tempfile.expects(:new).in_sequence(s).
272
+ with('backup-rsync-password').
273
+ returns(pwdfile)
274
+ pwdfile.expects(:write).in_sequence(s).with('my_password')
275
+ pwdfile.expects(:close).in_sequence(s)
276
+
277
+ syncer.send(:write_password_file!)
278
+ end
279
+
280
+ it 'should set @password_file to a file containing the password' do
281
+ syncer.send(:write_password_file!)
282
+ file = syncer.instance_variable_get(:@password_file)
283
+ File.exist?(file.path).should be_true
284
+ File.read(file.path).should == 'my_password'
285
+
286
+ # cleanup
287
+ file.delete
288
+ file.path.should be_nil
289
+ end
290
+ end
291
+
292
+ context 'when a @password is not set' do
293
+ before { syncer.password = nil }
294
+ it 'should return nil' do
295
+ Tempfile.expects(:new).never
296
+ pwdfile.expects(:write).never
297
+ pwdfile.expects(:close).never
298
+ syncer.send(:write_password_file!).should be_nil
299
+ end
300
+ end
301
+ end
302
+
303
+ describe '#remove_password_file!' do
304
+ let(:pwdfile) { mock }
305
+
306
+ context 'when @password_file is set' do
307
+ before do
308
+ syncer.instance_variable_set(:@password_file, pwdfile)
309
+ end
310
+
311
+ it 'should delete the file and reset @password_file' do
312
+ pwdfile.expects(:delete)
313
+ syncer.send(:remove_password_file!)
314
+ syncer.instance_variable_get(:@password_file).should be_nil
315
+ end
316
+ end
317
+
318
+ context 'when @password_file is not set' do
319
+ it 'should return nil' do
320
+ pwdfile.expects(:delete).never
321
+ syncer.send(:remove_password_file!).should be_nil
322
+ syncer.instance_variable_get(:@password_file).should be_nil
323
+ end
324
+ end
325
+ end
326
+
327
+ end
@@ -0,0 +1,192 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../../spec_helper.rb', __FILE__)
3
+
4
+ class Parallel; end
5
+
6
+ describe Backup::Syncer::S3 do
7
+ describe '#perform!' do
8
+ let(:syncer) { Backup::Syncer::S3.new }
9
+ let(:connection) { stub('connection',
10
+ :directories => stub('directories', :get => bucket)) }
11
+ let(:bucket) { stub('bucket', :files => files) }
12
+ let(:files) { [] }
13
+ let(:content) { stub('content') }
14
+
15
+ before :each do
16
+ Fog::Storage.stubs(:new).returns connection
17
+ File.stubs(:open).yields content
18
+ File.stubs(:exist?).returns true
19
+ files.stubs(:create).returns true
20
+
21
+ syncer.directories << 'tmp'
22
+ syncer.path = 'storage'
23
+
24
+ Backup::Syncer::S3::SyncContext.any_instance.
25
+ stubs(:`).returns 'MD5(tmp/foo)= 123abcdef'
26
+ end
27
+
28
+ it "respects the concurrency_type setting with threads" do
29
+ syncer.concurrency_type = :threads
30
+
31
+ Parallel.expects(:each).with(anything, {:in_threads => 2}, anything)
32
+
33
+ syncer.perform!
34
+ end
35
+
36
+ it "respects the parallel thread count" do
37
+ syncer.concurrency_type = :threads
38
+ syncer.concurrency_level = 10
39
+
40
+ Parallel.expects(:each).with(anything, {:in_threads => 10}, anything)
41
+
42
+ syncer.perform!
43
+ end
44
+
45
+ it "respects the concurrency_type setting with processors" do
46
+ syncer.concurrency_type = :processes
47
+
48
+ Parallel.expects(:each).with(anything, {:in_processes => 2}, anything)
49
+
50
+ syncer.perform!
51
+ end
52
+
53
+ it "respects the parallel thread count" do
54
+ syncer.concurrency_type = :processes
55
+ syncer.concurrency_level = 10
56
+
57
+ Parallel.expects(:each).with(anything, {:in_processes => 10}, anything)
58
+
59
+ syncer.perform!
60
+ end
61
+
62
+ context 'file exists locally' do
63
+ it "uploads a file if it does not exist remotely" do
64
+ files.expects(:create).with(:key => 'storage/tmp/foo', :body => content)
65
+
66
+ syncer.perform!
67
+ end
68
+
69
+ it "uploads a file if it exists remotely with a different MD5" do
70
+ files << stub('file', :key => 'storage/tmp/foo', :etag => 'abcdef123')
71
+
72
+ files.expects(:create).with(:key => 'storage/tmp/foo', :body => content)
73
+
74
+ syncer.perform!
75
+ end
76
+
77
+ it "does nothing if the file exists remotely with the same MD5" do
78
+ files << stub('file', :key => 'storage/tmp/foo', :etag => '123abcdef')
79
+
80
+ files.expects(:create).never
81
+
82
+ syncer.perform!
83
+ end
84
+
85
+ it "skips the file if it no longer exists locally" do
86
+ File.stubs(:exist?).returns false
87
+
88
+ files.expects(:create).never
89
+
90
+ syncer.perform!
91
+ end
92
+
93
+ it "respects the given path" do
94
+ syncer.path = 'box'
95
+
96
+ files.expects(:create).with(:key => 'box/tmp/foo', :body => content)
97
+
98
+ syncer.perform!
99
+ end
100
+
101
+ it "uploads the content of the local file" do
102
+ files.expects(:create).with(:key => 'storage/tmp/foo', :body => content)
103
+
104
+ syncer.perform!
105
+ end
106
+
107
+ it "creates the connection with the provided credentials" do
108
+ syncer.access_key_id = 'my-access'
109
+ syncer.secret_access_key = 'my-secret'
110
+ syncer.region = 'somewhere'
111
+
112
+ Fog::Storage.expects(:new).with(
113
+ :provider => 'AWS',
114
+ :aws_access_key_id => 'my-access',
115
+ :aws_secret_access_key => 'my-secret',
116
+ :region => 'somewhere'
117
+ ).returns connection
118
+
119
+ syncer.perform!
120
+ end
121
+
122
+ it "uses the bucket with the given name" do
123
+ syncer.bucket = 'leaky'
124
+
125
+ connection.directories.expects(:get).with('leaky').returns(bucket)
126
+
127
+ syncer.perform!
128
+ end
129
+
130
+ it "creates the bucket if one does not exist" do
131
+ syncer.bucket = 'leaky'
132
+ syncer.region = 'elsewhere'
133
+ connection.directories.stubs(:get).returns nil
134
+
135
+ connection.directories.expects(:create).
136
+ with(:key => 'leaky', :location => 'elsewhere').returns(bucket)
137
+
138
+ syncer.perform!
139
+ end
140
+
141
+ it "iterates over each directory" do
142
+ syncer.directories << 'files'
143
+
144
+ Backup::Syncer::S3::SyncContext.any_instance.expects(:`).
145
+ with('find tmp -print0 | xargs -0 openssl md5 2> /dev/null').
146
+ returns 'MD5(tmp/foo)= 123abcdef'
147
+ Backup::Syncer::S3::SyncContext.any_instance.expects(:`).
148
+ with('find files -print0 | xargs -0 openssl md5 2> /dev/null').
149
+ returns 'MD5(tmp/foo)= 123abcdef'
150
+
151
+ syncer.perform!
152
+ end
153
+ end
154
+
155
+ context 'file does not exist locally' do
156
+ let(:file) { stub('file', :key => 'storage/tmp/foo',
157
+ :etag => '123abcdef') }
158
+
159
+ before :each do
160
+ Backup::Syncer::S3::SyncContext.any_instance.
161
+ stubs(:`).returns ''
162
+ files << file
163
+ File.stubs(:exist?).returns false
164
+ end
165
+
166
+ it "removes the remote file when mirroring is turned on" do
167
+ syncer.mirror = true
168
+
169
+ file.expects(:destroy).once
170
+
171
+ syncer.perform!
172
+ end
173
+
174
+ it "leaves the remote file when mirroring is turned off" do
175
+ syncer.mirror = false
176
+
177
+ file.expects(:destroy).never
178
+
179
+ syncer.perform!
180
+ end
181
+
182
+ it "does not remove files not under one of the specified directories" do
183
+ file.stubs(:key).returns 'unsynced/tmp/foo'
184
+ syncer.mirror = true
185
+
186
+ file.expects(:destroy).never
187
+
188
+ syncer.perform!
189
+ end
190
+ end
191
+ end
192
+ end