backup 3.0.23 → 3.0.24

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 (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