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.
Files changed (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. 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(:ninefold) do
8
- Backup::Storage::Ninefold.new do |nf|
9
- nf.storage_token = 'my_storage_token'
10
- nf.storage_secret = 'my_storage_secret'
11
- nf.path = 'backups'
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
- before do
17
- Backup::Configuration::Storage::Ninefold.clear_defaults!
18
- end
19
-
20
- it 'should have defined the configuration properly' do
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
- it 'should use the defaults if a particular attribute has not been defined' do
27
- Backup::Configuration::Storage::Ninefold.defaults do |nf|
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
- ninefold = Backup::Storage::Ninefold.new do |nf|
33
- nf.path = 'my/backups'
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
- ninefold.storage_token.should == 'my_storage_token' # not defined, uses default
37
- ninefold.storage_secret.should == nil # not defined, no default
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
- describe '#provider' do
43
- it 'should be Ninefold' do
44
- ninefold.provider.should == 'Ninefold'
45
- end
46
- end
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 '#perform' do
49
- it 'should invoke transfer! and cycle!' do
50
- ninefold.expects(:transfer!)
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
- it 'should establish and re-use a connection to Ninefold' do
58
- Fog::Storage.expects(:new).once.with({
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 => 'my_storage_token',
61
- :ninefold_storage_secret => 'my_storage_secret'
62
- }).returns(true)
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
- ninefold.send(:connection)
65
- ninefold.send(:connection)
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 '#transfer!' do
70
- let(:connection) { mock('Fog::Storage') }
71
- let(:directories) { mock('Fog::Storage::Ninefold::Directories') }
72
- let(:directory) { mock('Fog::Storage::Ninefold::Directory') }
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
- Fog::Storage.expects(:new).once.returns(connection)
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 already exists' do
82
- it 'should transfer the provided file to the directory' do
83
- Backup::Model.new('blah', 'blah') {}
84
- file = mock("Backup::Storage::Ninefold::File")
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 yet exist' do
98
- it 'should transfer the provided file to the directory' do
99
- Backup::Model.new('blah', 'blah') {}
100
- file = mock("Backup::Storage::Ninefold::File")
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
- files.expects(:create) do |options|
109
- options[:key].should == "#{ Backup::TRIGGER }.tar"
110
- options[:body].should == file
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
- ninefold.send(:transfer!)
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 '#remove!' do
119
- let(:connection) { mock('Fog::Storage') }
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
- Fog::Storage.expects(:new).once.returns(connection)
127
- connection.stubs(:directories).returns(directories)
128
- directory.stubs(:files).returns(files)
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 the file from the bucket' do
132
- directories.expects(:get).
133
- with("backups/myapp/#{ Backup::TIME }").
134
- returns(directory)
135
- files.expects(:get).
136
- with("#{ Backup::TRIGGER }.tar").
137
- returns(file)
138
- file.expects(:destroy)
139
- directory.expects(:destroy)
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
- ninefold.send(:remove!)
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 raise an error if remote_path does not exist' do
145
- directories.expects(:get).
146
- with("backups/myapp/#{ Backup::TIME }").
147
- returns(nil)
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
- expect do
153
- ninefold.send(:remove!)
154
- end.to raise_error(
155
- Backup::Errors::Storage::Ninefold::NotFoundError,
156
- "Storage::Ninefold::NotFoundError: " +
157
- "Directory at 'backups/myapp/#{Backup::TIME}' not found"
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
- it 'should raise an error if remote_file does not exist' do
163
- directories.expects(:get).
164
- with("backups/myapp/#{ Backup::TIME }").
165
- returns(directory)
166
- files.expects(:get).
167
- with("#{ Backup::TRIGGER }.tar").
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
- expect do
173
- ninefold.send(:remove!)
174
- end.to raise_error(
175
- Backup::Errors::Storage::Ninefold::NotFoundError,
176
- "Storage::Ninefold::NotFoundError: " +
177
- "'#{Backup::TRIGGER}.tar' not found in 'backups/myapp/#{Backup::TIME}'"
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
- end
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
@@ -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(:rsync) do
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.port = 22
13
- rsync.path = '~/backups/'
12
+ rsync.keep = 5
14
13
  end
15
14
  end
16
15
 
17
- before do
18
- Backup::Configuration::Storage::RSync.clear_defaults!
19
- end
20
-
21
- it 'should have defined the configuration properly' do
22
- rsync.username.should == 'my_username'
23
- rsync.password.should == 'my_password'
24
- rsync.ip.should == '123.45.678.90'
25
- rsync.port.should == 22
26
- rsync.path.should == 'backups/'
27
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
28
- end
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
- it 'should use the defaults if a particular attribute has not been defined' do
31
- Backup::Configuration::Storage::RSync.defaults do |rsync|
32
- rsync.username = 'my_default_username'
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
- rsync = Backup::Storage::RSync.new do |rsync|
38
- rsync.password = 'my_password'
39
- rsync.ip = '123.45.678.90'
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
- rsync.username.should == 'my_default_username'
43
- rsync.password.should == 'my_password'
44
- rsync.ip.should == '123.45.678.90'
45
- rsync.port.should == 22
46
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
47
- end
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
- it 'should have its own defaults' do
50
- rsync = Backup::Storage::RSync.new
51
- rsync.port.should == 22
52
- rsync.path.should == 'backups'
53
- rsync.local.should == false
54
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
55
- end
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
- describe '#perform' do
58
- it 'should invoke transfer!' do
59
- s = sequence ''
60
- rsync.expects(:write_password_file!).in_sequence(s)
61
- rsync.expects(:transfer!).in_sequence(s)
62
- rsync.expects(:remove_password_file!).in_sequence(s)
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
- rsync.perform!
65
- end
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
- it 'should ensure any password file is removed' do
68
- s = sequence ''
69
- rsync.expects(:write_password_file!).in_sequence(s)
70
- rsync.expects(:transfer!).in_sequence(s).raises(Exception)
71
- rsync.expects(:remove_password_file!).in_sequence(s)
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
- expect do
74
- rsync.perform!
75
- end.to raise_error
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
- it 'should establish a connection to the remote server' do
81
- connection = mock
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
- rsync.send(:connection) do |ssh|
90
- ssh.should be connection
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(:local_file) { File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER }.tar") }
97
- let(:remote_file) { "#{ Backup::TRIGGER }/#{ Backup::TRIGGER }.tar" }
98
- let(:pwdfile) { stub(:path => 'path/to/password/file') }
127
+ let(:package) { mock }
128
+ let(:s) { sequence '' }
99
129
 
100
130
  before do
101
- rsync.expects(:create_remote_directories!)
102
- rsync.expects(:utility).returns('rsync')
103
- Backup::Logger.expects(:message).with(
104
- "Storage::RSync started transferring '#{rsync.filename}' to '#{rsync.ip}'."
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 performing a remote transfer' do
109
- context 'when a password is set' do
110
- before do
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
- it 'should transfer the provided file to the path' do
116
- rsync.expects(:run).with(
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
- rsync.send(:transfer!)
123
- end
124
- end
147
+ storage.expects(:create_remote_path!).in_sequence(s).with('remote/path')
125
148
 
126
- context 'when no password is set' do
127
- before { rsync.password = nil }
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
- it 'should not provide the --password-file option' do
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
- rsync.send(:transfer!)
137
- end
177
+ storage.send(:transfer!)
138
178
  end
139
179
 
140
- end # context 'when performing a remote transfer'
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
- context 'when performing a local transfer' do
143
- before { rsync.local = true }
196
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
197
+ returns('remote/path')
144
198
 
145
- it 'should save a local copy of backups' do
146
- rsync.expects(:run).with(
147
- "rsync '#{local_file}' 'backups/#{remote_file}'"
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
- rsync.send(:transfer!)
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 return nil' do
156
- rsync.send(:remove!).should == nil
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 '#create_remote_directories!' do
244
+ describe '#create_remote_path!' do
245
+ let(:connection) { mock }
161
246
 
162
- context 'when rsync.local is false' do
163
- it 'should create directories on the remote server' do
164
- ssh = mock
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
- rsync.send(:create_remote_directories!)
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 rsync.local is true' do
174
- before { rsync.local = true }
175
- it 'should create directories locally' do
176
- rsync.expects(:mkdir).with(rsync.remote_path)
177
- rsync.expects(:connection).never
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
- rsync.send(:create_remote_directories!)
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
- before do
188
- rsync.instance_variable_defined?(:@password_file).should be_false
189
- end
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
- context 'when a password is set' do
192
- it 'should write the password file' do
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 { rsync.password = nil }
202
- it 'should return nil' do
203
- rsync.send(:write_password_file!).should be_nil
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(:pwdfile) { mock }
296
+ let(:file) { mock }
211
297
 
212
298
  context 'when @password_file is set' do
213
- before do
214
- rsync.instance_variable_set(:@password_file, pwdfile)
215
- end
216
-
217
- it 'should remove the password file' do
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 return nil' do
225
- rsync.send(:remove_password_file!).should be_nil
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(:pwdfile) { stub(:path => 'path/to/password/file') }
316
+ let(:file) { mock }
233
317
 
234
318
  context 'when @password_file is set' do
235
- before do
236
- rsync.instance_variable_set(:@password_file, pwdfile)
237
- end
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 a password is not set' do
326
+ context 'when @password_file is not set' do
245
327
  it 'should return nil' do
246
- rsync.send(:rsync_password_file).should be_nil
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 port string for the rsync command' do
254
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
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 options string for the rsync command' do
260
- rsync.send(:rsync_options).should == "-z"
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