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.
- data/Gemfile.lock +42 -45
- data/Guardfile +7 -4
- data/README.md +10 -7
- data/backup.gemspec +2 -2
- data/lib/backup.rb +27 -97
- data/lib/backup/archive.rb +14 -6
- data/lib/backup/cli/helpers.rb +52 -49
- data/lib/backup/cli/utility.rb +9 -1
- data/lib/backup/compressor/base.rb +10 -4
- data/lib/backup/compressor/bzip2.rb +22 -26
- data/lib/backup/compressor/custom.rb +53 -0
- data/lib/backup/compressor/gzip.rb +22 -23
- data/lib/backup/compressor/lzma.rb +15 -13
- data/lib/backup/compressor/pbzip2.rb +20 -17
- data/lib/backup/config.rb +6 -3
- data/lib/backup/configuration.rb +33 -0
- data/lib/backup/configuration/helpers.rb +114 -28
- data/lib/backup/configuration/store.rb +24 -0
- data/lib/backup/database/base.rb +0 -6
- data/lib/backup/database/mongodb.rb +27 -11
- data/lib/backup/database/mysql.rb +19 -14
- data/lib/backup/database/postgresql.rb +16 -11
- data/lib/backup/database/redis.rb +7 -11
- data/lib/backup/database/riak.rb +3 -6
- data/lib/backup/dependency.rb +5 -11
- data/lib/backup/model.rb +14 -5
- data/lib/backup/notifier/campfire.rb +3 -16
- data/lib/backup/notifier/hipchat.rb +1 -7
- data/lib/backup/notifier/mail.rb +1 -1
- data/lib/backup/packager.rb +29 -19
- data/lib/backup/pipeline.rb +110 -0
- data/lib/backup/storage/dropbox.rb +4 -7
- data/lib/backup/syncer/base.rb +8 -4
- data/lib/backup/syncer/cloud/base.rb +247 -0
- data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
- data/lib/backup/syncer/cloud/s3.rb +68 -0
- data/lib/backup/syncer/rsync/base.rb +1 -4
- data/lib/backup/syncer/rsync/local.rb +9 -5
- data/lib/backup/syncer/rsync/pull.rb +1 -1
- data/lib/backup/syncer/rsync/push.rb +10 -5
- data/lib/backup/version.rb +1 -1
- data/spec-live/.gitignore +6 -0
- data/spec-live/README +7 -0
- data/spec-live/backups/config.rb +153 -0
- data/spec-live/backups/config.yml.template +43 -0
- data/spec-live/compressor/custom_spec.rb +30 -0
- data/spec-live/compressor/gzip_spec.rb +30 -0
- data/spec-live/notifier/mail_spec.rb +85 -0
- data/spec-live/spec_helper.rb +85 -0
- data/spec-live/storage/dropbox_spec.rb +151 -0
- data/spec-live/storage/local_spec.rb +83 -0
- data/spec-live/storage/scp_spec.rb +193 -0
- data/spec-live/syncer/cloud/s3_spec.rb +124 -0
- data/spec/archive_spec.rb +86 -31
- data/spec/cleaner_spec.rb +8 -0
- data/spec/cli/helpers_spec.rb +200 -75
- data/spec/cli/utility_spec.rb +11 -3
- data/spec/compressor/base_spec.rb +31 -10
- data/spec/compressor/bzip2_spec.rb +212 -57
- data/spec/compressor/custom_spec.rb +106 -0
- data/spec/compressor/gzip_spec.rb +212 -57
- data/spec/compressor/lzma_spec.rb +75 -35
- data/spec/compressor/pbzip2_spec.rb +93 -52
- data/spec/configuration/helpers_spec.rb +406 -0
- data/spec/configuration/store_spec.rb +39 -0
- data/spec/configuration_spec.rb +62 -0
- data/spec/database/base_spec.rb +19 -10
- data/spec/database/mongodb_spec.rb +195 -70
- data/spec/database/mysql_spec.rb +183 -64
- data/spec/database/postgresql_spec.rb +167 -53
- data/spec/database/redis_spec.rb +121 -46
- data/spec/database/riak_spec.rb +96 -27
- data/spec/dependency_spec.rb +2 -0
- data/spec/encryptor/base_spec.rb +10 -0
- data/spec/encryptor/gpg_spec.rb +29 -13
- data/spec/encryptor/open_ssl_spec.rb +40 -21
- data/spec/logger_spec.rb +4 -0
- data/spec/model_spec.rb +19 -2
- data/spec/notifier/base_spec.rb +32 -17
- data/spec/notifier/campfire_spec.rb +63 -45
- data/spec/notifier/hipchat_spec.rb +79 -56
- data/spec/notifier/mail_spec.rb +82 -46
- data/spec/notifier/prowl_spec.rb +53 -32
- data/spec/notifier/twitter_spec.rb +62 -41
- data/spec/packager_spec.rb +95 -36
- data/spec/pipeline_spec.rb +259 -0
- data/spec/spec_helper.rb +6 -5
- data/spec/storage/base_spec.rb +61 -41
- data/spec/storage/cloudfiles_spec.rb +69 -45
- data/spec/storage/dropbox_spec.rb +158 -36
- data/spec/storage/ftp_spec.rb +69 -45
- data/spec/storage/local_spec.rb +47 -23
- data/spec/storage/ninefold_spec.rb +55 -31
- data/spec/storage/rsync_spec.rb +67 -50
- data/spec/storage/s3_spec.rb +65 -41
- data/spec/storage/scp_spec.rb +65 -41
- data/spec/storage/sftp_spec.rb +65 -41
- data/spec/syncer/base_spec.rb +91 -4
- data/spec/syncer/cloud/base_spec.rb +511 -0
- data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
- data/spec/syncer/cloud/s3_spec.rb +174 -0
- data/spec/syncer/rsync/base_spec.rb +46 -66
- data/spec/syncer/rsync/local_spec.rb +55 -26
- data/spec/syncer/rsync/pull_spec.rb +15 -4
- data/spec/syncer/rsync/push_spec.rb +59 -52
- data/templates/cli/utility/compressor/bzip2 +1 -4
- data/templates/cli/utility/compressor/custom +11 -0
- data/templates/cli/utility/compressor/gzip +1 -4
- data/templates/cli/utility/compressor/lzma +3 -0
- data/templates/cli/utility/compressor/pbzip2 +3 -0
- data/templates/cli/utility/database/mysql +4 -1
- data/templates/cli/utility/syncer/cloud_files +17 -19
- data/templates/cli/utility/syncer/s3 +18 -20
- metadata +38 -92
- data/lib/backup/configuration/base.rb +0 -15
- data/lib/backup/configuration/compressor/base.rb +0 -9
- data/lib/backup/configuration/compressor/bzip2.rb +0 -23
- data/lib/backup/configuration/compressor/gzip.rb +0 -23
- data/lib/backup/configuration/compressor/lzma.rb +0 -23
- data/lib/backup/configuration/compressor/pbzip2.rb +0 -28
- data/lib/backup/configuration/database/base.rb +0 -19
- data/lib/backup/configuration/database/mongodb.rb +0 -49
- data/lib/backup/configuration/database/mysql.rb +0 -42
- data/lib/backup/configuration/database/postgresql.rb +0 -41
- data/lib/backup/configuration/database/redis.rb +0 -39
- data/lib/backup/configuration/database/riak.rb +0 -29
- data/lib/backup/configuration/encryptor/base.rb +0 -9
- data/lib/backup/configuration/encryptor/gpg.rb +0 -17
- data/lib/backup/configuration/encryptor/open_ssl.rb +0 -32
- data/lib/backup/configuration/notifier/base.rb +0 -28
- data/lib/backup/configuration/notifier/campfire.rb +0 -25
- data/lib/backup/configuration/notifier/hipchat.rb +0 -41
- data/lib/backup/configuration/notifier/mail.rb +0 -112
- data/lib/backup/configuration/notifier/presently.rb +0 -25
- data/lib/backup/configuration/notifier/prowl.rb +0 -23
- data/lib/backup/configuration/notifier/twitter.rb +0 -21
- data/lib/backup/configuration/storage/base.rb +0 -18
- data/lib/backup/configuration/storage/cloudfiles.rb +0 -25
- data/lib/backup/configuration/storage/dropbox.rb +0 -58
- data/lib/backup/configuration/storage/ftp.rb +0 -29
- data/lib/backup/configuration/storage/local.rb +0 -17
- data/lib/backup/configuration/storage/ninefold.rb +0 -20
- data/lib/backup/configuration/storage/rsync.rb +0 -29
- data/lib/backup/configuration/storage/s3.rb +0 -25
- data/lib/backup/configuration/storage/scp.rb +0 -25
- data/lib/backup/configuration/storage/sftp.rb +0 -25
- data/lib/backup/configuration/syncer/base.rb +0 -10
- data/lib/backup/configuration/syncer/cloud.rb +0 -23
- data/lib/backup/configuration/syncer/cloud_files.rb +0 -30
- data/lib/backup/configuration/syncer/rsync/base.rb +0 -28
- data/lib/backup/configuration/syncer/rsync/local.rb +0 -11
- data/lib/backup/configuration/syncer/rsync/pull.rb +0 -11
- data/lib/backup/configuration/syncer/rsync/push.rb +0 -31
- data/lib/backup/configuration/syncer/s3.rb +0 -23
- data/lib/backup/notifier/presently.rb +0 -88
- data/lib/backup/syncer/cloud.rb +0 -187
- data/lib/backup/syncer/cloud_files.rb +0 -56
- data/lib/backup/syncer/s3.rb +0 -47
- data/spec/configuration/base_spec.rb +0 -35
- data/spec/configuration/compressor/bzip2_spec.rb +0 -29
- data/spec/configuration/compressor/gzip_spec.rb +0 -29
- data/spec/configuration/compressor/lzma_spec.rb +0 -29
- data/spec/configuration/compressor/pbzip2_spec.rb +0 -32
- data/spec/configuration/database/base_spec.rb +0 -17
- data/spec/configuration/database/mongodb_spec.rb +0 -56
- data/spec/configuration/database/mysql_spec.rb +0 -53
- data/spec/configuration/database/postgresql_spec.rb +0 -53
- data/spec/configuration/database/redis_spec.rb +0 -50
- data/spec/configuration/database/riak_spec.rb +0 -35
- data/spec/configuration/encryptor/gpg_spec.rb +0 -26
- data/spec/configuration/encryptor/open_ssl_spec.rb +0 -35
- data/spec/configuration/notifier/base_spec.rb +0 -32
- data/spec/configuration/notifier/campfire_spec.rb +0 -32
- data/spec/configuration/notifier/hipchat_spec.rb +0 -44
- data/spec/configuration/notifier/mail_spec.rb +0 -71
- data/spec/configuration/notifier/presently_spec.rb +0 -35
- data/spec/configuration/notifier/prowl_spec.rb +0 -29
- data/spec/configuration/notifier/twitter_spec.rb +0 -35
- data/spec/configuration/storage/cloudfiles_spec.rb +0 -41
- data/spec/configuration/storage/dropbox_spec.rb +0 -38
- data/spec/configuration/storage/ftp_spec.rb +0 -44
- data/spec/configuration/storage/local_spec.rb +0 -29
- data/spec/configuration/storage/ninefold_spec.rb +0 -32
- data/spec/configuration/storage/rsync_spec.rb +0 -41
- data/spec/configuration/storage/s3_spec.rb +0 -38
- data/spec/configuration/storage/scp_spec.rb +0 -41
- data/spec/configuration/storage/sftp_spec.rb +0 -41
- data/spec/configuration/syncer/cloud_files_spec.rb +0 -44
- data/spec/configuration/syncer/rsync/base_spec.rb +0 -33
- data/spec/configuration/syncer/rsync/local_spec.rb +0 -10
- data/spec/configuration/syncer/rsync/pull_spec.rb +0 -10
- data/spec/configuration/syncer/rsync/push_spec.rb +0 -43
- data/spec/configuration/syncer/s3_spec.rb +0 -38
- data/spec/notifier/presently_spec.rb +0 -181
- data/spec/syncer/cloud_files_spec.rb +0 -192
- data/spec/syncer/s3_spec.rb +0 -192
- 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
|
|
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
|
-
|
|
157
|
-
"tar -
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
180
|
-
"tar -
|
|
181
|
-
|
|
182
|
-
|
|
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
|
|
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
|
-
|
|
203
|
-
"tar -h --xattrs -
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
231
|
-
"tar -h --xattrs -
|
|
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
|
-
|
|
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|
|
data/spec/cli/helpers_spec.rb
CHANGED
|
@@ -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(:
|
|
10
|
-
let(:
|
|
11
|
-
let(:
|
|
12
|
-
let(:process_status) {
|
|
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
|
-
|
|
32
|
-
|
|
15
|
+
context 'when the command is successful' do
|
|
16
|
+
let(:process_success) { true }
|
|
33
17
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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(/
|
|
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(/
|
|
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(/
|
|
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
|