backup-agoddard 3.0.27

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 (190) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +28 -0
  4. data/Guardfile +23 -0
  5. data/LICENSE.md +24 -0
  6. data/README.md +478 -0
  7. data/backup.gemspec +32 -0
  8. data/bin/backup +11 -0
  9. data/lib/backup.rb +133 -0
  10. data/lib/backup/archive.rb +117 -0
  11. data/lib/backup/binder.rb +22 -0
  12. data/lib/backup/cleaner.rb +121 -0
  13. data/lib/backup/cli/helpers.rb +93 -0
  14. data/lib/backup/cli/utility.rb +255 -0
  15. data/lib/backup/compressor/base.rb +35 -0
  16. data/lib/backup/compressor/bzip2.rb +50 -0
  17. data/lib/backup/compressor/custom.rb +53 -0
  18. data/lib/backup/compressor/gzip.rb +50 -0
  19. data/lib/backup/compressor/lzma.rb +52 -0
  20. data/lib/backup/compressor/pbzip2.rb +59 -0
  21. data/lib/backup/config.rb +174 -0
  22. data/lib/backup/configuration.rb +33 -0
  23. data/lib/backup/configuration/helpers.rb +130 -0
  24. data/lib/backup/configuration/store.rb +24 -0
  25. data/lib/backup/database/base.rb +53 -0
  26. data/lib/backup/database/mongodb.rb +230 -0
  27. data/lib/backup/database/mysql.rb +160 -0
  28. data/lib/backup/database/postgresql.rb +144 -0
  29. data/lib/backup/database/redis.rb +136 -0
  30. data/lib/backup/database/riak.rb +67 -0
  31. data/lib/backup/dependency.rb +108 -0
  32. data/lib/backup/encryptor/base.rb +29 -0
  33. data/lib/backup/encryptor/gpg.rb +760 -0
  34. data/lib/backup/encryptor/open_ssl.rb +72 -0
  35. data/lib/backup/errors.rb +124 -0
  36. data/lib/backup/hooks.rb +68 -0
  37. data/lib/backup/logger.rb +152 -0
  38. data/lib/backup/model.rb +409 -0
  39. data/lib/backup/notifier/base.rb +81 -0
  40. data/lib/backup/notifier/campfire.rb +155 -0
  41. data/lib/backup/notifier/hipchat.rb +93 -0
  42. data/lib/backup/notifier/mail.rb +206 -0
  43. data/lib/backup/notifier/prowl.rb +65 -0
  44. data/lib/backup/notifier/pushover.rb +88 -0
  45. data/lib/backup/notifier/twitter.rb +70 -0
  46. data/lib/backup/package.rb +47 -0
  47. data/lib/backup/packager.rb +100 -0
  48. data/lib/backup/pipeline.rb +110 -0
  49. data/lib/backup/splitter.rb +75 -0
  50. data/lib/backup/storage/base.rb +99 -0
  51. data/lib/backup/storage/cloudfiles.rb +87 -0
  52. data/lib/backup/storage/cycler.rb +117 -0
  53. data/lib/backup/storage/dropbox.rb +178 -0
  54. data/lib/backup/storage/ftp.rb +119 -0
  55. data/lib/backup/storage/local.rb +82 -0
  56. data/lib/backup/storage/ninefold.rb +116 -0
  57. data/lib/backup/storage/rsync.rb +149 -0
  58. data/lib/backup/storage/s3.rb +94 -0
  59. data/lib/backup/storage/scp.rb +99 -0
  60. data/lib/backup/storage/sftp.rb +108 -0
  61. data/lib/backup/syncer/base.rb +46 -0
  62. data/lib/backup/syncer/cloud/base.rb +247 -0
  63. data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
  64. data/lib/backup/syncer/cloud/s3.rb +68 -0
  65. data/lib/backup/syncer/rsync/base.rb +49 -0
  66. data/lib/backup/syncer/rsync/local.rb +55 -0
  67. data/lib/backup/syncer/rsync/pull.rb +36 -0
  68. data/lib/backup/syncer/rsync/push.rb +116 -0
  69. data/lib/backup/template.rb +46 -0
  70. data/lib/backup/version.rb +43 -0
  71. data/spec-live/.gitignore +6 -0
  72. data/spec-live/README +7 -0
  73. data/spec-live/backups/config.rb +83 -0
  74. data/spec-live/backups/config.yml.template +46 -0
  75. data/spec-live/backups/models.rb +184 -0
  76. data/spec-live/compressor/custom_spec.rb +30 -0
  77. data/spec-live/compressor/gzip_spec.rb +30 -0
  78. data/spec-live/encryptor/gpg_keys.rb +239 -0
  79. data/spec-live/encryptor/gpg_spec.rb +287 -0
  80. data/spec-live/notifier/mail_spec.rb +121 -0
  81. data/spec-live/spec_helper.rb +151 -0
  82. data/spec-live/storage/dropbox_spec.rb +151 -0
  83. data/spec-live/storage/local_spec.rb +83 -0
  84. data/spec-live/storage/scp_spec.rb +193 -0
  85. data/spec-live/syncer/cloud/s3_spec.rb +124 -0
  86. data/spec/archive_spec.rb +335 -0
  87. data/spec/cleaner_spec.rb +312 -0
  88. data/spec/cli/helpers_spec.rb +301 -0
  89. data/spec/cli/utility_spec.rb +411 -0
  90. data/spec/compressor/base_spec.rb +52 -0
  91. data/spec/compressor/bzip2_spec.rb +217 -0
  92. data/spec/compressor/custom_spec.rb +106 -0
  93. data/spec/compressor/gzip_spec.rb +217 -0
  94. data/spec/compressor/lzma_spec.rb +123 -0
  95. data/spec/compressor/pbzip2_spec.rb +165 -0
  96. data/spec/config_spec.rb +321 -0
  97. data/spec/configuration/helpers_spec.rb +247 -0
  98. data/spec/configuration/store_spec.rb +39 -0
  99. data/spec/configuration_spec.rb +62 -0
  100. data/spec/database/base_spec.rb +63 -0
  101. data/spec/database/mongodb_spec.rb +510 -0
  102. data/spec/database/mysql_spec.rb +411 -0
  103. data/spec/database/postgresql_spec.rb +353 -0
  104. data/spec/database/redis_spec.rb +334 -0
  105. data/spec/database/riak_spec.rb +176 -0
  106. data/spec/dependency_spec.rb +51 -0
  107. data/spec/encryptor/base_spec.rb +40 -0
  108. data/spec/encryptor/gpg_spec.rb +909 -0
  109. data/spec/encryptor/open_ssl_spec.rb +148 -0
  110. data/spec/errors_spec.rb +306 -0
  111. data/spec/hooks_spec.rb +35 -0
  112. data/spec/logger_spec.rb +367 -0
  113. data/spec/model_spec.rb +694 -0
  114. data/spec/notifier/base_spec.rb +104 -0
  115. data/spec/notifier/campfire_spec.rb +217 -0
  116. data/spec/notifier/hipchat_spec.rb +211 -0
  117. data/spec/notifier/mail_spec.rb +316 -0
  118. data/spec/notifier/prowl_spec.rb +138 -0
  119. data/spec/notifier/pushover_spec.rb +123 -0
  120. data/spec/notifier/twitter_spec.rb +153 -0
  121. data/spec/package_spec.rb +61 -0
  122. data/spec/packager_spec.rb +213 -0
  123. data/spec/pipeline_spec.rb +259 -0
  124. data/spec/spec_helper.rb +60 -0
  125. data/spec/splitter_spec.rb +120 -0
  126. data/spec/storage/base_spec.rb +166 -0
  127. data/spec/storage/cloudfiles_spec.rb +254 -0
  128. data/spec/storage/cycler_spec.rb +247 -0
  129. data/spec/storage/dropbox_spec.rb +480 -0
  130. data/spec/storage/ftp_spec.rb +271 -0
  131. data/spec/storage/local_spec.rb +259 -0
  132. data/spec/storage/ninefold_spec.rb +343 -0
  133. data/spec/storage/rsync_spec.rb +362 -0
  134. data/spec/storage/s3_spec.rb +245 -0
  135. data/spec/storage/scp_spec.rb +233 -0
  136. data/spec/storage/sftp_spec.rb +244 -0
  137. data/spec/syncer/base_spec.rb +109 -0
  138. data/spec/syncer/cloud/base_spec.rb +515 -0
  139. data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
  140. data/spec/syncer/cloud/s3_spec.rb +174 -0
  141. data/spec/syncer/rsync/base_spec.rb +98 -0
  142. data/spec/syncer/rsync/local_spec.rb +149 -0
  143. data/spec/syncer/rsync/pull_spec.rb +98 -0
  144. data/spec/syncer/rsync/push_spec.rb +333 -0
  145. data/spec/version_spec.rb +21 -0
  146. data/templates/cli/utility/archive +25 -0
  147. data/templates/cli/utility/compressor/bzip2 +4 -0
  148. data/templates/cli/utility/compressor/custom +11 -0
  149. data/templates/cli/utility/compressor/gzip +4 -0
  150. data/templates/cli/utility/compressor/lzma +10 -0
  151. data/templates/cli/utility/compressor/pbzip2 +10 -0
  152. data/templates/cli/utility/config +32 -0
  153. data/templates/cli/utility/database/mongodb +18 -0
  154. data/templates/cli/utility/database/mysql +21 -0
  155. data/templates/cli/utility/database/postgresql +17 -0
  156. data/templates/cli/utility/database/redis +16 -0
  157. data/templates/cli/utility/database/riak +11 -0
  158. data/templates/cli/utility/encryptor/gpg +27 -0
  159. data/templates/cli/utility/encryptor/openssl +9 -0
  160. data/templates/cli/utility/model.erb +23 -0
  161. data/templates/cli/utility/notifier/campfire +12 -0
  162. data/templates/cli/utility/notifier/hipchat +15 -0
  163. data/templates/cli/utility/notifier/mail +22 -0
  164. data/templates/cli/utility/notifier/prowl +11 -0
  165. data/templates/cli/utility/notifier/pushover +11 -0
  166. data/templates/cli/utility/notifier/twitter +13 -0
  167. data/templates/cli/utility/splitter +7 -0
  168. data/templates/cli/utility/storage/cloud_files +22 -0
  169. data/templates/cli/utility/storage/dropbox +20 -0
  170. data/templates/cli/utility/storage/ftp +12 -0
  171. data/templates/cli/utility/storage/local +7 -0
  172. data/templates/cli/utility/storage/ninefold +9 -0
  173. data/templates/cli/utility/storage/rsync +11 -0
  174. data/templates/cli/utility/storage/s3 +19 -0
  175. data/templates/cli/utility/storage/scp +11 -0
  176. data/templates/cli/utility/storage/sftp +11 -0
  177. data/templates/cli/utility/syncer/cloud_files +46 -0
  178. data/templates/cli/utility/syncer/rsync_local +12 -0
  179. data/templates/cli/utility/syncer/rsync_pull +17 -0
  180. data/templates/cli/utility/syncer/rsync_push +17 -0
  181. data/templates/cli/utility/syncer/s3 +43 -0
  182. data/templates/general/links +11 -0
  183. data/templates/general/version.erb +2 -0
  184. data/templates/notifier/mail/failure.erb +9 -0
  185. data/templates/notifier/mail/success.erb +7 -0
  186. data/templates/notifier/mail/warning.erb +9 -0
  187. data/templates/storage/dropbox/authorization_url.erb +6 -0
  188. data/templates/storage/dropbox/authorized.erb +4 -0
  189. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  190. metadata +277 -0
@@ -0,0 +1,149 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Syncer::RSync::Local do
6
+ let(:syncer) do
7
+ Backup::Syncer::RSync::Local.new do |rsync|
8
+ rsync.path = "~/my_backups"
9
+ rsync.mirror = true
10
+ rsync.additional_options = ['--opt-a', '--opt-b']
11
+
12
+ rsync.directories do |directory|
13
+ directory.add "/some/directory"
14
+ directory.add "~/home/directory"
15
+ end
16
+ end
17
+ end
18
+
19
+ it 'should be a subclass of Syncer::RSync::Base' do
20
+ Backup::Syncer::RSync::Local.
21
+ superclass.should == Backup::Syncer::RSync::Base
22
+ end
23
+
24
+ describe '#initialize' do
25
+ after { Backup::Syncer::RSync::Local.clear_defaults! }
26
+
27
+ it 'should load pre-configured defaults through Syncer::Base' do
28
+ Backup::Syncer::RSync::Local.any_instance.expects(:load_defaults!)
29
+ syncer
30
+ end
31
+
32
+ context 'when no pre-configured defaults have been set' do
33
+ it 'should use the values given' do
34
+ syncer.path.should == '~/my_backups'
35
+ syncer.mirror.should == true
36
+ syncer.directories.should == ["/some/directory", "~/home/directory"]
37
+ syncer.additional_options.should == ['--opt-a', '--opt-b']
38
+ end
39
+
40
+ it 'should use default values if none are given' do
41
+ syncer = Backup::Syncer::RSync::Local.new
42
+
43
+ # from Syncer::Base
44
+ syncer.path.should == 'backups'
45
+ syncer.mirror.should == false
46
+ syncer.directories.should == []
47
+
48
+ # from Syncer::RSync::Base
49
+ syncer.additional_options.should == []
50
+ end
51
+ end # context 'when no pre-configured defaults have been set'
52
+
53
+ context 'when pre-configured defaults have been set' do
54
+ before do
55
+ Backup::Syncer::RSync::Local.defaults do |rsync|
56
+ rsync.path = 'some_path'
57
+ rsync.mirror = 'some_mirror'
58
+ rsync.additional_options = 'some_additional_options'
59
+ end
60
+ end
61
+
62
+ it 'should use pre-configured defaults' do
63
+ syncer = Backup::Syncer::RSync::Local.new
64
+
65
+ syncer.path.should == 'some_path'
66
+ syncer.mirror.should == 'some_mirror'
67
+ syncer.directories.should == []
68
+ syncer.additional_options.should == 'some_additional_options'
69
+ end
70
+
71
+ it 'should override pre-configured defaults' do
72
+ syncer = Backup::Syncer::RSync::Local.new do |rsync|
73
+ rsync.path = 'new_path'
74
+ rsync.mirror = 'new_mirror'
75
+ rsync.additional_options = 'new_additional_options'
76
+ end
77
+
78
+ syncer.path.should == 'new_path'
79
+ syncer.mirror.should == 'new_mirror'
80
+ syncer.directories.should == []
81
+ syncer.additional_options.should == 'new_additional_options'
82
+ end
83
+ end # context 'when pre-configured defaults have been set'
84
+ end # describe '#initialize'
85
+
86
+ describe '#perform!' do
87
+ let(:s) { sequence '' }
88
+
89
+ before do
90
+ syncer.expects(:utility).with(:rsync).returns('rsync')
91
+ syncer.expects(:options).returns('options_output')
92
+ end
93
+
94
+ it 'should sync two directories' do
95
+ Backup::Logger.expects(:message).in_sequence(s).with(
96
+ "Syncer::RSync::Local started syncing the following directories:\n" +
97
+ " /some/directory\n" +
98
+ " ~/home/directory"
99
+ )
100
+ syncer.expects(:run).in_sequence(s).with(
101
+ "rsync options_output '/some/directory' " +
102
+ "'#{ File.expand_path('~/home/directory') }' " +
103
+ "'#{ File.expand_path('~/my_backups') }'"
104
+ )
105
+
106
+ syncer.perform!
107
+ end
108
+ end # describe '#perform!'
109
+
110
+ describe '#dest_path' do
111
+ it 'should return @path expanded' do
112
+ syncer.send(:dest_path).should == File.expand_path('~/my_backups')
113
+ end
114
+
115
+ it 'should set @dest_path' do
116
+ syncer.send(:dest_path)
117
+ syncer.instance_variable_get(:@dest_path).should ==
118
+ File.expand_path('~/my_backups')
119
+ end
120
+
121
+ it 'should return @dest_path if already set' do
122
+ syncer.instance_variable_set(:@dest_path, 'foo')
123
+ syncer.send(:dest_path).should == 'foo'
124
+ end
125
+ end
126
+
127
+ describe '#options' do
128
+ context 'when @mirror is true' do
129
+ it 'should return the options with mirroring enabled' do
130
+ syncer.send(:options).should == '--archive --delete --opt-a --opt-b'
131
+ end
132
+ end
133
+
134
+ context 'when @mirror is false' do
135
+ before { syncer.mirror = false }
136
+ it 'should return the options without mirroring enabled' do
137
+ syncer.send(:options).should == '--archive --opt-a --opt-b'
138
+ end
139
+ end
140
+
141
+ context 'when no additional options are given' do
142
+ before { syncer.additional_options = [] }
143
+ it 'should return the options without additional options' do
144
+ syncer.send(:options).should == '--archive --delete'
145
+ end
146
+ end
147
+ end
148
+
149
+ end
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Syncer::RSync::Pull do
6
+ let(:syncer) do
7
+ Backup::Syncer::RSync::Pull.new do |rsync|
8
+ rsync.username = 'my_username'
9
+ rsync.password = 'my_password'
10
+ rsync.ip = '123.45.678.90'
11
+ rsync.port = 22
12
+ rsync.compress = true
13
+ rsync.path = "~/my_backups"
14
+
15
+ rsync.directories do |directory|
16
+ directory.add "/some/directory"
17
+ directory.add "~/home/directory"
18
+ directory.add "another/directory"
19
+ end
20
+
21
+ rsync.mirror = true
22
+ rsync.additional_options = ['--opt-a', '--opt-b']
23
+ end
24
+ end
25
+
26
+ it 'should be a subclass of RSync::Push' do
27
+ Backup::Syncer::RSync::Pull.superclass.should == Backup::Syncer::RSync::Push
28
+ end
29
+
30
+ describe '#perform!' do
31
+ let(:s) { sequence '' }
32
+
33
+ it 'should perform the RSync::Pull operation on two directories' do
34
+ syncer.expects(:utility).times(3).with(:rsync).returns('rsync')
35
+ syncer.expects(:options).times(3).returns('options_output')
36
+
37
+ syncer.expects(:write_password_file!).in_sequence(s)
38
+
39
+ # first directory - uses the given full path
40
+ Backup::Logger.expects(:message).in_sequence(s).with(
41
+ "Syncer::RSync::Pull started syncing '/some/directory'."
42
+ )
43
+ syncer.expects(:run).in_sequence(s).with(
44
+ "rsync options_output 'my_username@123.45.678.90:/some/directory' " +
45
+ "'#{ File.expand_path('~/my_backups') }'"
46
+ )
47
+
48
+ # second directory - removes leading '~'
49
+ Backup::Logger.expects(:message).in_sequence(s).with(
50
+ "Syncer::RSync::Pull started syncing '~/home/directory'."
51
+ )
52
+ syncer.expects(:run).in_sequence(s).with(
53
+ "rsync options_output 'my_username@123.45.678.90:home/directory' " +
54
+ "'#{ File.expand_path('~/my_backups') }'"
55
+ )
56
+
57
+ # third directory - does not expand path
58
+ Backup::Logger.expects(:message).in_sequence(s).with(
59
+ "Syncer::RSync::Pull started syncing 'another/directory'."
60
+ )
61
+ syncer.expects(:run).in_sequence(s).with(
62
+ "rsync options_output 'my_username@123.45.678.90:another/directory' " +
63
+ "'#{ File.expand_path('~/my_backups') }'"
64
+ )
65
+
66
+ syncer.expects(:remove_password_file!).in_sequence(s)
67
+
68
+ syncer.perform!
69
+ end
70
+
71
+ it 'should ensure passoword file removal' do
72
+ syncer.expects(:write_password_file!).raises('error message')
73
+ syncer.expects(:remove_password_file!)
74
+
75
+ expect do
76
+ syncer.perform!
77
+ end.to raise_error(RuntimeError, 'error message')
78
+ end
79
+ end # describe '#perform!'
80
+
81
+ describe '#dest_path' do
82
+ it 'should return @path expanded' do
83
+ syncer.send(:dest_path).should == File.expand_path('~/my_backups')
84
+ end
85
+
86
+ it 'should set @dest_path' do
87
+ syncer.send(:dest_path)
88
+ syncer.instance_variable_get(:@dest_path).should ==
89
+ File.expand_path('~/my_backups')
90
+ end
91
+
92
+ it 'should return @dest_path if already set' do
93
+ syncer.instance_variable_set(:@dest_path, 'foo')
94
+ syncer.send(:dest_path).should == 'foo'
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,333 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Syncer::RSync::Push do
6
+ let(:syncer) do
7
+ Backup::Syncer::RSync::Push.new do |rsync|
8
+ rsync.username = 'my_username'
9
+ rsync.password = 'my_password'
10
+ rsync.ip = '123.45.678.90'
11
+ rsync.port = 22
12
+ rsync.compress = true
13
+ rsync.path = "~/my_backups"
14
+
15
+ rsync.directories do |directory|
16
+ directory.add "/some/directory"
17
+ directory.add "~/home/directory"
18
+ end
19
+
20
+ rsync.mirror = true
21
+ rsync.additional_options = ['--opt-a', '--opt-b']
22
+ end
23
+ end
24
+
25
+ it 'should be a subclass of Syncer::RSync::Base' do
26
+ Backup::Syncer::RSync::Push.
27
+ superclass.should == Backup::Syncer::RSync::Base
28
+ end
29
+
30
+ describe '#initialize' do
31
+ after { Backup::Syncer::RSync::Push.clear_defaults! }
32
+
33
+ it 'should load pre-configured defaults through Syncer::Base' do
34
+ Backup::Syncer::RSync::Push.any_instance.expects(:load_defaults!)
35
+ syncer
36
+ end
37
+
38
+ context 'when no pre-configured defaults have been set' do
39
+ it 'should use the values given' do
40
+ syncer.path.should == '~/my_backups'
41
+ syncer.mirror.should == true
42
+ syncer.directories.should == ["/some/directory", "~/home/directory"]
43
+ syncer.additional_options.should == ['--opt-a', '--opt-b']
44
+
45
+ syncer.username.should == 'my_username'
46
+ syncer.password.should == 'my_password'
47
+ syncer.ip.should == '123.45.678.90'
48
+ syncer.port.should == 22
49
+ syncer.compress.should == true
50
+ end
51
+
52
+ it 'should use default values if none are given' do
53
+ syncer = Backup::Syncer::RSync::Push.new
54
+
55
+ # from Syncer::Base
56
+ syncer.path.should == 'backups'
57
+ syncer.mirror.should == false
58
+ syncer.directories.should == []
59
+
60
+ # from Syncer::RSync::Base
61
+ syncer.additional_options.should == []
62
+
63
+ syncer.username.should == nil
64
+ syncer.password.should == nil
65
+ syncer.ip.should == nil
66
+ syncer.port.should == 22
67
+ syncer.compress.should == false
68
+ end
69
+ end # context 'when no pre-configured defaults have been set'
70
+
71
+ context 'when pre-configured defaults have been set' do
72
+ before do
73
+ Backup::Syncer::RSync::Push.defaults do |rsync|
74
+ rsync.path = 'some_path'
75
+ rsync.mirror = 'some_mirror'
76
+ rsync.additional_options = 'some_additional_options'
77
+
78
+ rsync.username = 'some_username'
79
+ rsync.password = 'some_password'
80
+ rsync.ip = 'some_ip'
81
+ rsync.port = 'some_port'
82
+ rsync.compress = 'some_compress'
83
+ end
84
+ end
85
+
86
+ it 'should use pre-configured defaults' do
87
+ syncer = Backup::Syncer::RSync::Push.new
88
+
89
+ syncer.path.should == 'some_path'
90
+ syncer.mirror.should == 'some_mirror'
91
+ syncer.directories.should == []
92
+ syncer.additional_options.should == 'some_additional_options'
93
+
94
+ syncer.username.should == 'some_username'
95
+ syncer.password.should == 'some_password'
96
+ syncer.ip.should == 'some_ip'
97
+ syncer.port.should == 'some_port'
98
+ syncer.compress.should == 'some_compress'
99
+ end
100
+
101
+ it 'should override pre-configured defaults' do
102
+ syncer = Backup::Syncer::RSync::Push.new do |rsync|
103
+ rsync.path = 'new_path'
104
+ rsync.mirror = 'new_mirror'
105
+ rsync.additional_options = 'new_additional_options'
106
+
107
+ rsync.username = 'new_username'
108
+ rsync.password = 'new_password'
109
+ rsync.ip = 'new_ip'
110
+ rsync.port = 'new_port'
111
+ rsync.compress = 'new_compress'
112
+ end
113
+
114
+ syncer.path.should == 'new_path'
115
+ syncer.mirror.should == 'new_mirror'
116
+ syncer.directories.should == []
117
+ syncer.additional_options.should == 'new_additional_options'
118
+
119
+ syncer.username.should == 'new_username'
120
+ syncer.password.should == 'new_password'
121
+ syncer.ip.should == 'new_ip'
122
+ syncer.port.should == 'new_port'
123
+ syncer.compress.should == 'new_compress'
124
+ end
125
+ end # context 'when pre-configured defaults have been set'
126
+ end # describe '#initialize'
127
+
128
+ describe '#perform!' do
129
+ let(:s) { sequence '' }
130
+
131
+ before do
132
+ syncer.expects(:utility).with(:rsync).returns('rsync')
133
+ syncer.expects(:options).returns('options_output')
134
+ end
135
+
136
+ it 'should sync two directories' do
137
+ syncer.expects(:write_password_file!).in_sequence(s)
138
+
139
+ Backup::Logger.expects(:message).in_sequence(s).with(
140
+ "Syncer::RSync::Push started syncing the following directories:\n" +
141
+ " /some/directory\n" +
142
+ " ~/home/directory"
143
+ )
144
+ syncer.expects(:run).in_sequence(s).with(
145
+ "rsync options_output '/some/directory' " +
146
+ "'#{ File.expand_path('~/home/directory') }' " +
147
+ "'my_username@123.45.678.90:my_backups'"
148
+ )
149
+
150
+ syncer.expects(:remove_password_file!).in_sequence(s)
151
+
152
+ syncer.perform!
153
+ end
154
+
155
+ it 'should ensure passoword file removal' do
156
+ syncer.expects(:write_password_file!).in_sequence(s)
157
+
158
+ Backup::Logger.expects(:message).in_sequence(s)
159
+ syncer.expects(:run).in_sequence(s).raises('error message')
160
+
161
+ syncer.expects(:remove_password_file!).in_sequence(s)
162
+
163
+ expect do
164
+ syncer.perform!
165
+ end.to raise_error(RuntimeError, 'error message')
166
+ end
167
+ end # describe '#perform!'
168
+
169
+ describe '#dest_path' do
170
+ it 'should remove any preceeding "~/" from @path' do
171
+ syncer.send(:dest_path).should == 'my_backups'
172
+ end
173
+
174
+ it 'should set @dest_path' do
175
+ syncer.send(:dest_path)
176
+ syncer.instance_variable_get(:@dest_path).should == 'my_backups'
177
+ end
178
+
179
+ it 'should return @dest_path if already set' do
180
+ syncer.instance_variable_set(:@dest_path, 'foo')
181
+ syncer.send(:dest_path).should == 'foo'
182
+ end
183
+ end
184
+
185
+ describe '#options' do
186
+ let(:pwdfile) { mock }
187
+
188
+ context 'when @compress is true' do
189
+ it 'should return the options string with compression enabled' do
190
+ syncer.send(:options).should ==
191
+ "--archive --delete --compress -e 'ssh -p 22' --opt-a --opt-b"
192
+ end
193
+ end
194
+
195
+ context 'when @compress is false' do
196
+ before { syncer.compress = false }
197
+ it 'should return the options string without compression enabled' do
198
+ syncer.send(:options).should ==
199
+ "--archive --delete -e 'ssh -p 22' --opt-a --opt-b"
200
+ end
201
+ end
202
+
203
+ context 'when a @password_file is set' do
204
+ before do
205
+ syncer.instance_variable_set(:@password_file, pwdfile)
206
+ pwdfile.expects(:path).returns('/path/to/pwdfile')
207
+ end
208
+
209
+ it 'should return the options string with the password_option' do
210
+ syncer.send(:options).should ==
211
+ "--archive --delete --compress -e 'ssh -p 22' " +
212
+ "--password-file='/path/to/pwdfile' --opt-a --opt-b"
213
+ end
214
+ end
215
+
216
+ context 'when no @additional_options are set' do
217
+ before { syncer.additional_options = [] }
218
+
219
+ it 'should return the options string without additional options' do
220
+ syncer.send(:options).should ==
221
+ "--archive --delete --compress -e 'ssh -p 22'"
222
+ end
223
+ end
224
+
225
+ end # describe '#options'
226
+
227
+ describe '#compress_option' do
228
+ context 'when @compress is true' do
229
+ it 'should return the compression flag' do
230
+ syncer.send(:compress_option).should == '--compress'
231
+ end
232
+ end
233
+
234
+ context 'when @compress is false' do
235
+ before { syncer.compress = false }
236
+ it 'should return nil' do
237
+ syncer.send(:compress_option).should be_nil
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#port_option' do
243
+ before { syncer.port = 40 }
244
+ it 'should return the option string with the defined port' do
245
+ syncer.send(:port_option).should == "-e 'ssh -p 40'"
246
+ end
247
+ end
248
+
249
+ describe '#password_option' do
250
+ let(:pwdfile) { mock }
251
+
252
+ context 'when @password_file is set' do
253
+ before do
254
+ syncer.instance_variable_set(:@password_file, pwdfile)
255
+ pwdfile.expects(:path).returns('/path/to/pwdfile')
256
+ end
257
+
258
+ it 'should return the option string' do
259
+ syncer.send(:password_option).should ==
260
+ "--password-file='/path/to/pwdfile'"
261
+ end
262
+ end
263
+
264
+ context 'when @password_file is not set' do
265
+ it 'should return nil' do
266
+ syncer.send(:password_option).should be_nil
267
+ end
268
+ end
269
+ end
270
+
271
+ describe '#write_password_file!' do
272
+ let(:pwdfile) { mock }
273
+ let(:s) { sequence '' }
274
+
275
+ context 'when a @password is set' do
276
+ it 'should create, write and close a temporary password file' do
277
+ Tempfile.expects(:new).in_sequence(s).
278
+ with('backup-rsync-password').
279
+ returns(pwdfile)
280
+ pwdfile.expects(:write).in_sequence(s).with('my_password')
281
+ pwdfile.expects(:close).in_sequence(s)
282
+
283
+ syncer.send(:write_password_file!)
284
+ end
285
+
286
+ it 'should set @password_file to a file containing the password' do
287
+ syncer.send(:write_password_file!)
288
+ file = syncer.instance_variable_get(:@password_file)
289
+ File.exist?(file.path).should be_true
290
+ File.read(file.path).should == 'my_password'
291
+
292
+ # cleanup
293
+ file.delete
294
+ file.path.should be_nil
295
+ end
296
+ end
297
+
298
+ context 'when a @password is not set' do
299
+ before { syncer.password = nil }
300
+ it 'should return nil' do
301
+ Tempfile.expects(:new).never
302
+ pwdfile.expects(:write).never
303
+ pwdfile.expects(:close).never
304
+ syncer.send(:write_password_file!).should be_nil
305
+ end
306
+ end
307
+ end
308
+
309
+ describe '#remove_password_file!' do
310
+ let(:pwdfile) { mock }
311
+
312
+ context 'when @password_file is set' do
313
+ before do
314
+ syncer.instance_variable_set(:@password_file, pwdfile)
315
+ end
316
+
317
+ it 'should delete the file and reset @password_file' do
318
+ pwdfile.expects(:delete)
319
+ syncer.send(:remove_password_file!)
320
+ syncer.instance_variable_get(:@password_file).should be_nil
321
+ end
322
+ end
323
+
324
+ context 'when @password_file is not set' do
325
+ it 'should return nil' do
326
+ pwdfile.expects(:delete).never
327
+ syncer.send(:remove_password_file!).should be_nil
328
+ syncer.instance_variable_get(:@password_file).should be_nil
329
+ end
330
+ end
331
+ end
332
+
333
+ end