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
@@ -25,47 +25,30 @@ module Backup
25
25
  attr_accessor :passive_mode
26
26
 
27
27
  ##
28
- # This is the remote path to where the backup files will be stored
29
- def remote_path
30
- File.join(path, TRIGGER, @time)
31
- end
32
-
33
- ##
34
- # Performs the backup transfer
35
- def perform!
36
- super
37
- transfer!
38
- cycle!
39
- end
40
-
41
- private
28
+ # Creates a new instance of the storage object
29
+ def initialize(model, storage_id = nil, &block)
30
+ super(model, storage_id)
42
31
 
43
- ##
44
- # Set configuration defaults before evaluating configuration block,
45
- # after setting defaults from Storage::Base
46
- def pre_configure
47
- super
48
32
  @port ||= 21
49
33
  @path ||= 'backups'
50
34
  @passive_mode ||= false
51
- end
52
35
 
53
- ##
54
- # Adjust configuration after evaluating configuration block,
55
- # after adjustments from Storage::Base
56
- def post_configure
57
- super
36
+ instance_eval(&block) if block_given?
37
+
58
38
  @path = path.sub(/^\~\//, '')
59
39
  end
60
40
 
41
+ private
42
+
61
43
  ##
62
- # Establishes a connection to the remote server and returns the Net::FTP object.
44
+ # Establishes a connection to the remote server
63
45
  #
64
- # Note *
65
- # Since the FTP port is defined as a constant in the Net::FTP class, and might be required
66
- # to change by the user, we dynamically remove and re-add the constant with the provided port value
46
+ # Note:
47
+ # Since the FTP port is defined as a constant in the Net::FTP class, and
48
+ # might be required to change by the user, we dynamically remove and
49
+ # re-add the constant with the provided port value
67
50
  def connection
68
- if defined? Net::FTP::FTP_PORT
51
+ if Net::FTP.const_defined?(:FTP_PORT)
69
52
  Net::FTP.send(:remove_const, :FTP_PORT)
70
53
  end; Net::FTP.send(:const_set, :FTP_PORT, port)
71
54
 
@@ -78,10 +61,12 @@ module Backup
78
61
  ##
79
62
  # Transfers the archived file to the specified remote server
80
63
  def transfer!
64
+ remote_path = remote_path_for(@package)
65
+
81
66
  connection do |ftp|
82
- create_remote_directories(ftp)
67
+ create_remote_path(remote_path, ftp)
83
68
 
84
- files_to_transfer do |local_file, remote_file|
69
+ files_to_transfer_for(@package) do |local_file, remote_file|
85
70
  Logger.message "#{storage_name} started transferring " +
86
71
  "'#{ local_file }' to '#{ ip }'."
87
72
  ftp.put(
@@ -93,10 +78,14 @@ module Backup
93
78
  end
94
79
 
95
80
  ##
96
- # Removes the transferred archive file from the server
97
- def remove!
81
+ # Removes the transferred archive file(s) from the storage location.
82
+ # Any error raised will be rescued during Cycling
83
+ # and a warning will be logged, containing the error message.
84
+ def remove!(package)
85
+ remote_path = remote_path_for(package)
86
+
98
87
  connection do |ftp|
99
- transferred_files do |local_file, remote_file|
88
+ transferred_files_for(package) do |local_file, remote_file|
100
89
  Logger.message "#{storage_name} started removing " +
101
90
  "'#{ local_file }' from '#{ ip }'."
102
91
 
@@ -110,11 +99,12 @@ module Backup
110
99
  ##
111
100
  # Creates (if they don't exist yet) all the directories on the remote
112
101
  # server in order to upload the backup file. Net::FTP does not support
113
- # paths to directories that don't yet exist when creating new directories.
114
- # Instead, we split the parts up in to an array (for each '/') and loop through
115
- # that to create the directories one by one. Net::FTP raises an exception when
116
- # the directory it's trying to create already exists, so we have rescue it
117
- def create_remote_directories(ftp)
102
+ # paths to directories that don't yet exist when creating new
103
+ # directories. Instead, we split the parts up in to an array (for each
104
+ # '/') and loop through that to create the directories one by one.
105
+ # Net::FTP raises an exception when the directory it's trying to create
106
+ # already exists, so we have rescue it
107
+ def create_remote_path(remote_path, ftp)
118
108
  path_parts = Array.new
119
109
  remote_path.split('/').each do |path_part|
120
110
  path_parts << path_part
@@ -1,70 +1,54 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # Load the Ruby FileUtils library
5
- require 'fileutils'
6
-
7
3
  module Backup
8
4
  module Storage
9
5
  class Local < Base
10
6
 
11
7
  ##
12
- # Path to store backups to
8
+ # Path where the backup will be stored.
13
9
  attr_accessor :path
14
10
 
15
11
  ##
16
- # This is the remote path to where the backup files will be stored.
17
- # Eventhough it says "remote", it's actually the "local" path, but
18
- # the naming is necessary for compatibility reasons
19
- def remote_path
20
- File.join(path, TRIGGER, @time)
21
- end
12
+ # Creates a new instance of the storage object
13
+ def initialize(model, storage_id = nil, &block)
14
+ super(model, storage_id)
22
15
 
23
- ##
24
- # Performs the backup transfer
25
- def perform!
26
- super
27
- transfer!
28
- cycle!
29
- end
16
+ @path ||= File.join(
17
+ File.expand_path(ENV['HOME'] || ''),
18
+ 'backups'
19
+ )
30
20
 
31
- private
21
+ instance_eval(&block) if block_given?
32
22
 
33
- ##
34
- # Set configuration defaults before evaluating configuration block,
35
- # after setting defaults from Storage::Base
36
- def pre_configure
37
- super
38
- @path ||= "#{ENV['HOME']}/backups"
23
+ @path = File.expand_path(@path)
39
24
  end
40
25
 
41
- ##
42
- # Adjust configuration after evaluating configuration block,
43
- # after adjustments from Storage::Base
44
- def post_configure
45
- super
46
- @path = File.expand_path(path)
47
- end
26
+ private
48
27
 
49
28
  ##
50
- # Transfers the archived file to the specified local path
29
+ # Transfers the archived file to the specified path
51
30
  def transfer!
52
- create_local_directories!
31
+ remote_path = remote_path_for(@package)
32
+ FileUtils.mkdir_p(remote_path)
53
33
 
54
- files_to_transfer do |local_file, remote_file|
34
+ files_to_transfer_for(@package) do |local_file, remote_file|
55
35
  Logger.message "#{storage_name} started transferring '#{ local_file }'."
56
- FileUtils.cp(
57
- File.join(local_path, local_file),
58
- File.join(remote_path, remote_file)
59
- )
36
+
37
+ src_path = File.join(local_path, local_file)
38
+ dst_path = File.join(remote_path, remote_file)
39
+ FileUtils.send(transfer_method, src_path, dst_path)
60
40
  end
61
41
  end
62
42
 
63
43
  ##
64
- # Removes the transferred archive file from the local path
65
- def remove!
44
+ # Removes the transferred archive file(s) from the storage location.
45
+ # Any error raised will be rescued during Cycling
46
+ # and a warning will be logged, containing the error message.
47
+ def remove!(package)
48
+ remote_path = remote_path_for(package)
49
+
66
50
  messages = []
67
- transferred_files do |local_file, remote_file|
51
+ transferred_files_for(package) do |local_file, remote_file|
68
52
  messages << "#{storage_name} started removing '#{ local_file }'."
69
53
  end
70
54
  Logger.message messages.join("\n")
@@ -73,9 +57,24 @@ module Backup
73
57
  end
74
58
 
75
59
  ##
76
- # Creates the path to where the backups are stored if it doesn't exist yet
77
- def create_local_directories!
78
- FileUtils.mkdir_p(remote_path)
60
+ # Set and return the transfer method.
61
+ # If this Local Storage is not the last Storage for the Model,
62
+ # force the transfer to use a *copy* operation and issue a warning.
63
+ def transfer_method
64
+ return @transfer_method if @transfer_method
65
+
66
+ if self == @model.storages.last
67
+ @transfer_method = :mv
68
+ else
69
+ Logger.warn Errors::Storage::Local::TransferError.new(<<-EOS)
70
+ Local File Copy Warning!
71
+ The final backup file(s) for '#{@model.label}' (#{@model.trigger})
72
+ will be *copied* to '#{remote_path_for(@package)}'
73
+ To avoid this, when using more than one Storage, the 'Local' Storage
74
+ should be added *last* so the files may be *moved* to their destination.
75
+ EOS
76
+ @transfer_method = :cp
77
+ end
79
78
  end
80
79
 
81
80
  end
@@ -17,48 +17,26 @@ module Backup
17
17
  attr_accessor :path
18
18
 
19
19
  ##
20
- # This is the remote path to where the backup files will be stored
21
- def remote_path
22
- File.join(path, TRIGGER, @time).sub(/^\//, '')
23
- end
20
+ # Creates a new instance of the storage object
21
+ def initialize(model, storage_id = nil, &block)
22
+ super(model, storage_id)
24
23
 
25
- ##
26
- # This is the provider that Fog uses for the Ninefold storage
27
- def provider
28
- 'Ninefold'
29
- end
24
+ @path ||= 'backups'
30
25
 
31
- ##
32
- # Performs the backup transfer
33
- def perform!
34
- super
35
- transfer!
36
- cycle!
26
+ instance_eval(&block) if block_given?
37
27
  end
38
28
 
39
- private
40
29
 
41
- ##
42
- # Set configuration defaults before evaluating configuration block,
43
- # after setting defaults from Storage::Base
44
- def pre_configure
45
- super
46
- @path ||= 'backups'
47
- end
30
+ private
48
31
 
49
32
  ##
50
- # Adjust configuration after evaluating configuration block,
51
- # after adjustments from Storage::Base
52
- def post_configure
53
- super
33
+ # This is the provider that Fog uses for the Ninefold storage
34
+ def provider
35
+ 'Ninefold'
54
36
  end
55
37
 
56
38
  ##
57
- # Establishes a connection to Amazon S3 and returns the Fog object.
58
- # Not doing any instance variable caching because this object gets persisted in YAML
59
- # format to a file and will issues. This, however has no impact on performance since it only
60
- # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
61
- # background anyway so even if it were a bit slower it shouldn't matter.
39
+ # Establishes a connection to Amazon S3
62
40
  def connection
63
41
  @connection ||= Fog::Storage.new(
64
42
  :provider => provider,
@@ -67,41 +45,69 @@ module Backup
67
45
  )
68
46
  end
69
47
 
48
+ ##
49
+ # Queries the connection for the directory for the given +remote_path+
50
+ # Returns nil if not found, or creates the directory if +create+ is true.
51
+ def directory_for(remote_path, create = false)
52
+ directory = connection.directories.get(remote_path)
53
+ if directory.nil? && create
54
+ directory = connection.directories.create(:key => remote_path)
55
+ end
56
+ directory
57
+ end
58
+
59
+ def remote_path_for(package)
60
+ super(package).sub(/^\//, '')
61
+ end
62
+
70
63
  ##
71
64
  # Transfers the archived file to the specified directory
72
65
  def transfer!
73
- files_to_transfer do |local_file, remote_file|
66
+ remote_path = remote_path_for(@package)
67
+
68
+ directory = directory_for(remote_path, true)
69
+
70
+ files_to_transfer_for(@package) do |local_file, remote_file|
74
71
  Logger.message "#{storage_name} started transferring '#{ local_file }'."
75
- directory = connection.directories.get(remote_path)
76
- directory ||= connection.directories.create(:key => remote_path)
77
- directory.files.create(
78
- :key => remote_file,
79
- :body => File.open(File.join(local_path, local_file))
80
- )
72
+
73
+ File.open(File.join(local_path, local_file), 'r') do |file|
74
+ directory.files.create(:key => remote_file, :body => file)
75
+ end
81
76
  end
82
77
  end
83
78
 
84
79
  ##
85
- # Removes the transferred archive file from the Amazon S3 bucket
86
- def remove!
87
- if directory = connection.directories.get(remote_path)
88
- transferred_files do |local_file, remote_file|
80
+ # Removes the transferred archive file(s) from the storage location.
81
+ # Any error raised will be rescued during Cycling
82
+ # and a warning will be logged, containing the error message.
83
+ def remove!(package)
84
+ remote_path = remote_path_for(package)
85
+
86
+ if directory = directory_for(remote_path)
87
+ not_found = []
88
+
89
+ transferred_files_for(package) do |local_file, remote_file|
89
90
  Logger.message "#{storage_name} started removing " +
90
- "'#{ local_file }' from Ninefold.'"
91
+ "'#{ local_file }' from Ninefold."
91
92
 
92
93
  if file = directory.files.get(remote_file)
93
94
  file.destroy
94
95
  else
95
- # Note: Fog-0.11.0 will return nil if remote_file is not found
96
- raise Errors::Storage::Ninefold::NotFoundError,
97
- "'#{remote_file}' not found in '#{remote_path}'", caller(1)
96
+ not_found << remote_file
98
97
  end
99
98
  end
99
+
100
100
  directory.destroy
101
+
102
+ unless not_found.empty?
103
+ raise Errors::Storage::Ninefold::NotFoundError, <<-EOS
104
+ The following file(s) were not found in '#{ remote_path }'
105
+ #{ not_found.join("\n") }
106
+ EOS
107
+ end
101
108
  else
102
- # Note: Fog-0.11.0 will return nil if remote_path is not found
103
109
  raise Errors::Storage::Ninefold::NotFoundError,
104
- "Directory at '#{remote_path}' not found", caller(1)
110
+ "Directory at '#{remote_path}' not found"
105
111
  end
106
112
  end
107
113
 
@@ -1,9 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
- ##
4
- # Require the tempfile Ruby library when Backup::Storage::RSync is loaded
5
- require 'tempfile'
6
-
7
3
  ##
8
4
  # Only load the Net::SSH library when the Backup::Storage::RSync class is loaded
9
5
  Backup::Dependency.load('net-ssh')
@@ -30,83 +26,79 @@ module Backup
30
26
  attr_accessor :local
31
27
 
32
28
  ##
33
- # This is the remote path to where the backup files will be stored
34
- def remote_path
35
- File.join(path, TRIGGER)
36
- end
37
-
38
- ##
39
- # Performs the backup transfer
40
- def perform!
41
- super
42
- write_password_file!
43
- transfer!
44
- ensure
45
- remove_password_file!
46
- end
47
-
48
- private
29
+ # Creates a new instance of the storage object
30
+ def initialize(model, storage_id = nil, &block)
31
+ super(model, storage_id)
49
32
 
50
- ##
51
- # Set configuration defaults before evaluating configuration block,
52
- # after setting defaults from Storage::Base
53
- def pre_configure
54
- super
55
33
  @port ||= 22
56
34
  @path ||= 'backups'
57
35
  @local ||= false
36
+
37
+ instance_eval(&block) if block_given?
38
+
39
+ @path = path.sub(/^\~\//, '')
58
40
  end
59
41
 
42
+ private
43
+
60
44
  ##
61
- # Adjust configuration after evaluating configuration block,
62
- # after adjustments from Storage::Base
63
- def post_configure
64
- super
65
- @path = path.sub(/^\~\//, '')
45
+ # This is the remote path to where the backup files will be stored
46
+ #
47
+ # Note: This overrides the superclass' method
48
+ def remote_path_for(package)
49
+ File.join(path, package.trigger)
66
50
  end
67
51
 
68
52
  ##
69
- # Establishes a connection to the remote server and returns the Net::SSH object.
53
+ # Establishes a connection to the remote server
70
54
  def connection
71
- Net::SSH.start(ip, username, :password => password, :port => port) do |ssh|
72
- yield ssh
73
- end
55
+ Net::SSH.start(
56
+ ip, username, :password => password, :port => port
57
+ ) {|ssh| yield ssh }
74
58
  end
75
59
 
76
60
  ##
77
61
  # Transfers the archived file to the specified remote server
78
62
  def transfer!
79
- create_remote_directories!
80
-
81
- Logger.message "#{storage_name} started transferring " +
82
- "'#{ filename }' to '#{ ip }'."
83
-
84
- if local
85
- run(
86
- "#{ utility(:rsync) } '#{ File.join(local_path, filename) }' " +
87
- "'#{ File.join(remote_path, filename[20..-1]) }'"
88
- )
89
- else
90
- run(
91
- "#{ utility(:rsync) } #{ rsync_options } #{ rsync_port } " +
92
- "#{ rsync_password_file } '#{ File.join(local_path, filename) }' " +
93
- "'#{ username }@#{ ip }:#{ File.join(remote_path, filename[20..-1]) }'"
94
- )
63
+ write_password_file! unless local
64
+
65
+ remote_path = remote_path_for(@package)
66
+
67
+ create_remote_path!(remote_path)
68
+
69
+ files_to_transfer_for(@package) do |local_file, remote_file|
70
+ if local
71
+ Logger.message "#{storage_name} started transferring " +
72
+ "'#{ local_file }' to '#{ remote_path }'."
73
+ run(
74
+ "#{ utility(:rsync) } '#{ File.join(local_path, local_file) }' " +
75
+ "'#{ File.join(remote_path, remote_file) }'"
76
+ )
77
+ else
78
+ Logger.message "#{storage_name} started transferring " +
79
+ "'#{ local_file }' to '#{ ip }'."
80
+ run(
81
+ "#{ utility(:rsync) } #{ rsync_options } #{ rsync_port } " +
82
+ "#{ rsync_password_file } '#{ File.join(local_path, local_file) }' " +
83
+ "'#{ username }@#{ ip }:#{ File.join(remote_path, remote_file) }'"
84
+ )
85
+ end
95
86
  end
87
+
88
+ ensure
89
+ remove_password_file! unless local
96
90
  end
97
91
 
98
92
  ##
99
- # Note: RSync::Storage doesn't cycle
100
- def remove!
101
- nil
102
- end
93
+ # Note: Storage::RSync doesn't cycle
94
+ def remove!; end
103
95
 
104
96
  ##
105
97
  # Creates (if they don't exist yet) all the directories on the remote
106
98
  # server in order to upload the backup file.
107
- def create_remote_directories!
99
+ def create_remote_path!(remote_path)
108
100
  if @local
109
- mkdir(remote_path)
101
+ FileUtils.mkdir_p(remote_path)
110
102
  else
111
103
  connection do |ssh|
112
104
  ssh.exec!("mkdir -p '#{ remote_path }'")
@@ -130,6 +122,7 @@ module Backup
130
122
  # (temporary file containing the password)
131
123
  def remove_password_file!
132
124
  @password_file.delete if @password_file
125
+ @password_file = nil
133
126
  end
134
127
 
135
128
  ##