backup_checksum 3.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/.travis.yml +10 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +130 -0
- data/Guardfile +21 -0
- data/LICENSE.md +24 -0
- data/README.md +476 -0
- data/backup_checksum.gemspec +32 -0
- data/bin/backup +11 -0
- data/lib/backup.rb +217 -0
- data/lib/backup/archive.rb +117 -0
- data/lib/backup/binder.rb +22 -0
- data/lib/backup/checksum/base.rb +44 -0
- data/lib/backup/checksum/shasum.rb +16 -0
- data/lib/backup/cleaner.rb +121 -0
- data/lib/backup/cli/helpers.rb +88 -0
- data/lib/backup/cli/utility.rb +247 -0
- data/lib/backup/compressor/base.rb +29 -0
- data/lib/backup/compressor/bzip2.rb +50 -0
- data/lib/backup/compressor/gzip.rb +47 -0
- data/lib/backup/compressor/lzma.rb +50 -0
- data/lib/backup/compressor/pbzip2.rb +56 -0
- data/lib/backup/config.rb +173 -0
- data/lib/backup/configuration/base.rb +15 -0
- data/lib/backup/configuration/checksum/base.rb +9 -0
- data/lib/backup/configuration/checksum/shasum.rb +9 -0
- data/lib/backup/configuration/compressor/base.rb +9 -0
- data/lib/backup/configuration/compressor/bzip2.rb +23 -0
- data/lib/backup/configuration/compressor/gzip.rb +23 -0
- data/lib/backup/configuration/compressor/lzma.rb +23 -0
- data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
- data/lib/backup/configuration/database/base.rb +19 -0
- data/lib/backup/configuration/database/mongodb.rb +49 -0
- data/lib/backup/configuration/database/mysql.rb +42 -0
- data/lib/backup/configuration/database/postgresql.rb +41 -0
- data/lib/backup/configuration/database/redis.rb +39 -0
- data/lib/backup/configuration/database/riak.rb +29 -0
- data/lib/backup/configuration/encryptor/base.rb +9 -0
- data/lib/backup/configuration/encryptor/gpg.rb +17 -0
- data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
- data/lib/backup/configuration/helpers.rb +52 -0
- data/lib/backup/configuration/notifier/base.rb +28 -0
- data/lib/backup/configuration/notifier/campfire.rb +25 -0
- data/lib/backup/configuration/notifier/hipchat.rb +41 -0
- data/lib/backup/configuration/notifier/mail.rb +112 -0
- data/lib/backup/configuration/notifier/presently.rb +25 -0
- data/lib/backup/configuration/notifier/prowl.rb +23 -0
- data/lib/backup/configuration/notifier/twitter.rb +21 -0
- data/lib/backup/configuration/storage/base.rb +18 -0
- data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
- data/lib/backup/configuration/storage/dropbox.rb +58 -0
- data/lib/backup/configuration/storage/ftp.rb +29 -0
- data/lib/backup/configuration/storage/local.rb +17 -0
- data/lib/backup/configuration/storage/ninefold.rb +20 -0
- data/lib/backup/configuration/storage/rsync.rb +29 -0
- data/lib/backup/configuration/storage/s3.rb +25 -0
- data/lib/backup/configuration/storage/scp.rb +25 -0
- data/lib/backup/configuration/storage/sftp.rb +25 -0
- data/lib/backup/configuration/syncer/base.rb +10 -0
- data/lib/backup/configuration/syncer/cloud.rb +23 -0
- data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
- data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
- data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
- data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
- data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
- data/lib/backup/configuration/syncer/s3.rb +23 -0
- data/lib/backup/database/base.rb +59 -0
- data/lib/backup/database/mongodb.rb +232 -0
- data/lib/backup/database/mysql.rb +163 -0
- data/lib/backup/database/postgresql.rb +146 -0
- data/lib/backup/database/redis.rb +139 -0
- data/lib/backup/database/riak.rb +69 -0
- data/lib/backup/dependency.rb +114 -0
- data/lib/backup/encryptor/base.rb +29 -0
- data/lib/backup/encryptor/gpg.rb +80 -0
- data/lib/backup/encryptor/open_ssl.rb +72 -0
- data/lib/backup/errors.rb +124 -0
- data/lib/backup/logger.rb +152 -0
- data/lib/backup/model.rb +386 -0
- data/lib/backup/notifier/base.rb +81 -0
- data/lib/backup/notifier/campfire.rb +168 -0
- data/lib/backup/notifier/hipchat.rb +99 -0
- data/lib/backup/notifier/mail.rb +206 -0
- data/lib/backup/notifier/presently.rb +88 -0
- data/lib/backup/notifier/prowl.rb +65 -0
- data/lib/backup/notifier/twitter.rb +70 -0
- data/lib/backup/package.rb +51 -0
- data/lib/backup/packager.rb +108 -0
- data/lib/backup/pipeline.rb +107 -0
- data/lib/backup/splitter.rb +75 -0
- data/lib/backup/storage/base.rb +119 -0
- data/lib/backup/storage/cloudfiles.rb +87 -0
- data/lib/backup/storage/cycler.rb +117 -0
- data/lib/backup/storage/dropbox.rb +181 -0
- data/lib/backup/storage/ftp.rb +119 -0
- data/lib/backup/storage/local.rb +82 -0
- data/lib/backup/storage/ninefold.rb +116 -0
- data/lib/backup/storage/rsync.rb +149 -0
- data/lib/backup/storage/s3.rb +94 -0
- data/lib/backup/storage/scp.rb +99 -0
- data/lib/backup/storage/sftp.rb +108 -0
- data/lib/backup/syncer/base.rb +42 -0
- data/lib/backup/syncer/cloud.rb +190 -0
- data/lib/backup/syncer/cloud_files.rb +56 -0
- data/lib/backup/syncer/rsync/base.rb +52 -0
- data/lib/backup/syncer/rsync/local.rb +53 -0
- data/lib/backup/syncer/rsync/pull.rb +38 -0
- data/lib/backup/syncer/rsync/push.rb +113 -0
- data/lib/backup/syncer/s3.rb +47 -0
- data/lib/backup/template.rb +46 -0
- data/lib/backup/version.rb +43 -0
- data/spec/archive_spec.rb +335 -0
- data/spec/cleaner_spec.rb +304 -0
- data/spec/cli/helpers_spec.rb +176 -0
- data/spec/cli/utility_spec.rb +363 -0
- data/spec/compressor/base_spec.rb +31 -0
- data/spec/compressor/bzip2_spec.rb +83 -0
- data/spec/compressor/gzip_spec.rb +83 -0
- data/spec/compressor/lzma_spec.rb +83 -0
- data/spec/compressor/pbzip2_spec.rb +124 -0
- data/spec/config_spec.rb +321 -0
- data/spec/configuration/base_spec.rb +35 -0
- data/spec/configuration/compressor/bzip2_spec.rb +29 -0
- data/spec/configuration/compressor/gzip_spec.rb +29 -0
- data/spec/configuration/compressor/lzma_spec.rb +29 -0
- data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
- data/spec/configuration/database/base_spec.rb +17 -0
- data/spec/configuration/database/mongodb_spec.rb +56 -0
- data/spec/configuration/database/mysql_spec.rb +53 -0
- data/spec/configuration/database/postgresql_spec.rb +53 -0
- data/spec/configuration/database/redis_spec.rb +50 -0
- data/spec/configuration/database/riak_spec.rb +35 -0
- data/spec/configuration/encryptor/gpg_spec.rb +26 -0
- data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
- data/spec/configuration/notifier/base_spec.rb +32 -0
- data/spec/configuration/notifier/campfire_spec.rb +32 -0
- data/spec/configuration/notifier/hipchat_spec.rb +44 -0
- data/spec/configuration/notifier/mail_spec.rb +71 -0
- data/spec/configuration/notifier/presently_spec.rb +35 -0
- data/spec/configuration/notifier/prowl_spec.rb +29 -0
- data/spec/configuration/notifier/twitter_spec.rb +35 -0
- data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
- data/spec/configuration/storage/dropbox_spec.rb +38 -0
- data/spec/configuration/storage/ftp_spec.rb +44 -0
- data/spec/configuration/storage/local_spec.rb +29 -0
- data/spec/configuration/storage/ninefold_spec.rb +32 -0
- data/spec/configuration/storage/rsync_spec.rb +41 -0
- data/spec/configuration/storage/s3_spec.rb +38 -0
- data/spec/configuration/storage/scp_spec.rb +41 -0
- data/spec/configuration/storage/sftp_spec.rb +41 -0
- data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
- data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
- data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
- data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
- data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
- data/spec/configuration/syncer/s3_spec.rb +38 -0
- data/spec/database/base_spec.rb +54 -0
- data/spec/database/mongodb_spec.rb +428 -0
- data/spec/database/mysql_spec.rb +335 -0
- data/spec/database/postgresql_spec.rb +278 -0
- data/spec/database/redis_spec.rb +260 -0
- data/spec/database/riak_spec.rb +108 -0
- data/spec/dependency_spec.rb +49 -0
- data/spec/encryptor/base_spec.rb +30 -0
- data/spec/encryptor/gpg_spec.rb +134 -0
- data/spec/encryptor/open_ssl_spec.rb +129 -0
- data/spec/errors_spec.rb +306 -0
- data/spec/logger_spec.rb +363 -0
- data/spec/model_spec.rb +649 -0
- data/spec/notifier/base_spec.rb +89 -0
- data/spec/notifier/campfire_spec.rb +199 -0
- data/spec/notifier/hipchat_spec.rb +188 -0
- data/spec/notifier/mail_spec.rb +280 -0
- data/spec/notifier/presently_spec.rb +181 -0
- data/spec/notifier/prowl_spec.rb +117 -0
- data/spec/notifier/twitter_spec.rb +132 -0
- data/spec/package_spec.rb +61 -0
- data/spec/packager_spec.rb +225 -0
- data/spec/pipeline_spec.rb +257 -0
- data/spec/spec_helper.rb +59 -0
- data/spec/splitter_spec.rb +120 -0
- data/spec/storage/base_spec.rb +160 -0
- data/spec/storage/cloudfiles_spec.rb +230 -0
- data/spec/storage/cycler_spec.rb +239 -0
- data/spec/storage/dropbox_spec.rb +370 -0
- data/spec/storage/ftp_spec.rb +247 -0
- data/spec/storage/local_spec.rb +235 -0
- data/spec/storage/ninefold_spec.rb +319 -0
- data/spec/storage/rsync_spec.rb +345 -0
- data/spec/storage/s3_spec.rb +221 -0
- data/spec/storage/scp_spec.rb +209 -0
- data/spec/storage/sftp_spec.rb +220 -0
- data/spec/syncer/base_spec.rb +22 -0
- data/spec/syncer/cloud_files_spec.rb +192 -0
- data/spec/syncer/rsync/base_spec.rb +118 -0
- data/spec/syncer/rsync/local_spec.rb +121 -0
- data/spec/syncer/rsync/pull_spec.rb +90 -0
- data/spec/syncer/rsync/push_spec.rb +327 -0
- data/spec/syncer/s3_spec.rb +192 -0
- data/spec/version_spec.rb +21 -0
- data/templates/cli/utility/archive +25 -0
- data/templates/cli/utility/compressor/bzip2 +7 -0
- data/templates/cli/utility/compressor/gzip +7 -0
- data/templates/cli/utility/compressor/lzma +7 -0
- data/templates/cli/utility/compressor/pbzip2 +7 -0
- data/templates/cli/utility/config +31 -0
- data/templates/cli/utility/database/mongodb +18 -0
- data/templates/cli/utility/database/mysql +21 -0
- data/templates/cli/utility/database/postgresql +17 -0
- data/templates/cli/utility/database/redis +16 -0
- data/templates/cli/utility/database/riak +11 -0
- data/templates/cli/utility/encryptor/gpg +12 -0
- data/templates/cli/utility/encryptor/openssl +9 -0
- data/templates/cli/utility/model.erb +23 -0
- data/templates/cli/utility/notifier/campfire +12 -0
- data/templates/cli/utility/notifier/hipchat +15 -0
- data/templates/cli/utility/notifier/mail +22 -0
- data/templates/cli/utility/notifier/presently +13 -0
- data/templates/cli/utility/notifier/prowl +11 -0
- data/templates/cli/utility/notifier/twitter +13 -0
- data/templates/cli/utility/splitter +7 -0
- data/templates/cli/utility/storage/cloud_files +22 -0
- data/templates/cli/utility/storage/dropbox +20 -0
- data/templates/cli/utility/storage/ftp +12 -0
- data/templates/cli/utility/storage/local +7 -0
- data/templates/cli/utility/storage/ninefold +9 -0
- data/templates/cli/utility/storage/rsync +11 -0
- data/templates/cli/utility/storage/s3 +19 -0
- data/templates/cli/utility/storage/scp +11 -0
- data/templates/cli/utility/storage/sftp +11 -0
- data/templates/cli/utility/syncer/cloud_files +48 -0
- data/templates/cli/utility/syncer/rsync_local +12 -0
- data/templates/cli/utility/syncer/rsync_pull +17 -0
- data/templates/cli/utility/syncer/rsync_push +17 -0
- data/templates/cli/utility/syncer/s3 +45 -0
- data/templates/general/links +11 -0
- data/templates/general/version.erb +2 -0
- data/templates/notifier/mail/failure.erb +9 -0
- data/templates/notifier/mail/success.erb +7 -0
- data/templates/notifier/mail/warning.erb +9 -0
- data/templates/storage/dropbox/authorization_url.erb +6 -0
- data/templates/storage/dropbox/authorized.erb +4 -0
- data/templates/storage/dropbox/cache_file_written.erb +10 -0
- metadata +311 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe Backup::CLI::Helpers do
|
|
6
|
+
let(:helpers) { Module.new.extend(Backup::CLI::Helpers) }
|
|
7
|
+
|
|
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
|
+
)
|
|
30
|
+
|
|
31
|
+
helpers.run('/path/to/command args').should == 'stdout message'
|
|
32
|
+
end
|
|
33
|
+
|
|
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
|
+
)
|
|
50
|
+
|
|
51
|
+
helpers.run(
|
|
52
|
+
'/path/to/command args', :ignore_exit_codes => [1, 2]
|
|
53
|
+
).should == 'stdout message'
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#utility' do
|
|
58
|
+
context 'when a system path for the utility is available' do
|
|
59
|
+
it 'should return the system path with newline removed' do
|
|
60
|
+
helpers.expects(:`).with('which foo 2>/dev/null').returns("system_path\n")
|
|
61
|
+
helpers.utility(:foo).should == 'system_path'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should cache the returned path' do
|
|
65
|
+
helpers.expects(:`).once.with('which cache_me 2>/dev/null').
|
|
66
|
+
returns("cached_path\n")
|
|
67
|
+
|
|
68
|
+
helpers.utility(:cache_me).should == 'cached_path'
|
|
69
|
+
helpers.utility(:cache_me).should == 'cached_path'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should cache the value for all extended objects' do
|
|
73
|
+
helpers.expects(:`).once.with('which once_only 2>/dev/null').
|
|
74
|
+
returns("cached_path\n")
|
|
75
|
+
|
|
76
|
+
helpers.utility(:once_only).should == 'cached_path'
|
|
77
|
+
Class.new.extend(Backup::CLI::Helpers).utility(:once_only).
|
|
78
|
+
should == 'cached_path'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
context 'when a system path for the utility is not available' do
|
|
84
|
+
it 'should raise an error' do
|
|
85
|
+
helpers.expects(:`).with('which unknown 2>/dev/null').returns("\n")
|
|
86
|
+
|
|
87
|
+
expect do
|
|
88
|
+
helpers.utility(:unknown)
|
|
89
|
+
end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
|
|
90
|
+
err.message.should match(/Path to 'unknown' could not be found/)
|
|
91
|
+
}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should not cache any value for the utility' do
|
|
95
|
+
helpers.expects(:`).with('which not_cached 2>/dev/null').twice.returns("\n")
|
|
96
|
+
|
|
97
|
+
expect do
|
|
98
|
+
helpers.utility(:not_cached)
|
|
99
|
+
end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
|
|
100
|
+
err.message.should match(/Path to 'not_cached' could not be found/)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
expect do
|
|
104
|
+
helpers.utility(:not_cached)
|
|
105
|
+
end.to raise_error(Backup::Errors::CLI::UtilityNotFoundError) {|err|
|
|
106
|
+
err.message.should match(/Path to 'not_cached' could not be found/)
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end # describe '#utility'
|
|
111
|
+
|
|
112
|
+
describe '#command_name' do
|
|
113
|
+
context 'given a command line path with no arguments' do
|
|
114
|
+
it 'should return the base command name' do
|
|
115
|
+
cmd = '/path/to/a/command'
|
|
116
|
+
helpers.command_name(cmd).should == 'command'
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'given a command line path with a single argument' do
|
|
121
|
+
it 'should return the base command name' do
|
|
122
|
+
cmd = '/path/to/a/command with_args'
|
|
123
|
+
helpers.command_name(cmd).should == 'command'
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context 'given a command line path with multiple arguments' do
|
|
128
|
+
it 'should return the base command name' do
|
|
129
|
+
cmd = '/path/to/a/command with multiple args'
|
|
130
|
+
helpers.command_name(cmd).should == 'command'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context 'given a command with no path and arguments' do
|
|
135
|
+
it 'should return the base command name' do
|
|
136
|
+
cmd = 'command args'
|
|
137
|
+
helpers.command_name(cmd).should == 'command'
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context 'given a command with no path and no arguments' do
|
|
142
|
+
it 'should return the base command name' do
|
|
143
|
+
cmd = 'command'
|
|
144
|
+
helpers.command_name(cmd).should == 'command'
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end # describe '#command_name'
|
|
148
|
+
|
|
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
|
+
end
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe 'Backup::CLI::Utility' do
|
|
6
|
+
let(:cli) { Backup::CLI::Utility }
|
|
7
|
+
let(:utility) { Backup::CLI::Utility.new }
|
|
8
|
+
let(:s) { sequence '' }
|
|
9
|
+
|
|
10
|
+
before { @argv_save = ARGV }
|
|
11
|
+
after { ARGV.replace(@argv_save) }
|
|
12
|
+
|
|
13
|
+
describe '#perform' do
|
|
14
|
+
let(:model_a) { Backup::Model.new(:test_trigger_a, 'test label a') }
|
|
15
|
+
let(:model_b) { Backup::Model.new(:test_trigger_b, 'test label b') }
|
|
16
|
+
|
|
17
|
+
before { Backup::Model.all.push(model_a, model_b) }
|
|
18
|
+
after { Backup::Model.all.clear }
|
|
19
|
+
|
|
20
|
+
it 'should perform the backup for the given trigger' do
|
|
21
|
+
Backup::Logger.expects(:quiet=).in_sequence(s)
|
|
22
|
+
Backup::Config.expects(:update).in_sequence(s)
|
|
23
|
+
Backup::Config.expects(:load_config!).in_sequence(s)
|
|
24
|
+
|
|
25
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.log_path)
|
|
26
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.cache_path)
|
|
27
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.tmp_path)
|
|
28
|
+
|
|
29
|
+
Backup::Logger.expects(:truncate!)
|
|
30
|
+
|
|
31
|
+
model_a.expects(:prepare!).in_sequence(s)
|
|
32
|
+
model_a.expects(:perform!).in_sequence(s)
|
|
33
|
+
Backup::Logger.expects(:clear!).in_sequence(s)
|
|
34
|
+
|
|
35
|
+
expect do
|
|
36
|
+
ARGV.replace(['perform', '-t', 'test_trigger_a'])
|
|
37
|
+
cli.start
|
|
38
|
+
end.not_to raise_error
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'should perform backups for the multiple triggers' do
|
|
42
|
+
Backup::Logger.expects(:quiet=).in_sequence(s)
|
|
43
|
+
Backup::Config.expects(:update).in_sequence(s)
|
|
44
|
+
Backup::Config.expects(:load_config!).in_sequence(s)
|
|
45
|
+
|
|
46
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.log_path)
|
|
47
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.cache_path)
|
|
48
|
+
FileUtils.expects(:mkdir_p).in_sequence(s).with(Backup::Config.tmp_path)
|
|
49
|
+
|
|
50
|
+
Backup::Logger.expects(:truncate!)
|
|
51
|
+
|
|
52
|
+
model_a.expects(:prepare!).in_sequence(s)
|
|
53
|
+
model_a.expects(:perform!).in_sequence(s)
|
|
54
|
+
Backup::Logger.expects(:clear!).in_sequence(s)
|
|
55
|
+
|
|
56
|
+
model_b.expects(:prepare!).in_sequence(s)
|
|
57
|
+
model_b.expects(:perform!).in_sequence(s)
|
|
58
|
+
Backup::Logger.expects(:clear!).in_sequence(s)
|
|
59
|
+
|
|
60
|
+
expect do
|
|
61
|
+
ARGV.replace(['perform', '-t', 'test_trigger_a,test_trigger_b'])
|
|
62
|
+
cli.start
|
|
63
|
+
end.not_to raise_error
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'when errors occur' do
|
|
67
|
+
it 'should log the error and exit' do
|
|
68
|
+
Backup::Logger.stubs(:quiet=).raises(SystemCallError, 'yikes!')
|
|
69
|
+
Backup::Logger.expects(:error).with do |err|
|
|
70
|
+
err.message.should ==
|
|
71
|
+
"CLIError: SystemCallError: unknown error - yikes!"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
expect do
|
|
75
|
+
ARGV.replace(['perform', '-t', 'foo'])
|
|
76
|
+
cli.start
|
|
77
|
+
end.to raise_error(SystemExit) {|exit| exit.status.should == 1 }
|
|
78
|
+
end
|
|
79
|
+
end # context 'when errors occur'
|
|
80
|
+
|
|
81
|
+
end # describe '#perform'
|
|
82
|
+
|
|
83
|
+
describe '#generate:model' do
|
|
84
|
+
before do
|
|
85
|
+
FileUtils.unstub(:mkdir_p)
|
|
86
|
+
FileUtils.unstub(:touch)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'when given a config_path' do
|
|
90
|
+
context 'when no config file exists' do
|
|
91
|
+
it 'should create both a config and a model under the given path' do
|
|
92
|
+
Dir.mktmpdir do |path|
|
|
93
|
+
model_file = File.join(path, 'custom', 'models', 'test_trigger.rb')
|
|
94
|
+
config_file = File.join(path, 'custom', 'config.rb')
|
|
95
|
+
|
|
96
|
+
out, err = capture_io do
|
|
97
|
+
ARGV.replace(['generate:model',
|
|
98
|
+
'--config-path', File.join(path, 'custom'),
|
|
99
|
+
'--trigger', 'test_trigger'
|
|
100
|
+
])
|
|
101
|
+
cli.start
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
out.should == "Generated model file: '#{ model_file }'.\n" +
|
|
105
|
+
"Generated configuration file: '#{ config_file }'.\n"
|
|
106
|
+
File.exist?(model_file).should be_true
|
|
107
|
+
File.exist?(config_file).should be_true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'when a config file already exists' do
|
|
113
|
+
it 'should only create a model under the given path' do
|
|
114
|
+
Dir.mktmpdir do |path|
|
|
115
|
+
model_file = File.join(path, 'custom', 'models', 'test_trigger.rb')
|
|
116
|
+
config_file = File.join(path, 'custom', 'config.rb')
|
|
117
|
+
FileUtils.mkdir_p(File.join(path, 'custom'))
|
|
118
|
+
FileUtils.touch(config_file)
|
|
119
|
+
|
|
120
|
+
out, err = capture_io do
|
|
121
|
+
ARGV.replace(['generate:model',
|
|
122
|
+
'--config-path', File.join(path, 'custom'),
|
|
123
|
+
'--trigger', 'test_trigger'
|
|
124
|
+
])
|
|
125
|
+
cli.start
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
out.should == "Generated model file: '#{ model_file }'.\n"
|
|
129
|
+
File.exist?(model_file).should be_true
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# These pass, but generate Thor warnings...
|
|
135
|
+
#
|
|
136
|
+
# context 'when a model file already exists' do
|
|
137
|
+
# it 'should prompt to overwrite the model under the given path' do
|
|
138
|
+
# Dir.mktmpdir do |path|
|
|
139
|
+
# model_file = File.join(path, 'models', 'test_trigger.rb')
|
|
140
|
+
# config_file = File.join(path, 'config.rb')
|
|
141
|
+
#
|
|
142
|
+
# cli.any_instance.expects(:overwrite?).with(model_file).returns(false)
|
|
143
|
+
#
|
|
144
|
+
# out, err = capture_io do
|
|
145
|
+
# ARGV.replace(['generate:model',
|
|
146
|
+
# '--config-path', path,
|
|
147
|
+
# '--trigger', 'test_trigger'
|
|
148
|
+
# ])
|
|
149
|
+
# cli.start
|
|
150
|
+
# end
|
|
151
|
+
#
|
|
152
|
+
# out.should == "Generated configuration file: '#{ config_file }'.\n"
|
|
153
|
+
# File.exist?(config_file).should be_true
|
|
154
|
+
# File.exist?(model_file).should be_false
|
|
155
|
+
# end
|
|
156
|
+
# end
|
|
157
|
+
# end
|
|
158
|
+
|
|
159
|
+
end # context 'when given a config_path'
|
|
160
|
+
|
|
161
|
+
context 'when not given a config_path' do
|
|
162
|
+
it 'should create both a config and a model under the root path' do
|
|
163
|
+
Dir.mktmpdir do |path|
|
|
164
|
+
Backup::Config.update(:root_path => path)
|
|
165
|
+
model_file = File.join(path, 'models', 'test_trigger.rb')
|
|
166
|
+
config_file = File.join(path, 'config.rb')
|
|
167
|
+
|
|
168
|
+
out, err = capture_io do
|
|
169
|
+
ARGV.replace(['generate:model', '--trigger', 'test_trigger'])
|
|
170
|
+
cli.start
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
out.should == "Generated model file: '#{ model_file }'.\n" +
|
|
174
|
+
"Generated configuration file: '#{ config_file }'.\n"
|
|
175
|
+
File.exist?(model_file).should be_true
|
|
176
|
+
File.exist?(config_file).should be_true
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'should generate the proper help output' do
|
|
182
|
+
ruby19_output = <<-EOS
|
|
183
|
+
Usage:
|
|
184
|
+
#{ File.basename($0) } generate:model --trigger=TRIGGER
|
|
185
|
+
|
|
186
|
+
Options:
|
|
187
|
+
--trigger=TRIGGER
|
|
188
|
+
[--config-path=CONFIG_PATH] # Path to your Backup configuration directory
|
|
189
|
+
[--databases=DATABASES] # (mongodb, mysql, postgresql, redis, riak)
|
|
190
|
+
[--storages=STORAGES] # (cloud_files, dropbox, ftp, local, ninefold, rsync, s3, scp, sftp)
|
|
191
|
+
[--syncers=SYNCERS] # (cloud_files, rsync_local, rsync_pull, rsync_push, s3)
|
|
192
|
+
[--encryptors=ENCRYPTORS] # (gpg, openssl)
|
|
193
|
+
[--compressors=COMPRESSORS] # (bzip2, gzip, lzma, pbzip2)
|
|
194
|
+
[--notifiers=NOTIFIERS] # (campfire, hipchat, mail, presently, prowl, twitter)
|
|
195
|
+
[--archives]
|
|
196
|
+
[--splitter] # use `--no-splitter` to disable
|
|
197
|
+
# Default: true
|
|
198
|
+
Generates a Backup model file
|
|
199
|
+
|
|
200
|
+
Note:
|
|
201
|
+
'--config-path' is the path to the directory where 'config.rb' is located.
|
|
202
|
+
The model file will be created as '<config_path>/models/<trigger>.rb'
|
|
203
|
+
Default: #{ Backup::Config.root_path }
|
|
204
|
+
EOS
|
|
205
|
+
|
|
206
|
+
out, err = capture_io do
|
|
207
|
+
ARGV.replace(['help', 'generate:model'])
|
|
208
|
+
cli.start
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
expected_lines = ruby19_output.split("\n").map(&:strip).select {|e| !e.empty? }
|
|
212
|
+
output_lines = out.split("\n").map(&:strip).select {|e| !e.empty? }
|
|
213
|
+
|
|
214
|
+
output_lines.sort.should == expected_lines.sort
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
describe '#generate:config' do
|
|
219
|
+
before do
|
|
220
|
+
FileUtils.unstub(:mkdir_p)
|
|
221
|
+
FileUtils.unstub(:touch)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when given a config_path' do
|
|
225
|
+
it 'should create a config file in the given path' do
|
|
226
|
+
Dir.mktmpdir do |path|
|
|
227
|
+
config_file = File.join(path, 'custom', 'config.rb')
|
|
228
|
+
|
|
229
|
+
out, err = capture_io do
|
|
230
|
+
ARGV.replace(['generate:config',
|
|
231
|
+
'--config-path', File.join(path, 'custom'),
|
|
232
|
+
])
|
|
233
|
+
cli.start
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
out.should == "Generated configuration file: '#{ config_file }'.\n"
|
|
237
|
+
File.exist?(config_file).should be_true
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
context 'when not given a config_path' do
|
|
243
|
+
it 'should create a config file in the root path' do
|
|
244
|
+
Dir.mktmpdir do |path|
|
|
245
|
+
Backup::Config.update(:root_path => path)
|
|
246
|
+
config_file = File.join(path, 'config.rb')
|
|
247
|
+
|
|
248
|
+
out, err = capture_io do
|
|
249
|
+
ARGV.replace(['generate:config'])
|
|
250
|
+
cli.start
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
out.should == "Generated configuration file: '#{ config_file }'.\n"
|
|
254
|
+
File.exist?(config_file).should be_true
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# These pass, but generate Thor warnings...
|
|
260
|
+
#
|
|
261
|
+
# context 'when a config file already exists' do
|
|
262
|
+
# it 'should prompt to overwrite the config file' do
|
|
263
|
+
# Dir.mktmpdir do |path|
|
|
264
|
+
# Backup::Config.update(:root_path => path)
|
|
265
|
+
# config_file = File.join(path, 'config.rb')
|
|
266
|
+
#
|
|
267
|
+
# cli.any_instance.expects(:overwrite?).with(config_file).returns(false)
|
|
268
|
+
#
|
|
269
|
+
# out, err = capture_io do
|
|
270
|
+
# ARGV.replace(['generate:config'])
|
|
271
|
+
# cli.start
|
|
272
|
+
# end
|
|
273
|
+
#
|
|
274
|
+
# out.should be_empty
|
|
275
|
+
# File.exist?(config_file).should be_false
|
|
276
|
+
# end
|
|
277
|
+
# end
|
|
278
|
+
# end
|
|
279
|
+
|
|
280
|
+
end # describe '#generate:config'
|
|
281
|
+
|
|
282
|
+
describe '#decrypt' do
|
|
283
|
+
|
|
284
|
+
# These pass, but generate Thor warnings...
|
|
285
|
+
#
|
|
286
|
+
# it 'should perform OpenSSL decryption' do
|
|
287
|
+
# ARGV.replace(['decrypt', '--encryptor', 'openssl',
|
|
288
|
+
# '--in', 'in_file',
|
|
289
|
+
# '--out', 'out_file',
|
|
290
|
+
# '--base64', '--salt',
|
|
291
|
+
# '--password-file', 'pwd_file'])
|
|
292
|
+
#
|
|
293
|
+
# cli.any_instance.expects(:`).with(
|
|
294
|
+
# "openssl aes-256-cbc -d -base64 -pass file:pwd_file -salt " +
|
|
295
|
+
# "-in 'in_file' -out 'out_file'"
|
|
296
|
+
# )
|
|
297
|
+
# cli.start
|
|
298
|
+
# end
|
|
299
|
+
#
|
|
300
|
+
# it 'should perform GnuPG decryption' do
|
|
301
|
+
# ARGV.replace(['decrypt', '--encryptor', 'gpg',
|
|
302
|
+
# '--in', 'in_file',
|
|
303
|
+
# '--out', 'out_file'])
|
|
304
|
+
#
|
|
305
|
+
# cli.any_instance.expects(:`).with(
|
|
306
|
+
# "gpg -o 'out_file' -d 'in_file'"
|
|
307
|
+
# )
|
|
308
|
+
# cli.start
|
|
309
|
+
# end
|
|
310
|
+
|
|
311
|
+
it 'should show a message if given an invalid encryptor' do
|
|
312
|
+
ARGV.replace(['decrypt', '--encryptor', 'foo',
|
|
313
|
+
'--in', 'in_file',
|
|
314
|
+
'--out', 'out_file'])
|
|
315
|
+
out, err = capture_io do
|
|
316
|
+
cli.start
|
|
317
|
+
end
|
|
318
|
+
err.should == ''
|
|
319
|
+
out.should == "Unknown encryptor: foo\n" +
|
|
320
|
+
"Use either 'openssl' or 'gpg'.\n"
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# would have the same Thor warnings issues...
|
|
325
|
+
# describe '#dependencies' do
|
|
326
|
+
# end
|
|
327
|
+
|
|
328
|
+
describe '#version' do
|
|
329
|
+
it 'should output the current version' do
|
|
330
|
+
utility.expects(:puts).with("Backup #{ Backup::Version.current }")
|
|
331
|
+
utility.version
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it 'should output the current version for "-v"' do
|
|
335
|
+
ARGV.replace ['-v']
|
|
336
|
+
out, err = capture_io do
|
|
337
|
+
cli.start
|
|
338
|
+
end
|
|
339
|
+
out.should == "Backup #{ Backup::Version.current }\n"
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
describe '#overwrite?' do
|
|
344
|
+
context 'when the path exists' do
|
|
345
|
+
before { File.expects(:exist?).returns(true) }
|
|
346
|
+
|
|
347
|
+
it 'should prompt user' do
|
|
348
|
+
utility.expects(:yes?).with(
|
|
349
|
+
"A file already exists at 'a/path'. Do you want to overwrite? [y/n]"
|
|
350
|
+
).returns(:response)
|
|
351
|
+
utility.send(:overwrite?, 'a/path').should == :response
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
context 'when the path does not exist' do
|
|
356
|
+
before { File.expects(:exist?).returns(false) }
|
|
357
|
+
it 'should return true' do
|
|
358
|
+
utility.expects(:yes?).never
|
|
359
|
+
utility.send(:overwrite?, 'a/path').should be_true
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|