backup 3.0.20 → 3.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. data/spec/syncer/rsync_spec.rb +0 -195
@@ -3,13 +3,9 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Database::MySQL do
6
-
7
- before do
8
- Backup::Database::MySQL.any_instance.stubs(:load_defaults!)
9
- end
10
-
6
+ let(:model) { Backup::Model.new('foo', 'foo') }
11
7
  let(:db) do
12
- Backup::Database::MySQL.new do |db|
8
+ Backup::Database::MySQL.new(model) do |db|
13
9
  db.name = 'mydatabase'
14
10
  db.username = 'someuser'
15
11
  db.password = 'secret'
@@ -20,10 +16,11 @@ describe Backup::Database::MySQL do
20
16
  db.skip_tables = ['logs', 'profiles']
21
17
  db.only_tables = ['users', 'pirates']
22
18
  db.additional_options = ['--single-transaction', '--quick']
19
+ db.mysqldump_utility = '/path/to/mysqldump'
23
20
  end
24
21
  end
25
22
 
26
- describe '#new' do
23
+ describe '#initialize' do
27
24
  it 'should read the adapter details correctly' do
28
25
  db.name.should == 'mydatabase'
29
26
  db.username.should == 'someuser'
@@ -35,116 +32,194 @@ describe Backup::Database::MySQL do
35
32
  db.skip_tables.should == ['logs', 'profiles']
36
33
  db.only_tables.should == ['users', 'pirates']
37
34
  db.additional_options.should == ['--single-transaction', '--quick']
35
+ db.mysqldump_utility.should == '/path/to/mysqldump'
38
36
  end
39
37
 
40
- it 'arrays should default to empty arrays when not specified' do
41
- db = Backup::Database::MySQL.new do |db|
42
- db.name = 'mydatabase'
43
- db.username = 'someuser'
44
- db.password = 'secret'
38
+ context 'when options are not set' do
39
+ before do
40
+ Backup::Database::MySQL.any_instance.expects(:utility).
41
+ with(:mysqldump).returns('/real/mysqldump')
45
42
  end
46
43
 
47
- db.skip_tables.should == []
48
- db.only_tables.should == []
49
- db.additional_options.should == []
44
+ it 'should use default values' do
45
+ db = Backup::Database::MySQL.new(model)
46
+
47
+ db.name.should be_nil
48
+ db.username.should be_nil
49
+ db.password.should be_nil
50
+ db.host.should be_nil
51
+ db.port.should be_nil
52
+ db.socket.should be_nil
53
+
54
+ db.skip_tables.should == []
55
+ db.only_tables.should == []
56
+ db.additional_options.should == []
57
+ db.mysqldump_utility.should == '/real/mysqldump'
58
+ end
50
59
  end
51
- end
52
60
 
53
- describe '#skip_tables' do
54
- it 'should return a string for the mysqldump --ignore-tables option' do
55
- db.tables_to_skip.should == "--ignore-table='mydatabase.logs'\s--ignore-table='mydatabase.profiles'"
61
+ context 'when configuration defaults have been set' do
62
+ after { Backup::Configuration::Database::MySQL.clear_defaults! }
63
+
64
+ it 'should use configuration defaults' do
65
+ Backup::Configuration::Database::MySQL.defaults do |db|
66
+ db.name = 'db_name'
67
+ db.username = 'db_username'
68
+ db.password = 'db_password'
69
+ db.host = 'db_host'
70
+ db.port = 789
71
+ db.socket = '/foo.sock'
72
+
73
+ db.skip_tables = ['skip', 'tables']
74
+ db.only_tables = ['only', 'tables']
75
+ db.additional_options = ['--add', '--opts']
76
+ db.mysqldump_utility = '/default/path/to/mysqldump'
77
+ end
78
+
79
+ db = Backup::Database::MySQL.new(model)
80
+ db.name.should == 'db_name'
81
+ db.username.should == 'db_username'
82
+ db.password.should == 'db_password'
83
+ db.host.should == 'db_host'
84
+ db.port.should == 789
85
+ db.socket.should == '/foo.sock'
86
+
87
+ db.skip_tables.should == ['skip', 'tables']
88
+ db.only_tables.should == ['only', 'tables']
89
+ db.additional_options.should == ['--add', '--opts']
90
+ db.mysqldump_utility.should == '/default/path/to/mysqldump'
91
+ end
56
92
  end
93
+ end # describe '#initialize'
57
94
 
58
- it 'should return an empty string' do
59
- db = Backup::Database::MySQL.new {}
60
- db.tables_to_skip.should == ""
95
+ describe '#perform!' do
96
+ let(:s) { sequence '' }
97
+ before do
98
+ # superclass actions
99
+ db.expects(:prepare!).in_sequence(s)
100
+ db.expects(:log!).in_sequence(s)
101
+ db.instance_variable_set(:@dump_path, '/dump/path')
102
+
103
+ db.stubs(:mysqldump).returns('mysqldump_command')
61
104
  end
62
- end
63
105
 
64
- describe '#only_tables' do
65
- it 'should return a string for the mysqldump selected table to dump option' do
66
- db.tables_to_dump.should == "users\spirates"
106
+ context 'when no compressor is configured' do
107
+ before do
108
+ model.expects(:compressor).in_sequence(s).returns(nil)
109
+ end
110
+
111
+ it 'should run mysqldump without compression' do
112
+ db.expects(:run).in_sequence(s).with(
113
+ "mysqldump_command > '/dump/path/mydatabase.sql'"
114
+ )
115
+ db.perform!
116
+ end
117
+ end
118
+
119
+ context 'when a compressor is configured' do
120
+ before do
121
+ compressor = mock
122
+ model.expects(:compressor).twice.in_sequence(s).returns(compressor)
123
+ compressor.expects(:compress_with).in_sequence(s).yields('gzip', '.gz')
124
+ end
125
+
126
+ it 'should run mysqldump with compression' do
127
+ db.expects(:run).in_sequence(s).with(
128
+ "mysqldump_command | gzip > '/dump/path/mydatabase.sql.gz'"
129
+ )
130
+ db.perform!
131
+ end
67
132
  end
68
133
 
69
- it 'should return an empty string' do
70
- db = Backup::Database::MySQL.new {}
71
- db.tables_to_dump.should == ""
134
+ end # describe '#perform!'
135
+
136
+ describe '#mysqldump' do
137
+ it 'should return the mysqldump command string' do
138
+ db.send(:mysqldump).should ==
139
+ "/path/to/mysqldump --user='someuser' --password='secret' " +
140
+ "--host='localhost' --port='123' --socket='/mysql.sock' " +
141
+ "--single-transaction --quick mydatabase users pirates " +
142
+ "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
72
143
  end
73
144
  end
74
145
 
75
146
  describe '#credential_options' do
76
- it 'should return the mysql syntax for the credential options' do
77
- db.credential_options.should == "--user='someuser' --password='secret'"
147
+ context 'when a password is set' do
148
+ it 'should return the command string for the user credentials' do
149
+ db.send(:credential_options).should ==
150
+ "--user='someuser' --password='secret'"
151
+ end
78
152
  end
79
153
 
80
- it 'should only return the mysql syntax for the user' do
81
- db = Backup::Database::MySQL.new do |db|
82
- db.username = 'someuser'
154
+ context 'when no password is set' do
155
+ before { db.password = nil }
156
+ it 'should return the command string for the user credentials' do
157
+ db.send(:credential_options).should ==
158
+ "--user='someuser'"
83
159
  end
84
-
85
- db.credential_options.should == "--user='someuser'"
86
160
  end
87
161
  end
88
162
 
89
163
  describe '#connectivity_options' do
90
164
  it 'should return the mysql syntax for the connectivity options' do
91
- db.connectivity_options.should == "--host='localhost' --port='123' --socket='/mysql.sock'"
165
+ db.send(:connectivity_options).should ==
166
+ "--host='localhost' --port='123' --socket='/mysql.sock'"
92
167
  end
93
168
 
94
- it 'should return only the socket' do
95
- db = Backup::Database::MySQL.new do |db|
169
+ context 'when only the socket is set' do
170
+ it 'should return only the socket' do
96
171
  db.host = ''
97
172
  db.port = nil
98
- db.socket = '/mysql.sock'
173
+ db.send(:connectivity_options).should == "--socket='/mysql.sock'"
99
174
  end
175
+ end
100
176
 
101
- db.connectivity_options.should == "--socket='/mysql.sock'"
177
+ context 'when only the host and port are set' do
178
+ it 'should return only the host and port' do
179
+ db.socket = nil
180
+ db.send(:connectivity_options).should ==
181
+ "--host='localhost' --port='123'"
182
+ end
102
183
  end
103
184
  end
104
185
 
105
- describe '#additional_options' do
186
+ describe '#user_options' do
106
187
  it 'should return a string of additional options specified by the user' do
107
- db.options.should == '--single-transaction --quick'
188
+ db.send(:user_options).should == '--single-transaction --quick'
108
189
  end
109
190
 
110
- it 'should return an empty string' do
111
- db = Backup::Database::MySQL.new {}
112
- db.options.should == ""
113
- end
114
- end
115
-
116
- describe '#mysqldump_string' do
117
- it 'should return the full mysqldump string' do
118
- db.expects(:utility).with(:mysqldump).returns('mysqldump')
119
- db.mysqldump.should ==
120
- "mysqldump --user='someuser' --password='secret' " +
121
- "--host='localhost' --port='123' --socket='/mysql.sock' " +
122
- "--single-transaction --quick mydatabase users pirates " +
123
- "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
191
+ context 'when #additional_options is not set' do
192
+ before { db.additional_options = [] }
193
+ it 'should return an empty string' do
194
+ db.send(:user_options).should == ''
195
+ end
124
196
  end
125
197
  end
126
198
 
127
- describe '#perform!' do
128
- before do
129
- db.stubs(:utility).returns('mysqldump')
130
- db.stubs(:mkdir)
131
- db.stubs(:run)
199
+ describe '#tables_to_dump' do
200
+ it 'should return a string for the mysqldump selected table to dump option' do
201
+ db.send(:tables_to_dump).should == 'users pirates'
132
202
  end
133
203
 
134
- it 'should ensure the directory is available' do
135
- db.expects(:mkdir).with(File.join(Backup::TMP_PATH, "myapp", "MySQL"))
136
- db.perform!
204
+ context 'when #only_tables is not set' do
205
+ before { db.only_tables = [] }
206
+ it 'should return an empty string' do
207
+ db.send(:tables_to_dump).should == ''
208
+ end
137
209
  end
210
+ end
138
211
 
139
- it 'should run the mysqldump command and dump it to the specified path' do
140
- db.expects(:run).with("#{db.mysqldump} > '#{Backup::TMP_PATH}/myapp/MySQL/mydatabase.sql'")
141
- db.perform!
212
+ describe '#tables_to_skip' do
213
+ it 'should return a string for the mysqldump --ignore-tables option' do
214
+ db.send(:tables_to_skip).should ==
215
+ "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
142
216
  end
143
217
 
144
- it do
145
- Backup::Logger.expects(:message).
146
- with("Backup::Database::MySQL started dumping and archiving 'mydatabase'.")
147
- db.perform!
218
+ context 'when #skip_tables is not set' do
219
+ before { db.skip_tables = [] }
220
+ it 'should return an empty string' do
221
+ db.send(:tables_to_skip).should == ''
222
+ end
148
223
  end
149
224
  end
150
225
  end
@@ -3,183 +3,238 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Database::PostgreSQL do
6
-
7
- before do
8
- Backup::Database::PostgreSQL.any_instance.stubs(:load_defaults!)
9
- end
10
-
6
+ let(:model) { Backup::Model.new('foo', 'foo') }
11
7
  let(:db) do
12
- Backup::Database::PostgreSQL.new do |db|
8
+ Backup::Database::PostgreSQL.new(model) do |db|
13
9
  db.name = 'mydatabase'
14
10
  db.username = 'someuser'
15
11
  db.password = 'secret'
16
12
  db.host = 'localhost'
17
13
  db.port = '123'
18
- db.socket = '/pg.sock'
14
+ db.socket = '/pgsql.sock'
19
15
 
20
16
  db.skip_tables = ['logs', 'profiles']
21
17
  db.only_tables = ['users', 'pirates']
22
18
  db.additional_options = ['--single-transaction', '--quick']
19
+ db.pg_dump_utility = '/path/to/pg_dump'
23
20
  end
24
21
  end
25
22
 
26
- describe '#new' do
23
+ describe '#initialize' do
27
24
  it 'should read the adapter details correctly' do
28
25
  db.name.should == 'mydatabase'
29
26
  db.username.should == 'someuser'
30
27
  db.password.should == 'secret'
31
28
  db.host.should == 'localhost'
32
29
  db.port.should == '123'
33
- db.socket.should == '/pg.sock'
30
+ db.socket.should == '/pgsql.sock'
34
31
 
35
32
  db.skip_tables.should == ['logs', 'profiles']
36
33
  db.only_tables.should == ['users', 'pirates']
37
34
  db.additional_options.should == ['--single-transaction', '--quick']
35
+ db.pg_dump_utility.should == '/path/to/pg_dump'
38
36
  end
39
37
 
40
- it 'arrays should default to empty arrays when not specified' do
41
- db = Backup::Database::PostgreSQL.new do |db|
42
- db.name = 'mydatabase'
43
- db.username = 'someuser'
44
- db.password = 'secret'
38
+ context 'when options are not set' do
39
+ before do
40
+ Backup::Database::PostgreSQL.any_instance.expects(:utility).
41
+ with(:pg_dump).returns('/real/pg_dump')
42
+ end
43
+
44
+ it 'should use default values' do
45
+ db = Backup::Database::PostgreSQL.new(model)
46
+
47
+ db.name.should be_nil
48
+ db.username.should be_nil
49
+ db.password.should be_nil
50
+ db.host.should be_nil
51
+ db.port.should be_nil
52
+ db.socket.should be_nil
53
+
54
+ db.skip_tables.should == []
55
+ db.only_tables.should == []
56
+ db.additional_options.should == []
57
+ db.pg_dump_utility.should == '/real/pg_dump'
45
58
  end
59
+ end
46
60
 
47
- db.skip_tables.should == []
48
- db.only_tables.should == []
49
- db.additional_options.should == []
61
+ context 'when configuration defaults have been set' do
62
+ after { Backup::Configuration::Database::PostgreSQL.clear_defaults! }
63
+
64
+ it 'should use configuration defaults' do
65
+ Backup::Configuration::Database::PostgreSQL.defaults do |db|
66
+ db.name = 'db_name'
67
+ db.username = 'db_username'
68
+ db.password = 'db_password'
69
+ db.host = 'db_host'
70
+ db.port = 789
71
+ db.socket = '/foo.sock'
72
+
73
+ db.skip_tables = ['skip', 'tables']
74
+ db.only_tables = ['only', 'tables']
75
+ db.additional_options = ['--add', '--opts']
76
+ db.pg_dump_utility = '/default/path/to/pg_dump'
77
+ end
78
+
79
+ db = Backup::Database::PostgreSQL.new(model)
80
+ db.name.should == 'db_name'
81
+ db.username.should == 'db_username'
82
+ db.password.should == 'db_password'
83
+ db.host.should == 'db_host'
84
+ db.port.should == 789
85
+ db.socket.should == '/foo.sock'
86
+
87
+ db.skip_tables.should == ['skip', 'tables']
88
+ db.only_tables.should == ['only', 'tables']
89
+ db.additional_options.should == ['--add', '--opts']
90
+ db.pg_dump_utility.should == '/default/path/to/pg_dump'
91
+ end
50
92
  end
93
+ end # describe '#initialize'
51
94
 
52
- it 'handles an empty username' do
53
- db = Backup::Database::PostgreSQL.new {}
54
- db.username = ''
95
+ describe '#perform!' do
96
+ let(:s) { sequence '' }
97
+ before do
98
+ # superclass actions
99
+ db.expects(:prepare!).in_sequence(s)
100
+ db.expects(:log!).in_sequence(s)
101
+ db.instance_variable_set(:@dump_path, '/dump/path')
55
102
 
56
- db.username_options.should == ''
57
- db.password_options.should == ''
103
+ db.stubs(:pgdump).returns('pgdump_command')
58
104
  end
59
105
 
60
- it 'handles a nil username' do
61
- db = Backup::Database::PostgreSQL.new {}
62
- db.username = nil
106
+ context 'when no compressor is configured' do
107
+ before do
108
+ model.expects(:compressor).in_sequence(s).returns(nil)
109
+ end
63
110
 
64
- db.username_options.should == ''
65
- db.password_options.should == ''
111
+ it 'should run pgdump without compression' do
112
+ db.expects(:run).in_sequence(s).with(
113
+ "pgdump_command > '/dump/path/mydatabase.sql'"
114
+ )
115
+ db.perform!
116
+ end
66
117
  end
67
- end
68
118
 
69
- describe '#skip_tables' do
70
- it 'should return a string for the pg_dump --ignore-tables option' do
71
- db.tables_to_skip.should == "--exclude-table='logs' --exclude-table='profiles'"
119
+ context 'when a compressor is configured' do
120
+ before do
121
+ compressor = mock
122
+ model.expects(:compressor).twice.in_sequence(s).returns(compressor)
123
+ compressor.expects(:compress_with).in_sequence(s).yields('gzip', '.gz')
124
+ end
125
+
126
+ it 'should run pgdump with compression' do
127
+ db.expects(:run).in_sequence(s).with(
128
+ "pgdump_command | gzip > '/dump/path/mydatabase.sql.gz'"
129
+ )
130
+ db.perform!
131
+ end
72
132
  end
73
133
 
74
- it 'should return an empty string' do
75
- db = Backup::Database::PostgreSQL.new {}
76
- db.tables_to_skip.should == ""
134
+ end # describe '#perform!'
135
+
136
+ describe '#pgdump' do
137
+ it 'should return the pgdump command string' do
138
+ db.send(:pgdump).should ==
139
+ "PGPASSWORD='secret' /path/to/pg_dump --username='someuser' " +
140
+ "--host='localhost' --port='123' --host='/pgsql.sock' " +
141
+ "--single-transaction --quick --table='users' --table='pirates' " +
142
+ "--exclude-table='logs' --exclude-table='profiles' mydatabase"
143
+ end
144
+
145
+ context 'without a password' do
146
+ before { db.password = nil }
147
+ it 'should not leave a preceeding space' do
148
+ db.send(:pgdump).should ==
149
+ "/path/to/pg_dump --username='someuser' " +
150
+ "--host='localhost' --port='123' --host='/pgsql.sock' " +
151
+ "--single-transaction --quick --table='users' --table='pirates' " +
152
+ "--exclude-table='logs' --exclude-table='profiles' mydatabase"
153
+ end
77
154
  end
78
155
  end
79
156
 
80
- describe '#only_tables' do
81
- it 'should return a string for the pg_dump selected table to dump option' do
82
- db.tables_to_dump.should == "--table='users' --table='pirates'"
157
+ describe '#password_options' do
158
+ it 'returns the environment variable set for the password' do
159
+ db.send(:password_options).should == "PGPASSWORD='secret' "
83
160
  end
84
161
 
85
- it 'should return an empty string' do
86
- db = Backup::Database::PostgreSQL.new {}
87
- db.tables_to_dump.should == ""
162
+ context 'when password is not set' do
163
+ before { db.password = nil }
164
+ it 'should return an empty string' do
165
+ db.send(:password_options).should == ''
166
+ end
88
167
  end
89
168
  end
90
169
 
91
170
  describe '#username_options' do
92
171
  it 'should return the postgresql syntax for the username options' do
93
- db.username_options.should == "--username='someuser'"
172
+ db.send(:username_options).should == "--username='someuser'"
94
173
  end
95
174
 
96
- it 'should only return the postgresql syntax for the user' do
97
- db = Backup::Database::PostgreSQL.new do |db|
98
- db.username = 'someuser'
175
+ context 'when username is not set' do
176
+ before { db.username = nil }
177
+ it 'should return an empty string' do
178
+ db.send(:username_options).should == ''
99
179
  end
100
-
101
- db.username_options.should == "--username='someuser'"
102
- end
103
- end
104
-
105
- describe '#password_options' do
106
- it 'returns the environment variable set for the password' do
107
- db.password_options.should == "PGPASSWORD='secret'"
108
180
  end
109
181
  end
110
182
 
111
183
  describe '#connectivity_options' do
112
184
  it 'should return the postgresql syntax for the connectivity options' do
113
- db.connectivity_options.should == "--host='localhost' --port='123' --host='/pg.sock'"
185
+ db.send(:connectivity_options).should ==
186
+ "--host='localhost' --port='123' --host='/pgsql.sock'"
114
187
  end
115
188
 
116
- it 'should return only the socket' do
117
- db = Backup::Database::PostgreSQL.new do |db|
189
+ context 'when only the socket is set' do
190
+ before do
118
191
  db.host = ''
119
192
  db.port = nil
120
- db.socket = '/pg.sock'
121
193
  end
122
194
 
123
- db.connectivity_options.should == "--host='/pg.sock'"
195
+ it 'should return only the socket' do
196
+ db.send(:connectivity_options).should == "--host='/pgsql.sock'"
197
+ end
124
198
  end
125
199
  end
126
200
 
127
- describe '#additional_options' do
201
+ describe '#user_options' do
128
202
  it 'should return a string of additional options specified by the user' do
129
- db.options.should == '--single-transaction --quick'
203
+ db.send(:user_options).should == '--single-transaction --quick'
130
204
  end
131
205
 
132
- it 'should return an empty string' do
133
- db = Backup::Database::PostgreSQL.new {}
134
- db.options.should == ""
206
+ context 'when #additional_options is not set' do
207
+ before { db.additional_options = [] }
208
+ it 'should return an empty string' do
209
+ db.send(:user_options).should == ''
210
+ end
135
211
  end
136
212
  end
137
213
 
138
- describe '#pg_dump_string' do
139
- before do
140
- db.expects(:utility).with(:pg_dump).returns('pg_dump')
141
- end
142
-
143
- it 'should return the full pg_dump string' do
144
- db.pgdump.should ==
145
- "PGPASSWORD='secret' pg_dump --username='someuser' " +
146
- "--host='localhost' --port='123' --host='/pg.sock' " +
147
- "--single-transaction --quick --table='users' --table='pirates' " +
148
- "--exclude-table='logs' --exclude-table='profiles' mydatabase"
214
+ describe '#tables_to_dump' do
215
+ it 'should return a string for the pg_dump selected table to dump option' do
216
+ db.send(:tables_to_dump).should == "--table='users' --table='pirates'"
149
217
  end
150
218
 
151
- it 'returns the full pg_dump string when a password is not specified' do
152
- db.password = nil
153
- db.pgdump.should ==
154
- "pg_dump --username='someuser' " +
155
- "--host='localhost' --port='123' --host='/pg.sock' " +
156
- "--single-transaction --quick --table='users' --table='pirates' " +
157
- "--exclude-table='logs' --exclude-table='profiles' mydatabase"
158
-
219
+ context 'when #only_tables is not set' do
220
+ before { db.only_tables = [] }
221
+ it 'should return an empty string' do
222
+ db.send(:tables_to_dump).should == ''
223
+ end
159
224
  end
160
225
  end
161
226
 
162
- describe '#perform!' do
163
- before do
164
- db.stubs(:utility).returns('pg_dump')
165
- db.stubs(:mkdir)
166
- db.stubs(:run)
167
- end
168
-
169
- it 'should ensure the directory is available' do
170
- db.expects(:mkdir).with(File.join(Backup::TMP_PATH, "myapp", "PostgreSQL"))
171
- db.perform!
172
- end
173
-
174
- it 'should run the pg_dump command and dump it to the specified path' do
175
- db.expects(:run).with("#{db.pgdump} > '#{Backup::TMP_PATH}/myapp/PostgreSQL/mydatabase.sql'")
176
- db.perform!
227
+ describe '#tables_to_skip' do
228
+ it 'should return a string for the pg_dump --ignore-tables option' do
229
+ db.send(:tables_to_skip).should == "--exclude-table='logs' --exclude-table='profiles'"
177
230
  end
178
231
 
179
- it do
180
- Backup::Logger.expects(:message).
181
- with("Backup::Database::PostgreSQL started dumping and archiving 'mydatabase'.")
182
- db.perform!
232
+ context 'when #skip_tables is not set' do
233
+ before { db.skip_tables = [] }
234
+ it 'should return an empty string' do
235
+ db.send(:tables_to_skip).should == ''
236
+ end
183
237
  end
184
238
  end
239
+
185
240
  end