chef_backup 0.0.1 → 0.1.0
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.rb +8 -8
- data/lib/chef_backup/config.rb +17 -17
- data/lib/chef_backup/data_map.rb +18 -12
- data/lib/chef_backup/deep_merge.rb +145 -0
- data/lib/chef_backup/helpers.rb +46 -10
- data/lib/chef_backup/logger.rb +2 -2
- data/lib/chef_backup/mash.rb +226 -0
- data/lib/chef_backup/runner.rb +11 -13
- data/lib/chef_backup/strategy.rb +10 -10
- 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 +23 -7
- data/lib/chef_backup/strategy/restore/tar.rb +69 -43
- data/lib/chef_backup/version.rb +1 -1
- metadata +20 -168
- 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 -98
- 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 -327
- 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 -255
- data/spec/unit/strategy_spec.rb +0 -36
File without changes
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
shared_examples 'a tar based backup' do
|
4
|
-
it 'populates the data map with services and configs' do
|
5
|
-
expect(subject).to receive(:populate_data_map).once
|
6
|
-
subject.backup
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'creates a backup manifest' do
|
10
|
-
expect(subject).to receive(:write_manifest).once
|
11
|
-
subject.backup
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'creates a tarball of the backup' do
|
15
|
-
expect(subject).to receive(:create_tarball).once
|
16
|
-
subject.backup
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'cleans up the temp directory' do
|
20
|
-
expect(subject).to receive(:cleanup).at_least(:once)
|
21
|
-
subject.backup
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
shared_examples 'a tar based frontend' do
|
26
|
-
it 'doesnt stop any services' do
|
27
|
-
expect(subject).to_not receive(:stop_service)
|
28
|
-
subject.backup
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'doesnt dump the db' do
|
32
|
-
expect(subject).to_not receive(:dump_db)
|
33
|
-
subject.backup
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
shared_examples 'a tar based online backend' do
|
38
|
-
it "doesn't start any services" do
|
39
|
-
expect(subject).to_not receive(:start_service)
|
40
|
-
subject.backup
|
41
|
-
end
|
42
|
-
|
43
|
-
it "doesn't stop any services" do
|
44
|
-
expect(subject).to_not receive(:stop_service)
|
45
|
-
subject.backup
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'dumps the db' do
|
49
|
-
expect(subject).to receive(:dump_db).once
|
50
|
-
subject.backup
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
shared_examples 'a tar based offline backend' do
|
55
|
-
it 'stops all services besides keepalived and postgres' do
|
56
|
-
expect(subject).to receive(:stop_chef_server).once
|
57
|
-
|
58
|
-
%w(postgresql keepalived).each do |service|
|
59
|
-
expect(subject).to_not receive(:stop_service).with(service)
|
60
|
-
end
|
61
|
-
|
62
|
-
subject.backup
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'starts all the services again' do
|
66
|
-
expect(subject).to receive(:start_chef_server).at_least(:once)
|
67
|
-
subject.backup
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'dumps the db' do
|
71
|
-
expect(subject).to receive(:dump_db).once
|
72
|
-
subject.backup
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'when the user has not agreed to go offline' do
|
76
|
-
before { private_chef('backup' => { 'agree_to_go_offline' => false }) }
|
77
|
-
|
78
|
-
it 'prompts the user' do
|
79
|
-
expect(subject).to receive(:ask_to_go_offline).once
|
80
|
-
subject.backup
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context 'when the user has agreed to go offline' do
|
85
|
-
before { private_chef('backup' => { 'agree_to_go_offline' => true }) }
|
86
|
-
|
87
|
-
it 'prompts the user' do
|
88
|
-
expect(subject).to_not receive(:ask_to_go_offline)
|
89
|
-
subject.backup
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,327 +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 'when config_only is true' do
|
30
|
-
before do
|
31
|
-
private_chef('backup' => { 'config_only' => true })
|
32
|
-
end
|
33
|
-
|
34
|
-
it_behaves_like 'a tar based backup'
|
35
|
-
it_behaves_like 'a tar based frontend'
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'on a frontend' do
|
39
|
-
before { private_chef('role' => 'frontend') }
|
40
|
-
|
41
|
-
it_behaves_like 'a tar based backup'
|
42
|
-
it_behaves_like 'a tar based frontend'
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'on a backend' do
|
46
|
-
before { private_chef('role' => 'backend') }
|
47
|
-
|
48
|
-
context 'during an online backup' do
|
49
|
-
before do
|
50
|
-
private_chef('role' => 'backend', 'backup' => { 'mode' => 'online' })
|
51
|
-
end
|
52
|
-
|
53
|
-
it_behaves_like 'a tar based backup'
|
54
|
-
it_behaves_like 'a tar based online backend'
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'during an offline backup' do
|
58
|
-
it_behaves_like 'a tar based backup'
|
59
|
-
it_behaves_like 'a tar based offline backend'
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'when no mode is configured' do
|
63
|
-
before do
|
64
|
-
private_chef('role' => 'backend', 'backup' => { 'mode' => nil })
|
65
|
-
end
|
66
|
-
|
67
|
-
it_behaves_like 'a tar based backup'
|
68
|
-
it_behaves_like 'a tar based offline backend'
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'on a standalone' do
|
73
|
-
before { private_chef('role' => 'standalone') }
|
74
|
-
|
75
|
-
context 'during an online backup' do
|
76
|
-
before do
|
77
|
-
private_chef('role' => 'standalone',
|
78
|
-
'backup' => { 'mode' => 'online' })
|
79
|
-
end
|
80
|
-
|
81
|
-
it_behaves_like 'a tar based backup'
|
82
|
-
it_behaves_like 'a tar based online backend'
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'during an offline backup' do
|
86
|
-
it_behaves_like 'a tar based backup'
|
87
|
-
it_behaves_like 'a tar based offline backend'
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when no mode is configured' do
|
91
|
-
before do
|
92
|
-
private_chef('role' => 'standalone', 'backup' => { 'mode' => nil })
|
93
|
-
end
|
94
|
-
|
95
|
-
it_behaves_like 'a tar based backup'
|
96
|
-
it_behaves_like 'a tar based offline backend'
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe '.dump_db' do
|
102
|
-
let(:dump_cmd) do
|
103
|
-
['/opt/opscode/embedded/bin/chpst',
|
104
|
-
'-u opscode-pgsql',
|
105
|
-
'/opt/opscode/embedded/bin/pg_dumpall',
|
106
|
-
"> #{tmp_dir}/chef_backup-#{backup_time}.sql"
|
107
|
-
].join(' ')
|
108
|
-
end
|
109
|
-
|
110
|
-
let(:pg_options) { ["PGOPTIONS=#{ChefBackup::Helpers::DEFAULT_PG_OPTIONS}"] }
|
111
|
-
let(:tmp_dir) { '/tmp/notaswear' }
|
112
|
-
let(:backup_time) { Time.now }
|
113
|
-
|
114
|
-
before do
|
115
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir)
|
116
|
-
allow(subject).to receive(:backup_time).and_return(backup_time)
|
117
|
-
allow(subject).to receive(:shell_out!).with(dump_cmd, env: pg_options).and_return(true)
|
118
|
-
private_chef('postgresql' => { 'username' => 'opscode-pgsql' })
|
119
|
-
subject.data_map.add_service('postgresql', '/data/dir')
|
120
|
-
end
|
121
|
-
|
122
|
-
%w(backend standalone).each do |role|
|
123
|
-
context "on a #{role}" do
|
124
|
-
before do
|
125
|
-
private_chef('role' => role)
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'dumps the db' do
|
129
|
-
expect(subject).to receive(:shell_out!).with(dump_cmd, env: pg_options)
|
130
|
-
subject.dump_db
|
131
|
-
end
|
132
|
-
|
133
|
-
it 'updates the data map' do
|
134
|
-
subject.dump_db
|
135
|
-
expect(subject.data_map.services['postgresql'])
|
136
|
-
.to include('pg_dump_success' => true)
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'adds the postgresql username to the data map' do
|
140
|
-
subject.dump_db
|
141
|
-
expect(subject.data_map.services['postgresql'])
|
142
|
-
.to include('username' => 'opscode-pgsql')
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'on a frontend' do
|
148
|
-
before { private_chef('role' => 'frontend') }
|
149
|
-
|
150
|
-
it "doesn't dump the db" do
|
151
|
-
expect(subject).to_not receive(:shell_out).with(/pg_dumpall/)
|
152
|
-
subject.dump_db
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
describe '.create_tarball' do
|
158
|
-
before do
|
159
|
-
allow(subject).to receive(:data_map).and_return(data_map)
|
160
|
-
allow(Dir).to receive(:[]).and_return(%w(sql.sql manifest.json))
|
161
|
-
end
|
162
|
-
|
163
|
-
it 'creates a tarball with all items in the temp directory' do
|
164
|
-
cmd = [
|
165
|
-
"tar -czf #{tmp_dir}/chef-backup-#{backup_time}.tgz",
|
166
|
-
data_map.services.map { |_, v| v['data_dir'] }.compact.join(' '),
|
167
|
-
data_map.configs.map { |_, v| v['data_dir'] }.compact.join(' '),
|
168
|
-
Dir["#{tmp_dir}/*"].map { |f| File.basename(f) }.join(' ')
|
169
|
-
].join(' ').strip
|
170
|
-
|
171
|
-
allow(subject).to receive(:shell_out).with(cmd, cdw: tmp_dir)
|
172
|
-
expect(subject).to receive(:shell_out).with(cmd, cwd: tmp_dir)
|
173
|
-
subject.create_tarball
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
describe '.export_tarball' do
|
178
|
-
before do
|
179
|
-
allow(subject).to receive(:export_dir).and_return('/mnt/chef-backups')
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'moves the tarball to the archive location' do
|
183
|
-
cmd = "rsync -chaz #{tmp_dir}/chef-backup-#{backup_time}.tgz"
|
184
|
-
cmd << " #{export_dir}/"
|
185
|
-
|
186
|
-
allow(subject).to receive(:shell_out).with(cmd)
|
187
|
-
expect(subject).to receive(:shell_out).with(cmd)
|
188
|
-
subject.export_tarball
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe '.write_manifest' do
|
193
|
-
let(:manifest) do
|
194
|
-
{ 'some' =>
|
195
|
-
{
|
196
|
-
'nested' => {
|
197
|
-
'hash' => true
|
198
|
-
},
|
199
|
-
'another' => true
|
200
|
-
}
|
201
|
-
}
|
202
|
-
end
|
203
|
-
|
204
|
-
let(:file) { double('file', write: true) }
|
205
|
-
|
206
|
-
before do
|
207
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
208
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir)
|
209
|
-
allow(File).to receive(:open).and_yield(file)
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'converts the manifest to json' do
|
213
|
-
json_manifest = JSON.pretty_generate(subject.manifest)
|
214
|
-
expect(file).to receive(:write).with(json_manifest)
|
215
|
-
subject.write_manifest
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'writes a json file to the tmp_dir' do
|
219
|
-
expect(File).to receive(:open).with("#{tmp_dir}/manifest.json", 'w')
|
220
|
-
subject.write_manifest
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe '.populate_data_map' do
|
225
|
-
let(:services) { %w(opscode-solr4 bookshelf rabbitmq) }
|
226
|
-
let(:configs) { %w(opscode opscode-manage opscode-analytics) }
|
227
|
-
let(:config) do
|
228
|
-
{ 'bookshelf' => { 'data_dir' => '/bookshelf/data' },
|
229
|
-
'opscode-solr4' => { 'data_dir' => '/solr4/data' },
|
230
|
-
'rabbitmq' => { 'data_dir' => '/rabbitmq/data' }
|
231
|
-
}
|
232
|
-
end
|
233
|
-
|
234
|
-
before do
|
235
|
-
allow(subject).to receive(:data_map).and_return(data_map)
|
236
|
-
allow(subject).to receive(:stateful_services).and_return(services)
|
237
|
-
allow(subject).to receive(:config_directories).and_return(configs)
|
238
|
-
%w(add_service add_config add_ha_info).each do |method|
|
239
|
-
allow(data_map).to receive(method.to_sym).and_return(true)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
%w(frontend backend standalone).each do |role|
|
244
|
-
context "on a #{role}" do
|
245
|
-
before { private_chef(config.merge('role' => role)) }
|
246
|
-
|
247
|
-
it 'populates the data map with config directories' do
|
248
|
-
configs.each do |config|
|
249
|
-
expect(subject.data_map)
|
250
|
-
.to receive(:add_config)
|
251
|
-
.with(config, "/etc/#{config}")
|
252
|
-
end
|
253
|
-
|
254
|
-
subject.populate_data_map
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
%w(backend standalone).each do |role|
|
260
|
-
context "on a #{role}" do
|
261
|
-
before { private_chef(config.merge('role' => role)) }
|
262
|
-
|
263
|
-
it 'populates the data map with service directories' do
|
264
|
-
services.each do |service|
|
265
|
-
expect(subject.data_map)
|
266
|
-
.to receive(:add_service)
|
267
|
-
.with(service, config[service]['data_dir'])
|
268
|
-
end
|
269
|
-
|
270
|
-
subject.populate_data_map
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'populates the data map with the upgrades' do
|
274
|
-
expect(subject.data_map)
|
275
|
-
.to receive(:add_service)
|
276
|
-
.with('upgrades', '/var/opt/opscode/upgrades')
|
277
|
-
|
278
|
-
subject.populate_data_map
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
context 'when config_only is true' do
|
284
|
-
before do
|
285
|
-
private_chef('role' => 'standalone', 'backup' => { 'config_only' => true })
|
286
|
-
data_mock = double('DataMap')
|
287
|
-
allow(subject).to receive(:data_map).and_return(data_mock)
|
288
|
-
end
|
289
|
-
|
290
|
-
it 'populates the data map with config and upgrade directories only' do
|
291
|
-
configs.each do |config|
|
292
|
-
expect(subject.data_map)
|
293
|
-
.to receive(:add_config)
|
294
|
-
.with(config, "/etc/#{config}")
|
295
|
-
end
|
296
|
-
|
297
|
-
expect(subject.data_map)
|
298
|
-
.to receive(:add_service)
|
299
|
-
.with('upgrades', '/var/opt/opscode/upgrades')
|
300
|
-
|
301
|
-
subject.populate_data_map
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
context 'on a frontend' do
|
306
|
-
before { private_chef(config.merge('role' => 'frontend')) }
|
307
|
-
|
308
|
-
it "doesn't populate the data map with the services" do
|
309
|
-
expect(subject.data_map).to_not receive(:add_service)
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
describe '.pg_dump?' do
|
315
|
-
it 'returns true' do
|
316
|
-
expect(subject.pg_dump?).to eq(true)
|
317
|
-
end
|
318
|
-
|
319
|
-
context 'when db dump is disabled' do
|
320
|
-
before { private_chef('backup' => { 'always_dump_db' => false }) }
|
321
|
-
|
322
|
-
it 'returns false' do
|
323
|
-
expect(subject.pg_dump?).to eq(false)
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
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
|