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
data/spec/model_spec.rb
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe 'Backup::Model' do
|
|
6
|
+
let(:model) { Backup::Model.new(:test_trigger, 'test label') }
|
|
7
|
+
let(:s) { sequence '' }
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
Backup::Model.all.clear
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '.all' do
|
|
14
|
+
it 'should be an empty array by default' do
|
|
15
|
+
Backup::Model.all.should == []
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe 'finder methods' do
|
|
20
|
+
before do
|
|
21
|
+
[:a, :b, :c, :b, :d].each_with_index do |sym, i|
|
|
22
|
+
Backup::Model.new("trigger_#{sym}", "label#{i}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '.find' do
|
|
27
|
+
it 'should return the first matching model' do
|
|
28
|
+
Backup::Model.find('trigger_b').label.should == 'label1'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should accept symbols' do
|
|
32
|
+
Backup::Model.find(:trigger_b).label.should == 'label1'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should raise an error if trigger is not found' do
|
|
36
|
+
expect do
|
|
37
|
+
Backup::Model.find(:f)
|
|
38
|
+
end.to raise_error(
|
|
39
|
+
Backup::Errors::Model::MissingTriggerError,
|
|
40
|
+
"Model::MissingTriggerError: Could not find trigger 'f'."
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '.find_matching' do
|
|
46
|
+
it 'should find all triggers matching a wildcard' do
|
|
47
|
+
Backup::Model.find_matching('tri*_b').count.should be(2)
|
|
48
|
+
Backup::Model.find_matching('trigg*').count.should be(5)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'should return an empty array if no matches are found' do
|
|
52
|
+
Backup::Model.find_matching('foo*').should == []
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end # describe 'finder methods'
|
|
57
|
+
|
|
58
|
+
describe '#initialize' do
|
|
59
|
+
|
|
60
|
+
it 'should convert trigger to a string' do
|
|
61
|
+
Backup::Model.new(:foo, :bar).trigger.should == 'foo'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should convert label to a string' do
|
|
65
|
+
Backup::Model.new(:foo, :bar).label.should == 'bar'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should set all procedure variables to an empty array' do
|
|
69
|
+
model.send(:procedure_instance_variables).each do |var|
|
|
70
|
+
model.instance_variable_get(var).should == []
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should accept and instance_eval a block' do
|
|
75
|
+
block = lambda {|model| throw(:instance, model) }
|
|
76
|
+
caught = catch(:instance) do
|
|
77
|
+
Backup::Model.new('gotcha', '', &block)
|
|
78
|
+
end
|
|
79
|
+
caught.trigger.should == 'gotcha'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'should add itself to Model.all' do
|
|
83
|
+
Backup::Model.all.should == [model]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end # describe '#initialize'
|
|
87
|
+
|
|
88
|
+
describe 'DSL Methods' do
|
|
89
|
+
|
|
90
|
+
module Fake
|
|
91
|
+
module NoArg
|
|
92
|
+
class Base
|
|
93
|
+
attr_accessor :block_arg
|
|
94
|
+
def initialize(&block)
|
|
95
|
+
instance_eval(&block) if block_given?
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
module OneArg
|
|
100
|
+
class Base
|
|
101
|
+
attr_accessor :arg1, :block_arg
|
|
102
|
+
def initialize(arg1, &block)
|
|
103
|
+
@arg1 = arg1
|
|
104
|
+
instance_eval(&block) if block_given?
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
module TwoArgs
|
|
109
|
+
class Base
|
|
110
|
+
attr_accessor :arg1, :arg2, :block_arg
|
|
111
|
+
def initialize(arg1, arg2, &block)
|
|
112
|
+
@arg1 = arg1
|
|
113
|
+
@arg2 = arg2
|
|
114
|
+
instance_eval(&block) if block_given?
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Set +const+ to +replacement+ for the calling block
|
|
121
|
+
def using_fake(const, replacement)
|
|
122
|
+
orig = Backup.const_get(const)
|
|
123
|
+
Backup.send(:remove_const, const)
|
|
124
|
+
Backup.const_set(const, replacement)
|
|
125
|
+
yield
|
|
126
|
+
Backup.send(:remove_const, const)
|
|
127
|
+
Backup.const_set(const, orig)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe '#archive' do
|
|
131
|
+
it 'should add archives' do
|
|
132
|
+
using_fake('Archive', Fake::TwoArgs::Base) do
|
|
133
|
+
model.archive('foo') {|a| a.block_arg = :foo }
|
|
134
|
+
model.archive('bar') {|a| a.block_arg = :bar }
|
|
135
|
+
model.archives.count.should == 2
|
|
136
|
+
a1, a2 = model.archives
|
|
137
|
+
a1.arg1.should be(model)
|
|
138
|
+
a1.arg2.should == 'foo'
|
|
139
|
+
a1.block_arg.should == :foo
|
|
140
|
+
a2.arg1.should be(model)
|
|
141
|
+
a2.arg2.should == 'bar'
|
|
142
|
+
a2.block_arg.should == :bar
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe '#database' do
|
|
148
|
+
it 'should add databases' do
|
|
149
|
+
using_fake('Database', Fake::OneArg) do
|
|
150
|
+
model.database('Base') {|a| a.block_arg = :foo }
|
|
151
|
+
model.database('Base') {|a| a.block_arg = :bar }
|
|
152
|
+
model.databases.count.should be(2)
|
|
153
|
+
d1, d2 = model.databases
|
|
154
|
+
d1.arg1.should be(model)
|
|
155
|
+
d1.block_arg.should == :foo
|
|
156
|
+
d2.arg1.should be(model)
|
|
157
|
+
d2.block_arg.should == :bar
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'should accept a nested class name' do
|
|
162
|
+
using_fake('Database', Fake) do
|
|
163
|
+
model.database('OneArg::Base')
|
|
164
|
+
model.databases.first.should be_an_instance_of Fake::OneArg::Base
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe '#store_with' do
|
|
170
|
+
it 'should add storages' do
|
|
171
|
+
using_fake('Storage', Fake::TwoArgs) do
|
|
172
|
+
model.store_with('Base', 'foo') {|a| a.block_arg = :foo }
|
|
173
|
+
model.store_with('Base', 'bar') {|a| a.block_arg = :bar }
|
|
174
|
+
model.storages.count.should be(2)
|
|
175
|
+
s1, s2 = model.storages
|
|
176
|
+
s1.arg1.should be(model)
|
|
177
|
+
s1.arg2.should == 'foo'
|
|
178
|
+
s1.block_arg.should == :foo
|
|
179
|
+
s2.arg1.should be(model)
|
|
180
|
+
s2.arg2.should == 'bar'
|
|
181
|
+
s2.block_arg.should == :bar
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'should accept a nested class name' do
|
|
186
|
+
using_fake('Storage', Fake) do
|
|
187
|
+
model.store_with('TwoArgs::Base')
|
|
188
|
+
model.storages.first.should be_an_instance_of Fake::TwoArgs::Base
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe '#sync_with' do
|
|
194
|
+
it 'should add syncers' do
|
|
195
|
+
using_fake('Syncer', Fake::NoArg) do
|
|
196
|
+
model.sync_with('Base') {|a| a.block_arg = :foo }
|
|
197
|
+
model.sync_with('Base') {|a| a.block_arg = :bar }
|
|
198
|
+
model.syncers.count.should be(2)
|
|
199
|
+
s1, s2 = model.syncers
|
|
200
|
+
s1.block_arg.should == :foo
|
|
201
|
+
s2.block_arg.should == :bar
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it 'should accept a nested class name' do
|
|
206
|
+
using_fake('Syncer', Fake) do
|
|
207
|
+
model.sync_with('NoArg::Base')
|
|
208
|
+
model.syncers.first.should be_an_instance_of Fake::NoArg::Base
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'should warn user of change from RSync to RSync::Local' do
|
|
213
|
+
Backup::Logger.expects(:warn)
|
|
214
|
+
model.sync_with('Backup::Config::RSync')
|
|
215
|
+
model.syncers.first.should be_an_instance_of Backup::Syncer::RSync::Local
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
describe '#notify_by' do
|
|
220
|
+
it 'should add notifiers' do
|
|
221
|
+
using_fake('Notifier', Fake::OneArg) do
|
|
222
|
+
model.notify_by('Base') {|a| a.block_arg = :foo }
|
|
223
|
+
model.notify_by('Base') {|a| a.block_arg = :bar }
|
|
224
|
+
model.notifiers.count.should be(2)
|
|
225
|
+
n1, n2 = model.notifiers
|
|
226
|
+
n1.arg1.should be(model)
|
|
227
|
+
n1.block_arg.should == :foo
|
|
228
|
+
n2.arg1.should be(model)
|
|
229
|
+
n2.block_arg.should == :bar
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it 'should accept a nested class name' do
|
|
234
|
+
using_fake('Notifier', Fake) do
|
|
235
|
+
model.notify_by('OneArg::Base')
|
|
236
|
+
model.notifiers.first.should be_an_instance_of Fake::OneArg::Base
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
describe '#encrypt_with' do
|
|
242
|
+
it 'should add an encryptor' do
|
|
243
|
+
using_fake('Encryptor', Fake::NoArg) do
|
|
244
|
+
model.encrypt_with('Base') {|a| a.block_arg = :foo }
|
|
245
|
+
model.encryptor.should be_an_instance_of Fake::NoArg::Base
|
|
246
|
+
model.encryptor.block_arg.should == :foo
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it 'should accept a nested class name' do
|
|
251
|
+
using_fake('Encryptor', Fake) do
|
|
252
|
+
model.encrypt_with('NoArg::Base')
|
|
253
|
+
model.encryptor.should be_an_instance_of Fake::NoArg::Base
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe '#compress_with' do
|
|
259
|
+
it 'should add a compressor' do
|
|
260
|
+
using_fake('Compressor', Fake::NoArg) do
|
|
261
|
+
model.compress_with('Base') {|a| a.block_arg = :foo }
|
|
262
|
+
model.compressor.should be_an_instance_of Fake::NoArg::Base
|
|
263
|
+
model.compressor.block_arg.should == :foo
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'should accept a nested class name' do
|
|
268
|
+
using_fake('Compressor', Fake) do
|
|
269
|
+
model.compress_with('NoArg::Base')
|
|
270
|
+
model.compressor.should be_an_instance_of Fake::NoArg::Base
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
describe '#split_into_chunks_of' do
|
|
276
|
+
it 'should add a splitter' do
|
|
277
|
+
using_fake('Splitter', Fake::TwoArgs::Base) do
|
|
278
|
+
model.split_into_chunks_of(123)
|
|
279
|
+
model.splitter.should be_an_instance_of Fake::TwoArgs::Base
|
|
280
|
+
model.splitter.arg1.should be(model)
|
|
281
|
+
model.splitter.arg2.should == 123
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
it 'should raise an error if chunk_size is not an Integer' do
|
|
286
|
+
expect do
|
|
287
|
+
model.split_into_chunks_of('345')
|
|
288
|
+
end.to raise_error {|err|
|
|
289
|
+
err.should be_an_instance_of Backup::Errors::Model::ConfigurationError
|
|
290
|
+
err.message.should match(/must be an Integer/)
|
|
291
|
+
}
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
end # describe 'DSL Methods'
|
|
296
|
+
|
|
297
|
+
describe '#prepare!' do
|
|
298
|
+
it 'should prepare for the backup' do
|
|
299
|
+
FileUtils.expects(:mkdir_p).with(
|
|
300
|
+
File.join(Backup::Config.data_path, 'test_trigger')
|
|
301
|
+
)
|
|
302
|
+
Backup::Cleaner.expects(:prepare).with(model)
|
|
303
|
+
|
|
304
|
+
model.prepare!
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
describe '#perform!' do
|
|
309
|
+
let(:procedure_a) { lambda {} }
|
|
310
|
+
let(:procedure_b) { mock }
|
|
311
|
+
let(:procedure_c) { mock }
|
|
312
|
+
let(:procedure_d) { lambda {} }
|
|
313
|
+
let(:procedure_e) { lambda {} }
|
|
314
|
+
let(:procedure_f) { mock }
|
|
315
|
+
let(:procedures) do
|
|
316
|
+
[ procedure_a, [procedure_b, procedure_c],
|
|
317
|
+
procedure_d, procedure_e, [procedure_f] ]
|
|
318
|
+
end
|
|
319
|
+
let(:syncer_a) { mock }
|
|
320
|
+
let(:syncer_b) { mock }
|
|
321
|
+
let(:syncers) { [syncer_a, syncer_b] }
|
|
322
|
+
let(:notifier_a) { mock }
|
|
323
|
+
let(:notifier_b) { mock }
|
|
324
|
+
let(:notifiers) { [notifier_a, notifier_b] }
|
|
325
|
+
|
|
326
|
+
it 'should set the @time and @started_at variables' do
|
|
327
|
+
Timecop.freeze(Time.now)
|
|
328
|
+
started_at = Time.now
|
|
329
|
+
time = started_at.strftime("%Y.%m.%d.%H.%M.%S")
|
|
330
|
+
|
|
331
|
+
model.perform!
|
|
332
|
+
model.time.should == time
|
|
333
|
+
model.instance_variable_get(:@started_at).should == started_at
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
context 'when no errors occur' do
|
|
337
|
+
before do
|
|
338
|
+
model.expects(:procedures).returns(procedures)
|
|
339
|
+
model.expects(:syncers).returns(syncers)
|
|
340
|
+
model.expects(:notifiers).returns(notifiers)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
context 'when databases are configured' do
|
|
344
|
+
before do
|
|
345
|
+
model.instance_variable_set(:@databases, [true])
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
it 'should perform all procedures' do
|
|
349
|
+
model.expects(:log!).in_sequence(s).with(:started)
|
|
350
|
+
|
|
351
|
+
procedure_a.expects(:call).in_sequence(s)
|
|
352
|
+
procedure_b.expects(:perform!).in_sequence(s)
|
|
353
|
+
procedure_c.expects(:perform!).in_sequence(s)
|
|
354
|
+
procedure_d.expects(:call).in_sequence(s)
|
|
355
|
+
procedure_e.expects(:call).in_sequence(s)
|
|
356
|
+
procedure_f.expects(:perform!).in_sequence(s)
|
|
357
|
+
|
|
358
|
+
syncer_a.expects(:perform!).in_sequence(s)
|
|
359
|
+
syncer_b.expects(:perform!).in_sequence(s)
|
|
360
|
+
|
|
361
|
+
notifier_a.expects(:perform!).in_sequence(s)
|
|
362
|
+
notifier_b.expects(:perform!).in_sequence(s)
|
|
363
|
+
|
|
364
|
+
model.expects(:log!).in_sequence(s).with(:finished)
|
|
365
|
+
|
|
366
|
+
model.perform!
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
context 'when archives are configured' do
|
|
371
|
+
before do
|
|
372
|
+
model.instance_variable_set(:@archives, [true])
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it 'should perform all procedures' do
|
|
376
|
+
model.expects(:log!).in_sequence(s).with(:started)
|
|
377
|
+
|
|
378
|
+
procedure_a.expects(:call).in_sequence(s)
|
|
379
|
+
procedure_b.expects(:perform!).in_sequence(s)
|
|
380
|
+
procedure_c.expects(:perform!).in_sequence(s)
|
|
381
|
+
procedure_d.expects(:call).in_sequence(s)
|
|
382
|
+
procedure_e.expects(:call).in_sequence(s)
|
|
383
|
+
procedure_f.expects(:perform!).in_sequence(s)
|
|
384
|
+
|
|
385
|
+
syncer_a.expects(:perform!).in_sequence(s)
|
|
386
|
+
syncer_b.expects(:perform!).in_sequence(s)
|
|
387
|
+
|
|
388
|
+
notifier_a.expects(:perform!).in_sequence(s)
|
|
389
|
+
notifier_b.expects(:perform!).in_sequence(s)
|
|
390
|
+
|
|
391
|
+
model.expects(:log!).in_sequence(s).with(:finished)
|
|
392
|
+
|
|
393
|
+
model.perform!
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
end # context 'when no errors occur'
|
|
398
|
+
|
|
399
|
+
# for the purposes of testing the error handling, we're just going to
|
|
400
|
+
# stub the first thing this method calls and raise an error
|
|
401
|
+
context 'when errors occur' do
|
|
402
|
+
let(:error_a) { mock }
|
|
403
|
+
let(:error_b) { mock }
|
|
404
|
+
let(:notifier) { mock }
|
|
405
|
+
|
|
406
|
+
before do
|
|
407
|
+
error_a.stubs(:backtrace).returns(['many', 'backtrace', 'lines'])
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
it 'logs, notifies and continues if a StandardError is rescued' do
|
|
411
|
+
Time.stubs(:now).raises(StandardError, 'non-fatal error')
|
|
412
|
+
|
|
413
|
+
Backup::Errors::ModelError.expects(:wrap).in_sequence(s).with do |err, msg|
|
|
414
|
+
err.message.should == 'non-fatal error'
|
|
415
|
+
msg.should match(/Backup for test label \(test_trigger\) Failed!/)
|
|
416
|
+
end.returns(error_a)
|
|
417
|
+
Backup::Logger.expects(:error).in_sequence(s).with(error_a)
|
|
418
|
+
Backup::Logger.expects(:error).in_sequence(s).with(
|
|
419
|
+
"\nBacktrace:\n\s\smany\n\s\sbacktrace\n\s\slines\n\n"
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
Backup::Cleaner.expects(:warnings).in_sequence(s).with(model)
|
|
423
|
+
|
|
424
|
+
Backup::Errors::ModelError.expects(:new).in_sequence(s).with do |msg|
|
|
425
|
+
msg.should match(/Backup will now attempt to continue/)
|
|
426
|
+
end.returns(error_b)
|
|
427
|
+
Backup::Logger.expects(:message).in_sequence(s).with(error_b)
|
|
428
|
+
|
|
429
|
+
# notifiers called, but any Exception is ignored
|
|
430
|
+
notifier.expects(:perform!).with(true).raises(Exception)
|
|
431
|
+
model.expects(:notifiers).returns([notifier])
|
|
432
|
+
|
|
433
|
+
# returns to allow next trigger to run
|
|
434
|
+
expect { model.perform! }.not_to raise_error
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
it 'logs, notifies and exits if an Exception is rescued' do
|
|
438
|
+
Time.stubs(:now).raises(Exception, 'fatal error')
|
|
439
|
+
|
|
440
|
+
Backup::Errors::ModelError.expects(:wrap).in_sequence(s).with do |err, msg|
|
|
441
|
+
err.message.should == 'fatal error'
|
|
442
|
+
msg.should match(/Backup for test label \(test_trigger\) Failed!/)
|
|
443
|
+
end.returns(error_a)
|
|
444
|
+
Backup::Logger.expects(:error).in_sequence(s).with(error_a)
|
|
445
|
+
Backup::Logger.expects(:error).in_sequence(s).with(
|
|
446
|
+
"\nBacktrace:\n\s\smany\n\s\sbacktrace\n\s\slines\n\n"
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
Backup::Cleaner.expects(:warnings).in_sequence(s).with(model)
|
|
450
|
+
|
|
451
|
+
Backup::Errors::ModelError.expects(:new).in_sequence(s).with do |msg|
|
|
452
|
+
msg.should match(/Backup will now exit/)
|
|
453
|
+
end.returns(error_b)
|
|
454
|
+
Backup::Logger.expects(:error).in_sequence(s).with(error_b)
|
|
455
|
+
|
|
456
|
+
expect do
|
|
457
|
+
# notifiers called, but any Exception is ignored
|
|
458
|
+
notifier = mock
|
|
459
|
+
notifier.expects(:perform!).with(true).raises(Exception)
|
|
460
|
+
model.expects(:notifiers).returns([notifier])
|
|
461
|
+
end.not_to raise_error
|
|
462
|
+
|
|
463
|
+
expect do
|
|
464
|
+
model.perform!
|
|
465
|
+
end.to raise_error(SystemExit) {|exit| exit.status.should be(1) }
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
end # context 'when errors occur'
|
|
469
|
+
|
|
470
|
+
end # describe '#perform!'
|
|
471
|
+
|
|
472
|
+
describe '#package!' do
|
|
473
|
+
it 'should package the backup' do
|
|
474
|
+
Backup::Packager.expects(:package!).in_sequence(s).with(model)
|
|
475
|
+
Backup::Cleaner.expects(:remove_packaging).in_sequence(s).with(model)
|
|
476
|
+
|
|
477
|
+
model.send(:package!)
|
|
478
|
+
model.package.should be_an_instance_of Backup::Package
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
describe '#clean' do
|
|
483
|
+
it 'should remove the final packaged files' do
|
|
484
|
+
package = mock
|
|
485
|
+
model.instance_variable_set(:@package, package)
|
|
486
|
+
Backup::Cleaner.expects(:remove_package).with(package)
|
|
487
|
+
|
|
488
|
+
model.send(:clean!)
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
describe '#procedures' do
|
|
493
|
+
it 'should return an array of specific, ordered procedures' do
|
|
494
|
+
model.stubs(:databases).returns(:databases)
|
|
495
|
+
model.stubs(:archives).returns(:archives)
|
|
496
|
+
model.stubs(:package!).returns(:package)
|
|
497
|
+
model.stubs(:storages).returns(:storages)
|
|
498
|
+
model.stubs(:clean!).returns(:clean)
|
|
499
|
+
|
|
500
|
+
one, two, three, four, five = model.send(:procedures)
|
|
501
|
+
one.should == :databases
|
|
502
|
+
two.should == :archives
|
|
503
|
+
three.call.should == :package
|
|
504
|
+
four.should == :storages
|
|
505
|
+
five.call.should == :clean
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
describe '#procedure_instance_variables' do
|
|
510
|
+
# these are all set to an empty Array in #initialize
|
|
511
|
+
it 'should return an array of Array holding instance variables' do
|
|
512
|
+
model.send(:procedure_instance_variables).should ==
|
|
513
|
+
[:@databases, :@archives, :@storages, :@notifiers, :@syncers]
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
describe '#get_class_from_scope' do
|
|
518
|
+
|
|
519
|
+
module Fake
|
|
520
|
+
module TestScope
|
|
521
|
+
class TestKlass; end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
module TestScope
|
|
525
|
+
module TestKlass; end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
context 'when name is given as a string' do
|
|
529
|
+
it 'should return the constant for the given scope and name' do
|
|
530
|
+
model.send(
|
|
531
|
+
:get_class_from_scope,
|
|
532
|
+
Fake,
|
|
533
|
+
'TestScope'
|
|
534
|
+
).should == Fake::TestScope
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
it 'should accept a nested class name' do
|
|
538
|
+
model.send(
|
|
539
|
+
:get_class_from_scope,
|
|
540
|
+
Fake,
|
|
541
|
+
'TestScope::TestKlass'
|
|
542
|
+
).should == Fake::TestScope::TestKlass
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
context 'when name is given as a module' do
|
|
547
|
+
it 'should return the constant for the given scope and name' do
|
|
548
|
+
model.send(
|
|
549
|
+
:get_class_from_scope,
|
|
550
|
+
Fake,
|
|
551
|
+
TestScope
|
|
552
|
+
).should == Fake::TestScope
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it 'should accept a nested class name' do
|
|
556
|
+
model.send(
|
|
557
|
+
:get_class_from_scope,
|
|
558
|
+
Fake,
|
|
559
|
+
TestScope::TestKlass
|
|
560
|
+
).should == Fake::TestScope::TestKlass
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
context 'when name is given as a module defined under Backup::Config' do
|
|
565
|
+
# this is necessary since the specs in spec/config_spec.rb
|
|
566
|
+
# remove all the constants from Backup::Config as part of those tests.
|
|
567
|
+
before(:all) do
|
|
568
|
+
module Backup::Config
|
|
569
|
+
module TestScope
|
|
570
|
+
module TestKlass; end
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
it 'should return the constant for the given scope and name' do
|
|
576
|
+
model.send(
|
|
577
|
+
:get_class_from_scope,
|
|
578
|
+
Fake,
|
|
579
|
+
Backup::Config::TestScope
|
|
580
|
+
).should == Fake::TestScope
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
it 'should accept a nested class name' do
|
|
584
|
+
model.send(
|
|
585
|
+
:get_class_from_scope,
|
|
586
|
+
Fake,
|
|
587
|
+
Backup::Config::TestScope::TestKlass
|
|
588
|
+
).should == Fake::TestScope::TestKlass
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
end # describe '#get_class_from_scope'
|
|
593
|
+
|
|
594
|
+
describe '#log!' do
|
|
595
|
+
context 'when action is :started' do
|
|
596
|
+
it 'should log that the backup has started with the version' do
|
|
597
|
+
Backup::Logger.expects(:message).with(
|
|
598
|
+
"Performing Backup for 'test label (test_trigger)'!\n" +
|
|
599
|
+
"[ backup #{ Backup::Version.current } : #{ RUBY_DESCRIPTION } ]"
|
|
600
|
+
)
|
|
601
|
+
model.send(:log!, :started)
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
context 'when action is :finished' do
|
|
606
|
+
before { model.expects(:elapsed_time).returns('01:02:03') }
|
|
607
|
+
context 'when warnings were issued' do
|
|
608
|
+
before { Backup::Logger.expects(:has_warnings?).returns(true) }
|
|
609
|
+
it 'should log a warning that the backup has finished with warnings' do
|
|
610
|
+
Backup::Logger.expects(:warn).with(
|
|
611
|
+
"Backup for 'test label (test_trigger)' " +
|
|
612
|
+
"Completed Successfully (with Warnings) in 01:02:03"
|
|
613
|
+
)
|
|
614
|
+
model.send(:log!, :finished)
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
context 'when no warnings were issued' do
|
|
619
|
+
it 'should log that the backup has finished with the elapsed time' do
|
|
620
|
+
Backup::Logger.expects(:message).with(
|
|
621
|
+
"Backup for 'test label (test_trigger)' " +
|
|
622
|
+
"Completed Successfully in 01:02:03"
|
|
623
|
+
)
|
|
624
|
+
model.send(:log!, :finished)
|
|
625
|
+
end
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
end # describe '#log!'
|
|
629
|
+
|
|
630
|
+
describe '#elapsed_time' do
|
|
631
|
+
it 'should return a string representing the elapsed time' do
|
|
632
|
+
Timecop.freeze(Time.now)
|
|
633
|
+
{ 0 => '00:00:00', 1 => '00:00:01', 59 => '00:00:59',
|
|
634
|
+
60 => '00:01:00', 61 => '00:01:01', 119 => '00:01:59',
|
|
635
|
+
3540 => '00:59:00', 3541 => '00:59:01', 3599 => '00:59:59',
|
|
636
|
+
3600 => '01:00:00', 3601 => '01:00:01', 3659 => '01:00:59',
|
|
637
|
+
3660 => '01:01:00', 3661 => '01:01:01', 3719 => '01:01:59',
|
|
638
|
+
7140 => '01:59:00', 7141 => '01:59:01', 7199 => '01:59:59',
|
|
639
|
+
212400 => '59:00:00', 212401 => '59:00:01', 212459 => '59:00:59',
|
|
640
|
+
212460 => '59:01:00', 212461 => '59:01:01', 212519 => '59:01:59',
|
|
641
|
+
215940 => '59:59:00', 215941 => '59:59:01', 215999 => '59:59:59'
|
|
642
|
+
}.each do |duration, expected|
|
|
643
|
+
model.instance_variable_set(:@started_at, Time.now - duration)
|
|
644
|
+
model.send(:elapsed_time).should == expected
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
end
|