chef_backup 0.0.1.dev.4 → 0.2.0.pre1
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.
- checksums.yaml +5 -5
- data/lib/chef_backup/config.rb +22 -12
- data/lib/chef_backup/data_map.rb +18 -12
- data/lib/chef_backup/deep_merge.rb +145 -0
- data/lib/chef_backup/helpers.rb +154 -28
- data/lib/chef_backup/logger.rb +11 -6
- data/lib/chef_backup/mash.rb +226 -0
- data/lib/chef_backup/runner.rb +24 -21
- data/lib/chef_backup/strategy/backup/custom.rb +1 -2
- data/lib/chef_backup/strategy/backup/ebs.rb +3 -6
- data/lib/chef_backup/strategy/backup/lvm.rb +2 -4
- data/lib/chef_backup/strategy/backup/object.rb +2 -4
- data/lib/chef_backup/strategy/backup/tar.rb +96 -40
- data/lib/chef_backup/strategy/restore/tar.rb +81 -51
- data/lib/chef_backup/strategy.rb +10 -10
- data/lib/chef_backup/version.rb +1 -1
- data/lib/chef_backup.rb +8 -8
- metadata +21 -162
- data/.gitignore +0 -23
- data/.kitchen.yml +0 -30
- data/.rubocop.yml +0 -21
- data/.travis.yml +0 -6
- data/Gemfile +0 -4
- data/Guardfile +0 -22
- data/README.md +0 -21
- data/Rakefile +0 -44
- data/chef_backup.gemspec +0 -33
- data/spec/fixtures/chef-server-running.json +0 -589
- data/spec/spec_helper.rb +0 -103
- data/spec/unit/data_map_spec.rb +0 -59
- data/spec/unit/helpers_spec.rb +0 -88
- data/spec/unit/runner_spec.rb +0 -185
- data/spec/unit/shared_examples/helpers.rb +0 -20
- data/spec/unit/strategy/backup/lvm_spec.rb +0 -0
- data/spec/unit/strategy/backup/shared_examples/backup.rb +0 -92
- data/spec/unit/strategy/backup/tar_spec.rb +0 -294
- data/spec/unit/strategy/restore/lvm_spec.rb +0 -0
- data/spec/unit/strategy/restore/shared_examples/restore.rb +0 -84
- data/spec/unit/strategy/restore/tar_spec.rb +0 -238
- data/spec/unit/strategy_spec.rb +0 -36
@@ -1,294 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'chef/mixin/deep_merge'
|
3
|
-
require_relative 'shared_examples/backup'
|
4
|
-
|
5
|
-
describe ChefBackup::Strategy::TarBackup do
|
6
|
-
set_common_variables
|
7
|
-
|
8
|
-
subject { described_class.new }
|
9
|
-
|
10
|
-
before do
|
11
|
-
use_default_running_config
|
12
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir)
|
13
|
-
allow(subject).to receive(:backup_time).and_return(backup_time)
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '.backup' do
|
17
|
-
before do
|
18
|
-
%i(write_manifest dump_db stop_service create_tarball cleanup
|
19
|
-
start_service export_tarball
|
20
|
-
).each do |method|
|
21
|
-
allow(subject).to receive(method).and_return(true)
|
22
|
-
end
|
23
|
-
|
24
|
-
allow(subject).to receive(:enabled_services).and_return(enabled_services)
|
25
|
-
allow(subject).to receive(:all_services).and_return(all_services)
|
26
|
-
allow(subject).to receive(:dump_db).and_return(true)
|
27
|
-
end
|
28
|
-
|
29
|
-
context 'on a frontend' do
|
30
|
-
before { private_chef('role' => 'frontend') }
|
31
|
-
|
32
|
-
it_behaves_like 'a tar based backup'
|
33
|
-
it_behaves_like 'a tar based frontend'
|
34
|
-
end
|
35
|
-
|
36
|
-
context 'on a backend' do
|
37
|
-
before { private_chef('role' => 'backend') }
|
38
|
-
|
39
|
-
context 'during an online backup' do
|
40
|
-
before do
|
41
|
-
private_chef('role' => 'backend', 'backup' => { 'mode' => 'online' })
|
42
|
-
end
|
43
|
-
|
44
|
-
it_behaves_like 'a tar based backup'
|
45
|
-
it_behaves_like 'a tar based online backend'
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'during an offline backup' do
|
49
|
-
it_behaves_like 'a tar based backup'
|
50
|
-
it_behaves_like 'a tar based offline backend'
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'when no mode is configured' do
|
54
|
-
before do
|
55
|
-
private_chef('role' => 'backend', 'backup' => { 'mode' => nil })
|
56
|
-
end
|
57
|
-
|
58
|
-
it_behaves_like 'a tar based backup'
|
59
|
-
it_behaves_like 'a tar based offline backend'
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'on a standalone' do
|
64
|
-
before { private_chef('role' => 'standalone') }
|
65
|
-
|
66
|
-
context 'during an online backup' do
|
67
|
-
before do
|
68
|
-
private_chef('role' => 'standalone',
|
69
|
-
'backup' => { 'mode' => 'online' })
|
70
|
-
end
|
71
|
-
|
72
|
-
it_behaves_like 'a tar based backup'
|
73
|
-
it_behaves_like 'a tar based online backend'
|
74
|
-
end
|
75
|
-
|
76
|
-
context 'during an offline backup' do
|
77
|
-
it_behaves_like 'a tar based backup'
|
78
|
-
it_behaves_like 'a tar based offline backend'
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when no mode is configured' do
|
82
|
-
before do
|
83
|
-
private_chef('role' => 'standalone', 'backup' => { 'mode' => nil })
|
84
|
-
end
|
85
|
-
|
86
|
-
it_behaves_like 'a tar based backup'
|
87
|
-
it_behaves_like 'a tar based offline backend'
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe '.dump_db' do
|
93
|
-
let(:dump_cmd) do
|
94
|
-
['/opt/opscode/embedded/bin/chpst',
|
95
|
-
'-u opscode-pgsql',
|
96
|
-
'/opt/opscode/embedded/bin/pg_dumpall',
|
97
|
-
"> #{tmp_dir}/chef_backup-#{backup_time}.sql"
|
98
|
-
].join(' ')
|
99
|
-
end
|
100
|
-
|
101
|
-
let(:tmp_dir) { '/tmp/notaswear' }
|
102
|
-
let(:backup_time) { Time.now }
|
103
|
-
|
104
|
-
before do
|
105
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir)
|
106
|
-
allow(subject).to receive(:backup_time).and_return(backup_time)
|
107
|
-
allow(subject).to receive(:shell_out!).with(dump_cmd).and_return(true)
|
108
|
-
private_chef('postgresql' => { 'username' => 'opscode-pgsql' })
|
109
|
-
subject.data_map.add_service('postgresql', '/data/dir')
|
110
|
-
end
|
111
|
-
|
112
|
-
%w(backend standalone).each do |role|
|
113
|
-
context "on a #{role}" do
|
114
|
-
before do
|
115
|
-
private_chef('role' => role)
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'dumps the db' do
|
119
|
-
expect(subject).to receive(:shell_out!).with(dump_cmd)
|
120
|
-
subject.dump_db
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'updates the data map' do
|
124
|
-
subject.dump_db
|
125
|
-
expect(subject.data_map.services['postgresql'])
|
126
|
-
.to include('pg_dump_success' => true)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'adds the postgresql username to the data map' do
|
130
|
-
subject.dump_db
|
131
|
-
expect(subject.data_map.services['postgresql'])
|
132
|
-
.to include('username' => 'opscode-pgsql')
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'on a frontend' do
|
138
|
-
before { private_chef('role' => 'frontend') }
|
139
|
-
|
140
|
-
it "doesn't dump the db" do
|
141
|
-
expect(subject).to_not receive(:shell_out).with(/pg_dumpall/)
|
142
|
-
subject.dump_db
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
describe '.create_tarball' do
|
148
|
-
before do
|
149
|
-
allow(subject).to receive(:data_map).and_return(data_map)
|
150
|
-
allow(Dir).to receive(:[]).and_return(%w(sql.sql manifest.json))
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'creates a tarball with all items in the temp directory' do
|
154
|
-
cmd = [
|
155
|
-
"tar -czf #{tmp_dir}/chef-backup-#{backup_time}.tgz",
|
156
|
-
data_map.services.map { |_, v| v['data_dir'] }.compact.join(' '),
|
157
|
-
data_map.configs.map { |_, v| v['data_dir'] }.compact.join(' '),
|
158
|
-
Dir["#{tmp_dir}/*"].map { |f| File.basename(f) }.join(' ')
|
159
|
-
].join(' ').strip
|
160
|
-
|
161
|
-
allow(subject).to receive(:shell_out).with(cmd, cdw: tmp_dir)
|
162
|
-
expect(subject).to receive(:shell_out).with(cmd, cwd: tmp_dir)
|
163
|
-
subject.create_tarball
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
describe '.export_tarball' do
|
168
|
-
before do
|
169
|
-
allow(subject).to receive(:export_dir).and_return('/mnt/chef-backups')
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'moves the tarball to the archive location' do
|
173
|
-
cmd = "rsync -chaz #{tmp_dir}/chef-backup-#{backup_time}.tgz"
|
174
|
-
cmd << " #{export_dir}/"
|
175
|
-
|
176
|
-
allow(subject).to receive(:shell_out).with(cmd)
|
177
|
-
expect(subject).to receive(:shell_out).with(cmd)
|
178
|
-
subject.export_tarball
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
describe '.write_manifest' do
|
183
|
-
let(:manifest) do
|
184
|
-
{ 'some' => {
|
185
|
-
'nested' => {
|
186
|
-
'hash' => true
|
187
|
-
},
|
188
|
-
'another' => true
|
189
|
-
}
|
190
|
-
}
|
191
|
-
end
|
192
|
-
|
193
|
-
let(:file) { double('file', write: true) }
|
194
|
-
|
195
|
-
before do
|
196
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
197
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir)
|
198
|
-
allow(File).to receive(:open).and_yield(file)
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'converts the manifest to json' do
|
202
|
-
json_manifest = JSON.pretty_generate(subject.manifest)
|
203
|
-
expect(file).to receive(:write).with(json_manifest)
|
204
|
-
subject.write_manifest
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'writes a json file to the tmp_dir' do
|
208
|
-
expect(File).to receive(:open).with("#{tmp_dir}/manifest.json", 'w')
|
209
|
-
subject.write_manifest
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
describe '.populate_data_map' do
|
214
|
-
let(:services) { %w(opscode-solr4 bookshelf rabbitmq) }
|
215
|
-
let(:configs) { %w(opscode opscode-manage opscode-analytics) }
|
216
|
-
let(:config) do
|
217
|
-
{ 'bookshelf' => { 'data_dir' => '/bookshelf/data' },
|
218
|
-
'opscode-solr4' => { 'data_dir' => '/solr4/data' },
|
219
|
-
'rabbitmq' => { 'data_dir' => '/rabbitmq/data' }
|
220
|
-
}
|
221
|
-
end
|
222
|
-
|
223
|
-
before do
|
224
|
-
allow(subject).to receive(:data_map).and_return(data_map)
|
225
|
-
allow(subject).to receive(:stateful_services).and_return(services)
|
226
|
-
allow(subject).to receive(:config_directories).and_return(configs)
|
227
|
-
%w(add_service add_config add_ha_info).each do |method|
|
228
|
-
allow(data_map).to receive(method.to_sym).and_return(true)
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
%w(frontend backend standalone).each do |role|
|
233
|
-
context "on a #{role}" do
|
234
|
-
before { private_chef(config.merge('role' => role)) }
|
235
|
-
|
236
|
-
it 'populates the data map with config directories' do
|
237
|
-
configs.each do |config|
|
238
|
-
expect(subject.data_map)
|
239
|
-
.to receive(:add_config)
|
240
|
-
.with(config, "/etc/#{config}")
|
241
|
-
end
|
242
|
-
|
243
|
-
subject.populate_data_map
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
%w(backend standalone).each do |role|
|
249
|
-
context "on a #{role}" do
|
250
|
-
before { private_chef(config.merge('role' => role)) }
|
251
|
-
|
252
|
-
it 'populates the data map with service directories' do
|
253
|
-
services.each do |service|
|
254
|
-
expect(subject.data_map)
|
255
|
-
.to receive(:add_service)
|
256
|
-
.with(service, config[service]['data_dir'])
|
257
|
-
end
|
258
|
-
|
259
|
-
subject.populate_data_map
|
260
|
-
end
|
261
|
-
|
262
|
-
it 'populates the data map with the upgrades' do
|
263
|
-
expect(subject.data_map)
|
264
|
-
.to receive(:add_service)
|
265
|
-
.with('upgrades', '/var/opt/opscode/upgrades')
|
266
|
-
|
267
|
-
subject.populate_data_map
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
context 'on a frontend' do
|
273
|
-
before { private_chef(config.merge('role' => 'frontend')) }
|
274
|
-
|
275
|
-
it "doesn't populate the data map with the services" do
|
276
|
-
expect(subject.data_map).to_not receive(:add_service)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
describe '.pg_dump?' do
|
282
|
-
it 'returns true' do
|
283
|
-
expect(subject.pg_dump?).to eq(true)
|
284
|
-
end
|
285
|
-
|
286
|
-
context 'when db dump is disabled' do
|
287
|
-
before { private_chef('backup' => { 'always_dump_db' => false }) }
|
288
|
-
|
289
|
-
it 'returns false' do
|
290
|
-
expect(subject.pg_dump?).to eq(false)
|
291
|
-
end
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|
File without changes
|
@@ -1,84 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
shared_examples 'a tar based restore' do
|
4
|
-
it "cleanse's the chef server" do
|
5
|
-
expect(subject).to receive(:cleanse_chef_server).once
|
6
|
-
subject.restore
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'restores the configs' do
|
10
|
-
configs.each do |config|
|
11
|
-
expect(subject).to receive(:restore_data).with(:configs, config).once
|
12
|
-
end
|
13
|
-
subject.restore
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'touches the bootstrap sentinel file' do
|
17
|
-
expect(subject).to receive(:touch_sentinel).once
|
18
|
-
subject.restore
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'reconfigures the server' do
|
22
|
-
expect(subject).to receive(:reconfigure_server).once
|
23
|
-
subject.restore
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'updates the config' do
|
27
|
-
expect(subject).to receive(:update_config).once
|
28
|
-
subject.restore
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'starts the server' do
|
32
|
-
expect(subject).to receive(:start_chef_server).once
|
33
|
-
subject.restore
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'cleans up the temp directory' do
|
37
|
-
expect(subject).to receive(:cleanup).once
|
38
|
-
subject.restore
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
shared_examples 'a tar based frontend restore' do
|
43
|
-
it 'does not restore services' do
|
44
|
-
expect(subject).to_not receive(:restore_services)
|
45
|
-
subject.restore
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'does not start postgres' do
|
49
|
-
expect(subject).to_not receive(:start_service).with(:postgresql)
|
50
|
-
subject.restore
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'does not attempt to import a database' do
|
54
|
-
expect(subject).to_not receive(:import_db)
|
55
|
-
subject.restore
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
shared_examples 'a tar based backend restore' do
|
60
|
-
it 'restores the stateful services' do
|
61
|
-
services.each do |service|
|
62
|
-
expect(subject)
|
63
|
-
.to receive(:restore_data)
|
64
|
-
.with(:services, service)
|
65
|
-
.once
|
66
|
-
end
|
67
|
-
subject.restore
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
shared_examples 'a tar based backend restore with db dump' do
|
72
|
-
it 'restores the db dump' do
|
73
|
-
expect(subject).to receive(:import_db)
|
74
|
-
subject.restore
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
shared_examples 'a tar based backend restore without db dump' do
|
79
|
-
it 'does not try to import a db dump' do
|
80
|
-
expect(subject).to_not receive(:import_db)
|
81
|
-
expect(subject).to_not receive(:start_service).with(:postgresql)
|
82
|
-
subject.restore
|
83
|
-
end
|
84
|
-
end
|
@@ -1,238 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'shared_examples/restore'
|
3
|
-
|
4
|
-
describe ChefBackup::Strategy::TarRestore do
|
5
|
-
let(:manifest) do
|
6
|
-
{ 'strategy' => 'tar',
|
7
|
-
'backup_time' => '2014-12-02-22-46-58',
|
8
|
-
'services' => {
|
9
|
-
'rabbitmq' => { 'data_dir' => '/var/opt/opscode/rabbitmq/db' },
|
10
|
-
'opscode-solr4' => {
|
11
|
-
'data_dir' => '/var/opt/opscode/opscode-solr4/data'
|
12
|
-
},
|
13
|
-
'redis_lb' => { 'data_dir' => '/var/opt/opscode/redis_lb/data' },
|
14
|
-
'postgresql' => {
|
15
|
-
'data_dir' => '/var/opt/opscode/postgresql/9.2/data',
|
16
|
-
'pg_dump_success' => pg_dump_success,
|
17
|
-
'username' => 'opscode-pgsql'
|
18
|
-
},
|
19
|
-
'bookshelf' => { 'data_dir' => '/var/opt/opscode/bookshelf/data' }
|
20
|
-
},
|
21
|
-
'configs' => {
|
22
|
-
'opscode' => { 'data_dir' => '/etc/opscode' },
|
23
|
-
'opscode-manage' => { 'data_dir' => '/etc/opscode-manage' },
|
24
|
-
'opscode-reporting' => { 'data_dir' => '/etc/opscode-reporting' },
|
25
|
-
'opscode-analytics' => { 'data_dir' => '/etc/opscode-analytics' }
|
26
|
-
}
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:pg_dump_success) { true }
|
31
|
-
let(:tarball_path) { '/var/backups/chef-backup-2014-12-02-22-46-58.tgz' }
|
32
|
-
let(:configs) { manifest['configs'].keys }
|
33
|
-
let(:services) { manifest['services'].keys }
|
34
|
-
let(:restore_dir) { ChefBackup::Config['restore_dir'] }
|
35
|
-
|
36
|
-
subject { described_class.new(tarball_path) }
|
37
|
-
|
38
|
-
before(:each) { use_default_cli_args }
|
39
|
-
|
40
|
-
describe '.restore' do
|
41
|
-
before do
|
42
|
-
%i(shell_out shell_out! unpack_tarball stop_chef_server ensure_file!
|
43
|
-
start_chef_server reconfigure_server cleanse_chef_server
|
44
|
-
update_config import_db touch_sentinel
|
45
|
-
).each do |method|
|
46
|
-
allow(subject).to receive(method).and_return(true)
|
47
|
-
end
|
48
|
-
configs.each do |config|
|
49
|
-
allow(subject)
|
50
|
-
.to receive(:restore_data)
|
51
|
-
.with(:configs, config)
|
52
|
-
.and_return(true)
|
53
|
-
end
|
54
|
-
services.each do |service|
|
55
|
-
allow(subject)
|
56
|
-
.to receive(:restore_data)
|
57
|
-
.with(:services, service)
|
58
|
-
.and_return(true)
|
59
|
-
end
|
60
|
-
|
61
|
-
allow(subject).to receive(:tarball_path).and_return(tarball_path)
|
62
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
63
|
-
end
|
64
|
-
|
65
|
-
it_behaves_like 'a tar based restore'
|
66
|
-
|
67
|
-
context 'on a frontend' do
|
68
|
-
before do
|
69
|
-
allow(subject).to receive(:frontend?).and_return(true)
|
70
|
-
end
|
71
|
-
|
72
|
-
it_behaves_like 'a tar based frontend restore'
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'on a backend' do
|
76
|
-
before do
|
77
|
-
allow(subject).to receive(:frontend?).and_return(false)
|
78
|
-
end
|
79
|
-
|
80
|
-
it_behaves_like 'a tar based backend restore'
|
81
|
-
|
82
|
-
context 'when a db dump is present' do
|
83
|
-
before do
|
84
|
-
allow(subject).to receive(:restore_db_dump?).and_return(true)
|
85
|
-
allow(subject)
|
86
|
-
.to receive(:start_service).with(:postgresql).and_return(true)
|
87
|
-
allow(subject).to receive(:import_db).and_return(true)
|
88
|
-
end
|
89
|
-
|
90
|
-
it_behaves_like 'a tar based backend restore with db dump'
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'when a db dump is not present' do
|
94
|
-
before do
|
95
|
-
allow(subject).to receive(:restore_db_dump?).and_return(false)
|
96
|
-
end
|
97
|
-
|
98
|
-
it_behaves_like 'a tar based backend restore without db dump'
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'on a standalone' do
|
103
|
-
before do
|
104
|
-
allow(subject).to receive(:frontend?).and_return(false)
|
105
|
-
end
|
106
|
-
|
107
|
-
it_behaves_like 'a tar based backend restore'
|
108
|
-
|
109
|
-
context 'when a db dump is present' do
|
110
|
-
before do
|
111
|
-
allow(subject).to receive(:restore_db_dump?).and_return(true)
|
112
|
-
end
|
113
|
-
|
114
|
-
it_behaves_like 'a tar based backend restore with db dump'
|
115
|
-
end
|
116
|
-
|
117
|
-
context 'when a db dump is not present' do
|
118
|
-
before do
|
119
|
-
allow(subject).to receive(:restore_db_dump?).and_return(false)
|
120
|
-
end
|
121
|
-
|
122
|
-
it_behaves_like 'a tar based backend restore without db dump'
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe '.manifest' do
|
128
|
-
let(:json) { "{\"some\":\"json\"}" }
|
129
|
-
let(:manifest_json) { File.join(restore_dir, 'manifest.json') }
|
130
|
-
|
131
|
-
it 'parses the manifest from the restore dir' do
|
132
|
-
allow(subject).to receive(:ensure_file!).and_return(true)
|
133
|
-
allow(File).to receive(:read).with(manifest_json).and_return(json)
|
134
|
-
expect(subject.manifest).to eq('some' => 'json')
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'raises an error if the manifest is invalid' do
|
138
|
-
expect { subject.manifest }
|
139
|
-
.to raise_error(
|
140
|
-
ChefBackup::Strategy::TarRestore::InvalidManifest,
|
141
|
-
"#{File.join(restore_dir, 'manifest.json')} not found"
|
142
|
-
)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe '.restore_data' do
|
147
|
-
before do
|
148
|
-
ChefBackup::Config['restore_dir'] = restore_dir
|
149
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
150
|
-
allow(subject).to receive(:shell_out!).and_return(true)
|
151
|
-
allow(File).to receive(:directory?).and_return(true)
|
152
|
-
end
|
153
|
-
|
154
|
-
context 'with config data' do
|
155
|
-
it 'rsyncs the config from the restore dir to the data_dir' do
|
156
|
-
source = File.expand_path(
|
157
|
-
File.join(restore_dir, manifest['configs']['opscode']['data_dir']))
|
158
|
-
destination = manifest['configs']['opscode']['data_dir']
|
159
|
-
cmd = "rsync -chaz --delete #{source}/ #{destination}"
|
160
|
-
|
161
|
-
expect(subject).to receive(:shell_out!).with(cmd)
|
162
|
-
subject.restore_data(:configs, 'opscode')
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
context 'with service data' do
|
167
|
-
it 'rsyncs the service from the restore dir to the data_dir' do
|
168
|
-
source = File.expand_path(
|
169
|
-
File.join(restore_dir, manifest['services']['rabbitmq']['data_dir']))
|
170
|
-
destination = manifest['services']['rabbitmq']['data_dir']
|
171
|
-
cmd = "rsync -chaz --delete #{source}/ #{destination}"
|
172
|
-
|
173
|
-
expect(subject).to receive(:shell_out!).with(cmd)
|
174
|
-
subject.restore_data(:services, 'rabbitmq')
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
describe '.import_db' do
|
180
|
-
before do
|
181
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
182
|
-
allow(subject).to receive(:shell_out!).and_return(true)
|
183
|
-
allow(subject).to receive(:running_config).and_return(running_config)
|
184
|
-
allow(subject)
|
185
|
-
.to receive(:start_service).with('postgresql').and_return(true)
|
186
|
-
end
|
187
|
-
|
188
|
-
context 'without a db dump' do
|
189
|
-
it 'raises an exception' do
|
190
|
-
expect { subject.import_db }
|
191
|
-
.to raise_error(ChefBackup::Exceptions::InvalidDatabaseDump)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
context 'with a db dump' do
|
196
|
-
let(:db_sql) do
|
197
|
-
File.join(restore_dir, "chef_backup-#{manifest['backup_time']}.sql")
|
198
|
-
end
|
199
|
-
|
200
|
-
let(:import_cmd) do
|
201
|
-
['/opt/opscode/embedded/bin/chpst -u opscode-pgsql',
|
202
|
-
'/opt/opscode/embedded/bin/psql -U opscode-pgsql',
|
203
|
-
"-d opscode_chef < #{db_sql}"
|
204
|
-
].join(' ')
|
205
|
-
end
|
206
|
-
|
207
|
-
before do
|
208
|
-
allow(subject)
|
209
|
-
.to receive(:ensure_file!)
|
210
|
-
.with(db_sql,
|
211
|
-
ChefBackup::Exceptions::InvalidDatabaseDump,
|
212
|
-
"#{db_sql} not found")
|
213
|
-
.and_return(true)
|
214
|
-
end
|
215
|
-
|
216
|
-
it 'imports the database' do
|
217
|
-
expect(subject).to receive(:shell_out!).with(import_cmd)
|
218
|
-
subject.import_db
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
describe '.touch_sentinel' do
|
224
|
-
let(:file) { double('File', write: true) }
|
225
|
-
let(:file_dir) { '/var/opt/opscode' }
|
226
|
-
let(:file_path) { File.join(file_dir, 'bootstrapped') }
|
227
|
-
|
228
|
-
before do
|
229
|
-
allow(FileUtils).to receive(:mkdir_p).with(file_dir).and_return(true)
|
230
|
-
allow(File).to receive(:open).with(file_path, 'w').and_yield(file)
|
231
|
-
end
|
232
|
-
|
233
|
-
it 'touches the bootstrap sentinel file' do
|
234
|
-
expect(file).to receive(:write).with('bootstrapped!')
|
235
|
-
subject.touch_sentinel
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
data/spec/unit/strategy_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ChefBackup::Strategy do
|
4
|
-
before do
|
5
|
-
# Backup Tester
|
6
|
-
class ChefBackup::Strategy::TestBackup
|
7
|
-
def initialize(_p = {})
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
# Restore Tester
|
12
|
-
class ChefBackup::Strategy::TestRestore
|
13
|
-
def initialize(_p = {})
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
after do
|
19
|
-
described_class.send(:remove_const, :TestBackup)
|
20
|
-
described_class.send(:remove_const, :TestRestore)
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '.backup' do
|
24
|
-
it 'it returns a backup strategy' do
|
25
|
-
expect(described_class.backup('test'))
|
26
|
-
.to be_an(ChefBackup::Strategy::TestBackup)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe '.restore' do
|
31
|
-
it 'it returns a restore strategy' do
|
32
|
-
expect(described_class.restore('test', '/some/backup.tgz'))
|
33
|
-
.to be_an(ChefBackup::Strategy::TestRestore)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|