chef_backup 0.0.1.dev.4 → 0.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/lib/chef_backup/config.rb +22 -12
  3. data/lib/chef_backup/data_map.rb +18 -12
  4. data/lib/chef_backup/deep_merge.rb +145 -0
  5. data/lib/chef_backup/helpers.rb +154 -28
  6. data/lib/chef_backup/logger.rb +11 -6
  7. data/lib/chef_backup/mash.rb +226 -0
  8. data/lib/chef_backup/runner.rb +24 -21
  9. data/lib/chef_backup/strategy/backup/custom.rb +1 -2
  10. data/lib/chef_backup/strategy/backup/ebs.rb +3 -6
  11. data/lib/chef_backup/strategy/backup/lvm.rb +2 -4
  12. data/lib/chef_backup/strategy/backup/object.rb +2 -4
  13. data/lib/chef_backup/strategy/backup/tar.rb +96 -40
  14. data/lib/chef_backup/strategy/restore/tar.rb +81 -51
  15. data/lib/chef_backup/strategy.rb +10 -10
  16. data/lib/chef_backup/version.rb +1 -1
  17. data/lib/chef_backup.rb +8 -8
  18. metadata +21 -162
  19. data/.gitignore +0 -23
  20. data/.kitchen.yml +0 -30
  21. data/.rubocop.yml +0 -21
  22. data/.travis.yml +0 -6
  23. data/Gemfile +0 -4
  24. data/Guardfile +0 -22
  25. data/README.md +0 -21
  26. data/Rakefile +0 -44
  27. data/chef_backup.gemspec +0 -33
  28. data/spec/fixtures/chef-server-running.json +0 -589
  29. data/spec/spec_helper.rb +0 -103
  30. data/spec/unit/data_map_spec.rb +0 -59
  31. data/spec/unit/helpers_spec.rb +0 -88
  32. data/spec/unit/runner_spec.rb +0 -185
  33. data/spec/unit/shared_examples/helpers.rb +0 -20
  34. data/spec/unit/strategy/backup/lvm_spec.rb +0 -0
  35. data/spec/unit/strategy/backup/shared_examples/backup.rb +0 -92
  36. data/spec/unit/strategy/backup/tar_spec.rb +0 -294
  37. data/spec/unit/strategy/restore/lvm_spec.rb +0 -0
  38. data/spec/unit/strategy/restore/shared_examples/restore.rb +0 -84
  39. data/spec/unit/strategy/restore/tar_spec.rb +0 -238
  40. data/spec/unit/strategy_spec.rb +0 -36
data/spec/spec_helper.rb DELETED
@@ -1,103 +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
- # Merge attributes into existing cli_args
21
- def cli_args(*args)
22
- Chef::Mixin::DeepMerge.deep_merge!(*args, ChefBackup::Config.config)
23
- end
24
-
25
- # Overwrite config with given CLI args
26
- def cli_args!(args)
27
- ChefBackup::Config.config = args
28
- end
29
-
30
- def use_default_running_config
31
- ChefBackup::Config.config = running_config
32
- end
33
-
34
- def use_default_cli_args
35
- ChefBackup::Config.config = cli_args
36
- end
37
-
38
- def clear_config
39
- ChefBackup::Config.config = {}
40
- end
41
-
42
- def set_common_variables
43
- let(:backup_tarball) { '/tmp/chef-backup-2014-12-10-20-31-40.tgz' }
44
- let(:backup_time) { '2014-08-21T23:10:57-07:00' }
45
- let(:tmp_dir) { '/tmp/chef-backup' }
46
- let(:strategy) { 'test' }
47
- let(:export_dir) { '/mnt/chef-backups' }
48
- let(:all_services) do
49
- %w(nginx oc_bifrost oc_id opscode-erchef opscode-expander
50
- opscode-expander-reindexer opscode-solr4 postgresql rabbitmq redis_lb
51
- )
52
- end
53
- let(:enabled_services) { all_services }
54
- let(:data_map) do
55
- double(
56
- 'DataMap',
57
- services: {
58
- 'postgresql' => {
59
- 'data_dir' => '/var/opt/opscode/postgresql_9.2/data'
60
- },
61
- 'couchdb' => {
62
- 'data_dir' => '/var/opt/opscode/couchdb/data'
63
- },
64
- 'rabbitmq' => {
65
- 'data_dir' => '/var/opt/opscode/rabbitdb/data'
66
- }
67
- },
68
- configs: {
69
- 'opscode' => {
70
- 'data_dir' => '/etc/opscode'
71
- },
72
- 'opscode-manage' => {
73
- 'data_dir' => '/etc/opscode-manage'
74
- }
75
- }
76
- )
77
- end
78
- end
79
-
80
- def running_config
81
- @config ||= begin
82
- f = File.expand_path('../fixtures/chef-server-running.json', __FILE__)
83
- JSON.parse(File.read(f))
84
- end
85
- @config.dup
86
- end
87
-
88
- def cli_args
89
- {
90
- 'tmp_dir' => '/tmp/chef_backup/tmp_dir',
91
- 'agree_to_cleanse' => nil,
92
- 'restore_arg' => '/tmp/chef_backup/backup.tgz',
93
- 'restore_dir' => File.join('/tmp/chef_backup/tmp_dir', 'restore_dir')
94
- }
95
- end
96
-
97
- RSpec.configure do |rspec|
98
- rspec.run_all_when_everything_filtered = true
99
- rspec.filter_run :focus
100
- rspec.order = 'random'
101
- rspec.expect_with(:rspec) { |c| c.syntax = :expect }
102
- rspec.before { allow($stdout).to receive(:write) }
103
- end
@@ -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
@@ -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
@@ -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
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