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
|
@@ -3,181 +3,317 @@
|
|
|
3
3
|
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
4
|
|
|
5
5
|
describe Backup::Storage::Ninefold do
|
|
6
|
-
|
|
7
|
-
let(:
|
|
8
|
-
Backup::Storage::Ninefold.new do |nf|
|
|
9
|
-
nf.storage_token
|
|
10
|
-
nf.storage_secret
|
|
11
|
-
nf.
|
|
12
|
-
nf.keep = 20
|
|
6
|
+
let(:model) { Backup::Model.new(:test_trigger, 'test label') }
|
|
7
|
+
let(:storage) do
|
|
8
|
+
Backup::Storage::Ninefold.new(model) do |nf|
|
|
9
|
+
nf.storage_token = 'my_token'
|
|
10
|
+
nf.storage_secret = 'my_secret'
|
|
11
|
+
nf.keep = 5
|
|
13
12
|
end
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
ninefold.storage_token.should == 'my_storage_token'
|
|
22
|
-
ninefold.storage_secret.should == 'my_storage_secret'
|
|
23
|
-
ninefold.keep.should == 20
|
|
24
|
-
end
|
|
15
|
+
describe '#initialize' do
|
|
16
|
+
it 'should set the correct values' do
|
|
17
|
+
storage.storage_token.should == 'my_token'
|
|
18
|
+
storage.storage_secret.should == 'my_secret'
|
|
19
|
+
storage.path.should == 'backups'
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
nf.storage_token = 'my_storage_token'
|
|
29
|
-
nf.keep = 500
|
|
21
|
+
storage.storage_id.should be_nil
|
|
22
|
+
storage.keep.should == 5
|
|
30
23
|
end
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
nf
|
|
25
|
+
it 'should set a storage_id if given' do
|
|
26
|
+
nf = Backup::Storage::Ninefold.new(model, 'my storage_id')
|
|
27
|
+
nf.storage_id.should == 'my storage_id'
|
|
34
28
|
end
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ninefold.path.should == 'my/backups' # overwritten from Backup::Storage::Ninefold
|
|
39
|
-
ninefold.keep.should == 500 # comes from the default configuration
|
|
40
|
-
end
|
|
30
|
+
context 'when setting configuration defaults' do
|
|
31
|
+
after { Backup::Configuration::Storage::Ninefold.clear_defaults! }
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
it 'should use the configured defaults' do
|
|
34
|
+
Backup::Configuration::Storage::Ninefold.defaults do |nf|
|
|
35
|
+
nf.storage_token = 'some_token'
|
|
36
|
+
nf.storage_secret = 'some_secret'
|
|
37
|
+
nf.path = 'some_path'
|
|
38
|
+
nf.keep = 15
|
|
39
|
+
end
|
|
40
|
+
storage = Backup::Storage::Ninefold.new(model)
|
|
41
|
+
storage.storage_token.should == 'some_token'
|
|
42
|
+
storage.storage_secret.should == 'some_secret'
|
|
43
|
+
storage.path.should == 'some_path'
|
|
44
|
+
|
|
45
|
+
storage.storage_id.should be_nil
|
|
46
|
+
storage.keep.should == 15
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should override the configured defaults' do
|
|
50
|
+
Backup::Configuration::Storage::Ninefold.defaults do |nf|
|
|
51
|
+
nf.storage_token = 'old_token'
|
|
52
|
+
nf.storage_secret = 'old_secret'
|
|
53
|
+
nf.path = 'old_path'
|
|
54
|
+
nf.keep = 15
|
|
55
|
+
end
|
|
56
|
+
storage = Backup::Storage::Ninefold.new(model) do |nf|
|
|
57
|
+
nf.storage_token = 'new_token'
|
|
58
|
+
nf.storage_secret = 'new_secret'
|
|
59
|
+
nf.path = 'new_path'
|
|
60
|
+
nf.keep = 10
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
storage.storage_token.should == 'new_token'
|
|
64
|
+
storage.storage_secret.should == 'new_secret'
|
|
65
|
+
storage.path.should == 'new_path'
|
|
66
|
+
|
|
67
|
+
storage.storage_id.should be_nil
|
|
68
|
+
storage.keep.should == 10
|
|
69
|
+
end
|
|
70
|
+
end # context 'when setting configuration defaults'
|
|
71
|
+
|
|
72
|
+
end # describe '#initialize'
|
|
47
73
|
|
|
48
|
-
describe '#
|
|
49
|
-
it 'should
|
|
50
|
-
|
|
51
|
-
ninefold.expects(:cycle!)
|
|
52
|
-
ninefold.perform!
|
|
74
|
+
describe '#provider' do
|
|
75
|
+
it 'should set the Fog provider' do
|
|
76
|
+
storage.send(:provider).should == 'Ninefold'
|
|
53
77
|
end
|
|
54
78
|
end
|
|
55
79
|
|
|
56
80
|
describe '#connection' do
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
let(:connection) { mock }
|
|
82
|
+
|
|
83
|
+
it 'should create a new connection' do
|
|
84
|
+
Fog::Storage.expects(:new).once.with(
|
|
59
85
|
:provider => 'Ninefold',
|
|
60
|
-
:ninefold_storage_token => '
|
|
61
|
-
:ninefold_storage_secret => '
|
|
62
|
-
|
|
86
|
+
:ninefold_storage_token => 'my_token',
|
|
87
|
+
:ninefold_storage_secret => 'my_secret'
|
|
88
|
+
).returns(connection)
|
|
89
|
+
storage.send(:connection).should == connection
|
|
90
|
+
end
|
|
63
91
|
|
|
64
|
-
|
|
65
|
-
|
|
92
|
+
it 'should return an existing connection' do
|
|
93
|
+
Fog::Storage.expects(:new).once.returns(connection)
|
|
94
|
+
storage.send(:connection).should == connection
|
|
95
|
+
storage.send(:connection).should == connection
|
|
66
96
|
end
|
|
67
|
-
end
|
|
97
|
+
end # describe '#connection'
|
|
68
98
|
|
|
69
|
-
describe '#
|
|
70
|
-
let(:connection) { mock
|
|
71
|
-
let(:directories) { mock
|
|
72
|
-
let(:directory) { mock
|
|
73
|
-
let(:files) { mock('Fog::Storage::Ninefold::Files') }
|
|
99
|
+
describe '#directory_for' do
|
|
100
|
+
let(:connection) { mock }
|
|
101
|
+
let(:directories) { mock }
|
|
102
|
+
let(:directory) { mock }
|
|
74
103
|
|
|
75
104
|
before do
|
|
76
|
-
|
|
105
|
+
storage.stubs(:connection).returns(connection)
|
|
77
106
|
connection.stubs(:directories).returns(directories)
|
|
78
|
-
directory.stubs(:files).returns(files)
|
|
79
107
|
end
|
|
80
108
|
|
|
81
|
-
context 'directory
|
|
82
|
-
it 'should
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
File.expects(:open).with("#{File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER}")}.tar").returns(file)
|
|
86
|
-
|
|
87
|
-
directories.expects(:get).with("backups/myapp/#{ Backup::TIME }").returns(directory)
|
|
88
|
-
files.expects(:create) do |options|
|
|
89
|
-
options[:key].should == "#{ Backup::TRIGGER }.tar"
|
|
90
|
-
options[:body].should == file
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
ninefold.send(:transfer!)
|
|
109
|
+
context 'when the directory for the remote_path exists' do
|
|
110
|
+
it 'should return the directory' do
|
|
111
|
+
directories.expects(:get).with('remote_path').returns(directory)
|
|
112
|
+
storage.send(:directory_for, 'remote_path').should be(directory)
|
|
94
113
|
end
|
|
95
114
|
end
|
|
96
115
|
|
|
97
|
-
context 'directory does not
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
File.expects(:open).with("#{File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER}")}.tar").returns(file)
|
|
102
|
-
|
|
103
|
-
directories.expects(:get).with("backups/myapp/#{ Backup::TIME }").returns(nil)
|
|
104
|
-
directories.expects(:create) { |options|
|
|
105
|
-
options[:key].should == "backups/myapp/#{ Backup::TIME }"
|
|
106
|
-
}.returns(directory)
|
|
116
|
+
context 'when the directory for the remote_path does not exist' do
|
|
117
|
+
before do
|
|
118
|
+
directories.expects(:get).with('remote_path').returns(nil)
|
|
119
|
+
end
|
|
107
120
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
121
|
+
context 'when create is set to false' do
|
|
122
|
+
it 'should return nil' do
|
|
123
|
+
storage.send(:directory_for, 'remote_path').should be_nil
|
|
111
124
|
end
|
|
125
|
+
end
|
|
112
126
|
|
|
113
|
-
|
|
127
|
+
context 'when create is set to true' do
|
|
128
|
+
it 'should create and return the directory' do
|
|
129
|
+
directories.expects(:create).with(:key => 'remote_path').returns(directory)
|
|
130
|
+
storage.send(:directory_for, 'remote_path', true).should be(directory)
|
|
131
|
+
end
|
|
114
132
|
end
|
|
115
133
|
end
|
|
116
|
-
end
|
|
134
|
+
end # describe '#directory_for'
|
|
117
135
|
|
|
118
|
-
describe '#
|
|
119
|
-
let(:
|
|
120
|
-
let(:directories) { mock('Fog::Storage::Ninefold::Directories') }
|
|
121
|
-
let(:directory) { mock('Fog::Storage::Ninefold::Directory') }
|
|
122
|
-
let(:files) { mock('Fog::Storage::Ninefold::Files') }
|
|
123
|
-
let(:file) { mock('Fog::Storage::Ninefold::File') }
|
|
136
|
+
describe '#remote_path_for' do
|
|
137
|
+
let(:package) { mock }
|
|
124
138
|
|
|
125
139
|
before do
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
140
|
+
# for superclass method
|
|
141
|
+
package.expects(:trigger).returns('trigger')
|
|
142
|
+
package.expects(:time).returns('time')
|
|
129
143
|
end
|
|
130
144
|
|
|
131
|
-
it 'should remove
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
it 'should remove any preceeding slash from the remote path' do
|
|
146
|
+
storage.path = '/backups'
|
|
147
|
+
storage.send(:remote_path_for, package).should == 'backups/trigger/time'
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe '#transfer!' do
|
|
152
|
+
let(:package) { mock }
|
|
153
|
+
let(:directory) { mock }
|
|
154
|
+
let(:directory_files) { mock }
|
|
155
|
+
let(:file) { mock }
|
|
156
|
+
let(:s) { sequence '' }
|
|
140
157
|
|
|
141
|
-
|
|
158
|
+
before do
|
|
159
|
+
storage.instance_variable_set(:@package, package)
|
|
160
|
+
storage.stubs(:storage_name).returns('Storage::Ninefold')
|
|
161
|
+
storage.stubs(:local_path).returns('/local/path')
|
|
162
|
+
directory.stubs(:files).returns(directory_files)
|
|
142
163
|
end
|
|
143
164
|
|
|
144
|
-
it 'should
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
files.expects(:get).never
|
|
149
|
-
file.expects(:destroy).never
|
|
150
|
-
directory.expects(:destroy).never
|
|
165
|
+
it 'should transfer the package files' do
|
|
166
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
167
|
+
returns('remote/path')
|
|
168
|
+
storage.expects(:directory_for).with('remote/path', true).returns(directory)
|
|
151
169
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
170
|
+
storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
|
|
171
|
+
multiple_yields(
|
|
172
|
+
['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
|
|
173
|
+
['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
|
|
174
|
+
)
|
|
175
|
+
# first yield
|
|
176
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
177
|
+
"Storage::Ninefold started transferring " +
|
|
178
|
+
"'2011.12.31.11.00.02.backup.tar.enc-aa'."
|
|
179
|
+
)
|
|
180
|
+
File.expects(:open).in_sequence(s).with(
|
|
181
|
+
File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'), 'r'
|
|
182
|
+
).yields(file)
|
|
183
|
+
directory_files.expects(:create).in_sequence(s).with(
|
|
184
|
+
:key => 'backup.tar.enc-aa', :body => file
|
|
185
|
+
)
|
|
186
|
+
# second yield
|
|
187
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
188
|
+
"Storage::Ninefold started transferring " +
|
|
189
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ab'."
|
|
190
|
+
)
|
|
191
|
+
File.expects(:open).in_sequence(s).with(
|
|
192
|
+
File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'), 'r'
|
|
193
|
+
).yields(file)
|
|
194
|
+
directory_files.expects(:create).in_sequence(s).with(
|
|
195
|
+
:key => 'backup.tar.enc-ab', :body => file
|
|
158
196
|
)
|
|
159
197
|
|
|
198
|
+
storage.send(:transfer!)
|
|
160
199
|
end
|
|
200
|
+
end # describe '#transfer!'
|
|
161
201
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
returns(nil)
|
|
169
|
-
file.expects(:destroy).never
|
|
170
|
-
directory.expects(:destroy).never
|
|
202
|
+
describe '#remove!' do
|
|
203
|
+
let(:package) { mock }
|
|
204
|
+
let(:directory) { mock }
|
|
205
|
+
let(:directory_files) { mock }
|
|
206
|
+
let(:file) { mock }
|
|
207
|
+
let(:s) { sequence '' }
|
|
171
208
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
209
|
+
before do
|
|
210
|
+
storage.stubs(:storage_name).returns('Storage::Ninefold')
|
|
211
|
+
directory.stubs(:files).returns(directory_files)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'should remove the package files' do
|
|
215
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
216
|
+
returns('remote/path')
|
|
217
|
+
storage.expects(:directory_for).with('remote/path').returns(directory)
|
|
218
|
+
|
|
219
|
+
storage.expects(:transferred_files_for).in_sequence(s).with(package).
|
|
220
|
+
multiple_yields(
|
|
221
|
+
['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
|
|
222
|
+
['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
|
|
178
223
|
)
|
|
224
|
+
# first yield
|
|
225
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
226
|
+
"Storage::Ninefold started removing " +
|
|
227
|
+
"'2011.12.31.11.00.02.backup.tar.enc-aa' from Ninefold."
|
|
228
|
+
)
|
|
229
|
+
directory_files.expects(:get).in_sequence(s).
|
|
230
|
+
with('backup.tar.enc-aa').returns(file)
|
|
231
|
+
file.expects(:destroy).in_sequence(s)
|
|
232
|
+
# second yield
|
|
233
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
234
|
+
"Storage::Ninefold started removing " +
|
|
235
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ab' from Ninefold."
|
|
236
|
+
)
|
|
237
|
+
directory_files.expects(:get).in_sequence(s).
|
|
238
|
+
with('backup.tar.enc-ab').returns(file)
|
|
239
|
+
file.expects(:destroy).in_sequence(s)
|
|
179
240
|
|
|
241
|
+
directory.expects(:destroy).in_sequence(s)
|
|
242
|
+
|
|
243
|
+
expect do
|
|
244
|
+
storage.send(:remove!, package)
|
|
245
|
+
end.not_to raise_error
|
|
180
246
|
end
|
|
181
|
-
|
|
247
|
+
|
|
248
|
+
context 'when the remote directory does not exist' do
|
|
249
|
+
it 'should raise an error' do
|
|
250
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
251
|
+
returns('remote/path')
|
|
252
|
+
storage.expects(:directory_for).with('remote/path').returns(nil)
|
|
253
|
+
|
|
254
|
+
storage.expects(:transferred_files_for).never
|
|
255
|
+
directory_files.expects(:get).never
|
|
256
|
+
file.expects(:destroy).never
|
|
257
|
+
directory.expects(:destroy).never
|
|
258
|
+
|
|
259
|
+
expect do
|
|
260
|
+
storage.send(:remove!, package)
|
|
261
|
+
end.to raise_error {|err|
|
|
262
|
+
err.should be_an_instance_of Backup::Errors::Storage::Ninefold::NotFoundError
|
|
263
|
+
err.message.should == 'Storage::Ninefold::NotFoundError: ' +
|
|
264
|
+
"Directory at 'remote/path' not found"
|
|
265
|
+
}
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context 'when remote files do not exist' do
|
|
270
|
+
it 'should collect their names and raise an error after proceeding' do
|
|
271
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
272
|
+
returns('remote/path')
|
|
273
|
+
storage.expects(:directory_for).with('remote/path').returns(directory)
|
|
274
|
+
|
|
275
|
+
storage.expects(:transferred_files_for).in_sequence(s).with(package).
|
|
276
|
+
multiple_yields(
|
|
277
|
+
['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
|
|
278
|
+
['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab'],
|
|
279
|
+
['2011.12.31.11.00.02.backup.tar.enc-ac', 'backup.tar.enc-ac']
|
|
280
|
+
)
|
|
281
|
+
# first yield (file not found)
|
|
282
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
283
|
+
"Storage::Ninefold started removing " +
|
|
284
|
+
"'2011.12.31.11.00.02.backup.tar.enc-aa' from Ninefold."
|
|
285
|
+
)
|
|
286
|
+
directory_files.expects(:get).in_sequence(s).
|
|
287
|
+
with('backup.tar.enc-aa').returns(nil)
|
|
288
|
+
# second yield (file found and removed)
|
|
289
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
290
|
+
"Storage::Ninefold started removing " +
|
|
291
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ab' from Ninefold."
|
|
292
|
+
)
|
|
293
|
+
directory_files.expects(:get).in_sequence(s).
|
|
294
|
+
with('backup.tar.enc-ab').returns(file)
|
|
295
|
+
file.expects(:destroy).in_sequence(s)
|
|
296
|
+
# third yield (file not found)
|
|
297
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
298
|
+
"Storage::Ninefold started removing " +
|
|
299
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ac' from Ninefold."
|
|
300
|
+
)
|
|
301
|
+
directory_files.expects(:get).in_sequence(s).
|
|
302
|
+
with('backup.tar.enc-ac').returns(nil)
|
|
303
|
+
|
|
304
|
+
# directory removed
|
|
305
|
+
directory.expects(:destroy).in_sequence(s)
|
|
306
|
+
|
|
307
|
+
expect do
|
|
308
|
+
storage.send(:remove!, package)
|
|
309
|
+
end.to raise_error {|err|
|
|
310
|
+
err.should be_an_instance_of Backup::Errors::Storage::Ninefold::NotFoundError
|
|
311
|
+
err.message.should == 'Storage::Ninefold::NotFoundError: ' +
|
|
312
|
+
"The following file(s) were not found in 'remote/path'\n" +
|
|
313
|
+
" backup.tar.enc-aa\n backup.tar.enc-ac"
|
|
314
|
+
}
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end # describe '#remove!'
|
|
182
318
|
|
|
183
319
|
end
|
data/spec/storage/rsync_spec.rb
CHANGED
|
@@ -3,261 +3,342 @@
|
|
|
3
3
|
require File.expand_path('../../spec_helper.rb', __FILE__)
|
|
4
4
|
|
|
5
5
|
describe Backup::Storage::RSync do
|
|
6
|
-
|
|
7
|
-
let(:
|
|
8
|
-
Backup::Storage::RSync.new do |rsync|
|
|
6
|
+
let(:model) { Backup::Model.new(:test_trigger, 'test label') }
|
|
7
|
+
let(:storage) do
|
|
8
|
+
Backup::Storage::RSync.new(model) do |rsync|
|
|
9
9
|
rsync.username = 'my_username'
|
|
10
10
|
rsync.password = 'my_password'
|
|
11
11
|
rsync.ip = '123.45.678.90'
|
|
12
|
-
rsync.
|
|
13
|
-
rsync.path = '~/backups/'
|
|
12
|
+
rsync.keep = 5
|
|
14
13
|
end
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
describe '#initialize' do
|
|
17
|
+
it 'should set the correct values' do
|
|
18
|
+
storage.username.should == 'my_username'
|
|
19
|
+
storage.password.should == 'my_password'
|
|
20
|
+
storage.ip.should == '123.45.678.90'
|
|
21
|
+
storage.port.should == 22
|
|
22
|
+
storage.path.should == 'backups'
|
|
23
|
+
storage.local.should == false
|
|
24
|
+
|
|
25
|
+
storage.storage_id.should be_nil
|
|
26
|
+
storage.keep.should == 5
|
|
27
|
+
end
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
rsync.
|
|
33
|
-
rsync.password = 'my_default_password'
|
|
34
|
-
rsync.path = '~/backups'
|
|
29
|
+
it 'should set a storage_id if given' do
|
|
30
|
+
rsync = Backup::Storage::RSync.new(model, 'my storage_id')
|
|
31
|
+
rsync.storage_id.should == 'my storage_id'
|
|
35
32
|
end
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
it 'should remove any preceeding tilde and slash from the path' do
|
|
35
|
+
storage = Backup::Storage::RSync.new(model) do |rsync|
|
|
36
|
+
rsync.path = '~/my_backups/path'
|
|
37
|
+
end
|
|
38
|
+
storage.path.should == 'my_backups/path'
|
|
40
39
|
end
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
context 'when setting configuration defaults' do
|
|
42
|
+
after { Backup::Configuration::Storage::RSync.clear_defaults! }
|
|
43
|
+
|
|
44
|
+
it 'should use the configured defaults' do
|
|
45
|
+
Backup::Configuration::Storage::RSync.defaults do |rsync|
|
|
46
|
+
rsync.username = 'some_username'
|
|
47
|
+
rsync.password = 'some_password'
|
|
48
|
+
rsync.ip = 'some_ip'
|
|
49
|
+
rsync.port = 'some_port'
|
|
50
|
+
rsync.path = 'some_path'
|
|
51
|
+
rsync.local = 'some_local'
|
|
52
|
+
rsync.keep = 'some_keep'
|
|
53
|
+
end
|
|
54
|
+
storage = Backup::Storage::RSync.new(model)
|
|
55
|
+
storage.username.should == 'some_username'
|
|
56
|
+
storage.password.should == 'some_password'
|
|
57
|
+
storage.ip.should == 'some_ip'
|
|
58
|
+
storage.port.should == 'some_port'
|
|
59
|
+
storage.path.should == 'some_path'
|
|
60
|
+
storage.local.should == 'some_local'
|
|
61
|
+
|
|
62
|
+
storage.storage_id.should be_nil
|
|
63
|
+
storage.keep.should == 'some_keep'
|
|
64
|
+
end
|
|
48
65
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
it 'should override the configured defaults' do
|
|
67
|
+
Backup::Configuration::Storage::RSync.defaults do |rsync|
|
|
68
|
+
rsync.username = 'old_username'
|
|
69
|
+
rsync.password = 'old_password'
|
|
70
|
+
rsync.ip = 'old_ip'
|
|
71
|
+
rsync.port = 'old_port'
|
|
72
|
+
rsync.path = 'old_path'
|
|
73
|
+
rsync.local = 'old_local'
|
|
74
|
+
rsync.keep = 'old_keep'
|
|
75
|
+
end
|
|
76
|
+
storage = Backup::Storage::RSync.new(model) do |rsync|
|
|
77
|
+
rsync.username = 'new_username'
|
|
78
|
+
rsync.password = 'new_password'
|
|
79
|
+
rsync.ip = 'new_ip'
|
|
80
|
+
rsync.port = 'new_port'
|
|
81
|
+
rsync.path = 'new_path'
|
|
82
|
+
rsync.local = 'new_local'
|
|
83
|
+
rsync.keep = 'new_keep'
|
|
84
|
+
end
|
|
56
85
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
storage.username.should == 'new_username'
|
|
87
|
+
storage.password.should == 'new_password'
|
|
88
|
+
storage.ip.should == 'new_ip'
|
|
89
|
+
storage.port.should == 'new_port'
|
|
90
|
+
storage.path.should == 'new_path'
|
|
91
|
+
storage.local.should == 'new_local'
|
|
63
92
|
|
|
64
|
-
|
|
65
|
-
|
|
93
|
+
storage.storage_id.should be_nil
|
|
94
|
+
storage.keep.should == 'new_keep'
|
|
95
|
+
end
|
|
96
|
+
end # context 'when setting configuration defaults'
|
|
97
|
+
|
|
98
|
+
end # describe '#initialize'
|
|
66
99
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
100
|
+
describe '#remote_path_for' do
|
|
101
|
+
let(:package) { mock }
|
|
102
|
+
before do
|
|
103
|
+
storage.instance_variable_set(:@package, package)
|
|
104
|
+
package.expects(:trigger).returns(model.trigger)
|
|
105
|
+
end
|
|
72
106
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
107
|
+
it 'should override superclass so the time folder is not used' do
|
|
108
|
+
storage.send(:remote_path_for, package).should ==
|
|
109
|
+
File.join('backups', 'test_trigger')
|
|
76
110
|
end
|
|
77
111
|
end
|
|
78
112
|
|
|
79
113
|
describe '#connection' do
|
|
80
|
-
|
|
81
|
-
|
|
114
|
+
let(:connection) { mock }
|
|
115
|
+
it 'should yield a Net::SSH connection' do
|
|
82
116
|
Net::SSH.expects(:start).with(
|
|
83
|
-
'123.45.678.90',
|
|
84
|
-
'my_username',
|
|
85
|
-
:password => 'my_password',
|
|
86
|
-
:port => 22
|
|
117
|
+
'123.45.678.90', 'my_username', :password => 'my_password', :port => 22
|
|
87
118
|
).yields(connection)
|
|
88
119
|
|
|
89
|
-
|
|
90
|
-
ssh.should be
|
|
120
|
+
storage.send(:connection) do |ssh|
|
|
121
|
+
ssh.should be(connection)
|
|
91
122
|
end
|
|
92
123
|
end
|
|
93
124
|
end
|
|
94
125
|
|
|
95
126
|
describe '#transfer!' do
|
|
96
|
-
let(:
|
|
97
|
-
let(:
|
|
98
|
-
let(:pwdfile) { stub(:path => 'path/to/password/file') }
|
|
127
|
+
let(:package) { mock }
|
|
128
|
+
let(:s) { sequence '' }
|
|
99
129
|
|
|
100
130
|
before do
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
131
|
+
storage.instance_variable_set(:@package, package)
|
|
132
|
+
storage.stubs(:storage_name).returns('Storage::RSync')
|
|
133
|
+
storage.stubs(:local_path).returns('/local/path')
|
|
134
|
+
storage.stubs(:rsync_options).returns(:rsync_options)
|
|
135
|
+
storage.stubs(:rsync_port).returns(:rsync_port)
|
|
136
|
+
storage.stubs(:rsync_password_file).returns(:rsync_password_file)
|
|
137
|
+
storage.expects(:utility).with(:rsync).times(0..2).returns('rsync')
|
|
106
138
|
end
|
|
107
139
|
|
|
108
|
-
context 'when
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
rsync.stubs(:write_password_file!)
|
|
112
|
-
rsync.instance_variable_set(:@password_file, pwdfile)
|
|
113
|
-
end
|
|
140
|
+
context 'when @local is set to false' do
|
|
141
|
+
it 'should transfer the package files to the remote' do
|
|
142
|
+
storage.expects(:write_password_file!).in_sequence(s)
|
|
114
143
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"rsync -z -e 'ssh -p 22' --password-file='path/to/password/file' " +
|
|
118
|
-
"'#{local_file}' " +
|
|
119
|
-
"'my_username@123.45.678.90:backups/#{remote_file}'"
|
|
120
|
-
)
|
|
144
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
145
|
+
returns('remote/path')
|
|
121
146
|
|
|
122
|
-
|
|
123
|
-
end
|
|
124
|
-
end
|
|
147
|
+
storage.expects(:create_remote_path!).in_sequence(s).with('remote/path')
|
|
125
148
|
|
|
126
|
-
|
|
127
|
-
|
|
149
|
+
storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
|
|
150
|
+
multiple_yields(
|
|
151
|
+
['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
|
|
152
|
+
['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
|
|
153
|
+
)
|
|
154
|
+
# first yield
|
|
155
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
156
|
+
"Storage::RSync started transferring " +
|
|
157
|
+
"'2011.12.31.11.00.02.backup.tar.enc-aa' to '123.45.678.90'."
|
|
158
|
+
)
|
|
159
|
+
storage.expects(:run).in_sequence(s).with(
|
|
160
|
+
"rsync rsync_options rsync_port rsync_password_file " +
|
|
161
|
+
"'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa') }' " +
|
|
162
|
+
"'my_username@123.45.678.90:#{ File.join('remote/path', 'backup.tar.enc-aa') }'"
|
|
163
|
+
)
|
|
164
|
+
# second yield
|
|
165
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
166
|
+
"Storage::RSync started transferring " +
|
|
167
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ab' to '123.45.678.90'."
|
|
168
|
+
)
|
|
169
|
+
storage.expects(:run).in_sequence(s).with(
|
|
170
|
+
"rsync rsync_options rsync_port rsync_password_file " +
|
|
171
|
+
"'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab') }' " +
|
|
172
|
+
"'my_username@123.45.678.90:#{ File.join('remote/path', 'backup.tar.enc-ab') }'"
|
|
173
|
+
)
|
|
128
174
|
|
|
129
|
-
|
|
130
|
-
rsync.expects(:run).with(
|
|
131
|
-
"rsync -z -e 'ssh -p 22' " +
|
|
132
|
-
"'#{local_file}' " +
|
|
133
|
-
"'my_username@123.45.678.90:backups/#{remote_file}'"
|
|
134
|
-
)
|
|
175
|
+
storage.expects(:remove_password_file!).in_sequence(s)
|
|
135
176
|
|
|
136
|
-
|
|
137
|
-
end
|
|
177
|
+
storage.send(:transfer!)
|
|
138
178
|
end
|
|
139
179
|
|
|
140
|
-
|
|
180
|
+
it 'should ensure password file removal' do
|
|
181
|
+
storage.expects(:write_password_file!).raises('error message')
|
|
182
|
+
storage.expects(:remove_password_file!)
|
|
183
|
+
|
|
184
|
+
expect do
|
|
185
|
+
storage.send(:transfer!)
|
|
186
|
+
end.to raise_error(RuntimeError, 'error message')
|
|
187
|
+
end
|
|
188
|
+
end # context 'when @local is set to false'
|
|
189
|
+
|
|
190
|
+
context 'when @local is set to true' do
|
|
191
|
+
before { storage.local = true }
|
|
192
|
+
|
|
193
|
+
it 'should transfer the package files locally' do
|
|
194
|
+
storage.expects(:write_password_file!).never
|
|
141
195
|
|
|
142
|
-
|
|
143
|
-
|
|
196
|
+
storage.expects(:remote_path_for).in_sequence(s).with(package).
|
|
197
|
+
returns('remote/path')
|
|
144
198
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
199
|
+
storage.expects(:create_remote_path!).in_sequence(s).with('remote/path')
|
|
200
|
+
|
|
201
|
+
storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
|
|
202
|
+
multiple_yields(
|
|
203
|
+
['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
|
|
204
|
+
['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
|
|
205
|
+
)
|
|
206
|
+
# first yield
|
|
207
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
208
|
+
"Storage::RSync started transferring " +
|
|
209
|
+
"'2011.12.31.11.00.02.backup.tar.enc-aa' to 'remote/path'."
|
|
210
|
+
)
|
|
211
|
+
storage.expects(:run).in_sequence(s).with(
|
|
212
|
+
"rsync " +
|
|
213
|
+
"'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa') }' " +
|
|
214
|
+
"'#{ File.join('remote/path', 'backup.tar.enc-aa') }'"
|
|
215
|
+
)
|
|
216
|
+
# second yield
|
|
217
|
+
Backup::Logger.expects(:message).in_sequence(s).with(
|
|
218
|
+
"Storage::RSync started transferring " +
|
|
219
|
+
"'2011.12.31.11.00.02.backup.tar.enc-ab' to 'remote/path'."
|
|
148
220
|
)
|
|
149
|
-
|
|
221
|
+
storage.expects(:run).in_sequence(s).with(
|
|
222
|
+
"rsync " +
|
|
223
|
+
"'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab') }' " +
|
|
224
|
+
"'#{ File.join('remote/path', 'backup.tar.enc-ab') }'"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
storage.expects(:remove_password_file!).never
|
|
228
|
+
|
|
229
|
+
storage.send(:transfer!)
|
|
150
230
|
end
|
|
151
|
-
end # context 'when performing a local transfer'
|
|
152
|
-
end
|
|
153
231
|
|
|
232
|
+
end # context 'when @local is set to true'
|
|
233
|
+
|
|
234
|
+
end # describe '#transfer!'
|
|
235
|
+
|
|
236
|
+
##
|
|
237
|
+
# Note: Storage::RSync doesn't cycle
|
|
154
238
|
describe '#remove!' do
|
|
155
|
-
it 'should
|
|
156
|
-
|
|
239
|
+
it 'should never even be called' do
|
|
240
|
+
storage.send(:remove!).should be_nil
|
|
157
241
|
end
|
|
158
242
|
end
|
|
159
243
|
|
|
160
|
-
describe '#
|
|
244
|
+
describe '#create_remote_path!' do
|
|
245
|
+
let(:connection) { mock }
|
|
161
246
|
|
|
162
|
-
context 'when
|
|
163
|
-
it 'should create
|
|
164
|
-
|
|
165
|
-
rsync.expects(:mkdir).never
|
|
166
|
-
rsync.expects(:connection).yields(ssh)
|
|
167
|
-
ssh.expects(:exec!).with("mkdir -p '#{rsync.remote_path}'")
|
|
247
|
+
context 'when @local is set to false' do
|
|
248
|
+
it 'should create the remote_path on the remote' do
|
|
249
|
+
FileUtils.expects(:mkdir_p).never
|
|
168
250
|
|
|
169
|
-
|
|
251
|
+
storage.expects(:connection).yields(connection)
|
|
252
|
+
connection.expects(:exec!).with("mkdir -p 'remote/path'")
|
|
253
|
+
|
|
254
|
+
storage.send(:create_remote_path!, 'remote/path')
|
|
170
255
|
end
|
|
171
256
|
end
|
|
172
257
|
|
|
173
|
-
context 'when
|
|
174
|
-
before {
|
|
175
|
-
it 'should create
|
|
176
|
-
|
|
177
|
-
|
|
258
|
+
context 'when @local is set to true' do
|
|
259
|
+
before { storage.local = true }
|
|
260
|
+
it 'should create the remote_path locally' do
|
|
261
|
+
storage.expects(:connection).never
|
|
262
|
+
|
|
263
|
+
FileUtils.expects(:mkdir_p).with('remote/path')
|
|
178
264
|
|
|
179
|
-
|
|
265
|
+
storage.send(:create_remote_path!, 'remote/path')
|
|
180
266
|
end
|
|
181
267
|
end
|
|
182
|
-
|
|
183
268
|
end
|
|
184
269
|
|
|
185
270
|
describe '#write_password_file!' do
|
|
271
|
+
let(:file) { mock }
|
|
186
272
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
273
|
+
context 'when a @password is set' do
|
|
274
|
+
it 'should write the password to file and set @password_file' do
|
|
275
|
+
Tempfile.expects(:new).with('backup-rsync-password').returns(file)
|
|
276
|
+
file.expects(:write).with('my_password')
|
|
277
|
+
file.expects(:close)
|
|
190
278
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
rsync.send(:write_password_file!)
|
|
194
|
-
password_file = rsync.instance_variable_get(:@password_file)
|
|
195
|
-
password_file.should respond_to(:path)
|
|
196
|
-
File.read(password_file.path).should == 'my_password'
|
|
279
|
+
storage.send(:write_password_file!)
|
|
280
|
+
storage.instance_variable_get(:@password_file).should be(file)
|
|
197
281
|
end
|
|
198
282
|
end
|
|
199
283
|
|
|
200
|
-
context 'when a password is not set' do
|
|
201
|
-
before {
|
|
202
|
-
it 'should
|
|
203
|
-
|
|
284
|
+
context 'when a @password is not set' do
|
|
285
|
+
before { storage.password = nil }
|
|
286
|
+
it 'should do nothing' do
|
|
287
|
+
Tempfile.expects(:new).never
|
|
288
|
+
|
|
289
|
+
storage.send(:write_password_file!)
|
|
290
|
+
storage.instance_variable_get(:@password_file).should be_nil
|
|
204
291
|
end
|
|
205
292
|
end
|
|
206
|
-
|
|
207
|
-
end # describe '#write_password_file!'
|
|
293
|
+
end
|
|
208
294
|
|
|
209
295
|
describe '#remove_password_file!' do
|
|
210
|
-
let(:
|
|
296
|
+
let(:file) { mock }
|
|
211
297
|
|
|
212
298
|
context 'when @password_file is set' do
|
|
213
|
-
before
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
pwdfile.expects(:delete)
|
|
219
|
-
rsync.send(:remove_password_file!)
|
|
299
|
+
before { storage.instance_variable_set(:@password_file, file) }
|
|
300
|
+
it 'should delete the file and clear @password_file' do
|
|
301
|
+
file.expects(:delete)
|
|
302
|
+
storage.send(:remove_password_file!)
|
|
303
|
+
storage.instance_variable_get(:@password_file).should be_nil
|
|
220
304
|
end
|
|
221
305
|
end
|
|
222
306
|
|
|
223
307
|
context 'when @password_file is not set' do
|
|
224
|
-
it 'should
|
|
225
|
-
|
|
308
|
+
it 'should do nothing' do
|
|
309
|
+
file.expects(:delete).never
|
|
310
|
+
storage.send(:remove_password_file!)
|
|
226
311
|
end
|
|
227
312
|
end
|
|
228
|
-
|
|
229
|
-
end # describe '#remove_password_file!'
|
|
313
|
+
end
|
|
230
314
|
|
|
231
315
|
describe '#rsync_password_file' do
|
|
232
|
-
let(:
|
|
316
|
+
let(:file) { mock }
|
|
233
317
|
|
|
234
318
|
context 'when @password_file is set' do
|
|
235
|
-
before
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
it 'should return the password file string for the rsync command' do
|
|
240
|
-
rsync.send(:rsync_password_file).should == "--password-file='path/to/password/file'"
|
|
319
|
+
before { storage.instance_variable_set(:@password_file, file) }
|
|
320
|
+
it 'should return the syntax for rsync to use the password file' do
|
|
321
|
+
file.expects(:path).returns('/path/to/file')
|
|
322
|
+
storage.send(:rsync_password_file).should == "--password-file='/path/to/file'"
|
|
241
323
|
end
|
|
242
324
|
end
|
|
243
325
|
|
|
244
|
-
context 'when
|
|
326
|
+
context 'when @password_file is not set' do
|
|
245
327
|
it 'should return nil' do
|
|
246
|
-
|
|
328
|
+
storage.send(:rsync_password_file).should be_nil
|
|
247
329
|
end
|
|
248
330
|
end
|
|
249
|
-
|
|
250
|
-
end # describe '#password_file'
|
|
331
|
+
end
|
|
251
332
|
|
|
252
333
|
describe '#rsync_port' do
|
|
253
|
-
it 'should return the
|
|
254
|
-
|
|
334
|
+
it 'should return the syntax for rsync to set the port' do
|
|
335
|
+
storage.send(:rsync_port).should == "-e 'ssh -p 22'"
|
|
255
336
|
end
|
|
256
337
|
end
|
|
257
338
|
|
|
258
339
|
describe '#rsync_options' do
|
|
259
|
-
it 'should return the
|
|
260
|
-
|
|
340
|
+
it 'should return the syntax for rsync to set other options' do
|
|
341
|
+
storage.send(:rsync_options).should == '-z'
|
|
261
342
|
end
|
|
262
343
|
end
|
|
263
344
|
|