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
data/spec/spec_helper.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
SimpleCov.start
|
3
|
-
|
4
|
-
require 'chef_backup'
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'json'
|
7
|
-
require 'tempfile'
|
8
|
-
require 'chef/mixin/deep_merge'
|
9
|
-
|
10
|
-
# Merge attributes into existing running_config
|
11
|
-
def private_chef(*args)
|
12
|
-
Chef::Mixin::DeepMerge.deep_merge!(*args, ChefBackup::Config['private_chef'])
|
13
|
-
end
|
14
|
-
|
15
|
-
# Overwrite config with given attributes
|
16
|
-
def private_chef!(args = {})
|
17
|
-
ChefBackup::Config.config = args
|
18
|
-
end
|
19
|
-
|
20
|
-
# Overwrite config with given CLI args
|
21
|
-
def cli_args!(args)
|
22
|
-
ChefBackup::Config.config = args
|
23
|
-
end
|
24
|
-
|
25
|
-
def use_default_running_config
|
26
|
-
ChefBackup::Config.config = running_config
|
27
|
-
end
|
28
|
-
|
29
|
-
def use_default_cli_args
|
30
|
-
ChefBackup::Config.config = cli_args
|
31
|
-
end
|
32
|
-
|
33
|
-
def clear_config
|
34
|
-
ChefBackup::Config.config = {}
|
35
|
-
end
|
36
|
-
|
37
|
-
def set_common_variables
|
38
|
-
let(:backup_tarball) { '/tmp/chef-backup-2014-12-10-20-31-40.tgz' }
|
39
|
-
let(:backup_time) { '2014-08-21T23:10:57-07:00' }
|
40
|
-
let(:tmp_dir) { '/tmp/chef-backup' }
|
41
|
-
let(:strategy) { 'test' }
|
42
|
-
let(:export_dir) { '/mnt/chef-backups' }
|
43
|
-
let(:all_services) do
|
44
|
-
%w(nginx oc_bifrost oc_id opscode-erchef opscode-expander
|
45
|
-
opscode-expander-reindexer opscode-solr4 postgresql rabbitmq redis_lb
|
46
|
-
)
|
47
|
-
end
|
48
|
-
let(:enabled_services) { all_services }
|
49
|
-
let(:data_map) do
|
50
|
-
double(
|
51
|
-
'DataMap',
|
52
|
-
services: {
|
53
|
-
'postgresql' => {
|
54
|
-
'data_dir' => '/var/opt/opscode/postgresql_9.2/data'
|
55
|
-
},
|
56
|
-
'couchdb' => {
|
57
|
-
'data_dir' => '/var/opt/opscode/couchdb/data'
|
58
|
-
},
|
59
|
-
'rabbitmq' => {
|
60
|
-
'data_dir' => '/var/opt/opscode/rabbitdb/data'
|
61
|
-
}
|
62
|
-
},
|
63
|
-
configs: {
|
64
|
-
'opscode' => {
|
65
|
-
'data_dir' => '/etc/opscode'
|
66
|
-
},
|
67
|
-
'opscode-manage' => {
|
68
|
-
'data_dir' => '/etc/opscode-manage'
|
69
|
-
}
|
70
|
-
}
|
71
|
-
)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def running_config
|
76
|
-
@config ||= begin
|
77
|
-
f = File.expand_path('../fixtures/chef-server-running.json', __FILE__)
|
78
|
-
JSON.parse(File.read(f))
|
79
|
-
end
|
80
|
-
@config.dup
|
81
|
-
end
|
82
|
-
|
83
|
-
def cli_args
|
84
|
-
{
|
85
|
-
'tmp_dir' => '/tmp/chef_backup/tmp_dir',
|
86
|
-
'agree_to_cleanse' => nil,
|
87
|
-
'restore_arg' => '/tmp/chef_backup/backup.tgz',
|
88
|
-
'restore_dir' => File.join('/tmp/chef_backup/tmp_dir', 'restore_dir')
|
89
|
-
}
|
90
|
-
end
|
91
|
-
|
92
|
-
RSpec.configure do |rspec|
|
93
|
-
rspec.run_all_when_everything_filtered = true
|
94
|
-
rspec.filter_run :focus
|
95
|
-
rspec.order = 'random'
|
96
|
-
rspec.expect_with(:rspec) { |c| c.syntax = :expect }
|
97
|
-
rspec.before { allow($stdout).to receive(:write) }
|
98
|
-
end
|
data/spec/unit/data_map_spec.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ChefBackup::DataMap do
|
4
|
-
set_common_variables
|
5
|
-
|
6
|
-
describe '.initialize' do
|
7
|
-
it 'yields a config block' do
|
8
|
-
expect { |b| described_class.new(&b) }.to yield_with_args
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '.add_service' do
|
13
|
-
subject { described_class.new }
|
14
|
-
|
15
|
-
it 'adds a service' do
|
16
|
-
subject.add_service('bookshelf', '/bookshelf/path')
|
17
|
-
expect(subject.services.keys.count).to eq(1)
|
18
|
-
expect(subject.services['bookshelf']['data_dir']).to eq('/bookshelf/path')
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '.add_config' do
|
23
|
-
subject { described_class.new }
|
24
|
-
|
25
|
-
it 'adds a config' do
|
26
|
-
subject.add_config('opscode-manage', '/opscode-manage/path')
|
27
|
-
expect(subject.configs.keys.count).to eq(1)
|
28
|
-
expect(subject.configs['opscode-manage']['data_dir'])
|
29
|
-
.to eq('/opscode-manage/path')
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '.manifest' do
|
34
|
-
subject do
|
35
|
-
described_class.new do |dm|
|
36
|
-
dm.strategy = 'test'
|
37
|
-
dm.backup_time = backup_time
|
38
|
-
dm.add_config('somethingstrange', 'inthehood')
|
39
|
-
dm.add_service('whoyagonnacall', 'ghostbusters')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'includes the backup strategy type' do
|
44
|
-
expect(subject.manifest).to include('strategy' => 'test')
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'includes the backup timestamp' do
|
48
|
-
expect(subject.manifest).to include('backup_time' => backup_time)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'includes the backup config' do
|
52
|
-
expect(subject.manifest).to include('configs' => subject.configs)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'includes the backup service' do
|
56
|
-
expect(subject.manifest).to include('services' => subject.services)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/spec/unit/helpers_spec.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'shared_examples/helpers'
|
3
|
-
|
4
|
-
describe ChefBackup::Helpers do
|
5
|
-
let(:tmp_dir_path) { '/tmp/chef_backup/tmp_dir' }
|
6
|
-
|
7
|
-
before do
|
8
|
-
# Test class to include our helpers methods
|
9
|
-
class HelperTest; include ChefBackup::Helpers; end
|
10
|
-
end
|
11
|
-
|
12
|
-
after do
|
13
|
-
Object.send(:remove_const, :HelperTest)
|
14
|
-
end
|
15
|
-
|
16
|
-
subject { HelperTest.new }
|
17
|
-
|
18
|
-
describe '.tmp_dir' do
|
19
|
-
context 'with CLI args' do
|
20
|
-
before { private_chef!('tmp_dir' => tmp_dir_path) }
|
21
|
-
|
22
|
-
context 'when the directory exists' do
|
23
|
-
before do
|
24
|
-
allow(File)
|
25
|
-
.to receive(:directory?).with(tmp_dir_path).and_return(true)
|
26
|
-
end
|
27
|
-
|
28
|
-
it_behaves_like '.tmp_dir with an existing specified directory'
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'when the directory does not exist' do
|
32
|
-
before do
|
33
|
-
allow(File)
|
34
|
-
.to receive(:directory?).with(tmp_dir_path).and_return(false)
|
35
|
-
allow(FileUtils)
|
36
|
-
.to receive(:mkdir_p).with(tmp_dir_path).and_return([tmp_dir_path])
|
37
|
-
end
|
38
|
-
|
39
|
-
it_behaves_like '.tmp_dir with a nonexisting specified directory'
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'with running_config args' do
|
44
|
-
before { private_chef!('tmp_dir' => tmp_dir_path) }
|
45
|
-
|
46
|
-
context 'when the directory exists' do
|
47
|
-
before do
|
48
|
-
allow(File)
|
49
|
-
.to receive(:directory?).with(tmp_dir_path).and_return(true)
|
50
|
-
end
|
51
|
-
|
52
|
-
it_behaves_like '.tmp_dir with an existing specified directory'
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'when the directory does not exist' do
|
56
|
-
before do
|
57
|
-
allow(File)
|
58
|
-
.to receive(:directory?).with(tmp_dir_path).and_return(false)
|
59
|
-
allow(FileUtils)
|
60
|
-
.to receive(:mkdir_p).with(tmp_dir_path).and_return([tmp_dir_path])
|
61
|
-
end
|
62
|
-
|
63
|
-
it_behaves_like '.tmp_dir with a nonexisting specified directory'
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'when no args are passed' do
|
68
|
-
before do
|
69
|
-
clear_config
|
70
|
-
allow(Dir).to receive(:mktmpdir).with('chef_backup')
|
71
|
-
end
|
72
|
-
|
73
|
-
it_behaves_like '.tmp_dir without a specified directory'
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe '.cleanup' do
|
78
|
-
before do
|
79
|
-
allow(subject).to receive(:tmp_dir).and_return(tmp_dir_path)
|
80
|
-
allow(FileUtils).to receive(:rm_r).with(tmp_dir_path)
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'cleans up all items in the temp directory' do
|
84
|
-
expect(FileUtils).to receive(:rm_r).with(tmp_dir_path)
|
85
|
-
subject.cleanup
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
data/spec/unit/runner_spec.rb
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ChefBackup::Runner do
|
4
|
-
let(:test_strategy) { double('TestBackup', backup: true, restore: true) }
|
5
|
-
let(:backup_tarball) { '/tmp/chef-backup-2014-12-10-20-31-40.tgz' }
|
6
|
-
let(:backup_name) { 'chef-backup-2014-12-10-20-31-40' }
|
7
|
-
let(:restore_dir) { ChefBackup::Config['restore_dir'] }
|
8
|
-
let(:manifest_json) { "#{restore_dir}/manifest.json" }
|
9
|
-
let(:manifest) { { 'strategy' => 'test_strategy' } }
|
10
|
-
let(:json) { '{"some":{"nested":{"hash":1}}}' }
|
11
|
-
let(:runner_config) do
|
12
|
-
{
|
13
|
-
'tmp_dir' => '/tmp/runner_spec_tmp_dir',
|
14
|
-
'restore_param' => backup_tarball,
|
15
|
-
'agree_to_cleanse' => 'yes',
|
16
|
-
'private_chef' => { 'backup' => { 'strategy' => 'test' } }
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
subject { described_class.new(runner_config) }
|
21
|
-
|
22
|
-
describe '.backup' do
|
23
|
-
it 'initializes a ChefBackup::Strategy and calls .backup' do
|
24
|
-
allow(ChefBackup::Strategy)
|
25
|
-
.to receive(:backup)
|
26
|
-
.with('test')
|
27
|
-
.and_return(test_strategy)
|
28
|
-
|
29
|
-
expect(test_strategy).to receive(:backup).once
|
30
|
-
subject.backup
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '.restore' do
|
35
|
-
it 'initializes a ChefBackup::Strategy and calls .restore' do
|
36
|
-
allow(subject).to receive(:restore_strategy).and_return('test')
|
37
|
-
allow(ChefBackup::Strategy)
|
38
|
-
.to receive(:restore)
|
39
|
-
.with('test', backup_tarball)
|
40
|
-
.and_return(test_strategy)
|
41
|
-
|
42
|
-
expect(test_strategy).to receive(:restore).once
|
43
|
-
subject.restore
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe '.manifest' do
|
48
|
-
before do
|
49
|
-
allow(subject).to receive(:restore_directory).and_return(restore_dir)
|
50
|
-
allow(subject).to receive(:ensure_file!).and_return(true)
|
51
|
-
allow(File).to receive(:read).with(manifest_json).and_return(json)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'verifies that the file exists' do
|
55
|
-
expect(subject).to receive(:ensure_file!)
|
56
|
-
subject.manifest
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'parses the manifest.json' do
|
60
|
-
expect(subject.manifest).to eq(JSON.parse(json).to_h)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe '.restore_directory' do
|
65
|
-
let(:rest_dir) do
|
66
|
-
ChefBackup::Config['tmp_dir'] = '/tmp/chef_backup'
|
67
|
-
File.join(ChefBackup::Config['tmp_dir'], backup_name)
|
68
|
-
end
|
69
|
-
|
70
|
-
before(:each) do
|
71
|
-
ChefBackup::Config['tmp_dir'] = '/tmp/chef_backup'
|
72
|
-
allow(subject).to receive(:backup_name).and_return(backup_name)
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'when the restore directory already exists' do
|
76
|
-
before do
|
77
|
-
allow(File).to receive(:directory?).and_return(true)
|
78
|
-
allow(Dir).to receive(:glob).and_return(%w(a b c))
|
79
|
-
allow(FileUtils).to receive(:rm_r).and_return(true)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'cleans the restore directory' do
|
83
|
-
# The directory needs to exist but has not been set in the config
|
84
|
-
ChefBackup::Config['restore_dir'] = nil
|
85
|
-
expect(FileUtils).to receive(:rm_r).with(%w(a b c))
|
86
|
-
subject.restore_directory
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'does not create a new directory' do
|
90
|
-
ChefBackup::Config['restore_dir'] = '/tmp/restore_dir'
|
91
|
-
subject.restore_directory
|
92
|
-
expect(ChefBackup::Config['restore_dir']).to eq(restore_dir)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
context 'when the restore directory does not exist' do
|
97
|
-
before do
|
98
|
-
allow(File).to receive(:directory?).and_return(false)
|
99
|
-
allow(FileUtils).to receive(:rm_r).and_return(true)
|
100
|
-
allow(FileUtils).to receive(:mkdir_p).and_return(true)
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'creates a restore directory in the runner tmp_dir' do
|
104
|
-
ChefBackup::Config['restore_dir'] = nil
|
105
|
-
expect(FileUtils).to receive(:mkdir_p).with(rest_dir)
|
106
|
-
subject.restore_directory
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'updates the config with the restore dir' do
|
110
|
-
ChefBackup::Config['restore_dir'] = nil
|
111
|
-
subject.restore_directory
|
112
|
-
expect(ChefBackup::Config['restore_dir']).to eq(restore_dir)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
describe '.unpack_tarball' do
|
118
|
-
before do
|
119
|
-
allow(subject).to receive(:restore_param).and_return(backup_tarball)
|
120
|
-
allow(subject).to receive(:restore_directory).and_return(restore_dir)
|
121
|
-
allow(subject).to receive(:shell_out!).and_return(true)
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'raises an error if the tarball is invalid' do
|
125
|
-
allow(File)
|
126
|
-
.to receive(:exist?).with(backup_tarball).and_return(false)
|
127
|
-
expect { subject.unpack_tarball }
|
128
|
-
.to raise_error(ChefBackup::Exceptions::InvalidTarball,
|
129
|
-
"#{backup_tarball} not found")
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'explodes the tarball into the restore directory' do
|
133
|
-
allow(subject).to receive(:ensure_file!).and_return(true)
|
134
|
-
|
135
|
-
cmd = "tar zxf #{backup_tarball} -C #{restore_dir}"
|
136
|
-
expect(subject).to receive(:shell_out!).with(cmd)
|
137
|
-
subject.unpack_tarball
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe '.restore_strategy' do
|
142
|
-
context 'when the restore param is a tarball' do
|
143
|
-
before do
|
144
|
-
allow(subject).to receive(:tarball?).and_return(true)
|
145
|
-
allow(subject).to receive(:unpack_tarball).and_return(true)
|
146
|
-
allow(subject).to receive(:manifest).and_return(manifest)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'unpacks the tarball' do
|
150
|
-
expect(subject).to receive(:unpack_tarball)
|
151
|
-
subject.restore_strategy
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'returns the strategy from the manifest' do
|
155
|
-
expect(subject.restore_strategy).to eq('test_strategy')
|
156
|
-
subject.restore_strategy
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
context 'when the restore param is an ebs snapshot' do
|
161
|
-
before do
|
162
|
-
allow(subject).to receive(:tarball?).and_return(false)
|
163
|
-
allow(subject).to receive(:ebs_snapshot?).and_return(true)
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'returns "ebs" as the strategy' do
|
167
|
-
expect(subject.restore_strategy).to eq('ebs')
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
context 'when the restore param is not valid' do
|
172
|
-
before do
|
173
|
-
allow(subject).to receive(:tarball?).and_return(false)
|
174
|
-
allow(subject).to receive(:ebs_snapshot?).and_return(false)
|
175
|
-
allow(subject).to receive(:restore_param).and_return('invalid_param')
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'raises an exception' do
|
179
|
-
expect { subject.restore_strategy }
|
180
|
-
.to raise_error(ChefBackup::Exceptions::InvalidStrategy,
|
181
|
-
'invalid_param is not a valid backup')
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
shared_examples '.tmp_dir with a nonexisting specified directory' do
|
2
|
-
it 'uses the specified directory' do
|
3
|
-
expect(FileUtils).to receive(:mkdir_p).with(tmp_dir_path)
|
4
|
-
expect(subject.tmp_dir).to eq(tmp_dir_path)
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
shared_examples '.tmp_dir with an existing specified directory' do
|
9
|
-
it 'does not create a directory' do
|
10
|
-
expect(FileUtils).to_not receive(:anything)
|
11
|
-
expect(subject.tmp_dir).to eq(tmp_dir_path)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
shared_examples '.tmp_dir without a specified directory' do
|
16
|
-
it 'creates a temp directory' do
|
17
|
-
expect(Dir).to receive(:mktmpdir).with('chef_backup')
|
18
|
-
subject.tmp_dir
|
19
|
-
end
|
20
|
-
end
|