backup 3.0.23 → 3.0.24

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 (197) hide show
  1. data/Gemfile.lock +42 -45
  2. data/Guardfile +7 -4
  3. data/README.md +10 -7
  4. data/backup.gemspec +2 -2
  5. data/lib/backup.rb +27 -97
  6. data/lib/backup/archive.rb +14 -6
  7. data/lib/backup/cli/helpers.rb +52 -49
  8. data/lib/backup/cli/utility.rb +9 -1
  9. data/lib/backup/compressor/base.rb +10 -4
  10. data/lib/backup/compressor/bzip2.rb +22 -26
  11. data/lib/backup/compressor/custom.rb +53 -0
  12. data/lib/backup/compressor/gzip.rb +22 -23
  13. data/lib/backup/compressor/lzma.rb +15 -13
  14. data/lib/backup/compressor/pbzip2.rb +20 -17
  15. data/lib/backup/config.rb +6 -3
  16. data/lib/backup/configuration.rb +33 -0
  17. data/lib/backup/configuration/helpers.rb +114 -28
  18. data/lib/backup/configuration/store.rb +24 -0
  19. data/lib/backup/database/base.rb +0 -6
  20. data/lib/backup/database/mongodb.rb +27 -11
  21. data/lib/backup/database/mysql.rb +19 -14
  22. data/lib/backup/database/postgresql.rb +16 -11
  23. data/lib/backup/database/redis.rb +7 -11
  24. data/lib/backup/database/riak.rb +3 -6
  25. data/lib/backup/dependency.rb +5 -11
  26. data/lib/backup/model.rb +14 -5
  27. data/lib/backup/notifier/campfire.rb +3 -16
  28. data/lib/backup/notifier/hipchat.rb +1 -7
  29. data/lib/backup/notifier/mail.rb +1 -1
  30. data/lib/backup/packager.rb +29 -19
  31. data/lib/backup/pipeline.rb +110 -0
  32. data/lib/backup/storage/dropbox.rb +4 -7
  33. data/lib/backup/syncer/base.rb +8 -4
  34. data/lib/backup/syncer/cloud/base.rb +247 -0
  35. data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
  36. data/lib/backup/syncer/cloud/s3.rb +68 -0
  37. data/lib/backup/syncer/rsync/base.rb +1 -4
  38. data/lib/backup/syncer/rsync/local.rb +9 -5
  39. data/lib/backup/syncer/rsync/pull.rb +1 -1
  40. data/lib/backup/syncer/rsync/push.rb +10 -5
  41. data/lib/backup/version.rb +1 -1
  42. data/spec-live/.gitignore +6 -0
  43. data/spec-live/README +7 -0
  44. data/spec-live/backups/config.rb +153 -0
  45. data/spec-live/backups/config.yml.template +43 -0
  46. data/spec-live/compressor/custom_spec.rb +30 -0
  47. data/spec-live/compressor/gzip_spec.rb +30 -0
  48. data/spec-live/notifier/mail_spec.rb +85 -0
  49. data/spec-live/spec_helper.rb +85 -0
  50. data/spec-live/storage/dropbox_spec.rb +151 -0
  51. data/spec-live/storage/local_spec.rb +83 -0
  52. data/spec-live/storage/scp_spec.rb +193 -0
  53. data/spec-live/syncer/cloud/s3_spec.rb +124 -0
  54. data/spec/archive_spec.rb +86 -31
  55. data/spec/cleaner_spec.rb +8 -0
  56. data/spec/cli/helpers_spec.rb +200 -75
  57. data/spec/cli/utility_spec.rb +11 -3
  58. data/spec/compressor/base_spec.rb +31 -10
  59. data/spec/compressor/bzip2_spec.rb +212 -57
  60. data/spec/compressor/custom_spec.rb +106 -0
  61. data/spec/compressor/gzip_spec.rb +212 -57
  62. data/spec/compressor/lzma_spec.rb +75 -35
  63. data/spec/compressor/pbzip2_spec.rb +93 -52
  64. data/spec/configuration/helpers_spec.rb +406 -0
  65. data/spec/configuration/store_spec.rb +39 -0
  66. data/spec/configuration_spec.rb +62 -0
  67. data/spec/database/base_spec.rb +19 -10
  68. data/spec/database/mongodb_spec.rb +195 -70
  69. data/spec/database/mysql_spec.rb +183 -64
  70. data/spec/database/postgresql_spec.rb +167 -53
  71. data/spec/database/redis_spec.rb +121 -46
  72. data/spec/database/riak_spec.rb +96 -27
  73. data/spec/dependency_spec.rb +2 -0
  74. data/spec/encryptor/base_spec.rb +10 -0
  75. data/spec/encryptor/gpg_spec.rb +29 -13
  76. data/spec/encryptor/open_ssl_spec.rb +40 -21
  77. data/spec/logger_spec.rb +4 -0
  78. data/spec/model_spec.rb +19 -2
  79. data/spec/notifier/base_spec.rb +32 -17
  80. data/spec/notifier/campfire_spec.rb +63 -45
  81. data/spec/notifier/hipchat_spec.rb +79 -56
  82. data/spec/notifier/mail_spec.rb +82 -46
  83. data/spec/notifier/prowl_spec.rb +53 -32
  84. data/spec/notifier/twitter_spec.rb +62 -41
  85. data/spec/packager_spec.rb +95 -36
  86. data/spec/pipeline_spec.rb +259 -0
  87. data/spec/spec_helper.rb +6 -5
  88. data/spec/storage/base_spec.rb +61 -41
  89. data/spec/storage/cloudfiles_spec.rb +69 -45
  90. data/spec/storage/dropbox_spec.rb +158 -36
  91. data/spec/storage/ftp_spec.rb +69 -45
  92. data/spec/storage/local_spec.rb +47 -23
  93. data/spec/storage/ninefold_spec.rb +55 -31
  94. data/spec/storage/rsync_spec.rb +67 -50
  95. data/spec/storage/s3_spec.rb +65 -41
  96. data/spec/storage/scp_spec.rb +65 -41
  97. data/spec/storage/sftp_spec.rb +65 -41
  98. data/spec/syncer/base_spec.rb +91 -4
  99. data/spec/syncer/cloud/base_spec.rb +511 -0
  100. data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
  101. data/spec/syncer/cloud/s3_spec.rb +174 -0
  102. data/spec/syncer/rsync/base_spec.rb +46 -66
  103. data/spec/syncer/rsync/local_spec.rb +55 -26
  104. data/spec/syncer/rsync/pull_spec.rb +15 -4
  105. data/spec/syncer/rsync/push_spec.rb +59 -52
  106. data/templates/cli/utility/compressor/bzip2 +1 -4
  107. data/templates/cli/utility/compressor/custom +11 -0
  108. data/templates/cli/utility/compressor/gzip +1 -4
  109. data/templates/cli/utility/compressor/lzma +3 -0
  110. data/templates/cli/utility/compressor/pbzip2 +3 -0
  111. data/templates/cli/utility/database/mysql +4 -1
  112. data/templates/cli/utility/syncer/cloud_files +17 -19
  113. data/templates/cli/utility/syncer/s3 +18 -20
  114. metadata +38 -92
  115. data/lib/backup/configuration/base.rb +0 -15
  116. data/lib/backup/configuration/compressor/base.rb +0 -9
  117. data/lib/backup/configuration/compressor/bzip2.rb +0 -23
  118. data/lib/backup/configuration/compressor/gzip.rb +0 -23
  119. data/lib/backup/configuration/compressor/lzma.rb +0 -23
  120. data/lib/backup/configuration/compressor/pbzip2.rb +0 -28
  121. data/lib/backup/configuration/database/base.rb +0 -19
  122. data/lib/backup/configuration/database/mongodb.rb +0 -49
  123. data/lib/backup/configuration/database/mysql.rb +0 -42
  124. data/lib/backup/configuration/database/postgresql.rb +0 -41
  125. data/lib/backup/configuration/database/redis.rb +0 -39
  126. data/lib/backup/configuration/database/riak.rb +0 -29
  127. data/lib/backup/configuration/encryptor/base.rb +0 -9
  128. data/lib/backup/configuration/encryptor/gpg.rb +0 -17
  129. data/lib/backup/configuration/encryptor/open_ssl.rb +0 -32
  130. data/lib/backup/configuration/notifier/base.rb +0 -28
  131. data/lib/backup/configuration/notifier/campfire.rb +0 -25
  132. data/lib/backup/configuration/notifier/hipchat.rb +0 -41
  133. data/lib/backup/configuration/notifier/mail.rb +0 -112
  134. data/lib/backup/configuration/notifier/presently.rb +0 -25
  135. data/lib/backup/configuration/notifier/prowl.rb +0 -23
  136. data/lib/backup/configuration/notifier/twitter.rb +0 -21
  137. data/lib/backup/configuration/storage/base.rb +0 -18
  138. data/lib/backup/configuration/storage/cloudfiles.rb +0 -25
  139. data/lib/backup/configuration/storage/dropbox.rb +0 -58
  140. data/lib/backup/configuration/storage/ftp.rb +0 -29
  141. data/lib/backup/configuration/storage/local.rb +0 -17
  142. data/lib/backup/configuration/storage/ninefold.rb +0 -20
  143. data/lib/backup/configuration/storage/rsync.rb +0 -29
  144. data/lib/backup/configuration/storage/s3.rb +0 -25
  145. data/lib/backup/configuration/storage/scp.rb +0 -25
  146. data/lib/backup/configuration/storage/sftp.rb +0 -25
  147. data/lib/backup/configuration/syncer/base.rb +0 -10
  148. data/lib/backup/configuration/syncer/cloud.rb +0 -23
  149. data/lib/backup/configuration/syncer/cloud_files.rb +0 -30
  150. data/lib/backup/configuration/syncer/rsync/base.rb +0 -28
  151. data/lib/backup/configuration/syncer/rsync/local.rb +0 -11
  152. data/lib/backup/configuration/syncer/rsync/pull.rb +0 -11
  153. data/lib/backup/configuration/syncer/rsync/push.rb +0 -31
  154. data/lib/backup/configuration/syncer/s3.rb +0 -23
  155. data/lib/backup/notifier/presently.rb +0 -88
  156. data/lib/backup/syncer/cloud.rb +0 -187
  157. data/lib/backup/syncer/cloud_files.rb +0 -56
  158. data/lib/backup/syncer/s3.rb +0 -47
  159. data/spec/configuration/base_spec.rb +0 -35
  160. data/spec/configuration/compressor/bzip2_spec.rb +0 -29
  161. data/spec/configuration/compressor/gzip_spec.rb +0 -29
  162. data/spec/configuration/compressor/lzma_spec.rb +0 -29
  163. data/spec/configuration/compressor/pbzip2_spec.rb +0 -32
  164. data/spec/configuration/database/base_spec.rb +0 -17
  165. data/spec/configuration/database/mongodb_spec.rb +0 -56
  166. data/spec/configuration/database/mysql_spec.rb +0 -53
  167. data/spec/configuration/database/postgresql_spec.rb +0 -53
  168. data/spec/configuration/database/redis_spec.rb +0 -50
  169. data/spec/configuration/database/riak_spec.rb +0 -35
  170. data/spec/configuration/encryptor/gpg_spec.rb +0 -26
  171. data/spec/configuration/encryptor/open_ssl_spec.rb +0 -35
  172. data/spec/configuration/notifier/base_spec.rb +0 -32
  173. data/spec/configuration/notifier/campfire_spec.rb +0 -32
  174. data/spec/configuration/notifier/hipchat_spec.rb +0 -44
  175. data/spec/configuration/notifier/mail_spec.rb +0 -71
  176. data/spec/configuration/notifier/presently_spec.rb +0 -35
  177. data/spec/configuration/notifier/prowl_spec.rb +0 -29
  178. data/spec/configuration/notifier/twitter_spec.rb +0 -35
  179. data/spec/configuration/storage/cloudfiles_spec.rb +0 -41
  180. data/spec/configuration/storage/dropbox_spec.rb +0 -38
  181. data/spec/configuration/storage/ftp_spec.rb +0 -44
  182. data/spec/configuration/storage/local_spec.rb +0 -29
  183. data/spec/configuration/storage/ninefold_spec.rb +0 -32
  184. data/spec/configuration/storage/rsync_spec.rb +0 -41
  185. data/spec/configuration/storage/s3_spec.rb +0 -38
  186. data/spec/configuration/storage/scp_spec.rb +0 -41
  187. data/spec/configuration/storage/sftp_spec.rb +0 -41
  188. data/spec/configuration/syncer/cloud_files_spec.rb +0 -44
  189. data/spec/configuration/syncer/rsync/base_spec.rb +0 -33
  190. data/spec/configuration/syncer/rsync/local_spec.rb +0 -10
  191. data/spec/configuration/syncer/rsync/pull_spec.rb +0 -10
  192. data/spec/configuration/syncer/rsync/push_spec.rb +0 -43
  193. data/spec/configuration/syncer/s3_spec.rb +0 -38
  194. data/spec/notifier/presently_spec.rb +0 -181
  195. data/spec/syncer/cloud_files_spec.rb +0 -192
  196. data/spec/syncer/s3_spec.rb +0 -192
  197. data/templates/cli/utility/notifier/presently +0 -13
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+
3
+ ## # Use Bundler
4
+ require 'rubygems' if RUBY_VERSION < '1.9'
5
+ require 'bundler/setup'
6
+
7
+ ##
8
+ # Load Backup
9
+ require 'backup'
10
+
11
+ module Backup
12
+ module SpecLive
13
+ PATH = File.expand_path('..', __FILE__)
14
+ # to archive local backups, etc...
15
+ TMP_PATH = PATH + '/tmp'
16
+ SYNC_PATH = PATH + '/sync'
17
+
18
+ config = PATH + '/backups/config.yml'
19
+ if File.exist?(config)
20
+ CONFIG = YAML.load_file(config)
21
+ else
22
+ puts "The 'spec-live/backups/config.yml' file is required."
23
+ puts "Use 'spec-live/backups/config.yml.template' to create one"
24
+ exit!
25
+ end
26
+
27
+ module ExampleHelpers
28
+
29
+ def h_set_trigger(trigger)
30
+ Backup::Logger.clear!
31
+ Backup::Model.all.clear
32
+ Backup::Config.load_config!
33
+ FileUtils.mkdir_p(File.join(Backup::Config.data_path, trigger))
34
+ Backup::Model.find(trigger)
35
+ end
36
+
37
+ def h_clean_data_paths!
38
+ paths = [:data_path, :log_path, :tmp_path ].map do |name|
39
+ Backup::Config.send(name)
40
+ end + [Backup::SpecLive::TMP_PATH]
41
+ paths.each do |path|
42
+ h_safety_check(path)
43
+ FileUtils.rm_rf(path)
44
+ FileUtils.mkdir_p(path)
45
+ end
46
+ end
47
+
48
+ def h_safety_check(path)
49
+ # Rule #1: Do No Harm.
50
+ unless (
51
+ path.start_with?(Backup::SpecLive::PATH) &&
52
+ Backup::SpecLive::PATH.end_with?('spec-live')
53
+ ) || path.include?('spec_live_test_dir')
54
+ warn "\nSafety Check Failed:\nPath: #{path}\n\n" +
55
+ caller(1).join("\n")
56
+ exit!
57
+ end
58
+ end
59
+
60
+ end # ExampleHelpers
61
+ end
62
+
63
+ Config.update(:root_path => SpecLive::PATH + '/backups')
64
+
65
+ Logger.quiet = true unless ENV['VERBOSE']
66
+ end
67
+
68
+ ##
69
+ # Use Mocha to mock with RSpec
70
+ require 'rspec'
71
+ RSpec.configure do |config|
72
+ config.mock_with :mocha
73
+ config.include Backup::SpecLive::ExampleHelpers
74
+ config.before(:each) do
75
+ h_clean_data_paths!
76
+ if ENV['VERBOSE']
77
+ /spec-live\/(.*):/ =~ self.example.metadata[:example_group][:block].inspect
78
+ puts "\n\nSPEC: #{$1}"
79
+ puts "DESC: #{self.example.metadata[:full_description]}"
80
+ puts '-' * 78
81
+ end
82
+ end
83
+ end
84
+
85
+ puts "\n\nRuby version: #{RUBY_DESCRIPTION}\n\n"
@@ -0,0 +1,151 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe 'Storage::Dropbox',
6
+ :if => Backup::SpecLive::CONFIG['storage']['dropbox']['specs_enabled'] do
7
+ let(:trigger) { 'archive_dropbox' }
8
+
9
+ def remote_files_for(storage, package)
10
+ remote_path = storage.send(:remote_path_for, package)
11
+
12
+ files = []
13
+ storage.send(:transferred_files_for, package) do |local_file, remote_file|
14
+ files << File.join(remote_path, remote_file)
15
+ end
16
+ files
17
+ end
18
+
19
+ def check_remote_for(storage, package, expectation = true)
20
+ remote_path = storage.send(:remote_path_for, package)
21
+
22
+ # search the remote_path folder for the trigger (base file name)
23
+ metadata = storage.send(:connection).search(
24
+ remote_path, package.trigger
25
+ )
26
+ files_found = metadata.map {|entry| File.basename(entry['path']) }
27
+
28
+ files = remote_files_for(storage, package).map {|file| File.basename(file) }
29
+
30
+ if expectation
31
+ files_found.sort.should == files.sort
32
+ else
33
+ files_found.should be_empty
34
+ end
35
+ end
36
+
37
+ def clean_remote!(storage, package)
38
+ storage.send(:remove!, package)
39
+ end
40
+
41
+ it 'should store the archive on the remote', :init => true do
42
+ model = h_set_trigger(trigger)
43
+
44
+ model.perform!
45
+
46
+ storage = model.storages.first
47
+ package = model.package
48
+ files = remote_files_for(storage, package)
49
+ files.count.should == 1
50
+
51
+ check_remote_for(storage, package)
52
+
53
+ clean_remote!(storage, package)
54
+ end
55
+
56
+ describe 'Storage::Dropbox Cycling' do
57
+ context 'when archives exceed `keep` setting' do
58
+ it 'should remove the oldest archive' do
59
+ packages = []
60
+
61
+ model = h_set_trigger(trigger)
62
+ storage = model.storages.first
63
+ model.perform!
64
+ package = model.package
65
+ package.filenames.count.should == 1
66
+ packages << package
67
+ sleep 1
68
+
69
+ check_remote_for(storage, packages[0])
70
+
71
+ model = h_set_trigger(trigger)
72
+ storage = model.storages.first
73
+ model.perform!
74
+ package = model.package
75
+ package.filenames.count.should == 1
76
+ packages << package
77
+ sleep 1
78
+
79
+ check_remote_for(storage, packages[1])
80
+
81
+ model = h_set_trigger(trigger)
82
+ storage = model.storages.first
83
+ model.perform!
84
+ package = model.package
85
+ package.filenames.count.should == 1
86
+ packages << package
87
+
88
+ check_remote_for(storage, packages[2])
89
+ clean_remote!(storage, packages[2])
90
+
91
+ check_remote_for(storage, packages[1])
92
+ clean_remote!(storage, packages[1])
93
+
94
+ check_remote_for(storage, packages[0], false)
95
+ end
96
+ end
97
+
98
+ context 'when an archive to be removed does not exist' do
99
+ it 'should log a warning and continue' do
100
+ packages = []
101
+
102
+ model = h_set_trigger(trigger)
103
+ storage = model.storages.first
104
+ model.perform!
105
+ package = model.package
106
+ package.filenames.count.should == 1
107
+ packages << package
108
+ sleep 1
109
+
110
+ check_remote_for(storage, packages[0])
111
+
112
+ model = h_set_trigger(trigger)
113
+ storage = model.storages.first
114
+ model.perform!
115
+ package = model.package
116
+ package.filenames.count.should == 1
117
+ packages << package
118
+
119
+ check_remote_for(storage, packages[1])
120
+
121
+ # remove archive directory cycle! will attempt to remove
122
+ clean_remote!(storage, packages[0])
123
+
124
+ check_remote_for(storage, packages[0], false)
125
+
126
+ check_remote_for(storage, packages[1])
127
+
128
+
129
+ model = h_set_trigger(trigger)
130
+ storage = model.storages.first
131
+ expect do
132
+ model.perform!
133
+ end.not_to raise_error
134
+
135
+ Backup::Logger.has_warnings?.should be_true
136
+
137
+ package = model.package
138
+ package.filenames.count.should == 1
139
+ packages << package
140
+
141
+ check_remote_for(storage, packages[1])
142
+ clean_remote!(storage, packages[1])
143
+
144
+ check_remote_for(storage, packages[2])
145
+ clean_remote!(storage, packages[2])
146
+ end
147
+ end
148
+
149
+ end # describe 'Storage::SCP Cycling'
150
+
151
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe 'Storage::Local' do
6
+ let(:trigger) { 'archive_local' }
7
+
8
+ def archive_file_for(model)
9
+ File.join(
10
+ Backup::SpecLive::TMP_PATH,
11
+ "#{model.trigger}", model.time, "#{model.trigger}.tar"
12
+ )
13
+ end
14
+
15
+ it 'should store a local archive' do
16
+ model = h_set_trigger(trigger)
17
+ model.perform!
18
+ File.exist?(archive_file_for(model)).should be_true
19
+ end
20
+
21
+ describe 'Storage::Local Cycling' do
22
+
23
+ context 'when archives exceed `keep` setting' do
24
+ it 'should remove the oldest archive' do
25
+ archives = []
26
+
27
+ model = h_set_trigger(trigger)
28
+ model.perform!
29
+ archives << archive_file_for(model)
30
+ sleep 1
31
+
32
+ model = h_set_trigger(trigger)
33
+ model.perform!
34
+ archives << archive_file_for(model)
35
+ sleep 1
36
+
37
+ model = h_set_trigger(trigger)
38
+ model.perform!
39
+ archives << archive_file_for(model)
40
+
41
+ File.exist?(archives[0]).should be_false
42
+ File.exist?(archives[1]).should be_true
43
+ File.exist?(archives[2]).should be_true
44
+ end
45
+ end
46
+
47
+ context 'when an archive to be removed does not exist' do
48
+ it 'should log a warning and continue' do
49
+ archives = []
50
+
51
+ model = h_set_trigger(trigger)
52
+ model.perform!
53
+ archives << archive_file_for(model)
54
+ sleep 1
55
+
56
+ model = h_set_trigger(trigger)
57
+ model.perform!
58
+ archives << archive_file_for(model)
59
+ sleep 1
60
+
61
+ File.exist?(archives[0]).should be_true
62
+ File.exist?(archives[1]).should be_true
63
+ # remove archive directory cycle! will attempt to remove
64
+ dir = archives[0].split('/')[0...-1].join('/')
65
+ h_safety_check(dir)
66
+ FileUtils.rm_r(dir)
67
+ File.exist?(archives[0]).should be_false
68
+
69
+ expect do
70
+ model = h_set_trigger(trigger)
71
+ model.perform!
72
+ archives << archive_file_for(model)
73
+ end.not_to raise_error
74
+
75
+ Backup::Logger.has_warnings?.should be_true
76
+
77
+ File.exist?(archives[1]).should be_true
78
+ File.exist?(archives[2]).should be_true
79
+ end
80
+ end
81
+
82
+ end # describe 'Storage::Local Cycling'
83
+ end
@@ -0,0 +1,193 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe 'Storage::SCP',
6
+ :if => Backup::SpecLive::CONFIG['storage']['scp']['specs_enabled'] do
7
+ let(:trigger) { 'archive_scp' }
8
+
9
+ def remote_files_for(storage, package)
10
+ remote_path = storage.send(:remote_path_for, package)
11
+
12
+ files = []
13
+ storage.send(:transferred_files_for, package) do |local_file, remote_file|
14
+ files << File.join(remote_path, remote_file)
15
+ end
16
+ files
17
+ end
18
+
19
+ def check_remote_for(storage, files)
20
+ if (storage.username == Backup::Config.user) &&
21
+ (storage.ip == 'localhost')
22
+ files.each do |file|
23
+ if !File.exist?(file)
24
+ return false
25
+ end
26
+ end
27
+ true
28
+ else
29
+ errors = []
30
+ storage.send(:connection) do |ssh|
31
+ files.each do |file|
32
+ ssh.exec!("ls '#{file}'") do |ch, stream, data|
33
+ errors << data if stream == :stderr
34
+ end
35
+ end
36
+ end
37
+ errors.empty?
38
+ end
39
+ end
40
+
41
+ def clean_remote!(storage, package)
42
+ return if (storage.username == Backup::Config.user) &&
43
+ (storage.ip == 'localhost') &&
44
+ (storage.path == Backup::SpecLive::TMP_PATH)
45
+
46
+ remote_path = storage.send(:remote_path_for, package)
47
+ h_safety_check(remote_path)
48
+ storage.send(:connection) do |ssh|
49
+ ssh.exec!("rm -r '#{remote_path}'")
50
+ end
51
+ end
52
+
53
+ it 'should store the archive on the remote' do
54
+ model = h_set_trigger(trigger)
55
+
56
+ model.perform!
57
+
58
+ storage = model.storages.first
59
+ package = model.package
60
+ files = remote_files_for(storage, package)
61
+ files.count.should == 1
62
+
63
+ check_remote_for(storage, files).should be_true
64
+
65
+ clean_remote!(storage, package)
66
+ end
67
+
68
+ describe 'Storage::SCP Cycling' do
69
+ context 'when archives exceed `keep` setting' do
70
+ it 'should remove the oldest archive' do
71
+ packages = []
72
+
73
+ model = h_set_trigger(trigger)
74
+ storage = model.storages.first
75
+ model.perform!
76
+ package = model.package
77
+ package.filenames.count.should == 1
78
+ packages << package
79
+ sleep 1
80
+
81
+ check_remote_for(
82
+ storage, remote_files_for(storage, packages[0])
83
+ ).should be_true
84
+
85
+ model = h_set_trigger(trigger)
86
+ storage = model.storages.first
87
+ model.perform!
88
+ package = model.package
89
+ package.filenames.count.should == 1
90
+ packages << package
91
+ sleep 1
92
+
93
+ check_remote_for(
94
+ storage, remote_files_for(storage, packages[1])
95
+ ).should be_true
96
+
97
+ model = h_set_trigger(trigger)
98
+ storage = model.storages.first
99
+ model.perform!
100
+ package = model.package
101
+ package.filenames.count.should == 1
102
+ packages << package
103
+
104
+ check_remote_for(
105
+ storage, remote_files_for(storage, packages[2])
106
+ ).should be_true
107
+ clean_remote!(storage, packages[2])
108
+
109
+ check_remote_for(
110
+ storage, remote_files_for(storage, packages[1])
111
+ ).should be_true
112
+ clean_remote!(storage, packages[1])
113
+
114
+ check_remote_for(
115
+ storage, remote_files_for(storage, packages[0])
116
+ ).should be_false
117
+ end
118
+ end
119
+
120
+ context 'when an archive to be removed does not exist' do
121
+ it 'should log a warning and continue' do
122
+ packages = []
123
+
124
+ model = h_set_trigger(trigger)
125
+ storage = model.storages.first
126
+ model.perform!
127
+ package = model.package
128
+ package.filenames.count.should == 1
129
+ packages << package
130
+ sleep 1
131
+
132
+ check_remote_for(
133
+ storage, remote_files_for(storage, packages[0])
134
+ ).should be_true
135
+
136
+ model = h_set_trigger(trigger)
137
+ storage = model.storages.first
138
+ model.perform!
139
+ package = model.package
140
+ package.filenames.count.should == 1
141
+ packages << package
142
+
143
+ check_remote_for(
144
+ storage, remote_files_for(storage, packages[1])
145
+ ).should be_true
146
+
147
+ # remove archive directory cycle! will attempt to remove
148
+
149
+ if (storage.username == Backup::Config.user) &&
150
+ (storage.ip == 'localhost')
151
+ remote_path = storage.send(:remote_path_for, packages[0])
152
+ h_safety_check(remote_path)
153
+ FileUtils.rm_r(remote_path)
154
+ else
155
+ clean_remote!(storage, packages[0])
156
+ end
157
+
158
+ check_remote_for(
159
+ storage, remote_files_for(storage, packages[0])
160
+ ).should be_false
161
+
162
+ check_remote_for(
163
+ storage, remote_files_for(storage, packages[1])
164
+ ).should be_true
165
+
166
+
167
+ model = h_set_trigger(trigger)
168
+ storage = model.storages.first
169
+ expect do
170
+ model.perform!
171
+ end.not_to raise_error
172
+
173
+ Backup::Logger.has_warnings?.should be_true
174
+
175
+ package = model.package
176
+ package.filenames.count.should == 1
177
+ packages << package
178
+
179
+ check_remote_for(
180
+ storage, remote_files_for(storage, packages[1])
181
+ ).should be_true
182
+ clean_remote!(storage, packages[1])
183
+
184
+ check_remote_for(
185
+ storage, remote_files_for(storage, packages[2])
186
+ ).should be_true
187
+ clean_remote!(storage, packages[2])
188
+ end
189
+ end
190
+
191
+ end # describe 'Storage::SCP Cycling'
192
+
193
+ end