dop_common 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +176 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE.txt +177 -0
  8. data/README.md +48 -0
  9. data/Rakefile +49 -0
  10. data/Vagrantfile +25 -0
  11. data/bin/dop-puppet-autosign +56 -0
  12. data/doc/examples/example_deploment_plan_v0.0.1.yaml +302 -0
  13. data/doc/plan_format_v0.0.1.md +919 -0
  14. data/doc/plan_format_v0.0.2_snippets.md +56 -0
  15. data/dop_common.gemspec +44 -0
  16. data/lib/dop_common/affinity_group.rb +57 -0
  17. data/lib/dop_common/cli/global_options.rb +37 -0
  18. data/lib/dop_common/cli/log.rb +51 -0
  19. data/lib/dop_common/cli/node_selection.rb +62 -0
  20. data/lib/dop_common/command.rb +125 -0
  21. data/lib/dop_common/config/helper.rb +39 -0
  22. data/lib/dop_common/config.rb +66 -0
  23. data/lib/dop_common/configuration.rb +37 -0
  24. data/lib/dop_common/credential.rb +152 -0
  25. data/lib/dop_common/data_disk.rb +62 -0
  26. data/lib/dop_common/dns.rb +55 -0
  27. data/lib/dop_common/hash_parser.rb +241 -0
  28. data/lib/dop_common/hooks.rb +81 -0
  29. data/lib/dop_common/infrastructure.rb +160 -0
  30. data/lib/dop_common/infrastructure_properties.rb +185 -0
  31. data/lib/dop_common/interface.rb +113 -0
  32. data/lib/dop_common/log.rb +78 -0
  33. data/lib/dop_common/network.rb +85 -0
  34. data/lib/dop_common/node/config.rb +159 -0
  35. data/lib/dop_common/node.rb +442 -0
  36. data/lib/dop_common/node_filter.rb +74 -0
  37. data/lib/dop_common/plan.rb +188 -0
  38. data/lib/dop_common/plan_cache.rb +83 -0
  39. data/lib/dop_common/plan_store.rb +263 -0
  40. data/lib/dop_common/pre_processor.rb +73 -0
  41. data/lib/dop_common/run_options.rb +56 -0
  42. data/lib/dop_common/signal_handler.rb +58 -0
  43. data/lib/dop_common/state_store.rb +95 -0
  44. data/lib/dop_common/step.rb +200 -0
  45. data/lib/dop_common/step_set.rb +41 -0
  46. data/lib/dop_common/thread_context_logger.rb +77 -0
  47. data/lib/dop_common/utils.rb +106 -0
  48. data/lib/dop_common/validator.rb +53 -0
  49. data/lib/dop_common/version.rb +3 -0
  50. data/lib/dop_common.rb +32 -0
  51. data/lib/hiera/backend/dop_backend.rb +94 -0
  52. data/lib/hiera/dop_logger.rb +20 -0
  53. data/spec/data/fake_hook_file_invalid +1 -0
  54. data/spec/data/fake_hook_file_valid +5 -0
  55. data/spec/data/fake_keyfile +1 -0
  56. data/spec/dop-puppet-autosign_spec_disable.rb +33 -0
  57. data/spec/dop_common/affinity_group_spec.rb +41 -0
  58. data/spec/dop_common/command_spec.rb +83 -0
  59. data/spec/dop_common/credential_spec.rb +73 -0
  60. data/spec/dop_common/data_disk_spec.rb +165 -0
  61. data/spec/dop_common/dns_spec.rb +33 -0
  62. data/spec/dop_common/hash_parser_spec.rb +181 -0
  63. data/spec/dop_common/hooks_spec.rb +33 -0
  64. data/spec/dop_common/infrastructure_properties_spec.rb +224 -0
  65. data/spec/dop_common/infrastructure_spec.rb +77 -0
  66. data/spec/dop_common/interface_spec.rb +192 -0
  67. data/spec/dop_common/network_spec.rb +92 -0
  68. data/spec/dop_common/node_filter_spec.rb +70 -0
  69. data/spec/dop_common/node_spec.rb +623 -0
  70. data/spec/dop_common/plan_cache_spec.rb +46 -0
  71. data/spec/dop_common/plan_spec.rb +136 -0
  72. data/spec/dop_common/plan_store_spec.rb +194 -0
  73. data/spec/dop_common/pre_processor_spec.rb +27 -0
  74. data/spec/dop_common/run_options_spec.rb +65 -0
  75. data/spec/dop_common/signal_handler_spec.rb +31 -0
  76. data/spec/dop_common/step_set_spec.rb +21 -0
  77. data/spec/dop_common/step_spec.rb +175 -0
  78. data/spec/dop_common/utils_spec.rb +27 -0
  79. data/spec/dop_common/validator_spec.rb +47 -0
  80. data/spec/example_plans_spec.rb +16 -0
  81. data/spec/fixtures/example_ssh_key +27 -0
  82. data/spec/fixtures/example_ssh_key.pub +1 -0
  83. data/spec/fixtures/incl/root_part.yaml +1 -0
  84. data/spec/fixtures/incl/some_list.yaml +2 -0
  85. data/spec/fixtures/other_plan_same_nodes.yaml +19 -0
  86. data/spec/fixtures/simple_include.yaml +6 -0
  87. data/spec/fixtures/simple_include_with_errors.yaml +4 -0
  88. data/spec/fixtures/simple_plan.yaml +19 -0
  89. data/spec/fixtures/simple_plan_invalid.yaml +18 -0
  90. data/spec/fixtures/simple_plan_modified.yaml +21 -0
  91. data/spec/spec_helper.rb +106 -0
  92. metadata +381 -0
@@ -0,0 +1,623 @@
1
+ require 'spec_helper'
2
+
3
+ describe DopCommon::Node do
4
+ before(:each) do
5
+ @infrastructures = [
6
+ DopCommon::Infrastructure.new(
7
+ 'rhev',
8
+ {
9
+ 'type' => 'rhev',
10
+ 'networks' => {
11
+ 'net0' => {},
12
+ 'net1' => {}
13
+ }
14
+ }
15
+ ),
16
+ DopCommon::Infrastructure.new(
17
+ 'rhos',
18
+ {
19
+ 'type' => 'rhos',
20
+ 'networks' => {
21
+ 'net0' => {},
22
+ 'net1' => {}
23
+ }
24
+ }
25
+ ),
26
+ DopCommon::Infrastructure.new(
27
+ 'vsphere',
28
+ {
29
+ 'type' => 'vsphere',
30
+ 'networks' => {
31
+ 'net0' => {},
32
+ 'net1' => {}
33
+ }
34
+ }
35
+ ),
36
+ DopCommon::Infrastructure.new('baremetal', {'type' => 'baremetal'}),
37
+ ]
38
+ end
39
+
40
+ describe '#range' do
41
+ it 'will return nil if the node is not inflatable' do
42
+ node = DopCommon::Node.new('mynode.example.com', {:range => '1..10'})
43
+ expect(node.range).to be nil
44
+ end
45
+ it 'will return a range object' do
46
+ node = DopCommon::Node.new('mynode{i}.example.com', {:range => '1..10'})
47
+ expect(node.range).to be_an_instance_of Range
48
+ end
49
+ it 'will throw and exception if the key is not defined' do
50
+ node = DopCommon::Node.new('mynode{i}.example.com', {})
51
+ expect{node.range}.to raise_error DopCommon::PlanParsingError
52
+ end
53
+ it 'will throw an exception if there are more than two numbers for the range' do
54
+ node = DopCommon::Node.new('mynode{i}.example.com', {:range => '1..10..100'})
55
+ expect{node.range}.to raise_error DopCommon::PlanParsingError
56
+ end
57
+ it 'will throw an exception if the first number is bigger than the second' do
58
+ node = DopCommon::Node.new('mynode{i}.example.com', {:range => '10..1'})
59
+ expect{node.range}.to raise_error DopCommon::PlanParsingError
60
+ end
61
+ end
62
+
63
+ describe '#digits' do
64
+ it 'will return the correct number for digits' do
65
+ node = DopCommon::Node.new('mynode{i}.example.com', {})
66
+ expect(node.digits).to be DopCommon::Node::DEFAULT_DIGITS
67
+ node = DopCommon::Node.new('mynode{i}.example.com', {:digits => 10})
68
+ expect(node.digits).to be 10
69
+ end
70
+ it 'will throw an exception if it is lower than 1' do
71
+ node = DopCommon::Node.new('mynode{i}.example.com', {:digits => -1})
72
+ expect{node.digits}.to raise_error DopCommon::PlanParsingError
73
+ end
74
+ it 'will throw an exception if is not a number' do
75
+ node = DopCommon::Node.new('mynode{i}.example.com', {:digits => 'foo'})
76
+ expect{node.digits}.to raise_error DopCommon::PlanParsingError
77
+ end
78
+ end
79
+
80
+ describe '#inflatable?' do
81
+ it 'will return true when the node inflatable' do
82
+ node = DopCommon::Node.new('mynode{i}.example.com', {})
83
+ expect(node.inflatable?).to be true
84
+ end
85
+ it 'will return false when the node is not inflatable' do
86
+ node = DopCommon::Node.new('mynode.example.com', {})
87
+ expect(node.inflatable?).to be false
88
+ end
89
+ end
90
+
91
+ describe '#inflate' do
92
+ it 'will return a new array of nodes' do
93
+ node = DopCommon::Node.new('mynode{i}.example.com', {:range => '1..10', :digits => 3})
94
+ nodes = node.inflate
95
+ expect(nodes.length).to be 10
96
+ expect(nodes[0].name).to eq 'mynode001.example.com'
97
+ expect(nodes[9].name).to eq 'mynode010.example.com'
98
+ end
99
+ end
100
+
101
+ describe '#fqdn' do
102
+ it 'will return FQDN is it is syntactically correct' do
103
+ node = DopCommon::Node.new('dummy', {})
104
+ expect(node.fqdn).to eq 'dummy'
105
+ node = DopCommon::Node.new('dummy', { 'fqdn' => 'f.q.dn.' })
106
+ expect(node.fqdn).to eq 'f.q.dn'
107
+ end
108
+
109
+ it 'will raise an error if it is not a string' do
110
+ node = DopCommon::Node.new('dummy', { 'fqdn' => :invalid })
111
+ expect{node.fqdn}.to raise_error DopCommon::PlanParsingError
112
+ end
113
+ it 'will raise an error if FQDN is too long' do
114
+ node = DopCommon::Node.new('dummy', { 'fqdn' => "#{'long'*300}.f.q.dn" })
115
+ expect{node.fqdn}.to raise_error DopCommon::PlanParsingError
116
+ end
117
+ it 'will raise an error if FQDN is syntactically invalid' do
118
+ node = DopCommon::Node.new('dummy', { 'fqdn' => 'invalid.f!.q.dn' })
119
+ expect{node.fqdn}.to raise_error DopCommon::PlanParsingError
120
+ end
121
+ end
122
+
123
+ describe '#infrastructure_properties' do
124
+ it 'will return infrastructure properties' do
125
+ node = DopCommon::Node.new(
126
+ 'dummy',
127
+ {
128
+ 'infrastructure' => 'rhev',
129
+ 'infrastructure_properties' => { 'datacenter' => 'foo', 'cluster' => 'bar' }
130
+ },
131
+ {:parsed_infrastructures => @infrastructures}
132
+ )
133
+ expect(node.infrastructure_properties).to be_an_instance_of DopCommon::InfrastructureProperties
134
+ end
135
+ it 'will raise an error if infrastructure properties is not hash' do
136
+ node = DopCommon::Node.new(
137
+ 'dummy',
138
+ {
139
+ 'infrastructure' => 'rhev',
140
+ 'infrastructure_properties' => 'foo'
141
+ },
142
+ {:parsed_infrastructures => @infrastructures}
143
+ )
144
+ expect{node.infrastructure_properties}.to raise_error DopCommon::PlanParsingError
145
+ end
146
+ end
147
+
148
+ describe '#image' do
149
+ it 'will return an image of a node' do
150
+ node = DopCommon::Node.new(
151
+ 'dummy',
152
+ {'infrastructure' => 'rhev', 'image' => 'dummy'},
153
+ {:parsed_infrastructures => @infrastructures}
154
+ )
155
+ expect(node.image).to eq 'dummy'
156
+ node = DopCommon::Node.new(
157
+ 'dummy',
158
+ {'infrastructure' => 'baremetal'},
159
+ {:parsed_infrastructures => @infrastructures}
160
+ )
161
+ expect(node.image).to eq nil
162
+ end
163
+
164
+ it 'will raise an error if image is not a string' do
165
+ node = DopCommon::Node.new(
166
+ 'dummy',
167
+ {'infrastructure' => 'rhev', 'image' => :invalid},
168
+ {:parsed_infrastructures => @infrastructures}
169
+ )
170
+ expect{node.image}.to raise_error DopCommon::PlanParsingError
171
+ end
172
+ end
173
+
174
+ describe '#full_clone' do
175
+ it 'will return "true" for OVirt/RHEVm-like provider if unspecified' do
176
+ node = DopCommon::Node.new(
177
+ 'dummy',
178
+ {'infrastructure' => 'rhev'},
179
+ {:parsed_infrastructures => @infrastructures}
180
+ )
181
+ expect(node.full_clone).to be true
182
+ end
183
+ it 'will return a boolean value if specified properly' do
184
+ node = DopCommon::Node.new(
185
+ 'dummy',
186
+ {'infrastructure' => 'rhev', 'full_clone' => true},
187
+ {:parsed_infrastructures => @infrastructures}
188
+ )
189
+ expect(node.full_clone).to be true
190
+ node = DopCommon::Node.new(
191
+ 'dummy',
192
+ {'infrastructure' => 'rhev', 'full_clone' => false},
193
+ {:parsed_infrastructures => @infrastructures}
194
+ )
195
+ expect(node.full_clone).to be false
196
+ end
197
+
198
+ it 'will return the default value in case of invalid provider type' do
199
+ node = DopCommon::Node.new(
200
+ 'dummy',
201
+ {'infrastructure' => 'baremetal'},
202
+ {:parsed_infrastructures => @infrastructures}
203
+ )
204
+ expect(node.full_clone).to be true
205
+ end
206
+ it 'will raise an error if "full_clone" is of invalid type' do
207
+ node = DopCommon::Node.new(
208
+ 'dummy',
209
+ {'infrastructure' => 'rhev', 'full_clone' => :invalid},
210
+ {:parsed_infrastructures => @infrastructures}
211
+ )
212
+ expect{node.full_clone}.to raise_error DopCommon::PlanParsingError
213
+ end
214
+ end
215
+
216
+ describe '#interfaces' do
217
+ it 'will return an array of interfaces if specified correctly' do
218
+ node = DopCommon::Node.new(
219
+ 'foo',
220
+ {
221
+ 'infrastructure' => 'rhev',
222
+ 'interfaces' => {'eth0' => {'network' => 'net0'}, 'eth1' => {'network' => 'net1'}}
223
+ },
224
+ {:parsed_infrastructures => @infrastructures}
225
+ )
226
+ expect(node.interfaces.length).to eq 2
227
+ expect(node.interfaces.all?{|i| i.kind_of?(DopCommon::Interface)}).to be true
228
+ end
229
+ it 'will return an empty array if interfaces is not specified' do
230
+ node = DopCommon::Node.new('foo', {})
231
+ expect(node.interfaces).to eq([])
232
+ end
233
+ it 'will raise an error if interfaces is not a hash' do
234
+ node = DopCommon::Node.new('foo', {:interfaces => 2})
235
+ expect{node.interfaces}.to raise_error DopCommon::PlanParsingError
236
+ end
237
+ it 'will raise an error if a key in interfaces is not a string' do
238
+ node = DopCommon::Node.new('foo', {:interfaces => {2 => {}}})
239
+ expect{node.interfaces}.to raise_error DopCommon::PlanParsingError
240
+ end
241
+ it 'will raise an error if a value in interfaces is not a hash' do
242
+ node = DopCommon::Node.new('foo', {:interfaces => {'eth0' => 2}})
243
+ expect{node.interfaces}.to raise_error DopCommon::PlanParsingError
244
+ end
245
+ end
246
+
247
+ describe '#flavor' do
248
+ it "will return nil if not specified and the provider isn't openstack" do
249
+ node = DopCommon::Node.new(
250
+ 'dummy',
251
+ {'infrastructure' => 'rhev'},
252
+ {:parsed_infrastructures => @infrastructures}
253
+ )
254
+ expect(node.flavor).to be_nil
255
+ end
256
+ it 'will return DEFAULT_OPENSTACK_FLAVOR if not specified and the provider is openstack' do
257
+ node = DopCommon::Node.new(
258
+ 'dummy',
259
+ {'infrastructure' => 'rhos'},
260
+ {:parsed_infrastructures => @infrastructures}
261
+ )
262
+ expect(node.flavor).to eq DopCommon::Node::DEFAULT_OPENSTACK_FLAVOR
263
+ end
264
+ it 'will return the flavor as-is if it is specified and the provider is openstack' do
265
+ node = DopCommon::Node.new(
266
+ 'dummy',
267
+ {'infrastructure' => 'rhos', 'flavor' => 'anyflavor'},
268
+ {:parsed_infrastructures => @infrastructures}
269
+ )
270
+ expect(node.flavor).to eq 'anyflavor'
271
+ end
272
+ it 'will return nil if it exists in VALID_FLAVIR_TYPES and the provider is not openstack' do
273
+ node = DopCommon::Node.new(
274
+ 'dummy',
275
+ {'infrastructure' => 'rhev', 'flavor' => 'tiny'},
276
+ {:parsed_infrastructures => @infrastructures}
277
+ )
278
+ expect(node.flavor).to be_nil
279
+ end
280
+ it 'will raise an error if flavor is defined together with one of cores, memory or storage' do
281
+ {'cores' => 2, 'memory' => '15G', 'storage' => '100GB'}.each do |k, v|
282
+ node = DopCommon::Node.new(
283
+ 'dummy',
284
+ {'infrastructure' => 'rhev', 'flavor' => 'medium', k => v},
285
+ {:parsed_infrastructures => @infrastructures}
286
+ )
287
+ expect{node.flavor}.to raise_error DopCommon::PlanParsingError
288
+ end
289
+ end
290
+ it "will raise an error if flavor is specified but it isn't a string" do
291
+ [1, [], {}, :sym].each do |flavor|
292
+ node = DopCommon::Node.new(
293
+ 'dummy',
294
+ {'infrastructure' => 'rhev', 'flavor' => flavor},
295
+ {:parsed_infrastructures => @infrastructures}
296
+ )
297
+ expect{node.flavor}.to raise_error DopCommon::PlanParsingError
298
+ end
299
+ end
300
+ it 'will raise an error if infrastructure is not openstack and the flavor is invalid' do
301
+ node = DopCommon::Node.new(
302
+ 'dummy',
303
+ {'infrastructure' => 'rhev', 'flavor' => 'invalid'},
304
+ {:parsed_infrastructures => @infrastructures}
305
+ )
306
+ expect{node.flavor}.to raise_error DopCommon::PlanParsingError
307
+ end
308
+ end
309
+
310
+ describe '#cores' do
311
+ it 'will return number of cores if specified properly' do
312
+ [1, 10].each do |cores|
313
+ node = DopCommon::Node.new(
314
+ 'dummy',
315
+ {'infrastructure' => 'rhev', 'cores' => cores},
316
+ {:parsed_infrastructures => @infrastructures}
317
+ )
318
+ expect(node.cores).to eq cores
319
+ end
320
+ end
321
+ it 'will raise an exception if specified for openstack provider' do
322
+ node = DopCommon::Node.new(
323
+ 'dummy',
324
+ {'infrastructure' => 'rhos', 'cores' => 2},
325
+ {:parsed_infrastructures => @infrastructures}
326
+ )
327
+ expect{node.cores}.to raise_error DopCommon::PlanParsingError
328
+ end
329
+ it 'will raise an exception in case of invalid input' do
330
+ [:invalid, 'four', '4'].each do |cores|
331
+ node = DopCommon::Node.new(
332
+ 'dummy',
333
+ {'infrastructure' => 'rhev', 'cores' => cores},
334
+ {:parsed_infrastructures => @infrastructures}
335
+ )
336
+ expect{node.cores}.to raise_error DopCommon::PlanParsingError
337
+ end
338
+ end
339
+ end
340
+
341
+ describe '#memory' do
342
+ it 'will return an instance of DopCommon::Utils::DataSize if specified correctly' do
343
+ [nil, '500K', '500M', '10G', '500KB', '500MB', '10GB'].each do |memory|
344
+ node = DopCommon::Node.new(
345
+ 'dummy',
346
+ {'infrastructure' => 'rhev', 'memory' => memory},
347
+ {:parsed_infrastructures => @infrastructures}
348
+ )
349
+ expect(node.memory).to be_an_instance_of(DopCommon::Utils::DataSize)
350
+ end
351
+ end
352
+ it "will return an instance of DopCommon::Utils::DataSize if not specified and the provider isn't openstack" do
353
+ node = DopCommon::Node.new(
354
+ 'dummy',
355
+ {'infrastructure' => 'rhev'},
356
+ {:parsed_infrastructures => @infrastructures}
357
+ )
358
+ expect(node.memory).to be_an_instance_of(DopCommon::Utils::DataSize)
359
+ expect(node.memory.bytes).to eq DopCommon::Node::DEFAULT_MEMORY
360
+ end
361
+ it 'will return an instance of DopCommon::Utils::DataSize if appropriate flavor is specified' do
362
+ flavor = 'tiny'
363
+ node = DopCommon::Node.new(
364
+ 'dummy',
365
+ {'infrastructure' => 'rhev', 'flavor' => flavor},
366
+ {:parsed_infrastructures => @infrastructures}
367
+ )
368
+ expect(node.memory).to be_an_instance_of(DopCommon::Utils::DataSize)
369
+ expect(node.memory.bytes).to eq DopCommon::Node::VALID_FLAVOR_TYPES[flavor.to_sym][:memory]
370
+ end
371
+ it 'will raise an exception if specified for openstack provider' do
372
+ node = DopCommon::Node.new(
373
+ 'dummy',
374
+ {'infrastructure' => 'rhos', 'memory' => '1G'},
375
+ {:parsed_infrastructures => @infrastructures}
376
+ )
377
+ expect{node.memory}.to raise_error DopCommon::PlanParsingError
378
+ end
379
+ it 'will raise an exception in case of invalid input' do
380
+ [:invalid, 'invalid', '500g'].each do |memory|
381
+ node = DopCommon::Node.new(
382
+ 'dummy',
383
+ {'infrastructure' => 'rhev', 'memory' => memory},
384
+ {:parsed_infrastructures => @infrastructures}
385
+ )
386
+ expect{node.memory.bytes}.to raise_error DopCommon::PlanParsingError
387
+ end
388
+ end
389
+ end
390
+
391
+ describe '#storage' do
392
+ it 'will return an instance of DopCommon::Utils::DataSize if specified correctly' do
393
+ [nil, '500K', '500M', '10G', '500KB', '500MB', '10GB'].each do |storage|
394
+ node = DopCommon::Node.new(
395
+ 'dummy',
396
+ {'infrastructure' => 'rhev', 'storage' => storage},
397
+ {:parsed_infrastructures => @infrastructures}
398
+ )
399
+ expect(node.storage).to be_an_instance_of(DopCommon::Utils::DataSize)
400
+ end
401
+ end
402
+ it "will return an instance of DopCommon::Utils::DataSize if not specified and the provider isn't openstack" do
403
+ node = DopCommon::Node.new(
404
+ 'dummy',
405
+ {'infrastructure' => 'rhev'},
406
+ {:parsed_infrastructures => @infrastructures}
407
+ )
408
+ expect(node.storage).to be_an_instance_of(DopCommon::Utils::DataSize)
409
+ expect(node.storage.bytes).to eq DopCommon::Node::DEFAULT_STORAGE
410
+ end
411
+ it 'will return an instance of DopCommon::Utils::DataSize if appropriate flavor is specified' do
412
+ flavor = 'tiny'
413
+ node = DopCommon::Node.new(
414
+ 'dummy',
415
+ {'infrastructure' => 'rhev', 'flavor' => flavor},
416
+ {:parsed_infrastructures => @infrastructures}
417
+ )
418
+ expect(node.storage).to be_an_instance_of(DopCommon::Utils::DataSize)
419
+ expect(node.storage.bytes).to eq DopCommon::Node::VALID_FLAVOR_TYPES[flavor.to_sym][:storage]
420
+ end
421
+ it 'will raise an exception if specified for openstack provider' do
422
+ node = DopCommon::Node.new(
423
+ 'dummy',
424
+ {'infrastructure' => 'rhos', 'storage' => '1G'},
425
+ {:parsed_infrastructures => @infrastructures}
426
+ )
427
+ expect{node.storage}.to raise_error DopCommon::PlanParsingError
428
+ end
429
+ it 'will raise an exception in case of invalid input' do
430
+ [:invalid, 'invalid', '500g'].each do |storage|
431
+ node = DopCommon::Node.new(
432
+ 'dummy',
433
+ {'infrastructure' => 'rhev', 'storage' => storage},
434
+ {:parsed_infrastructures => @infrastructures}
435
+ )
436
+ expect{node.storage.bytes}.to raise_error DopCommon::PlanParsingError
437
+ end
438
+ end
439
+ end
440
+
441
+ describe '#timezone' do
442
+ it "will return a parsed 'timezone' property" do
443
+ {'rhev' => nil, 'vsphere' => '095'}.each do |infrastructure, property_val|
444
+ node = DopCommon::Node.new(
445
+ 'dummy',
446
+ {'infrastructure' => infrastructure, 'timezone' => property_val },
447
+ {:parsed_infrastructures => @infrastructures}
448
+ )
449
+ expect(node.timezone).to eq property_val
450
+ end
451
+ end
452
+
453
+ it 'will trow an error if input timezone is invalid' do
454
+ [nil, "", :invalid, []].each do |property_val|
455
+ node = DopCommon::Node.new(
456
+ 'dummy',
457
+ {'infrastructure' => 'vsphere', 'timezone' => property_val},
458
+ {:parsed_infrastructures => @infrastructures}
459
+ )
460
+ expect{node.timezone}.to raise_error DopCommon::PlanParsingError
461
+ end
462
+ end
463
+ end
464
+
465
+ %w(product_id organization_name).each do |property_name|
466
+ describe "##{property_name}" do
467
+ it "will return a parsed '#{property_name}' property" do
468
+ ["", nil, "a74230-f3485-84"].each do |property_val|
469
+ next if property_name == "organization_name" && property_val == ""
470
+ node = DopCommon::Node.new(
471
+ 'dummy',
472
+ {'infrastructure' => 'vsphere', property_name => property_val }
473
+ )
474
+ expect(node.send(property_name.to_sym)).to eq property_val
475
+ end
476
+ end
477
+
478
+ it "will trow an error if #{property_name} format is invalid" do
479
+ ["", :invalid, []].each do |property_val|
480
+ next if property_name == "product_id" && property_val == ""
481
+ node = DopCommon::Node.new(
482
+ 'dummy',
483
+ {'infrastructure' => 'vsphere', property_name => property_val}
484
+ )
485
+ expect{node.send(property_name.to_sym)}.to raise_error DopCommon::PlanParsingError
486
+ end
487
+ end
488
+ end
489
+ end
490
+
491
+ describe '#credentials' do
492
+ before :all do
493
+ @credentials = {
494
+ 'test_up' => DopCommon::Credential.new('test_up', {
495
+ :type => 'username_password',
496
+ :username => 'alice',
497
+ :password => 'abc123',
498
+ }),
499
+ 'test_ssh' => DopCommon::Credential.new('test_ssh', {
500
+ :type => 'ssh_key',
501
+ :username => 'bob',
502
+ :public_key => 'spec/fixtures/example_ssh_key.pub',
503
+ }),
504
+ 'test_ssh2' => DopCommon::Credential.new('test_ssh2', {
505
+ :type => 'ssh_key',
506
+ :username => 'bob',
507
+ :private_key => 'spec/fixtures/example_ssh_key',
508
+ }),
509
+ }
510
+ end
511
+
512
+ it 'returns an empty array if nothing is defined' do
513
+ node = DopCommon::Node.new('dummy',{:parsed_credentials => @credentials })
514
+ expect(node.credentials).to be_an Array
515
+ expect(node.credentials.empty?).to be true
516
+ end
517
+
518
+ it 'returns an array if a credential if properly defined as a string' do
519
+ node = DopCommon::Node.new('dummy',
520
+ {:credentials => 'test_up'},
521
+ {:parsed_credentials => @credentials }
522
+ )
523
+ expect(node).to have_exactly(1).credentials
524
+ expect(node.credentials.all?{|c| c.kind_of?(DopCommon::Credential)}).to be true
525
+ end
526
+
527
+ it 'returns an array if an array of credentials if properly defined' do
528
+ node = DopCommon::Node.new('dummy',
529
+ {:credentials => ['test_up', 'test_ssh']},
530
+ {:parsed_credentials => @credentials }
531
+ )
532
+ expect(node).to have_exactly(2).credentials
533
+ expect(node.credentials.all?{|c| c.kind_of?(DopCommon::Credential)}).to be true
534
+ end
535
+
536
+ it 'will throw an error if credentials is not an array or string' do
537
+ node = DopCommon::Node.new('dummy',
538
+ {:credentials => 1},
539
+ {:parsed_credentials => @credentials }
540
+ )
541
+ expect{node.credentials}.to raise_error DopCommon::PlanParsingError
542
+ node = DopCommon::Node.new('dummy',
543
+ {:credentials => ['test_up', 1]},
544
+ {:parsed_credentials => @credentials }
545
+ )
546
+ expect{node.credentials}.to raise_error DopCommon::PlanParsingError
547
+ end
548
+
549
+ it 'will throw an error if a node includes a ssh_key credential without public_key' do
550
+ node = DopCommon::Node.new('dummy',
551
+ {:credentials => ['test_up', 'test_ssh2']},
552
+ {:parsed_credentials => @credentials }
553
+ )
554
+ expect{node.credentials}.to raise_error DopCommon::PlanParsingError
555
+ end
556
+
557
+ end
558
+
559
+ describe '#dns' do
560
+ #before :all do
561
+ # @dns = {
562
+ # 'valid_name_server' => { 'name_servers' => ['10.0.2.1'] }
563
+ # 'valid_search_domain' => { 'search_domains' => ['foo.bar'] }
564
+ # 'valid_dns' => { 'name_servers' => ['10.0.2.1', '172.16.0.1']
565
+ # }
566
+ #end
567
+ it 'returns a dns object if properly defined' do
568
+ [{}, {:dns => {:name_servers => ['10.0.1.1'], :search_domains => ['foo.bar']}}].each do |dns|
569
+ node = DopCommon::Node.new('dummy', dns)
570
+ expect(node.dns).to be_an_instance_of DopCommon::DNS
571
+ end
572
+ end
573
+
574
+ it "will throw an exception if dns object isn't properly defined" do
575
+ [{:dns => 'invalid'}, {:dns => nil}, {:dns => []}].each do |dns|
576
+ node = DopCommon::Node.new('dummy', dns)
577
+ expect{node.dns}.to raise_error DopCommon::PlanParsingError
578
+ end
579
+ end
580
+ end
581
+
582
+ describe '#data_disks' do
583
+ it 'returns an empty array if nothing is defined' do
584
+ node = DopCommon::Node.new('dummy', {:parsed_infrastructures => @infrastructures})
585
+ expect(node.data_disks).to be_an Array
586
+ expect(node.data_disks.empty?).to be true
587
+ end
588
+
589
+ it 'returns a list of data disk objects if properly defined' do
590
+ node = DopCommon::Node.new(
591
+ 'dummy',
592
+ {
593
+ 'infrastructure' => 'rhev',
594
+ 'infrastructure_properties' => {'default_pool' => 'test4'},
595
+ 'disks' => {
596
+ 'd1' => {'pool' => 'test1', 'size' => '1024M', 'thin' => true},
597
+ 'd2' => {'pool' => 'test2', 'size' => '1024G', 'thin' => false},
598
+ 'd3' => {'pool' => 'test3', 'size' => '1024K'},
599
+ 'd4' => {'size' => '1024K'}
600
+ }
601
+ },
602
+ {:parsed_infrastructures => @infrastructures}
603
+ )
604
+ expect(node).to have_exactly(4).data_disks
605
+ expect(node.data_disks.all?{|d| d.kind_of?(DopCommon::DataDisk)}).to be true
606
+ end
607
+
608
+ it 'will throw an error if a data disk specification is invalid' do
609
+ [nil, :invalid, [], {'d1' => nil}, {'d1' => :invalid}].each do |disks|
610
+ node = DopCommon::Node.new(
611
+ 'dummy',
612
+ {
613
+ :infrastructure => 'rhev',
614
+ :infrastructure_properties => {'datacenter' => 'test'},
615
+ :disks => disks
616
+ },
617
+ {:parsed_infrastructures => @infrastructures}
618
+ )
619
+ expect{node.data_disks}.to raise_error DopCommon::PlanParsingError
620
+ end
621
+ end
622
+ end
623
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe DopCommon::PlanCache do
4
+
5
+ before :each do
6
+ @tmpdir = Dir.mktmpdir
7
+ @plan_store = DopCommon::PlanStore.new(@tmpdir)
8
+ @plan_cache = DopCommon::PlanCache.new(@plan_store)
9
+ @plan_store.add(plan)
10
+ end
11
+
12
+ after :each do
13
+ FileUtils.remove_entry_secure(@tmpdir)
14
+ end
15
+
16
+ let(:plan) { 'spec/fixtures/simple_plan.yaml' }
17
+ let(:plan_name) { 'simple_plan' }
18
+ let(:plan_dir) { File.join(@tmpdir, plan_name) }
19
+ let(:versions_dir) { File.join(plan_dir, 'versions') }
20
+ let(:node_name) { 'linux01.example.com' }
21
+
22
+ describe '#plan_by_node' do
23
+ before :each do
24
+ @original_plan = @plan_cache.plan_by_node(node_name)
25
+ end
26
+ subject { @plan_cache.plan_by_node(node_name) }
27
+
28
+ context 'The plan in the store is unchanged' do
29
+ it { is_expected.to be_a(DopCommon::Plan) }
30
+ it { is_expected.to equal(@original_plan) }
31
+ end
32
+ context 'The plan in the store was updated' do
33
+ before do
34
+ @plan_store.update(plan)
35
+ end
36
+ it { is_expected.to be_a(DopCommon::Plan) }
37
+ it { is_expected.to_not equal(@original_plan) }
38
+ end
39
+ context 'There is no plan with this node' do
40
+ let(:node_name) { 'nonexisting.example.com' }
41
+ it { is_expected.to be(nil) }
42
+ end
43
+ end
44
+
45
+ end
46
+