dop_common 0.13.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.
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
+