poise 2.2.3 → 2.3.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile +0 -2
  5. data/lib/poise.rb +3 -1
  6. data/lib/poise/backports.rb +27 -0
  7. data/lib/poise/backports/not_passed.rb +52 -0
  8. data/lib/poise/helpers.rb +1 -0
  9. data/lib/poise/helpers/chefspec_matchers.rb +5 -1
  10. data/lib/poise/helpers/inversion.rb +36 -13
  11. data/lib/poise/helpers/option_collector.rb +15 -4
  12. data/lib/poise/helpers/resource_name.rb +1 -1
  13. data/lib/poise/helpers/resource_subclass.rb +81 -0
  14. data/lib/poise/helpers/subresources/child.rb +50 -9
  15. data/lib/poise/helpers/subresources/container.rb +33 -6
  16. data/lib/poise/resource.rb +3 -1
  17. data/lib/poise/subcontext/resource_collection.rb +20 -1
  18. data/lib/poise/utils.rb +79 -7
  19. data/lib/poise/utils/resource_provider_mixin.rb +2 -2
  20. data/lib/poise/version.rb +1 -1
  21. data/test/spec/backports/not_passed_spec.rb +29 -0
  22. data/test/spec/helpers/chefspec_matchers_spec.rb +17 -0
  23. data/test/spec/helpers/inversion_spec.rb +72 -0
  24. data/test/spec/helpers/lwrp_polyfill_spec.rb +9 -0
  25. data/test/spec/helpers/option_collector_spec.rb +66 -30
  26. data/test/spec/helpers/resource_name_spec.rb +15 -2
  27. data/test/spec/helpers/resource_subclass_spec.rb +97 -0
  28. data/test/spec/helpers/subresources/child_spec.rb +234 -2
  29. data/test/spec/helpers/subresources/container_spec.rb +37 -0
  30. data/test/spec/resource_spec.rb +31 -2
  31. data/test/spec/subcontext/resource_collection_spec.rb +99 -0
  32. data/test/spec/utils/resource_provider_mixin_spec.rb +22 -0
  33. data/test/spec/utils_spec.rb +187 -1
  34. metadata +11 -3
  35. data/Berksfile.lock +0 -10
@@ -21,6 +21,13 @@ class ResourceNameHelper < Chef::Resource
21
21
  provides(:provides_test)
22
22
  end
23
23
 
24
+ # Helper for testing multiple names.
25
+ class ResourceNameHelperTwo < Chef::Resource
26
+ include Poise::Helpers::ResourceName
27
+ provides(:provides_test_two)
28
+ provides(:provides_test_2)
29
+ end
30
+
24
31
  describe Poise::Helpers::ResourceName do
25
32
  context 'via class.name' do
26
33
  resource(:poise_test, auto: false) do
@@ -29,11 +36,17 @@ describe Poise::Helpers::ResourceName do
29
36
  subject { resource(:poise_test).new(nil, nil).resource_name }
30
37
 
31
38
  it { is_expected.to eq :poise_test }
32
- end
39
+ end # /context via class.name
33
40
 
34
41
  context 'via provides' do
35
42
  subject { ResourceNameHelper.new(nil, nil).resource_name }
36
43
 
37
44
  it { is_expected.to eq :provides_test }
38
- end
45
+ end # /context via provides
46
+
47
+ context 'with multiple names' do
48
+ subject { ResourceNameHelperTwo.new(nil, nil).resource_name }
49
+
50
+ it { is_expected.to eq :provides_test_two }
51
+ end # /context with multiple names
39
52
  end
@@ -0,0 +1,97 @@
1
+ #
2
+ # Copyright 2015, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'spec_helper'
18
+ require 'chef/resource'
19
+ require 'chef/provider'
20
+
21
+ # Not defined using the helpers because I need it to be visible outside of
22
+ # example execution.
23
+ module PoiseTestSubclass
24
+ class Resource < Chef::Resource
25
+ include Poise
26
+ provides(:poise_test_subclass)
27
+ end
28
+ class Provider < Chef::Provider
29
+ include Poise
30
+ provides(:poise_test_subclass)
31
+ def action_run
32
+ node.run_state[:really_did_run] = true
33
+ end
34
+ end
35
+ end
36
+
37
+ describe Poise::Helpers::ResourceSubclass do
38
+ describe '.subclass_providers!' do
39
+ resource(:poise_sub, parent: PoiseTestSubclass::Resource) do
40
+ provides(:poise_sub)
41
+ subclass_providers!
42
+ end
43
+ recipe do
44
+ poise_sub 'test'
45
+ end
46
+
47
+ it { is_expected.to run_poise_sub('test') }
48
+ it { expect(chef_run.node.run_state[:really_did_run]).to be true }
49
+ end # /describe .subclass_providers!
50
+
51
+ describe '.subclass_resource_equivalents' do
52
+ let(:test_class) { nil }
53
+ subject { test_class.subclass_resource_equivalents }
54
+ resource(:poise_sub, parent: PoiseTestSubclass::Resource) do
55
+ provides(:poise_sub)
56
+ subclass_providers!
57
+ end
58
+
59
+ context 'with a top-level class' do
60
+ let(:test_class) { PoiseTestSubclass::Resource }
61
+ it { is_expected.to eq %i{poise_test_subclass} }
62
+ end # /context with a top-level class
63
+
64
+ context 'with a subclass' do
65
+ let(:test_class) { resource(:poise_sub) }
66
+ it { is_expected.to eq %i{poise_sub poise_test_subclass} }
67
+ end # /context with a subclass
68
+
69
+ context 'with an unpatched subclass' do
70
+ resource(:poise_sub2, parent: PoiseTestSubclass::Resource) do
71
+ provides(:poise_sub2)
72
+ end
73
+ let(:test_class) { resource(:poise_sub2) }
74
+ it { is_expected.to eq %i{poise_sub2} }
75
+ end # /context with an unpatched subclass
76
+
77
+ context 'with two subclasses' do
78
+ resource(:poise_sub2, parent: :poise_sub) do
79
+ provides(:poise_sub2)
80
+ subclass_providers!
81
+ end
82
+ let(:test_class) { resource(:poise_sub2) }
83
+ it { is_expected.to eq %i{poise_sub2 poise_sub poise_test_subclass} }
84
+ end # /context with two subclasses
85
+
86
+ context 'with a non-poise parent' do
87
+ resource(:non_poise_parent)
88
+ resource(:poise_sub3, parent: :non_poise_parent) do
89
+ include Poise
90
+ provides(:poise_sub3)
91
+ subclass_providers!
92
+ end
93
+ let(:test_class) { resource(:poise_sub3) }
94
+ it { is_expected.to eq %i{poise_sub3 non_poise_parent} }
95
+ end # /context with a non-poise parent
96
+ end # /describe .subclass_resource_equivalents
97
+ end
@@ -31,6 +31,25 @@ describe Poise::Helpers::Subresources::Child do
31
31
  parent_type :poise_container
32
32
  end
33
33
 
34
+ context 'with an automatic parent' do
35
+ recipe do
36
+ poise_container 'test'
37
+ poise_test 'test'
38
+ end
39
+
40
+ it { is_expected.to run_poise_test('test').with(parent: container) }
41
+ end # /context with an automatic parent
42
+
43
+ context 'with an automatic parent and an extra container' do
44
+ recipe do
45
+ poise_container 'test'
46
+ poise_test 'test'
47
+ poise_container 'other'
48
+ end
49
+
50
+ it { is_expected.to run_poise_test('test').with(parent: container) }
51
+ end # /context with an automatic parent and an extra container
52
+
34
53
  context 'with a resource parent' do
35
54
  recipe do
36
55
  c = poise_container 'test'
@@ -42,6 +61,18 @@ describe Poise::Helpers::Subresources::Child do
42
61
  it { is_expected.to run_poise_test('test').with(parent: container) }
43
62
  end # /context with a resource parent
44
63
 
64
+ context 'with a resource parent and an extra container' do
65
+ recipe do
66
+ c = poise_container 'test'
67
+ poise_container 'other'
68
+ poise_test 'test' do
69
+ parent c
70
+ end
71
+ end
72
+
73
+ it { is_expected.to run_poise_test('test').with(parent: container) }
74
+ end # /context with a resource parent and an extra container
75
+
45
76
  context 'with a string name parent' do
46
77
  recipe do
47
78
  poise_container 'test'
@@ -214,6 +245,94 @@ describe Poise::Helpers::Subresources::Child do
214
245
 
215
246
  it { expect { subject }.to raise_error NoMethodError }
216
247
  end # /context with a parent type of true
248
+
249
+ context 'with a subclassed parent type' do
250
+ resource(:poise_sub, parent: :poise_container)
251
+ provider(:poise_sub, parent: :poise_container)
252
+ let(:sub) { chef_run.poise_sub('test') }
253
+
254
+ context 'with an automatic parent' do
255
+ recipe do
256
+ poise_sub 'test'
257
+ poise_test 'test'
258
+ end
259
+
260
+ it { is_expected.to run_poise_test('test').with(parent: sub) }
261
+ end # /context with an automatic parent
262
+
263
+ context 'with a resource parent' do
264
+ recipe do
265
+ c = poise_sub 'test'
266
+ poise_test 'test' do
267
+ parent c
268
+ end
269
+ end
270
+
271
+ it { is_expected.to run_poise_test('test').with(parent: sub) }
272
+ end # /context with a resource parent
273
+
274
+ context 'with a string name parent' do
275
+ recipe do
276
+ poise_sub 'test'
277
+ poise_test 'test' do
278
+ parent 'test'
279
+ end
280
+ end
281
+
282
+ it { is_expected.to run_poise_test('test').with(parent: sub) }
283
+ end # /context with a string name parent
284
+
285
+ context 'with an explicit string parent' do
286
+ recipe do
287
+ poise_sub 'test'
288
+ poise_test 'test' do
289
+ parent 'poise_sub[test]'
290
+ end
291
+ end
292
+
293
+ it { is_expected.to run_poise_test('test').with(parent: sub) }
294
+ end # /context with an explicit string parent
295
+
296
+ context 'with a hash parent' do
297
+ recipe do
298
+ poise_sub 'test'
299
+ poise_test 'test' do
300
+ parent poise_sub: 'test'
301
+ end
302
+ end
303
+
304
+ it { is_expected.to run_poise_test('test').with(parent: sub) }
305
+ end # /context with a hash parent
306
+ end # /context with a subclassed parent type
307
+
308
+ context 'with a default' do
309
+ resource(:poise_test) do
310
+ include described_class
311
+ parent_type :poise_container
312
+ parent_default Chef::DelayedEvaluator.new { run_context.resource_collection.find('poise_container[first]') }
313
+ end
314
+ recipe do
315
+ poise_container 'first'
316
+ poise_container 'second'
317
+ poise_test 'test'
318
+ end
319
+
320
+ it { is_expected.to run_poise_test('test').with(parent: chef_run.poise_container('first')) }
321
+ end # /context with a default
322
+
323
+ context 'setting the parent to itself' do
324
+ resource(:poise_test) do
325
+ include described_class
326
+ parent_type :poise_test
327
+ end
328
+ recipe do
329
+ poise_test 'test' do
330
+ parent self
331
+ end
332
+ end
333
+
334
+ it { expect { subject }.to raise_error Poise::Error }
335
+ end # /context setting the parent to itself
217
336
  end # /describe #parent
218
337
 
219
338
  describe '.parent_type' do
@@ -255,6 +374,15 @@ describe Poise::Helpers::Subresources::Child do
255
374
  it { is_expected.to eq :something }
256
375
  end # /context set to a symbol
257
376
 
377
+ context 'set to true' do
378
+ resource(:poise_test) do
379
+ include described_class
380
+ parent_type true
381
+ end
382
+
383
+ it { is_expected.to eq true }
384
+ end # /context set to true
385
+
258
386
  context 'set to an invalid value' do
259
387
  resource(:poise_test) do
260
388
  include described_class
@@ -287,7 +415,40 @@ describe Poise::Helpers::Subresources::Child do
287
415
  end
288
416
 
289
417
  it { is_expected.to eq :something }
290
- end
418
+ end # /context set via a mixin
419
+
420
+ context 'set to true via a mixin' do
421
+ # Various scoping shenanigans.
422
+ described = described_class
423
+ test_mod = Module.new do
424
+ include described
425
+ parent_type true
426
+ end
427
+ resource(:poise_test) do
428
+ include test_mod
429
+ end
430
+
431
+ it { is_expected.to eq true }
432
+ end # /context set to true via a mixin
433
+
434
+ context 'set via multiple mixins' do
435
+ # Various scoping shenanigans.
436
+ described = described_class
437
+ test_mod1 = Module.new do
438
+ include described
439
+ parent_type :something
440
+ end
441
+ test_mod2 = Module.new do
442
+ include described
443
+ parent_type true
444
+ end
445
+ resource(:poise_test) do
446
+ include test_mod1
447
+ include test_mod2
448
+ end
449
+
450
+ it { is_expected.to eq :something }
451
+ end # context set via multiple mixins
291
452
  end # /describe .parent_type
292
453
 
293
454
  describe '.parent_optional' do
@@ -350,7 +511,60 @@ describe Poise::Helpers::Subresources::Child do
350
511
 
351
512
  it { is_expected.to eq true }
352
513
  end # /context not set
353
- end
514
+ end # /describe .parent_auto
515
+
516
+ describe '.parent_default' do
517
+ subject { resource(:poise_test).parent_default }
518
+
519
+ context 'set directly' do
520
+ resource(:poise_test) do
521
+ include described_class
522
+ parent_default Chef::Resource.new(nil, nil)
523
+ end
524
+
525
+ it { is_expected.to be_a Chef::Resource }
526
+ end # /context set directly
527
+
528
+ context 'set on a parent class' do
529
+ resource(:poise_parent) do
530
+ include described_class
531
+ parent_default Chef::Resource.new(nil, nil)
532
+ end
533
+ resource(:poise_test, parent: :poise_parent)
534
+
535
+ it { is_expected.to be_a Chef::Resource }
536
+ end # /context set on a parent class
537
+
538
+ context 'not set' do
539
+ resource(:poise_test) do
540
+ include described_class
541
+ end
542
+
543
+ it { is_expected.to be_nil }
544
+ end # /context not set
545
+
546
+ context 'set to nil' do
547
+ resource(:poise_parent) do
548
+ include described_class
549
+ parent_default Chef::Resource.new(nil, nil)
550
+ end
551
+ resource(:poise_test, parent: :poise_parent) do
552
+ parent_default nil
553
+ end
554
+
555
+ it { is_expected.to be_nil }
556
+ end # /context set to nil
557
+
558
+ context 'set to lazy{}' do
559
+ resource(:poise_test) do
560
+ include described_class
561
+ include Poise::Helpers::LazyDefault
562
+ parent_default lazy { }
563
+ end
564
+
565
+ it { is_expected.to be_a Chef::DelayedEvaluator }
566
+ end # /context set to lazy{}
567
+ end # /describe .parent_default
354
568
 
355
569
  describe '.parent_attribute' do
356
570
  resource(:poise_test) do
@@ -405,4 +619,22 @@ describe Poise::Helpers::Subresources::Child do
405
619
  it { is_expected.to include 'parent nil' }
406
620
  end # /context without a parent
407
621
  end # /describe ParentRef
622
+
623
+ describe 'regression test for ordering bug' do
624
+ resource(:poise_test) do
625
+ include Poise
626
+ include Module.new {
627
+ include Poise::Resource
628
+ poise_subresource(true)
629
+ parent_attribute(:container, type: :poise_container, optional: true)
630
+ }
631
+ end
632
+ recipe do
633
+ poise_container 'one'
634
+ poise_test 'test'
635
+ poise_container 'two'
636
+ end
637
+
638
+ it { is_expected.to run_poise_test('test').with(parent_container: chef_run.poise_container('one')) }
639
+ end # /describe regression test for ordering bug
408
640
  end
@@ -146,6 +146,27 @@ describe Poise::Helpers::Subresources::Container do
146
146
  it { is_expected.to run_inner('container') }
147
147
  end # /context with a no namespace and no inner name
148
148
 
149
+ describe '#container_default' do
150
+ resource(:poise_test) do
151
+ include described_class
152
+ end
153
+ resource(:poise_sub, parent: :poise_test) do
154
+ container_default(false)
155
+ end
156
+ provider(:poise_sub, parent: :poise_test)
157
+ resource(:inner) do
158
+ include Poise(parent: :poise_test)
159
+ end
160
+ recipe do
161
+ poise_test 'one'
162
+ poise_test 'two'
163
+ poise_sub 'three'
164
+ inner 'inner'
165
+ end
166
+
167
+ it { is_expected.to run_inner('inner').with(parent: chef_run.poise_test('two')) }
168
+ end # /describe #container_default
169
+
149
170
  describe 'resource order' do
150
171
  resource(:poise_test) do
151
172
  include described_class
@@ -187,4 +208,20 @@ describe Poise::Helpers::Subresources::Container do
187
208
  is_expected.to run_inner('container::two')
188
209
  end
189
210
  end # /describe resource order
211
+
212
+ describe 'subclassing a container' do
213
+ resource(:poise_test) do
214
+ include described_class
215
+ end
216
+ resource(:poise_sub, parent: :poise_test)
217
+ provider(:poise_sub, parent: :poise_test)
218
+ recipe do
219
+ poise_sub 'test' do
220
+ inner 'one'
221
+ end
222
+ end
223
+
224
+ it { is_expected.to run_poise_sub('test') }
225
+ it { is_expected.to run_inner('test::one') }
226
+ end # /describe subclassing a container
190
227
  end