backup 3.0.23 → 3.0.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. data/Gemfile.lock +42 -45
  2. data/Guardfile +7 -4
  3. data/README.md +10 -7
  4. data/backup.gemspec +2 -2
  5. data/lib/backup.rb +27 -97
  6. data/lib/backup/archive.rb +14 -6
  7. data/lib/backup/cli/helpers.rb +52 -49
  8. data/lib/backup/cli/utility.rb +9 -1
  9. data/lib/backup/compressor/base.rb +10 -4
  10. data/lib/backup/compressor/bzip2.rb +22 -26
  11. data/lib/backup/compressor/custom.rb +53 -0
  12. data/lib/backup/compressor/gzip.rb +22 -23
  13. data/lib/backup/compressor/lzma.rb +15 -13
  14. data/lib/backup/compressor/pbzip2.rb +20 -17
  15. data/lib/backup/config.rb +6 -3
  16. data/lib/backup/configuration.rb +33 -0
  17. data/lib/backup/configuration/helpers.rb +114 -28
  18. data/lib/backup/configuration/store.rb +24 -0
  19. data/lib/backup/database/base.rb +0 -6
  20. data/lib/backup/database/mongodb.rb +27 -11
  21. data/lib/backup/database/mysql.rb +19 -14
  22. data/lib/backup/database/postgresql.rb +16 -11
  23. data/lib/backup/database/redis.rb +7 -11
  24. data/lib/backup/database/riak.rb +3 -6
  25. data/lib/backup/dependency.rb +5 -11
  26. data/lib/backup/model.rb +14 -5
  27. data/lib/backup/notifier/campfire.rb +3 -16
  28. data/lib/backup/notifier/hipchat.rb +1 -7
  29. data/lib/backup/notifier/mail.rb +1 -1
  30. data/lib/backup/packager.rb +29 -19
  31. data/lib/backup/pipeline.rb +110 -0
  32. data/lib/backup/storage/dropbox.rb +4 -7
  33. data/lib/backup/syncer/base.rb +8 -4
  34. data/lib/backup/syncer/cloud/base.rb +247 -0
  35. data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
  36. data/lib/backup/syncer/cloud/s3.rb +68 -0
  37. data/lib/backup/syncer/rsync/base.rb +1 -4
  38. data/lib/backup/syncer/rsync/local.rb +9 -5
  39. data/lib/backup/syncer/rsync/pull.rb +1 -1
  40. data/lib/backup/syncer/rsync/push.rb +10 -5
  41. data/lib/backup/version.rb +1 -1
  42. data/spec-live/.gitignore +6 -0
  43. data/spec-live/README +7 -0
  44. data/spec-live/backups/config.rb +153 -0
  45. data/spec-live/backups/config.yml.template +43 -0
  46. data/spec-live/compressor/custom_spec.rb +30 -0
  47. data/spec-live/compressor/gzip_spec.rb +30 -0
  48. data/spec-live/notifier/mail_spec.rb +85 -0
  49. data/spec-live/spec_helper.rb +85 -0
  50. data/spec-live/storage/dropbox_spec.rb +151 -0
  51. data/spec-live/storage/local_spec.rb +83 -0
  52. data/spec-live/storage/scp_spec.rb +193 -0
  53. data/spec-live/syncer/cloud/s3_spec.rb +124 -0
  54. data/spec/archive_spec.rb +86 -31
  55. data/spec/cleaner_spec.rb +8 -0
  56. data/spec/cli/helpers_spec.rb +200 -75
  57. data/spec/cli/utility_spec.rb +11 -3
  58. data/spec/compressor/base_spec.rb +31 -10
  59. data/spec/compressor/bzip2_spec.rb +212 -57
  60. data/spec/compressor/custom_spec.rb +106 -0
  61. data/spec/compressor/gzip_spec.rb +212 -57
  62. data/spec/compressor/lzma_spec.rb +75 -35
  63. data/spec/compressor/pbzip2_spec.rb +93 -52
  64. data/spec/configuration/helpers_spec.rb +406 -0
  65. data/spec/configuration/store_spec.rb +39 -0
  66. data/spec/configuration_spec.rb +62 -0
  67. data/spec/database/base_spec.rb +19 -10
  68. data/spec/database/mongodb_spec.rb +195 -70
  69. data/spec/database/mysql_spec.rb +183 -64
  70. data/spec/database/postgresql_spec.rb +167 -53
  71. data/spec/database/redis_spec.rb +121 -46
  72. data/spec/database/riak_spec.rb +96 -27
  73. data/spec/dependency_spec.rb +2 -0
  74. data/spec/encryptor/base_spec.rb +10 -0
  75. data/spec/encryptor/gpg_spec.rb +29 -13
  76. data/spec/encryptor/open_ssl_spec.rb +40 -21
  77. data/spec/logger_spec.rb +4 -0
  78. data/spec/model_spec.rb +19 -2
  79. data/spec/notifier/base_spec.rb +32 -17
  80. data/spec/notifier/campfire_spec.rb +63 -45
  81. data/spec/notifier/hipchat_spec.rb +79 -56
  82. data/spec/notifier/mail_spec.rb +82 -46
  83. data/spec/notifier/prowl_spec.rb +53 -32
  84. data/spec/notifier/twitter_spec.rb +62 -41
  85. data/spec/packager_spec.rb +95 -36
  86. data/spec/pipeline_spec.rb +259 -0
  87. data/spec/spec_helper.rb +6 -5
  88. data/spec/storage/base_spec.rb +61 -41
  89. data/spec/storage/cloudfiles_spec.rb +69 -45
  90. data/spec/storage/dropbox_spec.rb +158 -36
  91. data/spec/storage/ftp_spec.rb +69 -45
  92. data/spec/storage/local_spec.rb +47 -23
  93. data/spec/storage/ninefold_spec.rb +55 -31
  94. data/spec/storage/rsync_spec.rb +67 -50
  95. data/spec/storage/s3_spec.rb +65 -41
  96. data/spec/storage/scp_spec.rb +65 -41
  97. data/spec/storage/sftp_spec.rb +65 -41
  98. data/spec/syncer/base_spec.rb +91 -4
  99. data/spec/syncer/cloud/base_spec.rb +511 -0
  100. data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
  101. data/spec/syncer/cloud/s3_spec.rb +174 -0
  102. data/spec/syncer/rsync/base_spec.rb +46 -66
  103. data/spec/syncer/rsync/local_spec.rb +55 -26
  104. data/spec/syncer/rsync/pull_spec.rb +15 -4
  105. data/spec/syncer/rsync/push_spec.rb +59 -52
  106. data/templates/cli/utility/compressor/bzip2 +1 -4
  107. data/templates/cli/utility/compressor/custom +11 -0
  108. data/templates/cli/utility/compressor/gzip +1 -4
  109. data/templates/cli/utility/compressor/lzma +3 -0
  110. data/templates/cli/utility/compressor/pbzip2 +3 -0
  111. data/templates/cli/utility/database/mysql +4 -1
  112. data/templates/cli/utility/syncer/cloud_files +17 -19
  113. data/templates/cli/utility/syncer/s3 +18 -20
  114. metadata +38 -92
  115. data/lib/backup/configuration/base.rb +0 -15
  116. data/lib/backup/configuration/compressor/base.rb +0 -9
  117. data/lib/backup/configuration/compressor/bzip2.rb +0 -23
  118. data/lib/backup/configuration/compressor/gzip.rb +0 -23
  119. data/lib/backup/configuration/compressor/lzma.rb +0 -23
  120. data/lib/backup/configuration/compressor/pbzip2.rb +0 -28
  121. data/lib/backup/configuration/database/base.rb +0 -19
  122. data/lib/backup/configuration/database/mongodb.rb +0 -49
  123. data/lib/backup/configuration/database/mysql.rb +0 -42
  124. data/lib/backup/configuration/database/postgresql.rb +0 -41
  125. data/lib/backup/configuration/database/redis.rb +0 -39
  126. data/lib/backup/configuration/database/riak.rb +0 -29
  127. data/lib/backup/configuration/encryptor/base.rb +0 -9
  128. data/lib/backup/configuration/encryptor/gpg.rb +0 -17
  129. data/lib/backup/configuration/encryptor/open_ssl.rb +0 -32
  130. data/lib/backup/configuration/notifier/base.rb +0 -28
  131. data/lib/backup/configuration/notifier/campfire.rb +0 -25
  132. data/lib/backup/configuration/notifier/hipchat.rb +0 -41
  133. data/lib/backup/configuration/notifier/mail.rb +0 -112
  134. data/lib/backup/configuration/notifier/presently.rb +0 -25
  135. data/lib/backup/configuration/notifier/prowl.rb +0 -23
  136. data/lib/backup/configuration/notifier/twitter.rb +0 -21
  137. data/lib/backup/configuration/storage/base.rb +0 -18
  138. data/lib/backup/configuration/storage/cloudfiles.rb +0 -25
  139. data/lib/backup/configuration/storage/dropbox.rb +0 -58
  140. data/lib/backup/configuration/storage/ftp.rb +0 -29
  141. data/lib/backup/configuration/storage/local.rb +0 -17
  142. data/lib/backup/configuration/storage/ninefold.rb +0 -20
  143. data/lib/backup/configuration/storage/rsync.rb +0 -29
  144. data/lib/backup/configuration/storage/s3.rb +0 -25
  145. data/lib/backup/configuration/storage/scp.rb +0 -25
  146. data/lib/backup/configuration/storage/sftp.rb +0 -25
  147. data/lib/backup/configuration/syncer/base.rb +0 -10
  148. data/lib/backup/configuration/syncer/cloud.rb +0 -23
  149. data/lib/backup/configuration/syncer/cloud_files.rb +0 -30
  150. data/lib/backup/configuration/syncer/rsync/base.rb +0 -28
  151. data/lib/backup/configuration/syncer/rsync/local.rb +0 -11
  152. data/lib/backup/configuration/syncer/rsync/pull.rb +0 -11
  153. data/lib/backup/configuration/syncer/rsync/push.rb +0 -31
  154. data/lib/backup/configuration/syncer/s3.rb +0 -23
  155. data/lib/backup/notifier/presently.rb +0 -88
  156. data/lib/backup/syncer/cloud.rb +0 -187
  157. data/lib/backup/syncer/cloud_files.rb +0 -56
  158. data/lib/backup/syncer/s3.rb +0 -47
  159. data/spec/configuration/base_spec.rb +0 -35
  160. data/spec/configuration/compressor/bzip2_spec.rb +0 -29
  161. data/spec/configuration/compressor/gzip_spec.rb +0 -29
  162. data/spec/configuration/compressor/lzma_spec.rb +0 -29
  163. data/spec/configuration/compressor/pbzip2_spec.rb +0 -32
  164. data/spec/configuration/database/base_spec.rb +0 -17
  165. data/spec/configuration/database/mongodb_spec.rb +0 -56
  166. data/spec/configuration/database/mysql_spec.rb +0 -53
  167. data/spec/configuration/database/postgresql_spec.rb +0 -53
  168. data/spec/configuration/database/redis_spec.rb +0 -50
  169. data/spec/configuration/database/riak_spec.rb +0 -35
  170. data/spec/configuration/encryptor/gpg_spec.rb +0 -26
  171. data/spec/configuration/encryptor/open_ssl_spec.rb +0 -35
  172. data/spec/configuration/notifier/base_spec.rb +0 -32
  173. data/spec/configuration/notifier/campfire_spec.rb +0 -32
  174. data/spec/configuration/notifier/hipchat_spec.rb +0 -44
  175. data/spec/configuration/notifier/mail_spec.rb +0 -71
  176. data/spec/configuration/notifier/presently_spec.rb +0 -35
  177. data/spec/configuration/notifier/prowl_spec.rb +0 -29
  178. data/spec/configuration/notifier/twitter_spec.rb +0 -35
  179. data/spec/configuration/storage/cloudfiles_spec.rb +0 -41
  180. data/spec/configuration/storage/dropbox_spec.rb +0 -38
  181. data/spec/configuration/storage/ftp_spec.rb +0 -44
  182. data/spec/configuration/storage/local_spec.rb +0 -29
  183. data/spec/configuration/storage/ninefold_spec.rb +0 -32
  184. data/spec/configuration/storage/rsync_spec.rb +0 -41
  185. data/spec/configuration/storage/s3_spec.rb +0 -38
  186. data/spec/configuration/storage/scp_spec.rb +0 -41
  187. data/spec/configuration/storage/sftp_spec.rb +0 -41
  188. data/spec/configuration/syncer/cloud_files_spec.rb +0 -44
  189. data/spec/configuration/syncer/rsync/base_spec.rb +0 -33
  190. data/spec/configuration/syncer/rsync/local_spec.rb +0 -10
  191. data/spec/configuration/syncer/rsync/pull_spec.rb +0 -10
  192. data/spec/configuration/syncer/rsync/push_spec.rb +0 -43
  193. data/spec/configuration/syncer/s3_spec.rb +0 -38
  194. data/spec/notifier/presently_spec.rb +0 -181
  195. data/spec/syncer/cloud_files_spec.rb +0 -192
  196. data/spec/syncer/s3_spec.rb +0 -192
  197. data/templates/cli/utility/notifier/presently +0 -13
@@ -0,0 +1,124 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
4
+
5
+ describe 'Syncer::Cloud::S3 - No Concurrency',
6
+ :if => Backup::SpecLive::CONFIG['syncer']['cloud']['s3']['specs_enabled'] do
7
+ let(:trigger) { 'syncer_cloud_s3' }
8
+ let(:model) { h_set_trigger(trigger) }
9
+
10
+ before do
11
+ model # trigger model initialization so Fog is available
12
+ create_sync_files
13
+ clean_remote
14
+ end
15
+
16
+ after do
17
+ clean_sync_dir
18
+ clean_remote
19
+ end
20
+
21
+ it 'should work' do
22
+ model.perform!
23
+ remote_files.map {|file| [file.key, file.etag] }.sort.should == [
24
+ ["backups/dir_a/one.file", "d3b07384d113edec49eaa6238ad5ff00"],
25
+ ["backups/dir_b/dir_c/three.file", "d3b07384d113edec49eaa6238ad5ff00"],
26
+ ["backups/dir_b/two.file", "d3b07384d113edec49eaa6238ad5ff00"]
27
+ ]
28
+
29
+ update_sync_files
30
+
31
+ model.perform!
32
+ remote_files.map {|file| [file.key, file.etag] }.sort.should == [
33
+ ["backups/dir_a/dir_d/two.new", "14758f1afd44c09b7992073ccf00b43d"],
34
+ ["backups/dir_a/one.file", "14758f1afd44c09b7992073ccf00b43d"],
35
+ ["backups/dir_b/dir_c/three.file", "d3b07384d113edec49eaa6238ad5ff00"],
36
+ ["backups/dir_b/one.new", "14758f1afd44c09b7992073ccf00b43d"]
37
+ ]
38
+ end
39
+
40
+ private
41
+
42
+ ##
43
+ # Initial Files are MD5: d3b07384d113edec49eaa6238ad5ff00
44
+ #
45
+ # ├── dir_a
46
+ # │   └── one.file
47
+ # └── dir_b
48
+ # ├── dir_c
49
+ # │   └── three.file
50
+ # ├── bad\xFFfile
51
+ # └── two.file
52
+ def create_sync_files
53
+ clean_sync_dir
54
+
55
+ %w{ dir_a dir_b/dir_c }.each do |dir|
56
+ path = File.join(Backup::SpecLive::SYNC_PATH, dir)
57
+ FileUtils.mkdir_p(path)
58
+ end
59
+
60
+ %W{ dir_a/one.file
61
+ dir_b/two.file
62
+ dir_b/bad\xFFfile
63
+ dir_b/dir_c/three.file }.each do |file|
64
+ path = File.join(Backup::SpecLive::SYNC_PATH, file)
65
+ File.open(path, 'w') {|file| file.puts 'foo' }
66
+ end
67
+ end
68
+
69
+ ##
70
+ # Added/Updated Files are MD5: 14758f1afd44c09b7992073ccf00b43d
71
+ #
72
+ # ├── dir_a
73
+ # │   ├── dir_d (add)
74
+ # │   │   └── two.new (add)
75
+ # │   └── one.file (update)
76
+ # └── dir_b
77
+ # ├── dir_c
78
+ # │   └── three.file
79
+ # ├── bad\377file
80
+ # ├── one.new (add)
81
+ # └── two.file (remove)
82
+ def update_sync_files
83
+ FileUtils.mkdir_p(File.join(Backup::SpecLive::SYNC_PATH, 'dir_a/dir_d'))
84
+ %w{ dir_a/one.file
85
+ dir_b/one.new
86
+ dir_a/dir_d/two.new }.each do |file|
87
+ path = File.join(Backup::SpecLive::SYNC_PATH, file)
88
+ File.open(path, 'w') {|file| file.puts 'foobar' }
89
+ end
90
+
91
+ path = File.join(Backup::SpecLive::SYNC_PATH, 'dir_b/two.file')
92
+ h_safety_check(path)
93
+ FileUtils.rm(path)
94
+ end
95
+
96
+ def clean_sync_dir
97
+ path = Backup::SpecLive::SYNC_PATH
98
+ if File.directory?(path)
99
+ h_safety_check(path)
100
+ FileUtils.rm_r(path)
101
+ end
102
+ end
103
+
104
+ # use a new connection for each request
105
+ def connection
106
+ @opts = Backup::SpecLive::CONFIG['syncer']['cloud']['s3']
107
+ Fog::Storage.new(
108
+ :provider => 'AWS',
109
+ :aws_access_key_id => @opts['access_key_id'],
110
+ :aws_secret_access_key => @opts['secret_access_key'],
111
+ :region => @opts['region']
112
+ )
113
+ end
114
+
115
+ def remote_files
116
+ bucket = connection.directories.get(@opts['bucket'])
117
+ bucket.files.all(:prefix => 'backups')
118
+ end
119
+
120
+ def clean_remote
121
+ remote_files.each {|file| file.destroy }
122
+ end
123
+
124
+ end
data/spec/archive_spec.rb CHANGED
@@ -134,30 +134,41 @@ describe Backup::Archive do
134
134
  end
135
135
  let(:paths) { ['/path/to/add', '/another/path/to/add'] }
136
136
  let(:excludes) { ['/path/to/exclude', '/another/path/to/exclude'] }
137
+ let(:pipeline) { mock }
138
+ let(:s) { sequence '' }
137
139
 
138
140
  before do
141
+ archive.instance_variable_set(:@paths, paths)
139
142
  archive.expects(:utility).with(:tar).returns('tar')
140
143
  FileUtils.expects(:mkdir_p).with(archive_path)
144
+ Backup::Pipeline.expects(:new).returns(pipeline)
141
145
  end
142
146
 
143
147
  context 'when both #paths and #excludes were added' do
144
148
  before do
145
- archive.instance_variable_set(:@paths, paths)
146
149
  archive.instance_variable_set(:@excludes, excludes)
147
150
  end
148
151
 
149
152
  it 'should render the syntax for both' do
150
- Backup::Logger.expects(:message).with(
151
- "Backup::Archive started packaging and archiving:\n" +
153
+ Backup::Logger.expects(:message).in_sequence(s).with(
154
+ "Backup::Archive has started archiving:\n" +
152
155
  " /path/to/add\n" +
153
156
  " /another/path/to/add"
154
157
  )
155
158
 
156
- archive.expects(:run).with(
157
- "tar -cf - " +
159
+ pipeline.expects(:<<).in_sequence(s).with(
160
+ "tar -cPf - " +
158
161
  "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
159
- "'/path/to/add' '/another/path/to/add' " +
160
- "> '#{ File.join(archive_path, 'test_archive.tar') }'"
162
+ "'/path/to/add' '/another/path/to/add'"
163
+ )
164
+ pipeline.expects(:<<).in_sequence(s).with(
165
+ "cat > '#{ File.join(archive_path, 'test_archive.tar') }'"
166
+ )
167
+ pipeline.expects(:run).in_sequence(s)
168
+ pipeline.expects(:success?).in_sequence(s).returns(true)
169
+
170
+ Backup::Logger.expects(:message).in_sequence(s).with(
171
+ "Backup::Archive Complete!"
161
172
  )
162
173
 
163
174
  archive.perform!
@@ -165,45 +176,56 @@ describe Backup::Archive do
165
176
  end # context 'when both #paths and #excludes were added'
166
177
 
167
178
  context 'when no excludes were added' do
168
- before do
169
- archive.instance_variable_set(:@paths, paths)
170
- end
171
-
172
179
  it 'should render only the syntax for adds' do
173
- Backup::Logger.expects(:message).with(
174
- "Backup::Archive started packaging and archiving:\n" +
180
+ Backup::Logger.expects(:message).in_sequence(s).with(
181
+ "Backup::Archive has started archiving:\n" +
175
182
  " /path/to/add\n" +
176
183
  " /another/path/to/add"
177
184
  )
178
185
 
179
- archive.expects(:run).with(
180
- "tar -cf - " +
181
- "'/path/to/add' '/another/path/to/add' " +
182
- "> '#{ File.join(archive_path, 'test_archive.tar') }'"
186
+ pipeline.expects(:<<).in_sequence(s).with(
187
+ "tar -cPf - '/path/to/add' '/another/path/to/add'"
188
+ )
189
+ pipeline.expects(:<<).in_sequence(s).with(
190
+ "cat > '#{ File.join(archive_path, 'test_archive.tar') }'"
191
+ )
192
+ pipeline.expects(:run).in_sequence(s)
193
+ pipeline.expects(:success?).in_sequence(s).returns(true)
194
+
195
+ Backup::Logger.expects(:message).in_sequence(s).with(
196
+ "Backup::Archive Complete!"
183
197
  )
184
198
 
185
199
  archive.perform!
186
200
  end
187
201
  end # context 'when no excludes were added'
202
+
188
203
  context 'with #paths, #excludes and #tar_args' do
189
204
  before do
190
- archive.instance_variable_set(:@paths, paths)
191
205
  archive.instance_variable_set(:@excludes, excludes)
192
206
  archive.instance_variable_set(:@tar_args, '-h --xattrs')
193
207
  end
194
208
 
195
209
  it 'should render the syntax for all three' do
196
- Backup::Logger.expects(:message).with(
197
- "Backup::Archive started packaging and archiving:\n" +
210
+ Backup::Logger.expects(:message).in_sequence(s).with(
211
+ "Backup::Archive has started archiving:\n" +
198
212
  " /path/to/add\n" +
199
213
  " /another/path/to/add"
200
214
  )
201
215
 
202
- archive.expects(:run).with(
203
- "tar -h --xattrs -cf - " +
216
+ pipeline.expects(:<<).in_sequence(s).with(
217
+ "tar -h --xattrs -cPf - " +
204
218
  "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
205
- "'/path/to/add' '/another/path/to/add' " +
206
- "> '#{ File.join(archive_path, 'test_archive.tar') }'"
219
+ "'/path/to/add' '/another/path/to/add'"
220
+ )
221
+ pipeline.expects(:<<).in_sequence(s).with(
222
+ "cat > '#{ File.join(archive_path, 'test_archive.tar') }'"
223
+ )
224
+ pipeline.expects(:run).in_sequence(s)
225
+ pipeline.expects(:success?).in_sequence(s).returns(true)
226
+
227
+ Backup::Logger.expects(:message).in_sequence(s).with(
228
+ "Backup::Archive Complete!"
207
229
  )
208
230
 
209
231
  archive.perform!
@@ -212,7 +234,6 @@ describe Backup::Archive do
212
234
 
213
235
  context 'with #paths, #excludes, #tar_args and a Gzip Compressor' do
214
236
  before do
215
- archive.instance_variable_set(:@paths, paths)
216
237
  archive.instance_variable_set(:@excludes, excludes)
217
238
  archive.instance_variable_set(:@tar_args, '-h --xattrs')
218
239
  compressor = mock
@@ -221,23 +242,57 @@ describe Backup::Archive do
221
242
  end
222
243
 
223
244
  it 'should render the syntax with compressor modifications' do
224
- Backup::Logger.expects(:message).with(
225
- "Backup::Archive started packaging and archiving:\n" +
245
+ Backup::Logger.expects(:message).in_sequence(s).with(
246
+ "Backup::Archive has started archiving:\n" +
226
247
  " /path/to/add\n" +
227
248
  " /another/path/to/add"
228
249
  )
229
250
 
230
- archive.expects(:run).with(
231
- "tar -h --xattrs -cf - " +
251
+ pipeline.expects(:<<).in_sequence(s).with(
252
+ "tar -h --xattrs -cPf - " +
232
253
  "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
233
- "'/path/to/add' '/another/path/to/add' " +
234
- "| gzip > '#{ File.join(archive_path, 'test_archive.tar.gz') }'"
254
+ "'/path/to/add' '/another/path/to/add'"
255
+ )
256
+ pipeline.expects(:<<).in_sequence(s).with('gzip')
257
+ pipeline.expects(:<<).in_sequence(s).with(
258
+ "cat > '#{ File.join(archive_path, 'test_archive.tar.gz') }'"
259
+ )
260
+ pipeline.expects(:run).in_sequence(s)
261
+ pipeline.expects(:success?).in_sequence(s).returns(true)
262
+
263
+ Backup::Logger.expects(:message).in_sequence(s).with(
264
+ "Backup::Archive Complete!"
235
265
  )
236
266
 
237
267
  archive.perform!
238
268
  end
239
269
  end # context 'with #paths, #excludes, #tar_args and a Gzip Compressor'
240
270
 
271
+ context 'when pipeline command fails' do
272
+ before do
273
+ pipeline.stubs(:<<)
274
+ pipeline.expects(:run)
275
+ pipeline.expects(:success?).returns(false)
276
+ pipeline.expects(:error_messages).returns('pipeline_errors')
277
+ end
278
+
279
+ it 'should raise an error' do
280
+ Backup::Logger.expects(:message).with(
281
+ "Backup::Archive has started archiving:\n" +
282
+ " /path/to/add\n" +
283
+ " /another/path/to/add"
284
+ )
285
+
286
+ expect do
287
+ archive.perform!
288
+ end.to raise_error(
289
+ Backup::Errors::Archive::PipelineError,
290
+ "Archive::PipelineError: Failed to Create Backup Archive\n" +
291
+ " pipeline_errors"
292
+ )
293
+ end
294
+ end # context 'when pipeline command fails'
295
+
241
296
  end # describe '#perform!'
242
297
 
243
298
  describe '#paths_to_package' do
data/spec/cleaner_spec.rb CHANGED
@@ -221,6 +221,10 @@ describe 'Backup::Cleaner' do
221
221
  FileUtils.unstub(:mkdir_p)
222
222
  end
223
223
 
224
+ after do
225
+ Backup::Config.send(:reset!)
226
+ end
227
+
224
228
  context 'when files exist in the packaging folder' do
225
229
  it 'should return true' do
226
230
  Dir.mktmpdir do |path|
@@ -253,6 +257,10 @@ describe 'Backup::Cleaner' do
253
257
  FileUtils.unstub(:touch)
254
258
  end
255
259
 
260
+ after do
261
+ Backup::Config.send(:reset!)
262
+ end
263
+
256
264
  context 'when packaging files exist in the tmp_path' do
257
265
  it 'should return the files' do
258
266
  Dir.mktmpdir do |path|
@@ -6,55 +6,190 @@ describe Backup::CLI::Helpers do
6
6
  let(:helpers) { Module.new.extend(Backup::CLI::Helpers) }
7
7
 
8
8
  describe '#run' do
9
- let(:stdin) { mock }
10
- let(:stdout) { mock }
11
- let(:stderr) { mock }
12
- let(:process_status) { mock }
13
-
14
- it 'should run the given command using POpen4' do
15
- Open4.expects(:popen4).with('/path/to/command args').
16
- returns([123, stdin, stdout, stderr])
17
- Process.expects(:waitpid2).with(123).returns([123, process_status])
18
- stdout.expects(:read).returns('stdout message')
19
- stderr.expects(:read).returns('stderr message')
20
-
21
- helpers.expects(:command_name).with('/path/to/command args').
22
- returns('command')
23
- helpers.expects(:raise_if_command_failed!).with(
24
- 'command',
25
- {:status => process_status,
26
- :stdout => 'stdout message',
27
- :stderr => 'stderr message',
28
- :ignore_exit_codes => [0]}
29
- )
9
+ let(:stdout_io) { stub(:read => stdout_messages) }
10
+ let(:stderr_io) { stub(:read => stderr_messages) }
11
+ let(:stdin_io) { stub(:close) }
12
+ let(:process_status) { stub(:success? => process_success) }
13
+ let(:command) { '/path/to/cmd_name arg1 arg2' }
30
14
 
31
- helpers.run('/path/to/command args').should == 'stdout message'
32
- end
15
+ context 'when the command is successful' do
16
+ let(:process_success) { true }
33
17
 
34
- it 'should accept ignore_exit_codes and add 0 to the list' do
35
- Open4.expects(:popen4).with('/path/to/command args').
36
- returns([123, stdin, stdout, stderr])
37
- Process.expects(:waitpid2).with(123).returns([123, process_status])
38
- stdout.expects(:read).returns('stdout message')
39
- stderr.expects(:read).returns('stderr message')
40
-
41
- helpers.expects(:command_name).with('/path/to/command args').
42
- returns('command')
43
- helpers.expects(:raise_if_command_failed!).with(
44
- 'command',
45
- {:status => process_status,
46
- :stdout => 'stdout message',
47
- :stderr => 'stderr message',
48
- :ignore_exit_codes => [1, 2, 0]}
49
- )
18
+ before do
19
+ Backup::Logger.expects(:message).with(
20
+ "Running system utility 'cmd_name'..."
21
+ )
50
22
 
51
- helpers.run(
52
- '/path/to/command args', :ignore_exit_codes => [1, 2]
53
- ).should == 'stdout message'
54
- end
55
- end
23
+ Open4.expects(:popen4).with(command).yields(
24
+ nil, stdin_io, stdout_io, stderr_io
25
+ ).returns(process_status)
26
+ end
27
+
28
+ context 'and generates no messages' do
29
+ let(:stdout_messages) { '' }
30
+ let(:stderr_messages) { '' }
31
+
32
+ it 'should generate no additional log messages' do
33
+ helpers.run(command).should be_nil
34
+ end
35
+ end
36
+
37
+ context 'and generates only stdout messages' do
38
+ let(:stdout_messages) { "out line1\nout line2\n" }
39
+ let(:stderr_messages) { '' }
40
+
41
+ it 'should log the stdout messages' do
42
+ Backup::Logger.expects(:message).with(
43
+ "cmd_name:STDOUT: out line1\ncmd_name:STDOUT: out line2"
44
+ )
45
+ helpers.run(command).should be_nil
46
+ end
47
+ end
48
+
49
+ context 'and generates only stderr messages' do
50
+ let(:stdout_messages) { '' }
51
+ let(:stderr_messages) { "err line1\nerr line2\n" }
52
+
53
+ it 'should log the stderr messages' do
54
+ Backup::Logger.expects(:warn).with(
55
+ "cmd_name:STDERR: err line1\ncmd_name:STDERR: err line2"
56
+ )
57
+ helpers.run(command).should be_nil
58
+ end
59
+ end
60
+
61
+ context 'and generates messages on both stdout and stderr' do
62
+ let(:stdout_messages) { "out line1\nout line2\n" }
63
+ let(:stderr_messages) { "err line1\nerr line2\n" }
64
+
65
+ it 'should log both stdout and stderr messages' do
66
+ Backup::Logger.expects(:message).with(
67
+ "cmd_name:STDOUT: out line1\ncmd_name:STDOUT: out line2"
68
+ )
69
+ Backup::Logger.expects(:warn).with(
70
+ "cmd_name:STDERR: err line1\ncmd_name:STDERR: err line2"
71
+ )
72
+ helpers.run(command).should be_nil
73
+ end
74
+ end
75
+ end # context 'when the command is successful'
76
+
77
+ context 'when the command is not successful' do
78
+ let(:process_success) { false }
79
+ let(:message_head) do
80
+ "CLI::SystemCallError: 'cmd_name' Failed on #{ RUBY_PLATFORM }\n" +
81
+ " The following information should help to determine the problem:\n" +
82
+ " Command was: /path/to/cmd_name arg1 arg2\n" +
83
+ " Exit Status: 1\n"
84
+ end
85
+
86
+ before do
87
+ Backup::Logger.expects(:message).with(
88
+ "Running system utility 'cmd_name'..."
89
+ )
90
+
91
+ Open4.expects(:popen4).with(command).yields(
92
+ nil, stdin_io, stdout_io, stderr_io
93
+ ).returns(process_status)
94
+
95
+ process_status.stubs(:exitstatus).returns(1)
96
+ end
97
+
98
+ context 'and generates no messages' do
99
+ let(:stdout_messages) { '' }
100
+ let(:stderr_messages) { '' }
101
+
102
+ it 'should raise an error reporting no messages' do
103
+ expect do
104
+ helpers.run(command)
105
+ end.to raise_error {|err|
106
+ err.message.should == message_head +
107
+ " STDOUT Messages: None\n" +
108
+ " STDERR Messages: None"
109
+ }
110
+ end
111
+ end
112
+
113
+ context 'and generates only stdout messages' do
114
+ let(:stdout_messages) { "out line1\nout line2\n" }
115
+ let(:stderr_messages) { '' }
116
+
117
+ it 'should raise an error and report the stdout messages' do
118
+ expect do
119
+ helpers.run(command)
120
+ end.to raise_error {|err|
121
+ err.message.should == message_head +
122
+ " STDOUT Messages: \n" +
123
+ " out line1\n" +
124
+ " out line2\n" +
125
+ " STDERR Messages: None"
126
+ }
127
+ end
128
+ end
129
+
130
+ context 'and generates only stderr messages' do
131
+ let(:stdout_messages) { '' }
132
+ let(:stderr_messages) { "err line1\nerr line2\n" }
133
+
134
+ it 'should raise an error and report the stderr messages' do
135
+ expect do
136
+ helpers.run(command)
137
+ end.to raise_error {|err|
138
+ err.message.should == message_head +
139
+ " STDOUT Messages: None\n" +
140
+ " STDERR Messages: \n" +
141
+ " err line1\n" +
142
+ " err line2"
143
+ }
144
+ end
145
+ end
146
+
147
+ context 'and generates messages on both stdout and stderr' do
148
+ let(:stdout_messages) { "out line1\nout line2\n" }
149
+ let(:stderr_messages) { "err line1\nerr line2\n" }
150
+
151
+ it 'should raise an error and report the stdout and stderr messages' do
152
+ expect do
153
+ helpers.run(command)
154
+ end.to raise_error {|err|
155
+ err.message.should == message_head +
156
+ " STDOUT Messages: \n" +
157
+ " out line1\n" +
158
+ " out line2\n" +
159
+ " STDERR Messages: \n" +
160
+ " err line1\n" +
161
+ " err line2"
162
+ }
163
+ end
164
+ end
165
+ end # context 'when the command is not successful'
166
+
167
+ context 'when the system fails to execute the command' do
168
+ before do
169
+ Backup::Logger.expects(:message).with(
170
+ "Running system utility 'cmd_name'..."
171
+ )
172
+
173
+ Open4.expects(:popen4).raises("exec call failed")
174
+ end
175
+
176
+ it 'should raise an error wrapping the system error raised' do
177
+ expect do
178
+ helpers.run(command)
179
+ end.to raise_error {|err|
180
+ err.message.should == "CLI::SystemCallError: " +
181
+ "Failed to execute system command on #{ RUBY_PLATFORM }\n" +
182
+ " Command was: /path/to/cmd_name arg1 arg2\n" +
183
+ " Reason: RuntimeError\n" +
184
+ " exec call failed"
185
+ }
186
+ end
187
+ end # context 'when the system fails to execute the command'
188
+ end # describe '#run'
56
189
 
57
190
  describe '#utility' do
191
+ after { Backup::CLI::Helpers::UTILITY.clear }
192
+
58
193
  context 'when a system path for the utility is available' do
59
194
  it 'should return the system path with newline removed' do
60
195
  helpers.expects(:`).with('which foo 2>/dev/null').returns("system_path\n")
@@ -79,7 +214,6 @@ describe Backup::CLI::Helpers do
79
214
  end
80
215
  end
81
216
 
82
-
83
217
  context 'when a system path for the utility is not available' do
84
218
  it 'should raise an error' do
85
219
  helpers.expects(:`).with('which unknown 2>/dev/null').returns("\n")
@@ -87,7 +221,7 @@ describe Backup::CLI::Helpers do
87
221
  expect do
88
222
  helpers.utility(:unknown)
89
223
  end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
90
- err.message.should match(/Path to 'unknown' could not be found/)
224
+ err.message.should match(/Could not locate 'unknown'/)
91
225
  }
92
226
  end
93
227
 
@@ -97,16 +231,34 @@ describe Backup::CLI::Helpers do
97
231
  expect do
98
232
  helpers.utility(:not_cached)
99
233
  end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
100
- err.message.should match(/Path to 'not_cached' could not be found/)
234
+ err.message.should match(/Could not locate 'not_cached'/)
101
235
  }
102
236
 
103
237
  expect do
104
238
  helpers.utility(:not_cached)
105
239
  end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
106
- err.message.should match(/Path to 'not_cached' could not be found/)
240
+ err.message.should match(/Could not locate 'not_cached'/)
107
241
  }
108
242
  end
109
243
  end
244
+
245
+ it 'should raise an error if name is nil' do
246
+ expect do
247
+ helpers.utility(nil)
248
+ end.to raise_error(
249
+ Backup::Errors::CLI::UtilityNotFoundError,
250
+ 'CLI::UtilityNotFoundError: Utility Name Empty'
251
+ )
252
+ end
253
+
254
+ it 'should raise an error if name is empty' do
255
+ expect do
256
+ helpers.utility(' ')
257
+ end.to raise_error(
258
+ Backup::Errors::CLI::UtilityNotFoundError,
259
+ 'CLI::UtilityNotFoundError: Utility Name Empty'
260
+ )
261
+ end
110
262
  end # describe '#utility'
111
263
 
112
264
  describe '#command_name' do
@@ -146,31 +298,4 @@ describe Backup::CLI::Helpers do
146
298
  end
147
299
  end # describe '#command_name'
148
300
 
149
- describe '#raise_if_command_failed!' do
150
-
151
- it 'returns nil if status exit code is in ignore_exit_codes' do
152
- process_data = { :status => '3', :ignore_exit_codes => [1,3,5] }
153
- helpers.raise_if_command_failed!('foo', process_data).should be_nil
154
- end
155
-
156
- it 'raises an error with stdout/stderr data' do
157
- process_data = { :status => '3', :ignore_exit_codes => [2,4,6],
158
- :stdout => 'stdout data', :stderr => 'stderr data' }
159
-
160
- expect do
161
- helpers.raise_if_command_failed!('utility_name', process_data)
162
- end.to raise_error(
163
- Backup::Errors::CLI::SystemCallError,
164
- "CLI::SystemCallError: Failed to run utility_name on #{RUBY_PLATFORM}\n" +
165
- " The following information should help to determine the problem:\n" +
166
- " Exit Code: 3\n" +
167
- " STDERR:\n" +
168
- " stderr data\n" +
169
- " STDOUT:\n" +
170
- " stdout data"
171
- )
172
- end
173
-
174
- end
175
-
176
301
  end