backup 3.0.20 → 3.0.21
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 +1 -5
- data/Gemfile.lock +46 -50
- data/README.md +54 -27
- data/lib/backup.rb +16 -39
- data/lib/backup/archive.rb +42 -18
- data/lib/backup/cleaner.rb +110 -25
- data/lib/backup/cli/helpers.rb +17 -32
- data/lib/backup/cli/utility.rb +46 -107
- data/lib/backup/compressor/base.rb +14 -2
- data/lib/backup/compressor/bzip2.rb +10 -24
- data/lib/backup/compressor/gzip.rb +10 -24
- data/lib/backup/compressor/lzma.rb +10 -23
- data/lib/backup/compressor/pbzip2.rb +12 -32
- data/lib/backup/config.rb +171 -0
- data/lib/backup/configuration/compressor/base.rb +1 -2
- data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
- data/lib/backup/configuration/database/base.rb +2 -1
- data/lib/backup/configuration/database/mongodb.rb +8 -0
- data/lib/backup/configuration/database/mysql.rb +4 -0
- data/lib/backup/configuration/database/postgresql.rb +4 -0
- data/lib/backup/configuration/database/redis.rb +4 -0
- data/lib/backup/configuration/database/riak.rb +5 -1
- data/lib/backup/configuration/encryptor/base.rb +1 -2
- data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
- data/lib/backup/configuration/helpers.rb +7 -2
- data/lib/backup/configuration/notifier/base.rb +4 -28
- data/lib/backup/configuration/storage/base.rb +1 -1
- data/lib/backup/configuration/storage/dropbox.rb +14 -4
- data/lib/backup/configuration/syncer/base.rb +10 -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 +0 -4
- data/lib/backup/database/base.rb +25 -7
- data/lib/backup/database/mongodb.rb +112 -75
- data/lib/backup/database/mysql.rb +54 -29
- data/lib/backup/database/postgresql.rb +60 -42
- data/lib/backup/database/redis.rb +61 -39
- data/lib/backup/database/riak.rb +35 -11
- data/lib/backup/dependency.rb +4 -5
- data/lib/backup/encryptor/base.rb +13 -1
- data/lib/backup/encryptor/gpg.rb +39 -39
- data/lib/backup/encryptor/open_ssl.rb +28 -38
- data/lib/backup/logger.rb +20 -11
- data/lib/backup/model.rb +206 -163
- data/lib/backup/notifier/base.rb +27 -25
- data/lib/backup/notifier/campfire.rb +7 -13
- data/lib/backup/notifier/hipchat.rb +28 -28
- data/lib/backup/notifier/mail.rb +24 -26
- data/lib/backup/notifier/presently.rb +10 -18
- data/lib/backup/notifier/prowl.rb +9 -17
- data/lib/backup/notifier/twitter.rb +11 -18
- data/lib/backup/package.rb +47 -0
- data/lib/backup/packager.rb +81 -16
- data/lib/backup/splitter.rb +48 -35
- data/lib/backup/storage/base.rb +44 -172
- data/lib/backup/storage/cloudfiles.rb +31 -46
- data/lib/backup/storage/cycler.rb +117 -0
- data/lib/backup/storage/dropbox.rb +92 -76
- data/lib/backup/storage/ftp.rb +30 -40
- data/lib/backup/storage/local.rb +44 -45
- data/lib/backup/storage/ninefold.rb +55 -49
- data/lib/backup/storage/rsync.rb +49 -56
- data/lib/backup/storage/s3.rb +33 -44
- data/lib/backup/storage/scp.rb +21 -48
- data/lib/backup/storage/sftp.rb +26 -40
- data/lib/backup/syncer/base.rb +7 -0
- data/lib/backup/syncer/rsync/base.rb +78 -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 +42 -32
- data/lib/backup/version.rb +1 -1
- data/spec/archive_spec.rb +235 -69
- data/spec/cleaner_spec.rb +304 -0
- data/spec/cli/helpers_spec.rb +142 -1
- data/spec/cli/utility_spec.rb +338 -13
- data/spec/compressor/base_spec.rb +31 -0
- data/spec/compressor/bzip2_spec.rb +60 -35
- data/spec/compressor/gzip_spec.rb +60 -35
- data/spec/compressor/lzma_spec.rb +60 -35
- data/spec/compressor/pbzip2_spec.rb +98 -37
- data/spec/config_spec.rb +321 -0
- data/spec/configuration/base_spec.rb +4 -4
- data/spec/configuration/compressor/bzip2_spec.rb +1 -0
- data/spec/configuration/compressor/gzip_spec.rb +1 -0
- data/spec/configuration/compressor/lzma_spec.rb +1 -0
- data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
- data/spec/configuration/database/base_spec.rb +2 -1
- data/spec/configuration/database/mongodb_spec.rb +26 -16
- data/spec/configuration/database/mysql_spec.rb +4 -0
- data/spec/configuration/database/postgresql_spec.rb +4 -0
- data/spec/configuration/database/redis_spec.rb +4 -0
- data/spec/configuration/database/riak_spec.rb +4 -0
- data/spec/configuration/encryptor/gpg_spec.rb +1 -0
- data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
- data/spec/configuration/notifier/base_spec.rb +32 -0
- data/spec/configuration/notifier/campfire_spec.rb +1 -0
- data/spec/configuration/notifier/hipchat_spec.rb +1 -0
- data/spec/configuration/notifier/mail_spec.rb +1 -0
- data/spec/configuration/notifier/presently_spec.rb +1 -0
- data/spec/configuration/notifier/prowl_spec.rb +1 -0
- data/spec/configuration/notifier/twitter_spec.rb +1 -0
- data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
- data/spec/configuration/storage/dropbox_spec.rb +4 -3
- data/spec/configuration/storage/ftp_spec.rb +1 -0
- data/spec/configuration/storage/local_spec.rb +1 -0
- data/spec/configuration/storage/ninefold_spec.rb +1 -0
- data/spec/configuration/storage/rsync_spec.rb +3 -1
- data/spec/configuration/storage/s3_spec.rb +1 -0
- data/spec/configuration/storage/scp_spec.rb +1 -0
- data/spec/configuration/storage/sftp_spec.rb +1 -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_spec.rb → rsync/push_spec.rb} +12 -15
- data/spec/configuration/syncer/s3_spec.rb +2 -3
- data/spec/database/base_spec.rb +35 -20
- data/spec/database/mongodb_spec.rb +298 -119
- data/spec/database/mysql_spec.rb +147 -72
- data/spec/database/postgresql_spec.rb +155 -100
- data/spec/database/redis_spec.rb +200 -97
- data/spec/database/riak_spec.rb +82 -24
- data/spec/dependency_spec.rb +49 -0
- data/spec/encryptor/base_spec.rb +30 -0
- data/spec/encryptor/gpg_spec.rb +105 -28
- data/spec/encryptor/open_ssl_spec.rb +85 -114
- data/spec/logger_spec.rb +74 -8
- data/spec/model_spec.rb +528 -220
- data/spec/notifier/base_spec.rb +89 -0
- data/spec/notifier/campfire_spec.rb +147 -119
- data/spec/notifier/hipchat_spec.rb +140 -145
- data/spec/notifier/mail_spec.rb +190 -248
- data/spec/notifier/presently_spec.rb +147 -282
- data/spec/notifier/prowl_spec.rb +79 -111
- data/spec/notifier/twitter_spec.rb +87 -106
- data/spec/package_spec.rb +61 -0
- data/spec/packager_spec.rb +154 -0
- data/spec/spec_helper.rb +36 -13
- data/spec/splitter_spec.rb +90 -41
- data/spec/storage/base_spec.rb +95 -239
- data/spec/storage/cloudfiles_spec.rb +185 -75
- data/spec/storage/cycler_spec.rb +239 -0
- data/spec/storage/dropbox_spec.rb +318 -87
- data/spec/storage/ftp_spec.rb +165 -152
- data/spec/storage/local_spec.rb +206 -54
- data/spec/storage/ninefold_spec.rb +264 -128
- data/spec/storage/rsync_spec.rb +244 -163
- data/spec/storage/s3_spec.rb +175 -64
- data/spec/storage/scp_spec.rb +156 -150
- data/spec/storage/sftp_spec.rb +153 -135
- data/spec/syncer/base_spec.rb +22 -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 +180 -91
- data/templates/cli/utility/config +1 -1
- data/templates/cli/utility/database/mongodb +4 -0
- data/templates/cli/utility/database/mysql +3 -0
- data/templates/cli/utility/database/postgresql +3 -0
- data/templates/cli/utility/database/redis +3 -0
- data/templates/cli/utility/database/riak +3 -0
- data/templates/cli/utility/storage/dropbox +4 -1
- data/templates/cli/utility/syncer/rsync_local +12 -0
- data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
- data/templates/cli/utility/syncer/rsync_push +17 -0
- data/templates/storage/dropbox/authorization_url.erb +1 -1
- metadata +42 -17
- data/lib/backup/configuration/syncer/rsync.rb +0 -45
- data/lib/backup/finder.rb +0 -87
- data/lib/backup/storage/object.rb +0 -47
- data/lib/backup/syncer/rsync.rb +0 -152
- data/spec/backup_spec.rb +0 -11
- data/spec/finder_spec.rb +0 -91
- data/spec/storage/object_spec.rb +0 -74
- data/spec/syncer/rsync_spec.rb +0 -195
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../../../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe Backup::Configuration::Syncer::RSync::Base do
|
|
6
|
+
before do
|
|
7
|
+
Backup::Configuration::Syncer::RSync::Base.defaults do |rsync|
|
|
8
|
+
#rsync.directories = 'cannot_have_a_default_value'
|
|
9
|
+
rsync.path = '~/backups/'
|
|
10
|
+
rsync.mirror = true
|
|
11
|
+
rsync.additional_options = []
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
after { Backup::Configuration::Syncer::RSync::Base.clear_defaults! }
|
|
15
|
+
|
|
16
|
+
it 'should set the default rsync configuration' do
|
|
17
|
+
rsync = Backup::Configuration::Syncer::RSync::Base
|
|
18
|
+
rsync.path.should == '~/backups/'
|
|
19
|
+
rsync.mirror.should == true
|
|
20
|
+
rsync.additional_options.should == []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#clear_defaults!' do
|
|
24
|
+
it 'should clear all the defaults, resetting them to nil' do
|
|
25
|
+
Backup::Configuration::Syncer::RSync::Base.clear_defaults!
|
|
26
|
+
|
|
27
|
+
rsync = Backup::Configuration::Syncer::RSync::Base
|
|
28
|
+
rsync.path.should == nil
|
|
29
|
+
rsync.mirror.should == nil
|
|
30
|
+
rsync.additional_options.should == nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../../../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe Backup::Configuration::Syncer::RSync::Local do
|
|
6
|
+
it 'should be a subclass of RSync::Base' do
|
|
7
|
+
rsync = Backup::Configuration::Syncer::RSync::Local
|
|
8
|
+
rsync.superclass.should == Backup::Configuration::Syncer::RSync::Base
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../../../../spec_helper.rb', __FILE__)
|
|
4
|
+
|
|
5
|
+
describe Backup::Configuration::Syncer::RSync::Pull do
|
|
6
|
+
it 'should be a subclass of RSync::Push' do
|
|
7
|
+
rsync = Backup::Configuration::Syncer::RSync::Pull
|
|
8
|
+
rsync.superclass.should == Backup::Configuration::Syncer::RSync::Push
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -1,46 +1,43 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
-
require File.expand_path('
|
|
3
|
+
require File.expand_path('../../../../spec_helper.rb', __FILE__)
|
|
4
4
|
|
|
5
|
-
describe Backup::Configuration::Syncer::RSync do
|
|
5
|
+
describe Backup::Configuration::Syncer::RSync::Push do
|
|
6
6
|
before do
|
|
7
|
-
Backup::Configuration::Syncer::RSync.defaults do |rsync|
|
|
7
|
+
Backup::Configuration::Syncer::RSync::Push.defaults do |rsync|
|
|
8
8
|
rsync.username = 'my_username'
|
|
9
9
|
rsync.password = 'my_password'
|
|
10
10
|
rsync.ip = '123.45.678.90'
|
|
11
11
|
rsync.port = 22
|
|
12
|
-
rsync.path = '~/backups/'
|
|
13
|
-
rsync.mirror = true
|
|
14
12
|
rsync.compress = true
|
|
15
|
-
rsync.additional_options = []
|
|
16
13
|
end
|
|
17
14
|
end
|
|
15
|
+
after { Backup::Configuration::Syncer::RSync::Push.clear_defaults! }
|
|
16
|
+
|
|
17
|
+
it 'should be a subclass of RSync::Base' do
|
|
18
|
+
rsync = Backup::Configuration::Syncer::RSync::Push
|
|
19
|
+
rsync.superclass.should == Backup::Configuration::Syncer::RSync::Base
|
|
20
|
+
end
|
|
18
21
|
|
|
19
22
|
it 'should set the default rsync configuration' do
|
|
20
|
-
rsync = Backup::Configuration::Syncer::RSync
|
|
23
|
+
rsync = Backup::Configuration::Syncer::RSync::Push
|
|
21
24
|
rsync.username.should == 'my_username'
|
|
22
25
|
rsync.password.should == 'my_password'
|
|
23
26
|
rsync.ip.should == '123.45.678.90'
|
|
24
27
|
rsync.port.should == 22
|
|
25
|
-
rsync.path.should == '~/backups/'
|
|
26
|
-
rsync.mirror.should == true
|
|
27
28
|
rsync.compress.should == true
|
|
28
|
-
rsync.additional_options.should == []
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
describe '#clear_defaults!' do
|
|
32
32
|
it 'should clear all the defaults, resetting them to nil' do
|
|
33
|
-
Backup::Configuration::Syncer::RSync.clear_defaults!
|
|
33
|
+
Backup::Configuration::Syncer::RSync::Push.clear_defaults!
|
|
34
34
|
|
|
35
|
-
rsync = Backup::Configuration::Syncer::RSync
|
|
35
|
+
rsync = Backup::Configuration::Syncer::RSync::Push
|
|
36
36
|
rsync.username.should == nil
|
|
37
37
|
rsync.password.should == nil
|
|
38
38
|
rsync.ip.should == nil
|
|
39
39
|
rsync.port.should == nil
|
|
40
|
-
rsync.path.should == nil
|
|
41
|
-
rsync.mirror.should == nil
|
|
42
40
|
rsync.compress.should == nil
|
|
43
|
-
rsync.additional_options.should == nil
|
|
44
41
|
end
|
|
45
42
|
end
|
|
46
43
|
end
|
|
@@ -9,11 +9,12 @@ describe Backup::Configuration::Syncer::S3 do
|
|
|
9
9
|
s3.secret_access_key = 'my_secret_access_key'
|
|
10
10
|
s3.bucket = 'my-bucket'
|
|
11
11
|
s3.path = '/backups/'
|
|
12
|
-
s3.directories = '
|
|
12
|
+
#s3.directories = 'cannot_have_a_default_value'
|
|
13
13
|
s3.mirror = true
|
|
14
14
|
s3.additional_options = ['--exclude="*.rb"']
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
|
+
after { Backup::Configuration::Syncer::S3.clear_defaults! }
|
|
17
18
|
|
|
18
19
|
it 'should set the default s3 configuration' do
|
|
19
20
|
s3 = Backup::Configuration::Syncer::S3
|
|
@@ -21,7 +22,6 @@ describe Backup::Configuration::Syncer::S3 do
|
|
|
21
22
|
s3.secret_access_key.should == 'my_secret_access_key'
|
|
22
23
|
s3.bucket.should == 'my-bucket'
|
|
23
24
|
s3.path.should == '/backups/'
|
|
24
|
-
s3.directories.should == '/directories/to/backup/'
|
|
25
25
|
s3.mirror.should == true
|
|
26
26
|
s3.additional_options.should == ['--exclude="*.rb"']
|
|
27
27
|
end
|
|
@@ -35,7 +35,6 @@ describe Backup::Configuration::Syncer::S3 do
|
|
|
35
35
|
s3.secret_access_key.should == nil
|
|
36
36
|
s3.bucket.should == nil
|
|
37
37
|
s3.path.should == nil
|
|
38
|
-
s3.directories.should == nil
|
|
39
38
|
s3.mirror.should == nil
|
|
40
39
|
s3.additional_options.should == nil
|
|
41
40
|
end
|
data/spec/database/base_spec.rb
CHANGED
|
@@ -3,37 +3,52 @@
|
|
|
3
3
|
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
4
|
|
|
5
5
|
describe Backup::Database::Base do
|
|
6
|
+
let(:model) { Backup::Model.new('foo', 'foo') }
|
|
7
|
+
let(:db) { Backup::Database::Base.new(model) }
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
end
|
|
12
|
-
end
|
|
9
|
+
it 'should set #utility_path' do
|
|
10
|
+
db.utility_path.should be_nil
|
|
11
|
+
db.utility_path = 'utility path'
|
|
12
|
+
db.utility_path.should == 'utility path'
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
describe '#perform!' do
|
|
16
|
+
it 'should invoke prepare! and log!' do
|
|
17
|
+
s = sequence ''
|
|
18
|
+
db.expects(:prepare!).in_sequence(s)
|
|
19
|
+
db.expects(:log!).in_sequence(s)
|
|
20
|
+
|
|
21
|
+
db.perform!
|
|
18
22
|
end
|
|
19
23
|
end
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
context 'since CLI::Helpers are included' do
|
|
26
|
+
it 'should respond to the #utility method' do
|
|
27
|
+
db.respond_to?(:utility).should be_true
|
|
28
|
+
end
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
describe '#prepare!' do
|
|
32
|
+
it 'should set and create #dump_path' do
|
|
33
|
+
model = stub(:trigger => 'test_trigger')
|
|
34
|
+
db.instance_variable_set(:@model, model)
|
|
35
|
+
FileUtils.expects(:mkdir_p).with(
|
|
36
|
+
File.join(Backup::Config.tmp_path, 'test_trigger', 'databases', 'Base')
|
|
37
|
+
)
|
|
38
|
+
db.send(:prepare!)
|
|
39
|
+
db.instance_variable_get(:@dump_path).should ==
|
|
40
|
+
File.join(Backup::Config.tmp_path, 'test_trigger', 'databases', 'Base')
|
|
41
|
+
end
|
|
28
42
|
end
|
|
29
43
|
|
|
30
|
-
describe '#
|
|
31
|
-
it 'should
|
|
32
|
-
db.
|
|
33
|
-
|
|
44
|
+
describe '#log!' do
|
|
45
|
+
it 'should use #database_name' do
|
|
46
|
+
db.stubs(:name).returns('database_name')
|
|
47
|
+
Backup::Logger.expects(:message).with(
|
|
48
|
+
"Database::Base started dumping and archiving 'database_name'."
|
|
49
|
+
)
|
|
34
50
|
|
|
35
|
-
db.
|
|
51
|
+
db.send(:log!)
|
|
36
52
|
end
|
|
37
53
|
end
|
|
38
|
-
|
|
39
54
|
end
|
|
@@ -3,13 +3,9 @@
|
|
|
3
3
|
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
4
|
|
|
5
5
|
describe Backup::Database::MongoDB do
|
|
6
|
-
|
|
7
|
-
before do
|
|
8
|
-
Backup::Database::MongoDB.any_instance.stubs(:load_defaults!)
|
|
9
|
-
end
|
|
10
|
-
|
|
6
|
+
let(:model) { Backup::Model.new(:test_trigger, 'test label') }
|
|
11
7
|
let(:db) do
|
|
12
|
-
Backup::Database::MongoDB.new do |db|
|
|
8
|
+
Backup::Database::MongoDB.new(model) do |db|
|
|
13
9
|
db.name = 'mydatabase'
|
|
14
10
|
db.username = 'someuser'
|
|
15
11
|
db.password = 'secret'
|
|
@@ -18,11 +14,14 @@ describe Backup::Database::MongoDB do
|
|
|
18
14
|
|
|
19
15
|
db.ipv6 = true
|
|
20
16
|
db.only_collections = ['users', 'pirates']
|
|
21
|
-
db.additional_options = ['--query']
|
|
17
|
+
db.additional_options = ['--query', '--foo']
|
|
18
|
+
db.mongodump_utility = '/path/to/mongodump'
|
|
19
|
+
db.mongo_utility = '/path/to/mongo'
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
|
|
25
|
-
describe '#
|
|
23
|
+
describe '#initialize' do
|
|
24
|
+
|
|
26
25
|
it 'should read the adapter details correctly' do
|
|
27
26
|
db.name.should == 'mydatabase'
|
|
28
27
|
db.username.should == 'someuser'
|
|
@@ -30,178 +29,358 @@ describe Backup::Database::MongoDB do
|
|
|
30
29
|
db.host.should == 'localhost'
|
|
31
30
|
db.port.should == 123
|
|
32
31
|
|
|
33
|
-
db.
|
|
34
|
-
db.
|
|
32
|
+
db.ipv6.should == true
|
|
33
|
+
db.only_collections.should == ['users', 'pirates']
|
|
34
|
+
db.additional_options.should == ['--query', '--foo']
|
|
35
|
+
db.mongodump_utility.should == '/path/to/mongodump'
|
|
36
|
+
db.mongo_utility.should == '/path/to/mongo'
|
|
37
|
+
db.lock.should == false
|
|
35
38
|
end
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
context 'when options are not set' do
|
|
41
|
+
before do
|
|
42
|
+
Backup::Database::MongoDB.any_instance.expects(:utility).
|
|
43
|
+
with(:mongodump).returns('/real/mongodump')
|
|
44
|
+
Backup::Database::MongoDB.any_instance.expects(:utility).
|
|
45
|
+
with(:mongo).returns('/real/mongo')
|
|
42
46
|
end
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
it 'should use default values' do
|
|
49
|
+
db = Backup::Database::MongoDB.new(model)
|
|
50
|
+
|
|
51
|
+
db.name.should be_nil
|
|
52
|
+
db.username.should be_nil
|
|
53
|
+
db.password.should be_nil
|
|
54
|
+
db.host.should be_nil
|
|
55
|
+
db.port.should be_nil
|
|
56
|
+
|
|
57
|
+
db.ipv6.should be_false
|
|
58
|
+
db.only_collections.should == []
|
|
59
|
+
db.additional_options.should == []
|
|
60
|
+
db.mongodump_utility.should == '/real/mongodump'
|
|
61
|
+
db.mongo_utility.should == '/real/mongo'
|
|
62
|
+
db.lock.should be_false
|
|
63
|
+
end
|
|
46
64
|
end
|
|
47
|
-
end
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
context 'when configuration defaults have been set' do
|
|
67
|
+
after { Backup::Configuration::Database::MongoDB.clear_defaults! }
|
|
68
|
+
|
|
69
|
+
it 'should use configuration defaults' do
|
|
70
|
+
Backup::Configuration::Database::MongoDB.defaults do |db|
|
|
71
|
+
db.name = 'db_name'
|
|
72
|
+
db.username = 'db_username'
|
|
73
|
+
db.password = 'db_password'
|
|
74
|
+
db.host = 'db_host'
|
|
75
|
+
db.port = 789
|
|
76
|
+
|
|
77
|
+
db.ipv6 = true
|
|
78
|
+
db.only_collections = ['collection']
|
|
79
|
+
db.additional_options = ['--opt']
|
|
80
|
+
db.mongodump_utility = '/default/path/to/mongodump'
|
|
81
|
+
db.mongo_utility = '/default/path/to/mongo'
|
|
82
|
+
db.lock = true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
db = Backup::Database::MongoDB.new(model)
|
|
86
|
+
db.name.should == 'db_name'
|
|
87
|
+
db.username.should == 'db_username'
|
|
88
|
+
db.password.should == 'db_password'
|
|
89
|
+
db.host.should == 'db_host'
|
|
90
|
+
db.port.should == 789
|
|
91
|
+
|
|
92
|
+
db.ipv6.should be_true
|
|
93
|
+
db.only_collections.should == ['collection']
|
|
94
|
+
db.additional_options.should == ['--opt']
|
|
95
|
+
db.mongodump_utility.should == '/default/path/to/mongodump'
|
|
96
|
+
db.mongo_utility.should == '/default/path/to/mongo'
|
|
97
|
+
db.lock.should be_true
|
|
98
|
+
end
|
|
52
99
|
end
|
|
53
|
-
end
|
|
100
|
+
end # describe '#initialize'
|
|
54
101
|
|
|
55
|
-
describe '#
|
|
56
|
-
|
|
57
|
-
|
|
102
|
+
describe '#perform!' do
|
|
103
|
+
let(:s) { sequence '' }
|
|
104
|
+
|
|
105
|
+
before do
|
|
106
|
+
# superclass actions
|
|
107
|
+
db.expects(:prepare!).in_sequence(s)
|
|
108
|
+
db.expects(:log!).in_sequence(s)
|
|
58
109
|
end
|
|
59
110
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
111
|
+
context 'when #lock is set to false' do
|
|
112
|
+
|
|
113
|
+
context 'when #only_collections has not been specified' do
|
|
114
|
+
before { db.only_collections = [] }
|
|
115
|
+
it 'should dump everything without locking' do
|
|
116
|
+
db.expects(:lock_database).never
|
|
117
|
+
db.expects(:unlock_database).never
|
|
118
|
+
db.expects(:specific_collection_dump!).never
|
|
119
|
+
|
|
120
|
+
db.expects(:dump!).in_sequence(s)
|
|
121
|
+
db.expects(:package!).in_sequence(s)
|
|
122
|
+
db.perform!
|
|
123
|
+
end
|
|
63
124
|
end
|
|
64
125
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
126
|
+
context 'when #only_collections has been specified' do
|
|
127
|
+
it 'should dump specific collections without locking' do
|
|
128
|
+
db.expects(:lock_database).never
|
|
129
|
+
db.expects(:unlock_database).never
|
|
130
|
+
db.expects(:dump!).never
|
|
68
131
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
132
|
+
db.expects(:specific_collection_dump!).in_sequence(s)
|
|
133
|
+
db.expects(:package!).in_sequence(s)
|
|
134
|
+
db.perform!
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end # context 'when #lock is set to false'
|
|
73
139
|
|
|
74
|
-
|
|
75
|
-
db =
|
|
76
|
-
|
|
77
|
-
|
|
140
|
+
context 'when #lock is set to true' do
|
|
141
|
+
before { db.lock = true }
|
|
142
|
+
|
|
143
|
+
context 'when #only_collections has not been specified' do
|
|
144
|
+
before { db.only_collections = [] }
|
|
145
|
+
it 'should dump everything while locking the database' do
|
|
146
|
+
db.expects(:specific_collection_dump!).never
|
|
147
|
+
|
|
148
|
+
db.expects(:lock_database).in_sequence(s)
|
|
149
|
+
db.expects(:dump!).in_sequence(s)
|
|
150
|
+
db.expects(:unlock_database).in_sequence(s)
|
|
151
|
+
db.expects(:package!).in_sequence(s)
|
|
152
|
+
db.perform!
|
|
153
|
+
end
|
|
78
154
|
end
|
|
79
155
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
156
|
+
context 'when #only_collections has been specified' do
|
|
157
|
+
it 'should dump specific collections without locking' do
|
|
158
|
+
db.expects(:lock_database).never
|
|
159
|
+
db.expects(:unlock_database).never
|
|
160
|
+
db.expects(:dump!).never
|
|
161
|
+
|
|
162
|
+
db.expects(:lock_database).in_sequence(s)
|
|
163
|
+
db.expects(:specific_collection_dump!).in_sequence(s)
|
|
164
|
+
db.expects(:unlock_database).in_sequence(s)
|
|
165
|
+
db.expects(:package!).in_sequence(s)
|
|
166
|
+
db.perform!
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end # context 'when #lock is set to true'
|
|
171
|
+
|
|
172
|
+
context 'when errors occur' do
|
|
173
|
+
it 'should re-raise error and skip package!' do
|
|
174
|
+
db.expects(:specific_collection_dump!).in_sequence(s).
|
|
175
|
+
raises('Test Error Message')
|
|
176
|
+
db.expects(:package!).never
|
|
177
|
+
|
|
178
|
+
expect do
|
|
179
|
+
db.perform!
|
|
180
|
+
end.to raise_error(
|
|
181
|
+
Backup::Errors::Database::MongoDBError,
|
|
182
|
+
"Database::MongoDBError: Database Dump Failed!\n" +
|
|
183
|
+
" Reason: RuntimeError\n" +
|
|
184
|
+
" Test Error Message"
|
|
185
|
+
)
|
|
186
|
+
end
|
|
83
187
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
188
|
+
it 'should ensure database is unlocked' do
|
|
189
|
+
db.lock = true
|
|
190
|
+
|
|
191
|
+
db.expects(:lock_database).in_sequence(s)
|
|
192
|
+
db.expects(:specific_collection_dump!).in_sequence(s).
|
|
193
|
+
raises('Test Error Message')
|
|
194
|
+
db.expects(:unlock_database).in_sequence(s)
|
|
195
|
+
db.expects(:package!).never
|
|
196
|
+
|
|
197
|
+
expect do
|
|
198
|
+
db.perform!
|
|
199
|
+
end.to raise_error(
|
|
200
|
+
Backup::Errors::Database::MongoDBError,
|
|
201
|
+
"Database::MongoDBError: Database Dump Failed!\n" +
|
|
202
|
+
" Reason: RuntimeError\n" +
|
|
203
|
+
" Test Error Message"
|
|
204
|
+
)
|
|
205
|
+
end
|
|
88
206
|
end
|
|
89
207
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
208
|
+
end # describe '#perform!'
|
|
209
|
+
|
|
210
|
+
describe '#dump!' do
|
|
211
|
+
it 'should run the mongodb dump command' do
|
|
212
|
+
db.expects(:mongodump).returns(:dump_command)
|
|
213
|
+
db.expects(:run).with(:dump_command)
|
|
214
|
+
db.send(:dump!)
|
|
93
215
|
end
|
|
94
216
|
end
|
|
95
217
|
|
|
96
|
-
describe '#
|
|
97
|
-
it 'should
|
|
98
|
-
db.expects(:
|
|
99
|
-
db.
|
|
100
|
-
db.
|
|
101
|
-
|
|
102
|
-
"--host='localhost' --port='123' --ipv6 --query --out='#{ File.join(Backup::TMP_PATH, Backup::TRIGGER, 'MongoDB') }'"
|
|
218
|
+
describe '#specific_collection_dump!' do
|
|
219
|
+
it 'should run the mongodb dump command for each collection' do
|
|
220
|
+
db.expects(:mongodump).twice.returns('dump_command')
|
|
221
|
+
db.expects(:run).with("dump_command --collection='users'")
|
|
222
|
+
db.expects(:run).with("dump_command --collection='pirates'")
|
|
223
|
+
db.send(:specific_collection_dump!)
|
|
103
224
|
end
|
|
104
225
|
end
|
|
105
226
|
|
|
106
|
-
describe '#
|
|
227
|
+
describe '#mongodump' do
|
|
107
228
|
before do
|
|
108
|
-
db.
|
|
109
|
-
db.stubs(:mkdir)
|
|
110
|
-
db.stubs(:run)
|
|
229
|
+
db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
|
|
111
230
|
end
|
|
112
231
|
|
|
113
|
-
it 'should
|
|
114
|
-
db.
|
|
115
|
-
|
|
232
|
+
it 'should return the mongodb dump command string' do
|
|
233
|
+
db.send(:mongodump).should == "/path/to/mongodump " +
|
|
234
|
+
"--db='mydatabase' --username='someuser' --password='secret' " +
|
|
235
|
+
"--host='localhost' --port='123' --ipv6 " +
|
|
236
|
+
"--query --foo --out='/path/to/dump/folder'"
|
|
116
237
|
end
|
|
238
|
+
end
|
|
117
239
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
db.expects(:dump!)
|
|
240
|
+
describe '#package!' do
|
|
241
|
+
let(:compressor) { mock }
|
|
121
242
|
|
|
122
|
-
|
|
123
|
-
|
|
243
|
+
context 'when a compressor is configured' do
|
|
244
|
+
before do
|
|
245
|
+
Timecop.freeze(Time.now)
|
|
246
|
+
db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
|
|
247
|
+
db.expects(:utility).with(:tar).returns('tar')
|
|
248
|
+
model.expects(:compressor).twice.returns(compressor)
|
|
249
|
+
compressor.expects(:compress_with).yields('compressor_command', '.gz')
|
|
250
|
+
end
|
|
124
251
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
252
|
+
it 'should package the dump directory, then remove it' do
|
|
253
|
+
timestamp = Time.now.to_i.to_s[-5, 5]
|
|
254
|
+
db.expects(:run).with(
|
|
255
|
+
"tar -cf - -C '/path/to/dump' 'folder' | compressor_command" +
|
|
256
|
+
" > /path/to/dump/folder-#{ timestamp }.tar.gz"
|
|
257
|
+
)
|
|
258
|
+
FileUtils.expects(:rm_rf).with('/path/to/dump/folder')
|
|
128
259
|
|
|
129
|
-
|
|
260
|
+
db.send(:package!)
|
|
261
|
+
end
|
|
130
262
|
end
|
|
131
263
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
264
|
+
context 'when a compressor is not configured' do
|
|
265
|
+
before do
|
|
266
|
+
model.expects(:compressor).returns(nil)
|
|
267
|
+
end
|
|
135
268
|
|
|
136
|
-
|
|
269
|
+
it 'should return nil' do
|
|
270
|
+
db.expects(:run).never
|
|
271
|
+
db.send(:package!).should be_nil
|
|
272
|
+
end
|
|
137
273
|
end
|
|
274
|
+
end
|
|
138
275
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
276
|
+
describe '#database' do
|
|
277
|
+
context 'when a database name is given' do
|
|
278
|
+
it 'should return the command string for the database' do
|
|
279
|
+
db.send(:database).should == "--db='mydatabase'"
|
|
280
|
+
end
|
|
144
281
|
end
|
|
145
282
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
283
|
+
context 'when no database name is given' do
|
|
284
|
+
it 'should return nil' do
|
|
285
|
+
db.name = nil
|
|
286
|
+
db.send(:database).should be_nil
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
149
290
|
|
|
150
|
-
|
|
291
|
+
describe '#credential_options' do
|
|
292
|
+
it 'should return the command string for the user credentials' do
|
|
293
|
+
db.send(:credential_options).should ==
|
|
294
|
+
"--username='someuser' --password='secret'"
|
|
151
295
|
end
|
|
296
|
+
end
|
|
152
297
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
db.
|
|
156
|
-
|
|
157
|
-
|
|
298
|
+
describe '#connectivity_options' do
|
|
299
|
+
it 'should return the command string for the connectivity options' do
|
|
300
|
+
db.send(:connectivity_options).should == "--host='localhost' --port='123'"
|
|
301
|
+
end
|
|
302
|
+
end
|
|
158
303
|
|
|
159
|
-
|
|
304
|
+
describe '#ipv6_option' do
|
|
305
|
+
context 'when #ipv6 is set true' do
|
|
306
|
+
it 'should return the command string for the ipv6 option' do
|
|
307
|
+
db.send(:ipv6_option).should == '--ipv6'
|
|
308
|
+
end
|
|
160
309
|
end
|
|
161
310
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
311
|
+
context 'when #ipv6 is set false' do
|
|
312
|
+
it 'should return and empty string' do
|
|
313
|
+
db.ipv6 = false
|
|
314
|
+
db.send(:ipv6_option).should == ''
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
165
318
|
|
|
166
|
-
|
|
319
|
+
describe '#user_options' do
|
|
320
|
+
context 'when #additional_options are set' do
|
|
321
|
+
it 'should return the command string for the options' do
|
|
322
|
+
db.send(:user_options).should == '--query --foo'
|
|
323
|
+
end
|
|
167
324
|
end
|
|
168
325
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
326
|
+
context 'when #additional_options are not set' do
|
|
327
|
+
it 'should return an empty string' do
|
|
328
|
+
db.additional_options = []
|
|
329
|
+
db.send(:user_options).should == ''
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
172
333
|
|
|
173
|
-
|
|
334
|
+
describe '#dump_directory' do
|
|
335
|
+
it 'should return the command string for the dump path' do
|
|
336
|
+
db.instance_variable_set(:@dump_path, '/path/to/dump/folder')
|
|
337
|
+
db.send(:dump_directory).should == "--out='/path/to/dump/folder'"
|
|
174
338
|
end
|
|
339
|
+
end
|
|
175
340
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
db.
|
|
341
|
+
describe '#lock_database' do
|
|
342
|
+
it 'should return the command to lock the database' do
|
|
343
|
+
db.stubs(:mongo_uri).returns(:mongo_uri_output)
|
|
344
|
+
db.expects(:run).with(
|
|
345
|
+
" echo 'use admin\n" +
|
|
346
|
+
' db.runCommand({"fsync" : 1, "lock" : 1})\' | /path/to/mongo mongo_uri_output' +
|
|
347
|
+
"\n"
|
|
348
|
+
)
|
|
349
|
+
db.send(:lock_database)
|
|
180
350
|
end
|
|
181
351
|
end
|
|
182
352
|
|
|
183
|
-
describe
|
|
184
|
-
|
|
185
|
-
db.
|
|
186
|
-
db.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
353
|
+
describe '#unlock_database' do
|
|
354
|
+
it 'should return the command to unlock the database' do
|
|
355
|
+
db.stubs(:mongo_uri).returns(:mongo_uri_output)
|
|
356
|
+
db.expects(:run).with(
|
|
357
|
+
" echo 'use admin\n" +
|
|
358
|
+
' db.$cmd.sys.unlock.findOne()\' | /path/to/mongo mongo_uri_output' +
|
|
359
|
+
"\n"
|
|
360
|
+
)
|
|
361
|
+
db.send(:unlock_database)
|
|
190
362
|
end
|
|
363
|
+
end
|
|
191
364
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
db.
|
|
365
|
+
describe '#mongo_uri' do
|
|
366
|
+
before do
|
|
367
|
+
db.stubs(:credential_options).returns(:credential_options_output)
|
|
368
|
+
db.stubs(:ipv6_option).returns(:ipv6_option_output)
|
|
195
369
|
end
|
|
196
370
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
371
|
+
context 'when a database name is given' do
|
|
372
|
+
it 'should return the URI specifying the database' do
|
|
373
|
+
db.send(:mongo_uri).should ==
|
|
374
|
+
"localhost:123/mydatabase credential_options_output ipv6_option_output"
|
|
375
|
+
end
|
|
200
376
|
end
|
|
201
377
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
378
|
+
context 'when no database name is given' do
|
|
379
|
+
it 'should return the URI without specifying the database' do
|
|
380
|
+
db.name = nil
|
|
381
|
+
db.send(:mongo_uri).should ==
|
|
382
|
+
"localhost:123 credential_options_output ipv6_option_output"
|
|
383
|
+
end
|
|
205
384
|
end
|
|
206
385
|
end
|
|
207
386
|
end
|