backup 3.0.19 → 3.0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +9 -8
  3. data/Gemfile.lock +19 -1
  4. data/Guardfile +13 -9
  5. data/README.md +93 -31
  6. data/backup.gemspec +3 -3
  7. data/bin/backup +6 -283
  8. data/lib/backup.rb +101 -72
  9. data/lib/backup/archive.rb +21 -9
  10. data/lib/backup/binder.rb +22 -0
  11. data/lib/backup/cleaner.rb +36 -0
  12. data/lib/backup/cli/helpers.rb +103 -0
  13. data/lib/backup/cli/utility.rb +308 -0
  14. data/lib/backup/compressor/base.rb +2 -2
  15. data/lib/backup/compressor/pbzip2.rb +76 -0
  16. data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
  17. data/lib/backup/configuration/database/riak.rb +25 -0
  18. data/lib/backup/configuration/encryptor/open_ssl.rb +6 -0
  19. data/lib/backup/configuration/helpers.rb +5 -18
  20. data/lib/backup/configuration/notifier/base.rb +13 -0
  21. data/lib/backup/configuration/notifier/hipchat.rb +41 -0
  22. data/lib/backup/configuration/notifier/mail.rb +38 -0
  23. data/lib/backup/configuration/notifier/prowl.rb +23 -0
  24. data/lib/backup/configuration/storage/cloudfiles.rb +4 -0
  25. data/lib/backup/configuration/storage/dropbox.rb +8 -4
  26. data/lib/backup/database/base.rb +10 -2
  27. data/lib/backup/database/mongodb.rb +16 -19
  28. data/lib/backup/database/mysql.rb +2 -2
  29. data/lib/backup/database/postgresql.rb +2 -2
  30. data/lib/backup/database/redis.rb +15 -7
  31. data/lib/backup/database/riak.rb +45 -0
  32. data/lib/backup/dependency.rb +21 -7
  33. data/lib/backup/encryptor/base.rb +1 -1
  34. data/lib/backup/encryptor/open_ssl.rb +20 -5
  35. data/lib/backup/errors.rb +124 -0
  36. data/lib/backup/finder.rb +11 -3
  37. data/lib/backup/logger.rb +121 -82
  38. data/lib/backup/model.rb +103 -44
  39. data/lib/backup/notifier/base.rb +50 -0
  40. data/lib/backup/notifier/campfire.rb +32 -52
  41. data/lib/backup/notifier/hipchat.rb +99 -0
  42. data/lib/backup/notifier/mail.rb +100 -61
  43. data/lib/backup/notifier/presently.rb +31 -40
  44. data/lib/backup/notifier/prowl.rb +73 -0
  45. data/lib/backup/notifier/twitter.rb +29 -39
  46. data/lib/backup/packager.rb +25 -0
  47. data/lib/backup/splitter.rb +62 -0
  48. data/lib/backup/storage/base.rb +178 -18
  49. data/lib/backup/storage/cloudfiles.rb +34 -28
  50. data/lib/backup/storage/dropbox.rb +64 -67
  51. data/lib/backup/storage/ftp.rb +48 -40
  52. data/lib/backup/storage/local.rb +33 -28
  53. data/lib/backup/storage/ninefold.rb +40 -26
  54. data/lib/backup/storage/object.rb +8 -6
  55. data/lib/backup/storage/rsync.rb +61 -51
  56. data/lib/backup/storage/s3.rb +29 -27
  57. data/lib/backup/storage/scp.rb +56 -36
  58. data/lib/backup/storage/sftp.rb +49 -33
  59. data/lib/backup/syncer/base.rb +1 -1
  60. data/lib/backup/syncer/rsync.rb +1 -1
  61. data/lib/backup/template.rb +46 -0
  62. data/lib/backup/version.rb +1 -1
  63. data/spec/archive_spec.rb +34 -9
  64. data/spec/backup_spec.rb +1 -1
  65. data/spec/cli/helpers_spec.rb +35 -0
  66. data/spec/cli/utility_spec.rb +38 -0
  67. data/spec/compressor/bzip2_spec.rb +1 -1
  68. data/spec/compressor/gzip_spec.rb +1 -1
  69. data/spec/compressor/lzma_spec.rb +1 -1
  70. data/spec/compressor/pbzip2_spec.rb +63 -0
  71. data/spec/configuration/base_spec.rb +1 -1
  72. data/spec/configuration/compressor/bzip2_spec.rb +1 -1
  73. data/spec/configuration/compressor/gzip_spec.rb +1 -1
  74. data/spec/configuration/compressor/lzma_spec.rb +1 -1
  75. data/spec/configuration/database/base_spec.rb +1 -1
  76. data/spec/configuration/database/mongodb_spec.rb +1 -1
  77. data/spec/configuration/database/mysql_spec.rb +1 -1
  78. data/spec/configuration/database/postgresql_spec.rb +1 -1
  79. data/spec/configuration/database/redis_spec.rb +1 -1
  80. data/spec/configuration/database/riak_spec.rb +31 -0
  81. data/spec/configuration/encryptor/gpg_spec.rb +1 -1
  82. data/spec/configuration/encryptor/open_ssl_spec.rb +4 -1
  83. data/spec/configuration/notifier/campfire_spec.rb +1 -1
  84. data/spec/configuration/notifier/hipchat_spec.rb +43 -0
  85. data/spec/configuration/notifier/mail_spec.rb +34 -22
  86. data/spec/configuration/notifier/presently_spec.rb +1 -1
  87. data/spec/configuration/notifier/prowl_spec.rb +28 -0
  88. data/spec/configuration/notifier/twitter_spec.rb +1 -1
  89. data/spec/configuration/storage/cloudfiles_spec.rb +19 -16
  90. data/spec/configuration/storage/dropbox_spec.rb +1 -1
  91. data/spec/configuration/storage/ftp_spec.rb +1 -1
  92. data/spec/configuration/storage/local_spec.rb +1 -1
  93. data/spec/configuration/storage/ninefold_spec.rb +1 -1
  94. data/spec/configuration/storage/rsync_spec.rb +1 -1
  95. data/spec/configuration/storage/s3_spec.rb +1 -1
  96. data/spec/configuration/storage/scp_spec.rb +1 -1
  97. data/spec/configuration/storage/sftp_spec.rb +1 -1
  98. data/spec/configuration/syncer/rsync_spec.rb +1 -1
  99. data/spec/configuration/syncer/s3_spec.rb +1 -1
  100. data/spec/database/base_spec.rb +10 -1
  101. data/spec/database/mongodb_spec.rb +34 -7
  102. data/spec/database/mysql_spec.rb +8 -7
  103. data/spec/database/postgresql_spec.rb +8 -7
  104. data/spec/database/redis_spec.rb +39 -9
  105. data/spec/database/riak_spec.rb +50 -0
  106. data/spec/encryptor/gpg_spec.rb +1 -1
  107. data/spec/encryptor/open_ssl_spec.rb +77 -20
  108. data/spec/errors_spec.rb +306 -0
  109. data/spec/finder_spec.rb +91 -0
  110. data/spec/logger_spec.rb +254 -33
  111. data/spec/model_spec.rb +120 -15
  112. data/spec/notifier/campfire_spec.rb +127 -52
  113. data/spec/notifier/hipchat_spec.rb +193 -0
  114. data/spec/notifier/mail_spec.rb +290 -74
  115. data/spec/notifier/presently_spec.rb +290 -73
  116. data/spec/notifier/prowl_spec.rb +149 -0
  117. data/spec/notifier/twitter_spec.rb +106 -41
  118. data/spec/spec_helper.rb +8 -2
  119. data/spec/splitter_spec.rb +71 -0
  120. data/spec/storage/base_spec.rb +280 -19
  121. data/spec/storage/cloudfiles_spec.rb +38 -22
  122. data/spec/storage/dropbox_spec.rb +17 -13
  123. data/spec/storage/ftp_spec.rb +145 -55
  124. data/spec/storage/local_spec.rb +6 -6
  125. data/spec/storage/ninefold_spec.rb +70 -29
  126. data/spec/storage/object_spec.rb +44 -44
  127. data/spec/storage/rsync_spec.rb +186 -63
  128. data/spec/storage/s3_spec.rb +23 -24
  129. data/spec/storage/scp_spec.rb +116 -41
  130. data/spec/storage/sftp_spec.rb +124 -46
  131. data/spec/syncer/rsync_spec.rb +3 -3
  132. data/spec/syncer/s3_spec.rb +1 -1
  133. data/spec/version_spec.rb +1 -1
  134. data/templates/cli/utility/archive +13 -0
  135. data/{lib/templates → templates/cli/utility}/compressor/bzip2 +1 -1
  136. data/{lib/templates → templates/cli/utility}/compressor/gzip +1 -1
  137. data/{lib/templates → templates/cli/utility}/compressor/lzma +0 -0
  138. data/templates/cli/utility/compressor/pbzip2 +7 -0
  139. data/templates/cli/utility/config +31 -0
  140. data/{lib/templates → templates/cli/utility}/database/mongodb +1 -1
  141. data/{lib/templates → templates/cli/utility}/database/mysql +1 -1
  142. data/{lib/templates → templates/cli/utility}/database/postgresql +1 -1
  143. data/{lib/templates → templates/cli/utility}/database/redis +1 -1
  144. data/templates/cli/utility/database/riak +8 -0
  145. data/{lib/templates → templates/cli/utility}/encryptor/gpg +1 -1
  146. data/templates/cli/utility/encryptor/openssl +9 -0
  147. data/templates/cli/utility/model.erb +23 -0
  148. data/{lib/templates → templates/cli/utility}/notifier/campfire +2 -1
  149. data/templates/cli/utility/notifier/hipchat +15 -0
  150. data/{lib/templates → templates/cli/utility}/notifier/mail +6 -1
  151. data/{lib/templates → templates/cli/utility}/notifier/presently +1 -0
  152. data/templates/cli/utility/notifier/prowl +11 -0
  153. data/{lib/templates → templates/cli/utility}/notifier/twitter +2 -1
  154. data/templates/cli/utility/splitter +7 -0
  155. data/templates/cli/utility/storage/cloudfiles +12 -0
  156. data/{lib/templates → templates/cli/utility}/storage/dropbox +1 -1
  157. data/{lib/templates → templates/cli/utility}/storage/ftp +0 -0
  158. data/templates/cli/utility/storage/local +7 -0
  159. data/{lib/templates → templates/cli/utility}/storage/ninefold +1 -1
  160. data/templates/cli/utility/storage/rsync +11 -0
  161. data/{lib/templates → templates/cli/utility}/storage/s3 +0 -2
  162. data/templates/cli/utility/storage/scp +11 -0
  163. data/templates/cli/utility/storage/sftp +11 -0
  164. data/{lib/templates → templates/cli/utility}/syncer/rsync +1 -1
  165. data/{lib/templates → templates/cli/utility}/syncer/s3 +1 -1
  166. data/templates/general/links +11 -0
  167. data/templates/general/version.erb +2 -0
  168. data/templates/notifier/mail/failure.erb +9 -0
  169. data/templates/notifier/mail/success.erb +7 -0
  170. data/templates/notifier/mail/warning.erb +9 -0
  171. data/templates/storage/dropbox/authorization_url.erb +6 -0
  172. data/templates/storage/dropbox/authorized.erb +4 -0
  173. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  174. metadata +81 -45
  175. data/lib/backup/cli.rb +0 -110
  176. data/lib/backup/exception/command_failed.rb +0 -8
  177. data/lib/backup/exception/command_not_found.rb +0 -8
  178. data/lib/backup/notifier/binder.rb +0 -32
  179. data/lib/backup/notifier/templates/notify_failure.erb +0 -33
  180. data/lib/backup/notifier/templates/notify_success.erb +0 -16
  181. data/lib/templates/archive +0 -7
  182. data/lib/templates/encryptor/openssl +0 -8
  183. data/lib/templates/readme +0 -15
  184. data/lib/templates/storage/cloudfiles +0 -11
  185. data/lib/templates/storage/local +0 -7
  186. data/lib/templates/storage/rsync +0 -11
  187. data/lib/templates/storage/scp +0 -11
  188. data/lib/templates/storage/sftp +0 -11
@@ -20,27 +20,10 @@ module Backup
20
20
  # Region of the specified S3 bucket
21
21
  attr_accessor :region
22
22
 
23
- ##
24
- # Creates a new instance of the Amazon S3 storage object
25
- # First it sets the defaults (if any exist) and then evaluates
26
- # the configuration block which may overwrite these defaults
27
- #
28
- # Currently available regions:
29
- # eu-west-1, us-east-1, ap-southeast-1, us-west-1
30
- def initialize(&block)
31
- load_defaults!
32
-
33
- @path ||= 'backups'
34
-
35
- instance_eval(&block) if block_given?
36
-
37
- @time = TIME
38
- end
39
-
40
23
  ##
41
24
  # This is the remote path to where the backup files will be stored
42
25
  def remote_path
43
- File.join(path, TRIGGER).sub(/^\//, '')
26
+ File.join(path, TRIGGER, @time).sub(/^\//, '')
44
27
  end
45
28
 
46
29
  ##
@@ -52,12 +35,28 @@ module Backup
52
35
  ##
53
36
  # Performs the backup transfer
54
37
  def perform!
38
+ super
55
39
  transfer!
56
40
  cycle!
57
41
  end
58
42
 
59
43
  private
60
44
 
45
+ ##
46
+ # Set configuration defaults before evaluating configuration block,
47
+ # after setting defaults from Storage::Base
48
+ def pre_configure
49
+ super
50
+ @path ||= 'backups'
51
+ end
52
+
53
+ ##
54
+ # Adjust configuration after evaluating configuration block,
55
+ # after adjustments from Storage::Base
56
+ def post_configure
57
+ super
58
+ end
59
+
61
60
  ##
62
61
  # Establishes a connection to Amazon S3 and returns the Fog object.
63
62
  # Not doing any instance variable caching because this object gets persisted in YAML
@@ -65,7 +64,7 @@ module Backup
65
64
  # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
66
65
  # background anyway so even if it were a bit slower it shouldn't matter.
67
66
  def connection
68
- Fog::Storage.new(
67
+ @connection ||= Fog::Storage.new(
69
68
  :provider => provider,
70
69
  :aws_access_key_id => access_key_id,
71
70
  :aws_secret_access_key => secret_access_key,
@@ -76,26 +75,29 @@ module Backup
76
75
  ##
77
76
  # Transfers the archived file to the specified Amazon S3 bucket
78
77
  def transfer!
79
- begin
80
- Logger.message("#{ self.class } started transferring \"#{ remote_file }\" to bucket \"#{ bucket }\"")
81
- connection.sync_clock
78
+ connection.sync_clock
79
+ files_to_transfer do |local_file, remote_file|
80
+ Logger.message "#{storage_name} started transferring " +
81
+ "'#{ local_file }' to bucket '#{ bucket }'"
82
+
82
83
  connection.put_object(
83
84
  bucket,
84
85
  File.join(remote_path, remote_file),
85
86
  File.open(File.join(local_path, local_file))
86
87
  )
87
- rescue Excon::Errors::NotFound
88
- raise "An error occurred while trying to transfer the backup, please make sure the bucket exists."
89
88
  end
90
89
  end
91
90
 
92
91
  ##
93
92
  # Removes the transferred archive file from the Amazon S3 bucket
94
93
  def remove!
95
- begin
96
- connection.sync_clock
94
+ connection.sync_clock
95
+ transferred_files do |local_file, remote_file|
96
+ Logger.message "#{storage_name} started removing " +
97
+ "'#{ local_file }' from bucket '#{ bucket }'"
98
+
97
99
  connection.delete_object(bucket, File.join(remote_path, remote_file))
98
- rescue Excon::Errors::SocketError; end
100
+ end
99
101
  end
100
102
 
101
103
  end
@@ -23,31 +23,16 @@ module Backup
23
23
  # Path to store backups to
24
24
  attr_accessor :path
25
25
 
26
- ##
27
- # Creates a new instance of the SCP storage object
28
- # First it sets the defaults (if any exist) and then evaluates
29
- # the configuration block which may overwrite these defaults
30
- def initialize(&block)
31
- load_defaults!
32
-
33
- @port ||= 22
34
- @path ||= 'backups'
35
-
36
- instance_eval(&block) if block_given?
37
-
38
- @time = TIME
39
- @path = path.sub(/^\~\//, '')
40
- end
41
-
42
26
  ##
43
27
  # This is the remote path to where the backup files will be stored
44
28
  def remote_path
45
- File.join(path, TRIGGER)
29
+ File.join(path, TRIGGER, @time)
46
30
  end
47
31
 
48
32
  ##
49
33
  # Performs the backup transfer
50
34
  def perform!
35
+ super
51
36
  transfer!
52
37
  cycle!
53
38
  end
@@ -55,34 +40,69 @@ module Backup
55
40
  private
56
41
 
57
42
  ##
58
- # Establishes a connection to the remote server and returns the Net::SSH object.
59
- # Not doing any instance variable caching because this object gets persisted in YAML
60
- # format to a file and will issues. This, however has no impact on performance since it only
61
- # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
62
- # background anyway so even if it were a bit slower it shouldn't matter.
63
- #
64
- # We will be using Net::SSH, and use Net::SCP through Net::SSH to transfer backups
43
+ # Set configuration defaults before evaluating configuration block,
44
+ # after setting defaults from Storage::Base
45
+ def pre_configure
46
+ super
47
+ @port ||= 22
48
+ @path ||= 'backups'
49
+ end
50
+
51
+ ##
52
+ # Adjust configuration after evaluating configuration block,
53
+ # after adjustments from Storage::Base
54
+ def post_configure
55
+ super
56
+ @path = path.sub(/^\~\//, '')
57
+ end
58
+
59
+ ##
60
+ # Establishes a connection to the remote server
61
+ # and yields the Net::SSH connection.
62
+ # Net::SCP will use this connection to transfer backups
65
63
  def connection
66
- Net::SSH.start(ip, username, :password => password, :port => port)
64
+ Net::SSH.start(
65
+ ip, username, :password => password, :port => port
66
+ ) {|ssh| yield ssh }
67
67
  end
68
68
 
69
69
  ##
70
70
  # Transfers the archived file to the specified remote server
71
71
  def transfer!
72
- Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
73
- create_remote_directories!
74
- connection.scp.upload!(
75
- File.join(local_path, local_file),
76
- File.join(remote_path, remote_file)
77
- )
72
+ connection do |ssh|
73
+ create_remote_directories(ssh)
74
+
75
+ files_to_transfer do |local_file, remote_file|
76
+ Logger.message "#{storage_name} started transferring " +
77
+ "'#{local_file}' to '#{ip}'."
78
+
79
+ ssh.scp.upload!(
80
+ File.join(local_path, local_file),
81
+ File.join(remote_path, remote_file)
82
+ )
83
+ end
84
+ end
78
85
  end
79
86
 
80
87
  ##
81
88
  # Removes the transferred archive file from the server
82
89
  def remove!
83
- response = connection.exec!("rm #{ File.join(remote_path, remote_file) }")
84
- if response =~ /No such file or directory/
85
- Logger.warn "Could not remove file \"#{ File.join(remote_path, remote_file) }\"."
90
+ messages = []
91
+ transferred_files do |local_file, remote_file|
92
+ messages << "#{storage_name} started removing '#{local_file}' from '#{ip}'."
93
+ end
94
+ Logger.message messages.join("\n")
95
+
96
+ errors = []
97
+ connection do |ssh|
98
+ ssh.exec!("rm -r '#{remote_path}'") do |ch, stream, data|
99
+ errors << data if stream == :stderr
100
+ end
101
+ end
102
+ unless errors.empty?
103
+ raise Errors::Storage::SCP::SSHError,
104
+ "Net::SSH reported the following errors:\n" +
105
+ errors.join("\n"), caller(1)
86
106
  end
87
107
  end
88
108
 
@@ -93,11 +113,11 @@ module Backup
93
113
  # Instead, we split the parts up in to an array (for each '/') and loop through
94
114
  # that to create the directories one by one. Net::SCP raises an exception when
95
115
  # the directory it's trying ot create already exists, so we have rescue it
96
- def create_remote_directories!
116
+ def create_remote_directories(ssh)
97
117
  path_parts = Array.new
98
118
  remote_path.split('/').each do |path_part|
99
119
  path_parts << path_part
100
- connection.exec!("mkdir '#{ path_parts.join('/') }'")
120
+ ssh.exec!("mkdir '#{path_parts.join('/')}'")
101
121
  end
102
122
  end
103
123
 
@@ -20,37 +20,39 @@ module Backup
20
20
  # Path to store backups to
21
21
  attr_accessor :path
22
22
 
23
- ##
24
- # Creates a new instance of the SFTP storage object
25
- # First it sets the defaults (if any exist) and then evaluates
26
- # the configuration block which may overwrite these defaults
27
- def initialize(&block)
28
- load_defaults!
29
-
30
- @port ||= 22
31
- @path ||= 'backups'
32
-
33
- instance_eval(&block) if block_given?
34
-
35
- @time = TIME
36
- @path = path.sub(/^\~\//, '')
37
- end
38
-
39
23
  ##
40
24
  # This is the remote path to where the backup files will be stored
41
25
  def remote_path
42
- File.join(path, TRIGGER)
26
+ File.join(path, TRIGGER, @time)
43
27
  end
44
28
 
45
29
  ##
46
30
  # Performs the backup transfer
47
31
  def perform!
32
+ super
48
33
  transfer!
49
34
  cycle!
50
35
  end
51
36
 
52
37
  private
53
38
 
39
+ ##
40
+ # Set configuration defaults before evaluating configuration block,
41
+ # after setting defaults from Storage::Base
42
+ def pre_configure
43
+ super
44
+ @port ||= 22
45
+ @path ||= 'backups'
46
+ end
47
+
48
+ ##
49
+ # Adjust configuration after evaluating configuration block,
50
+ # after adjustments from Storage::Base
51
+ def post_configure
52
+ super
53
+ @path = path.sub(/^\~\//, '')
54
+ end
55
+
54
56
  ##
55
57
  # Establishes a connection to the remote server and returns the Net::SFTP object.
56
58
  # Not doing any instance variable caching because this object gets persisted in YAML
@@ -58,29 +60,43 @@ module Backup
58
60
  # gets invoked once per object for a #transfer! and once for a remove! Backups run in the
59
61
  # background anyway so even if it were a bit slower it shouldn't matter.
60
62
  def connection
61
- Net::SFTP.start(ip, username, :password => password, :port => port)
63
+ Net::SFTP.start(
64
+ ip, username,
65
+ :password => password,
66
+ :port => port
67
+ ) {|sftp| yield sftp }
62
68
  end
63
69
 
64
70
  ##
65
71
  # Transfers the archived file to the specified remote server
66
72
  def transfer!
67
- Logger.message("#{ self.class } started transferring \"#{ remote_file }\".")
68
- create_remote_directories!
69
- connection.upload!(
70
- File.join(local_path, local_file),
71
- File.join(remote_path, remote_file)
72
- )
73
+ connection do |sftp|
74
+ create_remote_directories(sftp)
75
+
76
+ files_to_transfer do |local_file, remote_file|
77
+ Logger.message "#{storage_name} started transferring " +
78
+ "'#{ local_file }' to '#{ ip }'."
79
+
80
+ sftp.upload!(
81
+ File.join(local_path, local_file),
82
+ File.join(remote_path, remote_file)
83
+ )
84
+ end
85
+ end
73
86
  end
74
87
 
75
88
  ##
76
89
  # Removes the transferred archive file from the server
77
90
  def remove!
78
- begin
79
- connection.remove!(
80
- File.join(remote_path, remote_file)
81
- )
82
- rescue Net::SFTP::StatusException
83
- Logger.warn "Could not remove file \"#{ File.join(remote_path, remote_file) }\"."
91
+ connection do |sftp|
92
+ transferred_files do |local_file, remote_file|
93
+ Logger.message "#{storage_name} started removing " +
94
+ "'#{ local_file }' from '#{ ip }'."
95
+
96
+ sftp.remove!(File.join(remote_path, remote_file))
97
+ end
98
+
99
+ sftp.rmdir!(remote_path)
84
100
  end
85
101
  end
86
102
 
@@ -90,13 +106,13 @@ module Backup
90
106
  # paths to directories that don't yet exist when creating new directories.
91
107
  # Instead, we split the parts up in to an array (for each '/') and loop through
92
108
  # that to create the directories one by one. Net::SFTP raises an exception when
93
- # the directory it's trying ot create already exists, so we have rescue it
94
- def create_remote_directories!
109
+ # the directory it's trying to create already exists, so we have rescue it
110
+ def create_remote_directories(sftp)
95
111
  path_parts = Array.new
96
112
  remote_path.split('/').each do |path_part|
97
113
  path_parts << path_part
98
114
  begin
99
- connection.mkdir!(path_parts.join('/'))
115
+ sftp.mkdir!(path_parts.join('/'))
100
116
  rescue Net::SFTP::StatusException; end
101
117
  end
102
118
  end
@@ -3,7 +3,7 @@
3
3
  module Backup
4
4
  module Syncer
5
5
  class Base
6
- include Backup::CLI
6
+ include Backup::CLI::Helpers
7
7
  include Backup::Configuration::Helpers
8
8
  end
9
9
  end
@@ -67,7 +67,7 @@ module Backup
67
67
  def perform!
68
68
  Logger.message("#{ self.class } started syncing #{ directories }.")
69
69
  Logger.silent(
70
- run("#{ utility(:rsync) } -vhP #{ options } #{ directories } '#{ username }@#{ ip }:#{ path }'")
70
+ run("#{ utility(:rsync) } #{ options } #{ directories } '#{ username }@#{ ip }:#{ path }'")
71
71
  )
72
72
 
73
73
  remove_password_file!
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ module Backup
6
+ class Template
7
+
8
+ # Holds a binding object. Nil if not provided.
9
+ attr_accessor :binding
10
+
11
+ ##
12
+ # Creates a new instance of the Backup::Template class
13
+ # and optionally takes an argument that can be either a binding object, a Hash or nil
14
+ def initialize(object = nil)
15
+ if object.is_a?(Binding)
16
+ @binding = object
17
+ elsif object.is_a?(Hash)
18
+ @binding = Backup::Binder.new(object).get_binding
19
+ else
20
+ @binding = nil
21
+ end
22
+ end
23
+
24
+ ##
25
+ # Renders the provided file (in the context of the binding if any) to the console
26
+ def render(file)
27
+ puts result(file)
28
+ end
29
+
30
+ ##
31
+ # Returns a String object containing the contents of the file (in the context of the binding if any)
32
+ def result(file)
33
+ ERB.new(file_contents(file), nil, '<>').result(binding)
34
+ end
35
+
36
+ private
37
+
38
+ ##
39
+ # Reads and returns the contents of the provided file path,
40
+ # relative from the Backup::TEMPLATE_PATH
41
+ def file_contents(file)
42
+ File.read(File.join(Backup::TEMPLATE_PATH, file))
43
+ end
44
+
45
+ end
46
+ end
@@ -13,7 +13,7 @@ module Backup
13
13
  # Defines the minor version
14
14
  # PATCH:
15
15
  # Defines the patch version
16
- MAJOR, MINOR, PATCH = 3, 0, 19
16
+ MAJOR, MINOR, PATCH = 3, 0, 20
17
17
 
18
18
  ##
19
19
  # Returns the major version ( big release based off of multiple minor releases )
data/spec/archive_spec.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  # encoding: utf-8
2
2
 
3
- require File.dirname(__FILE__) + '/spec_helper'
3
+ require File.expand_path('../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Archive do
6
6
 
7
7
  let(:archive) do
8
8
  Backup::Archive.new(:dummy_archive) do |a|
9
9
  a.add '/home/rspecuser/somefile'
10
- a.add '/home/rspecuser/logs/'
11
- a.add '/home/rspecuser/dotfiles/'
10
+ a.add '/home/rspecuser/logs'
11
+ a.add '/home/rspecuser/dotfiles'
12
12
  a.exclude '/home/rspecuser/badfile'
13
- a.exclude '/home/rspecuser/wrongdir/'
13
+ a.exclude '/home/rspecuser/wrongdir'
14
14
  end
15
15
  end
16
16
 
@@ -39,7 +39,7 @@ describe Backup::Archive do
39
39
  describe '#paths_to_package' do
40
40
  it 'should return a tar -c friendly string' do
41
41
  archive.send(:paths_to_package).should ==
42
- "'/home/rspecuser/somefile' '/home/rspecuser/logs/' '/home/rspecuser/dotfiles/'"
42
+ "'/home/rspecuser/somefile' '/home/rspecuser/logs' '/home/rspecuser/dotfiles'"
43
43
  end
44
44
  end
45
45
 
@@ -51,7 +51,7 @@ describe Backup::Archive do
51
51
 
52
52
  it 'should return a tar -c friendly string' do
53
53
  archive.send(:paths_to_exclude).should ==
54
- "--exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir/'"
54
+ "--exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir'"
55
55
  end
56
56
  end
57
57
 
@@ -63,7 +63,10 @@ describe Backup::Archive do
63
63
  context 'when both paths were added and paths that should be excluded were added' do
64
64
  it 'should render both the syntax for the paths that be included as well as excluded' do
65
65
  archive.expects(:mkdir).with(File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive'))
66
- archive.expects(:run).with("tar -c -f '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' --exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir/' '/home/rspecuser/somefile' '/home/rspecuser/logs/' '/home/rspecuser/dotfiles/' 2> /dev/null")
66
+ archive.expects(:run).with(
67
+ "tar -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' --exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir' '/home/rspecuser/somefile' '/home/rspecuser/logs' '/home/rspecuser/dotfiles'",
68
+ :ignore_exit_codes => [1]
69
+ )
67
70
  archive.expects(:utility).with(:tar).returns(:tar)
68
71
  archive.perform!
69
72
  end
@@ -76,13 +79,35 @@ describe Backup::Archive do
76
79
  end
77
80
 
78
81
  archive.stubs(:utility).returns(:tar)
79
- archive.expects(:run).with("tar -c -f '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' '/path/to/archive' 2> /dev/null")
82
+ archive.expects(:run).with(
83
+ "tar -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' '/path/to/archive'",
84
+ :ignore_exit_codes => [1]
85
+ )
80
86
  archive.perform!
81
87
  end
82
88
  end
83
89
 
90
+ context 'when tar_options are given' do
91
+ it 'should add the options to the tar command' do
92
+ archive = Backup::Archive.new(:dummy_archive) do |a|
93
+ a.add '/path/to/archive'
94
+ a.tar_options '-h --xattrs'
95
+ end
96
+
97
+ archive.stubs(:utility).returns(:tar)
98
+ archive.expects(:run).with(
99
+ "tar -h --xattrs -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' '/path/to/archive'",
100
+ :ignore_exit_codes => [1]
101
+ )
102
+ archive.perform!
103
+ end
104
+ end
84
105
  it 'should log the status' do
85
- Backup::Logger.expects(:message).with("Backup::Archive started packaging and archiving \"/home/rspecuser/somefile\", \"/home/rspecuser/logs/\", \"/home/rspecuser/dotfiles/\".")
106
+ Backup::Logger.expects(:message).
107
+ with("Backup::Archive started packaging and archiving:\n" +
108
+ " /home/rspecuser/somefile\n" +
109
+ " /home/rspecuser/logs\n" +
110
+ " /home/rspecuser/dotfiles")
86
111
  archive.perform!
87
112
  end
88
113
  end