dop_common 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +176 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +177 -0
- data/README.md +48 -0
- data/Rakefile +49 -0
- data/Vagrantfile +25 -0
- data/bin/dop-puppet-autosign +56 -0
- data/doc/examples/example_deploment_plan_v0.0.1.yaml +302 -0
- data/doc/plan_format_v0.0.1.md +919 -0
- data/doc/plan_format_v0.0.2_snippets.md +56 -0
- data/dop_common.gemspec +44 -0
- data/lib/dop_common/affinity_group.rb +57 -0
- data/lib/dop_common/cli/global_options.rb +37 -0
- data/lib/dop_common/cli/log.rb +51 -0
- data/lib/dop_common/cli/node_selection.rb +62 -0
- data/lib/dop_common/command.rb +125 -0
- data/lib/dop_common/config/helper.rb +39 -0
- data/lib/dop_common/config.rb +66 -0
- data/lib/dop_common/configuration.rb +37 -0
- data/lib/dop_common/credential.rb +152 -0
- data/lib/dop_common/data_disk.rb +62 -0
- data/lib/dop_common/dns.rb +55 -0
- data/lib/dop_common/hash_parser.rb +241 -0
- data/lib/dop_common/hooks.rb +81 -0
- data/lib/dop_common/infrastructure.rb +160 -0
- data/lib/dop_common/infrastructure_properties.rb +185 -0
- data/lib/dop_common/interface.rb +113 -0
- data/lib/dop_common/log.rb +78 -0
- data/lib/dop_common/network.rb +85 -0
- data/lib/dop_common/node/config.rb +159 -0
- data/lib/dop_common/node.rb +442 -0
- data/lib/dop_common/node_filter.rb +74 -0
- data/lib/dop_common/plan.rb +188 -0
- data/lib/dop_common/plan_cache.rb +83 -0
- data/lib/dop_common/plan_store.rb +263 -0
- data/lib/dop_common/pre_processor.rb +73 -0
- data/lib/dop_common/run_options.rb +56 -0
- data/lib/dop_common/signal_handler.rb +58 -0
- data/lib/dop_common/state_store.rb +95 -0
- data/lib/dop_common/step.rb +200 -0
- data/lib/dop_common/step_set.rb +41 -0
- data/lib/dop_common/thread_context_logger.rb +77 -0
- data/lib/dop_common/utils.rb +106 -0
- data/lib/dop_common/validator.rb +53 -0
- data/lib/dop_common/version.rb +3 -0
- data/lib/dop_common.rb +32 -0
- data/lib/hiera/backend/dop_backend.rb +94 -0
- data/lib/hiera/dop_logger.rb +20 -0
- data/spec/data/fake_hook_file_invalid +1 -0
- data/spec/data/fake_hook_file_valid +5 -0
- data/spec/data/fake_keyfile +1 -0
- data/spec/dop-puppet-autosign_spec_disable.rb +33 -0
- data/spec/dop_common/affinity_group_spec.rb +41 -0
- data/spec/dop_common/command_spec.rb +83 -0
- data/spec/dop_common/credential_spec.rb +73 -0
- data/spec/dop_common/data_disk_spec.rb +165 -0
- data/spec/dop_common/dns_spec.rb +33 -0
- data/spec/dop_common/hash_parser_spec.rb +181 -0
- data/spec/dop_common/hooks_spec.rb +33 -0
- data/spec/dop_common/infrastructure_properties_spec.rb +224 -0
- data/spec/dop_common/infrastructure_spec.rb +77 -0
- data/spec/dop_common/interface_spec.rb +192 -0
- data/spec/dop_common/network_spec.rb +92 -0
- data/spec/dop_common/node_filter_spec.rb +70 -0
- data/spec/dop_common/node_spec.rb +623 -0
- data/spec/dop_common/plan_cache_spec.rb +46 -0
- data/spec/dop_common/plan_spec.rb +136 -0
- data/spec/dop_common/plan_store_spec.rb +194 -0
- data/spec/dop_common/pre_processor_spec.rb +27 -0
- data/spec/dop_common/run_options_spec.rb +65 -0
- data/spec/dop_common/signal_handler_spec.rb +31 -0
- data/spec/dop_common/step_set_spec.rb +21 -0
- data/spec/dop_common/step_spec.rb +175 -0
- data/spec/dop_common/utils_spec.rb +27 -0
- data/spec/dop_common/validator_spec.rb +47 -0
- data/spec/example_plans_spec.rb +16 -0
- data/spec/fixtures/example_ssh_key +27 -0
- data/spec/fixtures/example_ssh_key.pub +1 -0
- data/spec/fixtures/incl/root_part.yaml +1 -0
- data/spec/fixtures/incl/some_list.yaml +2 -0
- data/spec/fixtures/other_plan_same_nodes.yaml +19 -0
- data/spec/fixtures/simple_include.yaml +6 -0
- data/spec/fixtures/simple_include_with_errors.yaml +4 -0
- data/spec/fixtures/simple_plan.yaml +19 -0
- data/spec/fixtures/simple_plan_invalid.yaml +18 -0
- data/spec/fixtures/simple_plan_modified.yaml +21 -0
- data/spec/spec_helper.rb +106 -0
- metadata +381 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::Plan do
|
4
|
+
|
5
|
+
describe '#name' do
|
6
|
+
it 'will return a hash if no name is defined' do
|
7
|
+
plan = DopCommon::Plan.new({})
|
8
|
+
if RUBY_VERSION <= '1.8.7'
|
9
|
+
expect(plan.name).to eq 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
10
|
+
else
|
11
|
+
expect(plan.name).to eq '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it 'will return the correct value if name is defined' do
|
15
|
+
plan = DopCommon::Plan.new({:name => 'myplan'})
|
16
|
+
expect(plan.name).to eq 'myplan'
|
17
|
+
plan = DopCommon::Plan.new({:name => 'my-plan'})
|
18
|
+
expect(plan.name).to eq 'my-plan'
|
19
|
+
end
|
20
|
+
it 'will throw and exception if the value is not a String' do
|
21
|
+
plan = DopCommon::Plan.new({:name => 2})
|
22
|
+
expect{plan.name}.to raise_error DopCommon::PlanParsingError
|
23
|
+
end
|
24
|
+
it 'will throw and exception if the value contais illegal chars' do
|
25
|
+
plan = DopCommon::Plan.new({:name => 'my(plan'})
|
26
|
+
expect{plan.name}.to raise_error DopCommon::PlanParsingError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#infrastructures' do
|
31
|
+
it 'will throw and exception if the infrastructures key is not defined' do
|
32
|
+
plan = DopCommon::Plan.new({})
|
33
|
+
expect{plan.infrastructures}.to raise_error DopCommon::PlanParsingError
|
34
|
+
end
|
35
|
+
it 'will throw and exception if the infrastructures value is not a Hash' do
|
36
|
+
plan = DopCommon::Plan.new({:infrastructures => 'foo'})
|
37
|
+
expect{plan.infrastructures}.to raise_error DopCommon::PlanParsingError
|
38
|
+
end
|
39
|
+
it 'will throw and exception if the infrastructures hash is empty' do
|
40
|
+
plan = DopCommon::Plan.new({:infrastructures => {}})
|
41
|
+
expect{plan.infrastructures}.to raise_error DopCommon::PlanParsingError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#nodes' do
|
46
|
+
it 'will return a list of nodes' do
|
47
|
+
plan = DopCommon::Plan.new({:infrastructures => {:management => {}}, :nodes => {'mynode{i}.example.com' =>{:range => '1..10', :digits => 3}}})
|
48
|
+
expect(plan.nodes.length).to be 10
|
49
|
+
expect(plan.nodes[0].name).to eq 'mynode001.example.com'
|
50
|
+
expect(plan.nodes[9].name).to eq 'mynode010.example.com'
|
51
|
+
end
|
52
|
+
it 'will throw and exception if the nodes key is not defined' do
|
53
|
+
plan = DopCommon::Plan.new({})
|
54
|
+
expect{plan.nodes}.to raise_error DopCommon::PlanParsingError
|
55
|
+
end
|
56
|
+
it 'will throw and exception if the nodes value is not a Hash' do
|
57
|
+
plan = DopCommon::Plan.new({:nodes => 'foo'})
|
58
|
+
expect{plan.nodes}.to raise_error DopCommon::PlanParsingError
|
59
|
+
end
|
60
|
+
it 'will throw and exception if the nodes hash is empty' do
|
61
|
+
plan = DopCommon::Plan.new({:nodes => {}})
|
62
|
+
expect{plan.nodes}.to raise_error DopCommon::PlanParsingError
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#step_sets' do
|
67
|
+
it 'will return an empty array if the steps key is not defined' do
|
68
|
+
plan = DopCommon::Plan.new({})
|
69
|
+
expect(plan.step_sets).to eq([])
|
70
|
+
end
|
71
|
+
it 'will return a StepSet object if the stepset is specified correctly' do
|
72
|
+
plan = DopCommon::Plan.new({:steps => []})
|
73
|
+
expect(plan.step_sets.all?{|s| s.kind_of?(DopCommon::StepSet)}).to be true
|
74
|
+
plan = DopCommon::Plan.new({:steps => {'foo' => []}})
|
75
|
+
expect(plan.step_sets.all?{|s| s.kind_of?(DopCommon::StepSet)}).to be true
|
76
|
+
end
|
77
|
+
it 'will throw and exception if the value is not an Array or Hash' do
|
78
|
+
plan = DopCommon::Plan.new({:steps => 'foo'})
|
79
|
+
expect{plan.step_sets}.to raise_error DopCommon::PlanParsingError
|
80
|
+
end
|
81
|
+
it 'will throw and exception if the hash is empty' do
|
82
|
+
plan = DopCommon::Plan.new({:steps => {}})
|
83
|
+
expect{plan.step_sets}.to raise_error DopCommon::PlanParsingError
|
84
|
+
end
|
85
|
+
it 'will throw and exception if the hash is invalid' do
|
86
|
+
plan = DopCommon::Plan.new({:steps => {2 => {}}})
|
87
|
+
expect{plan.step_sets}.to raise_error DopCommon::PlanParsingError
|
88
|
+
plan = DopCommon::Plan.new({:steps => {'foo' => 2}})
|
89
|
+
expect{plan.step_sets}.to raise_error DopCommon::PlanParsingError
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#credentials' do
|
94
|
+
it 'will return an empty Hash of credentials if nothing is specified' do
|
95
|
+
plan = DopCommon::Plan.new({})
|
96
|
+
expect(plan.credentials).to eq({})
|
97
|
+
end
|
98
|
+
it 'will return a Hash of credentials if correctly specified' do
|
99
|
+
plan = DopCommon::Plan.new({:credentials => {'test' => {
|
100
|
+
:type => :username_password,
|
101
|
+
:username => 'a',
|
102
|
+
:password => 'b'
|
103
|
+
}}})
|
104
|
+
expect(plan.credentials.key?('test')).to be true
|
105
|
+
expect(plan.credentials['test']).to be_a ::DopCommon::Credential
|
106
|
+
end
|
107
|
+
it 'will raise an exception if the the key is not valid' do
|
108
|
+
plan = DopCommon::Plan.new({:credentials => {2 => {}}})
|
109
|
+
expect{plan.credentials}.to raise_error DopCommon::PlanParsingError
|
110
|
+
end
|
111
|
+
it 'will raise an exception if the value is not a hash' do
|
112
|
+
plan = DopCommon::Plan.new({:credentials => {'test' => 2}})
|
113
|
+
expect{plan.credentials}.to raise_error DopCommon::PlanParsingError
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#hooks' do
|
118
|
+
it 'will return hooks object if specified properly' do
|
119
|
+
plan = ::DopCommon::Plan.new({})
|
120
|
+
expect(plan.hooks).to be_a(::DopCommon::Hooks)
|
121
|
+
%w(create update destroy).each do |action|
|
122
|
+
%w(pre post).each do |prefix|
|
123
|
+
hook_name = "#{prefix}_#{action}_vm"
|
124
|
+
plan = ::DopCommon::Plan.new({'hooks' => {hook_name => []}})
|
125
|
+
expect(plan.hooks).to be_an_instance_of(::DopCommon::Hooks)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
it 'will raise an error if not specified correctly' do
|
130
|
+
plan = ::DopCommon::Plan.new({'hooks' => {}})
|
131
|
+
expect { plan.hooks }.to raise_error ::DopCommon::PlanParsingError
|
132
|
+
plan = ::DopCommon::Plan.new({'hooks' => {'invalid' => ['/foo/bar/baz']}})
|
133
|
+
expect { plan.hooks }.to raise_error ::DopCommon::PlanParsingError
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::PlanStore do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@tmpdir = Dir.mktmpdir
|
7
|
+
@plan_store = DopCommon::PlanStore.new(@tmpdir)
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
FileUtils.remove_entry_secure(@tmpdir)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:plan) { 'spec/fixtures/simple_plan.yaml' }
|
15
|
+
let(:plan_name) { 'simple_plan' }
|
16
|
+
let(:plan_dir) { File.join(@tmpdir, plan_name) }
|
17
|
+
let(:versions_dir) { File.join(plan_dir, 'versions') }
|
18
|
+
|
19
|
+
describe '#add' do
|
20
|
+
subject { @plan_store.add(plan) }
|
21
|
+
|
22
|
+
context 'The plan file is correct' do
|
23
|
+
it { is_expected.to eq('simple_plan') }
|
24
|
+
it { subject; expect(Dir[versions_dir + '/*.yaml'].length).to be 1 }
|
25
|
+
end
|
26
|
+
context 'The plan is in hash form' do
|
27
|
+
let(:plan) { YAML.load_file('spec/fixtures/simple_plan.yaml') }
|
28
|
+
it { is_expected.to eq('simple_plan') }
|
29
|
+
it { subject; expect(Dir[versions_dir + '/*.yaml'].length).to be 1 }
|
30
|
+
end
|
31
|
+
context 'The plan is invalid' do
|
32
|
+
let(:plan) { 'spec/fixtures/simple_plan_invalid.yaml' }
|
33
|
+
it { expect{subject}.to raise_error StandardError }
|
34
|
+
end
|
35
|
+
context 'The plan was already added' do
|
36
|
+
before { @plan_store.add(plan) }
|
37
|
+
it { expect{subject}.to raise_error StandardError }
|
38
|
+
end
|
39
|
+
context 'A node is already present' do
|
40
|
+
before { @plan_store.add('spec/fixtures/other_plan_same_nodes.yaml') }
|
41
|
+
it { expect{subject}.to raise_error StandardError }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#update' do
|
46
|
+
before do |example|
|
47
|
+
@plan_store.add(plan) unless example.metadata[:skip_before]
|
48
|
+
end
|
49
|
+
subject { @plan_store.update(plan) }
|
50
|
+
|
51
|
+
context 'The plan file is correct' do
|
52
|
+
it { is_expected.to eq('simple_plan') }
|
53
|
+
it { subject; expect(Dir[versions_dir + '/*.yaml'].length).to be 2 }
|
54
|
+
end
|
55
|
+
context 'The plan is in hash form' do
|
56
|
+
let(:plan) { YAML.load_file('spec/fixtures/simple_plan.yaml') }
|
57
|
+
it { is_expected.to eq('simple_plan') }
|
58
|
+
it { subject; expect(Dir[versions_dir + '/*.yaml'].length).to be 2 }
|
59
|
+
end
|
60
|
+
context 'The plan is invalid' do
|
61
|
+
let(:invalid_plan) { 'spec/fixtures/simple_plan_invalid.yaml' }
|
62
|
+
subject { @plan_store.update(invalid_plan) }
|
63
|
+
it { expect{subject}.to raise_error StandardError }
|
64
|
+
end
|
65
|
+
context 'The plan was not already added', :skip_before => true do
|
66
|
+
it { expect{subject}.to raise_error StandardError }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#remove' do
|
71
|
+
before :example do
|
72
|
+
@plan_store.add(plan)
|
73
|
+
end
|
74
|
+
let(:dopi_state) { File.join(plan_dir, 'dopi.yaml') }
|
75
|
+
let(:dopv_state) { File.join(plan_dir, 'dopv.yaml') }
|
76
|
+
|
77
|
+
context 'plan exists and default state remove options' do
|
78
|
+
subject { @plan_store.remove(plan_name) }
|
79
|
+
it { is_expected.to eq('simple_plan') }
|
80
|
+
it { subject; expect(File.exists?(versions_dir)).to be false }
|
81
|
+
it { subject; expect(File.exists?(dopi_state)).to be false }
|
82
|
+
it { subject; expect(File.exists?(dopv_state)).to be true }
|
83
|
+
it { subject; expect(File.exists?(plan_dir)).to be true }
|
84
|
+
end
|
85
|
+
context 'plan exists and keep dopi state' do
|
86
|
+
subject { @plan_store.remove(plan_name, false) }
|
87
|
+
it { is_expected.to eq('simple_plan') }
|
88
|
+
it { subject; expect(File.exists?(versions_dir)).to be false }
|
89
|
+
it { subject; expect(File.exists?(dopi_state)).to be true }
|
90
|
+
it { subject; expect(File.exists?(dopv_state)).to be true }
|
91
|
+
it { subject; expect(File.exists?(plan_dir)).to be true }
|
92
|
+
end
|
93
|
+
context 'plan exists and remove dopv state' do
|
94
|
+
subject { @plan_store.remove(plan_name, true, true) }
|
95
|
+
it { is_expected.to eq('simple_plan') }
|
96
|
+
it { subject; expect(File.exists?(versions_dir)).to be false }
|
97
|
+
it { subject; expect(File.exists?(dopi_state)).to be false }
|
98
|
+
it { subject; expect(File.exists?(dopv_state)).to be false }
|
99
|
+
it { subject; expect(File.exists?(plan_dir)).to be false }
|
100
|
+
end
|
101
|
+
context 'plan does not exist' do
|
102
|
+
let(:plan_name) { 'not_existing_plan' }
|
103
|
+
it { expect{subject}.to raise_error StandardError }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#list' do
|
108
|
+
before { @plan_store.add(plan) }
|
109
|
+
subject { @plan_store.list }
|
110
|
+
|
111
|
+
context 'one plan is in the store' do
|
112
|
+
it { is_expected.to be_an Array }
|
113
|
+
it { is_expected.to have_exactly(1).items }
|
114
|
+
it { is_expected.to include plan_name }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#show_versions' do
|
119
|
+
before do |example|
|
120
|
+
@plan_store.add(plan) unless example.metadata[:skip_before]
|
121
|
+
end
|
122
|
+
subject { @plan_store.show_versions(plan_name) }
|
123
|
+
|
124
|
+
context 'the plan is in the store' do
|
125
|
+
it { is_expected.to be_an Array }
|
126
|
+
it { is_expected.to have_exactly(1).items }
|
127
|
+
end
|
128
|
+
context 'the plan is not in the store', :skip_before => true do
|
129
|
+
it { expect{subject}.to raise_error StandardError }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#get_plan_hash' do
|
134
|
+
before do |example|
|
135
|
+
@plan_store.add(plan) unless example.metadata[:skip_before]
|
136
|
+
end
|
137
|
+
subject { @plan_store.get_plan_hash(plan_name) }
|
138
|
+
|
139
|
+
context 'the plan is in the store' do
|
140
|
+
it { is_expected.to be_a Hash }
|
141
|
+
it { is_expected.to have_key 'name' }
|
142
|
+
end
|
143
|
+
context 'the plan is not in the store', :skip_before => true do
|
144
|
+
it { expect{subject}.to raise_error StandardError }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#get_plan_hash_diff' do
|
149
|
+
before do |example|
|
150
|
+
unless example.metadata[:skip_before]
|
151
|
+
@plan_store.add(plan)
|
152
|
+
@plan_store.update('spec/fixtures/simple_plan_modified.yaml')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
let(:old_version) { @plan_store.show_versions(plan_name).first }
|
156
|
+
subject { @plan_store.get_plan_hash_diff(plan_name, old_version) }
|
157
|
+
|
158
|
+
context 'the plan is in the store' do
|
159
|
+
it { is_expected.to be_an Array }
|
160
|
+
end
|
161
|
+
context 'the plan is not in the store', :skip_before => true do
|
162
|
+
it { expect{subject}.to raise_error StandardError }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#get_plan' do
|
167
|
+
before do |example|
|
168
|
+
@plan_store.add(plan) unless example.metadata[:skip_before]
|
169
|
+
end
|
170
|
+
subject { @plan_store.get_plan(plan_name) }
|
171
|
+
|
172
|
+
context 'the plan is in the store' do
|
173
|
+
it { is_expected.to be_a DopCommon::Plan }
|
174
|
+
it { expect(subject.name).to eq(plan_name) }
|
175
|
+
end
|
176
|
+
context 'the plan is not in the store', :skip_before => true do
|
177
|
+
it { expect{subject}.to raise_error StandardError }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#run_lock' do
|
182
|
+
pending
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#run_lock?' do
|
186
|
+
pending
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '#state_store' do
|
190
|
+
pending
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::PreProcessor do
|
4
|
+
|
5
|
+
describe '#load_plan' do
|
6
|
+
subject{ DopCommon::PreProcessor.load_plan(file) }
|
7
|
+
|
8
|
+
context 'All the include files are present and correct' do
|
9
|
+
let(:file) { 'spec/fixtures/simple_include.yaml' }
|
10
|
+
it{ is_expected.to be_a String }
|
11
|
+
it do
|
12
|
+
expect(YAML.load(subject)).to eq({
|
13
|
+
'name' => 'simple_include_test',
|
14
|
+
'some_root_key' => 'some_value',
|
15
|
+
'some_key' => ['an_item', 'another_item'],
|
16
|
+
})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'Included files are missing' do
|
21
|
+
let(:file) { 'spec/fixtures/simple_include_with_errors.yaml' }
|
22
|
+
it{ expect{subject}.to raise_error DopCommon::PlanParsingError }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class RunOptionsTestKlass
|
4
|
+
include DopCommon::RunOptions
|
5
|
+
def initialize(hash); @hash = hash; end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe DopCommon::RunOptions do
|
9
|
+
|
10
|
+
describe '#max_in_flight' do
|
11
|
+
it 'will return nil if max_in_flight is not defined' do
|
12
|
+
run_options = RunOptionsTestKlass.new({})
|
13
|
+
expect(run_options.max_in_flight).to be nil
|
14
|
+
end
|
15
|
+
it 'will return the correct value if max_in_flight is defined' do
|
16
|
+
run_options = RunOptionsTestKlass.new({:max_in_flight => 10})
|
17
|
+
expect(run_options.max_in_flight).to be 10
|
18
|
+
end
|
19
|
+
it 'will throw and exception if the value is not a Fixnum' do
|
20
|
+
run_options = RunOptionsTestKlass.new({:max_in_flight => 'foo'})
|
21
|
+
expect{run_options.max_in_flight}.to raise_error DopCommon::PlanParsingError
|
22
|
+
end
|
23
|
+
it 'will throw and exception if the value is < -1' do
|
24
|
+
run_options = RunOptionsTestKlass.new({:max_in_flight => -2})
|
25
|
+
expect{run_options.max_in_flight}.to raise_error DopCommon::PlanParsingError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#max_per_role' do
|
30
|
+
it 'will return nil if max_per_role is not defined' do
|
31
|
+
run_options = RunOptionsTestKlass.new({})
|
32
|
+
expect(run_options.max_per_role).to be nil
|
33
|
+
end
|
34
|
+
it 'will return the correct value if max_per_role is defined' do
|
35
|
+
run_options = RunOptionsTestKlass.new({:max_per_role => 10})
|
36
|
+
expect(run_options.max_per_role).to be 10
|
37
|
+
end
|
38
|
+
it 'will throw and exception if the value is not a Fixnum' do
|
39
|
+
run_options = RunOptionsTestKlass.new({:max_per_role => 'foo'})
|
40
|
+
expect{run_options.max_per_role}.to raise_error DopCommon::PlanParsingError
|
41
|
+
end
|
42
|
+
it 'will throw and exception if the value is < -1' do
|
43
|
+
run_options = RunOptionsTestKlass.new({:max_per_role => -2})
|
44
|
+
expect{run_options.max_per_role}.to raise_error DopCommon::PlanParsingError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#canary_host' do
|
49
|
+
it 'returns false if the key is missing' do
|
50
|
+
run_options = RunOptionsTestKlass.new({})
|
51
|
+
expect(run_options.canary_host).to eq false
|
52
|
+
end
|
53
|
+
it 'returns the correct result if the key is set' do
|
54
|
+
run_options = RunOptionsTestKlass.new({:canary_host => true})
|
55
|
+
expect(run_options.canary_host).to eq true
|
56
|
+
run_options = RunOptionsTestKlass.new({:canary_host => false})
|
57
|
+
expect(run_options.canary_host).to eq false
|
58
|
+
end
|
59
|
+
it 'throws an exception if the value is not a boolean' do
|
60
|
+
run_options = RunOptionsTestKlass.new({:canary_host => 'foo'})
|
61
|
+
expect{run_options.canary_host}.to raise_error DopCommon::PlanParsingError
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Test the SignalHandler class
|
3
|
+
#
|
4
|
+
# This test was created with the help of the very useful blog post at
|
5
|
+
# http://timuruski.net/blog/2014/testing-signal-handlers/
|
6
|
+
#
|
7
|
+
require 'spec_helper'
|
8
|
+
|
9
|
+
describe DopCommon::SignalHandler do
|
10
|
+
|
11
|
+
it 'receives the signal, executes the block and then exits' do
|
12
|
+
pipe_reader, pipe_writer = IO.pipe
|
13
|
+
|
14
|
+
ruby = fork do
|
15
|
+
pipe_reader.close
|
16
|
+
DopCommon::SignalHandler.new.handle_signals(:INT) do
|
17
|
+
pipe_writer.puts('received')
|
18
|
+
raise 'signal received'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
pipe_writer.close
|
23
|
+
sleep(0.1)
|
24
|
+
Process.kill(:INT, ruby)
|
25
|
+
expect(pipe_reader.gets).to eq("received\n")
|
26
|
+
pid, status = Process.waitpid2(ruby)
|
27
|
+
expect(status.success?).to be true
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::StepSet do
|
4
|
+
|
5
|
+
describe '#steps' do
|
6
|
+
it 'will return an array of steps if correctly specified' do
|
7
|
+
step_set = DopCommon::StepSet.new('foo', [{:name => 'foo'}])
|
8
|
+
expect(step_set.steps).to be_a Array
|
9
|
+
expect(step_set.steps.first).to be_a ::DopCommon::Step
|
10
|
+
end
|
11
|
+
it 'will raise an error if the array is empty' do
|
12
|
+
step_set = DopCommon::StepSet.new('foo', [])
|
13
|
+
expect{step_set.steps}.to raise_error DopCommon::PlanParsingError
|
14
|
+
end
|
15
|
+
it 'will raise an error if the array contains something other than hashes' do
|
16
|
+
step_set = DopCommon::StepSet.new('foo', [{}, 1])
|
17
|
+
expect{step_set.steps}.to raise_error DopCommon::PlanParsingError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::Step do
|
4
|
+
|
5
|
+
describe '#name' do
|
6
|
+
it 'returns the name if it is specified correctly' do
|
7
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
8
|
+
expect(step.name).to eq 'foo'
|
9
|
+
end
|
10
|
+
it 'throws an exception if the key is missing' do
|
11
|
+
step = DopCommon::Step.new({})
|
12
|
+
expect{step.name}.to raise_error DopCommon::PlanParsingError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
[:nodes, :exclude_nodes, :roles, :exclude_roles].each do |method_name|
|
18
|
+
describe '#' + method_name.to_s do
|
19
|
+
it 'returns an array with entries if correctly specified' do
|
20
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => ['foo']})
|
21
|
+
expect(step.send(method_name)).to eq(['foo'])
|
22
|
+
end
|
23
|
+
it 'returns an empty array if the key is missing' do
|
24
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
25
|
+
expect(step.send(method_name)).to eq([])
|
26
|
+
end
|
27
|
+
it 'returns an array with one element if the value is a string' do
|
28
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => 'foo'})
|
29
|
+
expect(step.send(method_name)).to eq(['foo'])
|
30
|
+
end
|
31
|
+
it 'throws an exception if the value is something other than an array or a string' do
|
32
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => 1})
|
33
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
34
|
+
end
|
35
|
+
it 'throws an exception if the array contains something other than a string' do
|
36
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => ['foo', 1]})
|
37
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
38
|
+
end
|
39
|
+
it 'throws an exception if the array contains an invalid regexp' do
|
40
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => ['/][/']})
|
41
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
[:nodes_by_config, :exclude_nodes_by_config].each do |method_name|
|
47
|
+
describe '#' + method_name.to_s do
|
48
|
+
it 'returns a Hash if correctly specified' do
|
49
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => {'my_alias' => 'foo'}})
|
50
|
+
expect(step.send(method_name)).to eq({'my_alias' => ['foo']})
|
51
|
+
end
|
52
|
+
it 'returns an empty hash if the key is missing' do
|
53
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
54
|
+
expect(step.send(method_name)).to eq({})
|
55
|
+
end
|
56
|
+
it 'throws an exception if the value is something other than a hash' do
|
57
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => 1})
|
58
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
59
|
+
end
|
60
|
+
it 'throws an exception if the hash contains something other than a string as a key' do
|
61
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => {1 => 'foo'}})
|
62
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
63
|
+
end
|
64
|
+
it 'throws an exception if the hash contains something other than a string as a value' do
|
65
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => {'my_alias' => 1}})
|
66
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
67
|
+
end
|
68
|
+
it 'throws an exception if the hash contains an invalid regexp' do
|
69
|
+
step = DopCommon::Step.new({:name => 'foo', method_name => {'my_alias' => '/][/'}})
|
70
|
+
expect{step.send(method_name)}.to raise_error DopCommon::PlanParsingError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#commands' do
|
76
|
+
it 'returns the command objects if a command hash is specified' do
|
77
|
+
step = DopCommon::Step.new({:name => 'foo', :command => {:plugin => 'dummy'}})
|
78
|
+
expect(step.commands).to be_an Array
|
79
|
+
expect(step.commands.all?{|c| c.kind_of?(DopCommon::Command)}).to be true
|
80
|
+
end
|
81
|
+
it 'returns the command objects if a command hash is specified' do
|
82
|
+
step = DopCommon::Step.new({:name => 'foo', :commands => [{:plugin => 'dummy'}, 'dummy']})
|
83
|
+
expect(step.commands).to be_an Array
|
84
|
+
expect(step.commands.all?{|c| c.kind_of?(DopCommon::Command)}).to be true
|
85
|
+
end
|
86
|
+
it 'throws an exception if the command is not specified' do
|
87
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
88
|
+
expect{step.commands}.to raise_error DopCommon::PlanParsingError
|
89
|
+
end
|
90
|
+
it 'throws an exception if the value for command is something other than a String or a Hash' do
|
91
|
+
step = DopCommon::Step.new({:name => 'foo', :command => 1})
|
92
|
+
expect{step.commands}.to raise_error DopCommon::PlanParsingError
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#set_plugin_defaults' do
|
97
|
+
it 'returns an Array if correctly specified (normal plugin string)' do
|
98
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => [{ :plugin => 'ssh/custom', :credentials => 'my_cred'}]})
|
99
|
+
expect(step.set_plugin_defaults).to eq([{:plugins => ['ssh/custom'], :credentials => 'my_cred'}])
|
100
|
+
end
|
101
|
+
it 'returns an Array if correctly specified (plugins :all)' do
|
102
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => [{ :plugins => :all, :credentials => 'my_cred'}]})
|
103
|
+
expect(step.set_plugin_defaults).to eq([{:plugins => :all, :credentials => 'my_cred'}])
|
104
|
+
end
|
105
|
+
it 'returns an Array if correctly specified (plugins array)' do
|
106
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => [{ :plugins => ['ssh/custom', 'ssh/something'], :credentials => 'my_cred'}]})
|
107
|
+
expect(step.set_plugin_defaults).to eq([{:plugins => ['ssh/custom', 'ssh/something'], :credentials => 'my_cred'}])
|
108
|
+
end
|
109
|
+
it 'returns an Array if correctly specified (plugins array)' do
|
110
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => [{ :plugins => '/^ssh/', :credentials => 'my_cred'}]})
|
111
|
+
expect(step.set_plugin_defaults).to eq([{:plugins => [Regexp.new('^ssh')], :credentials => 'my_cred'}])
|
112
|
+
end
|
113
|
+
it 'returns an empty Array if the key is missing' do
|
114
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
115
|
+
expect(step.set_plugin_defaults).to eq([])
|
116
|
+
end
|
117
|
+
it 'throws an exception if the value is something other than an array' do
|
118
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => 1})
|
119
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
120
|
+
end
|
121
|
+
it 'throws an exception if an entry is not a hash' do
|
122
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => [1]})
|
123
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
124
|
+
end
|
125
|
+
it 'throws an exception if no plugins key is present' do
|
126
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => {}})
|
127
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
128
|
+
end
|
129
|
+
it 'throws an exception if the plugins value is not valid' do
|
130
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => {:plugins => 1}})
|
131
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
132
|
+
end
|
133
|
+
it 'throws an exception if the plugins value is an invalid Regexp' do
|
134
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => {:plugins => '/][/'}})
|
135
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
136
|
+
end
|
137
|
+
it 'throws an exception if one of the keys is not a string or symbol' do
|
138
|
+
step = DopCommon::Step.new({:name => 'foo', :set_plugin_defaults => {:plugins => 'ssh/custom', 1 => 2}})
|
139
|
+
expect{step.set_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#delete_plugin_defaults' do
|
144
|
+
it 'returns an Array if correctly specified (normal plugin string)' do
|
145
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => [{:plugin => 'ssh/custom', :delete_keys => ['credentials']}]})
|
146
|
+
expect(step.delete_plugin_defaults).to eq([{:plugins => ['ssh/custom'], :delete_keys => ['credentials']}])
|
147
|
+
end
|
148
|
+
it 'returns an Array if correctly specified (singular)' do
|
149
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => [{:plugin => 'ssh/custom', :delete_key => 'credentials'}]})
|
150
|
+
expect(step.delete_plugin_defaults).to eq([{:plugins => ['ssh/custom'], :delete_keys => ['credentials']}])
|
151
|
+
end
|
152
|
+
it 'returns an Array if correctly specified (delete all for plugin)' do
|
153
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => [{:plugin => 'ssh/custom', :delete_keys => :all}]})
|
154
|
+
expect(step.delete_plugin_defaults).to eq([{:plugins => ['ssh/custom'], :delete_keys => :all}])
|
155
|
+
end
|
156
|
+
it 'returns :all if correctly specified (delete all)' do
|
157
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => :all})
|
158
|
+
expect(step.delete_plugin_defaults).to eq(:all)
|
159
|
+
end
|
160
|
+
it 'returns an empty Array if the key is missing' do
|
161
|
+
step = DopCommon::Step.new({:name => 'foo'})
|
162
|
+
expect(step.delete_plugin_defaults).to eq([])
|
163
|
+
end
|
164
|
+
it 'throws an exception if the delete_keys is invalid' do
|
165
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => [{:plugin => 'ssh/custom', :delete_keys => 2}]})
|
166
|
+
expect{step.delete_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
167
|
+
end
|
168
|
+
it 'throws an exception if an element in delete_keys is invalid' do
|
169
|
+
step = DopCommon::Step.new({:name => 'foo', :delete_plugin_defaults => [{:plugin => 'ssh/custom', :delete_keys => ['foo', 2]}]})
|
170
|
+
expect{step.delete_plugin_defaults}.to raise_error DopCommon::PlanParsingError
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DopCommon::Utils::DataSize do
|
4
|
+
describe '#size' do
|
5
|
+
{
|
6
|
+
1000 => 1000,
|
7
|
+
'1000K' => 1000*1024,
|
8
|
+
'512M' => 512*1024*1024,
|
9
|
+
'1000G' => 1000*1024*1024*1024,
|
10
|
+
'1KB' => 1000,
|
11
|
+
'1000MB' => 1000*1000*1000,
|
12
|
+
'2500GB' => 2500*1000*1000*1000,
|
13
|
+
}.each do |k, v|
|
14
|
+
it 'will return size in bytes if specified properly' do
|
15
|
+
size = DopCommon::Utils::DataSize.new(k)
|
16
|
+
expect(size).to be_an_instance_of(DopCommon::Utils::DataSize)
|
17
|
+
expect(size.bytes).to eq v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
[nil, [], 2.4, '2500m', '1000'].each do |input|
|
21
|
+
it 'will raise an exception if not specified properly' do
|
22
|
+
size = DopCommon::Utils::DataSize.new(input)
|
23
|
+
expect{size.bytes}.to raise_error DopCommon::PlanParsingError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|