poise 2.0.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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.kitchen.travis.yml +9 -0
  4. data/.kitchen.yml +18 -0
  5. data/.rubocop.yml +2 -0
  6. data/.travis.yml +25 -0
  7. data/.yardopts +5 -0
  8. data/Berksfile +26 -0
  9. data/Berksfile.lock +10 -0
  10. data/CHANGELOG.md +58 -0
  11. data/Gemfile +32 -0
  12. data/LICENSE +202 -0
  13. data/README.md +198 -0
  14. data/Rakefile +17 -0
  15. data/lib/poise.rb +71 -0
  16. data/lib/poise/error.rb +24 -0
  17. data/lib/poise/helpers.rb +33 -0
  18. data/lib/poise/helpers/chefspec_matchers.rb +92 -0
  19. data/lib/poise/helpers/defined_in.rb +111 -0
  20. data/lib/poise/helpers/fused.rb +127 -0
  21. data/lib/poise/helpers/include_recipe.rb +62 -0
  22. data/lib/poise/helpers/inversion.rb +374 -0
  23. data/lib/poise/helpers/inversion/options_provider.rb +41 -0
  24. data/lib/poise/helpers/inversion/options_resource.rb +101 -0
  25. data/lib/poise/helpers/lazy_default.rb +62 -0
  26. data/lib/poise/helpers/lwrp_polyfill.rb +96 -0
  27. data/lib/poise/helpers/notifying_block.rb +78 -0
  28. data/lib/poise/helpers/option_collector.rb +117 -0
  29. data/lib/poise/helpers/resource_name.rb +99 -0
  30. data/lib/poise/helpers/subcontext_block.rb +58 -0
  31. data/lib/poise/helpers/subresources.rb +29 -0
  32. data/lib/poise/helpers/subresources/child.rb +217 -0
  33. data/lib/poise/helpers/subresources/container.rb +165 -0
  34. data/lib/poise/helpers/subresources/default_containers.rb +73 -0
  35. data/lib/poise/helpers/template_content.rb +165 -0
  36. data/lib/poise/provider.rb +55 -0
  37. data/lib/poise/resource.rb +75 -0
  38. data/lib/poise/subcontext.rb +27 -0
  39. data/lib/poise/subcontext/resource_collection.rb +56 -0
  40. data/lib/poise/subcontext/runner.rb +50 -0
  41. data/lib/poise/utils.rb +60 -0
  42. data/lib/poise/utils/resource_provider_mixin.rb +53 -0
  43. data/lib/poise/version.rb +20 -0
  44. data/poise.gemspec +38 -0
  45. data/test/cookbooks/poise_test/attributes/default.rb +17 -0
  46. data/test/cookbooks/poise_test/libraries/app.rb +43 -0
  47. data/test/cookbooks/poise_test/libraries/app_config.rb +46 -0
  48. data/test/cookbooks/poise_test/libraries/inversion.rb +67 -0
  49. data/test/cookbooks/poise_test/metadata.rb +18 -0
  50. data/test/cookbooks/poise_test/recipes/default.rb +25 -0
  51. data/test/cookbooks/poise_test/recipes/inversion.rb +42 -0
  52. data/test/gemfiles/chef-12.0.gemfile +18 -0
  53. data/test/gemfiles/chef-12.1.gemfile +18 -0
  54. data/test/gemfiles/chef-12.2.gemfile +18 -0
  55. data/test/gemfiles/chef-12.gemfile +18 -0
  56. data/test/gemfiles/master.gemfile +20 -0
  57. data/test/integration/default/serverspec/default_spec.rb +35 -0
  58. data/test/integration/default/serverspec/inversion_spec.rb +43 -0
  59. data/test/spec/helpers/chefspec_matchers_spec.rb +45 -0
  60. data/test/spec/helpers/defined_in_spec.rb +62 -0
  61. data/test/spec/helpers/fused_spec.rb +92 -0
  62. data/test/spec/helpers/include_recipe_spec.rb +34 -0
  63. data/test/spec/helpers/inversion/options_resource_spec.rb +212 -0
  64. data/test/spec/helpers/inversion_spec.rb +273 -0
  65. data/test/spec/helpers/lazy_default_spec.rb +74 -0
  66. data/test/spec/helpers/lwrp_polyfill_spec.rb +128 -0
  67. data/test/spec/helpers/notifying_block_spec.rb +87 -0
  68. data/test/spec/helpers/option_collector_spec.rb +82 -0
  69. data/test/spec/helpers/resource_name_spec.rb +39 -0
  70. data/test/spec/helpers/subcontext_block_spec.rb +94 -0
  71. data/test/spec/helpers/subresources/child_spec.rb +339 -0
  72. data/test/spec/helpers/subresources/container_spec.rb +175 -0
  73. data/test/spec/helpers/template_context_spec.rb +147 -0
  74. data/test/spec/poise_spec.rb +185 -0
  75. data/test/spec/provider_spec.rb +28 -0
  76. data/test/spec/resource_spec.rb +85 -0
  77. data/test/spec/spec_helper.rb +18 -0
  78. data/test/spec/utils/resource_provider_mixin_spec.rb +52 -0
  79. data/test/spec/utils_spec.rb +110 -0
  80. metadata +190 -0
@@ -0,0 +1,74 @@
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
+
19
+ LAZY_DEFAULT_GLOBAL = [0]
20
+
21
+ describe Poise::Helpers::LazyDefault do
22
+ resource(:poise_test) do
23
+ include Poise::Helpers::LWRPPolyfill
24
+ include described_class
25
+ attribute(:value, default: lazy { name + '_lazy' })
26
+ end
27
+ provider(:poise_test)
28
+ recipe do
29
+ poise_test 'test'
30
+ end
31
+
32
+ it { is_expected.to run_poise_test('test').with(value: 'test_lazy') }
33
+
34
+ context 'with an explicit value' do
35
+ recipe do
36
+ poise_test 'test' do
37
+ value 'value'
38
+ end
39
+ end
40
+
41
+ it { is_expected.to run_poise_test('test').with(value: 'value') }
42
+ end
43
+
44
+ context 'in a subclass' do
45
+ resource(:poise_sub, parent: :poise_test)
46
+ provider(:poise_sub)
47
+ recipe do
48
+ poise_sub 'test'
49
+ end
50
+
51
+ it { is_expected.to run_poise_test('test').with(value: 'test_lazy') }
52
+ end
53
+
54
+ context 'with an external global' do
55
+ resource(:poise_test) do
56
+ include Poise::Helpers::LWRPPolyfill
57
+ include described_class
58
+ attribute(:value, default: lazy { LAZY_DEFAULT_GLOBAL.first })
59
+ end
60
+
61
+ it 'does not cache the value before retrieval' do
62
+ LAZY_DEFAULT_GLOBAL[0] = 42
63
+ is_expected.to run_poise_test('test').with(value: 42)
64
+ end
65
+
66
+ # This is actually part of set_or_return, but make sure we didn't break semantics
67
+ it 'caches the value once retrieved' do
68
+ LAZY_DEFAULT_GLOBAL[0] = 0
69
+ is_expected.to run_poise_test('test').with(value: 0)
70
+ LAZY_DEFAULT_GLOBAL[0] = 42
71
+ is_expected.to run_poise_test('test').with(value: 0)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,128 @@
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
+
19
+ describe Poise::Helpers::LWRPPolyfill do
20
+ describe Poise::Helpers::LWRPPolyfill::Resource do
21
+ describe '#attribute' do
22
+ resource(:poise_test) do
23
+ include described_class
24
+ attribute(:boolean, equal_to: [true, false])
25
+ end
26
+
27
+ provider(:poise_test)
28
+
29
+ context 'with default value' do
30
+ recipe do
31
+ poise_test 'nil'
32
+ end
33
+
34
+ it { is_expected.to run_poise_test('nil').with(boolean: nil) }
35
+ end
36
+
37
+ context 'with true value' do
38
+ recipe do
39
+ poise_test 'true' do
40
+ boolean true
41
+ end
42
+ end
43
+
44
+ it { is_expected.to run_poise_test('true').with(boolean: true) }
45
+ end
46
+
47
+ context 'with false value' do
48
+ recipe do
49
+ poise_test 'false' do
50
+ boolean false
51
+ end
52
+ end
53
+
54
+ it { is_expected.to run_poise_test('false').with(boolean: false) }
55
+ end
56
+
57
+ context 'with string value' do
58
+ recipe do
59
+ poise_test 'true' do
60
+ boolean 'boom'
61
+ end
62
+ end
63
+
64
+ it { expect { subject }.to raise_error Chef::Exceptions::ValidationFailed }
65
+ end
66
+ end # /describe #attribute
67
+
68
+ describe '#default_action' do
69
+ resource(:poise_test) do
70
+ include described_class
71
+ default_action(:one)
72
+ actions(:two)
73
+ end
74
+ provider(:poise_test) do
75
+ def action_one; end
76
+ def action_two; end
77
+ end
78
+ recipe do
79
+ poise_test 'test'
80
+ end
81
+
82
+ it { is_expected.to one_poise_test('test') }
83
+ end # /describe #default_action
84
+ end # /describe Poise::Helpers::LWRPPolyfill::Resource
85
+
86
+ describe Poise::Helpers::LWRPPolyfill::Provider do
87
+ describe 'load_current_resource override' do
88
+ subject { provider(:poise_test).new(nil, nil).load_current_resource }
89
+
90
+ context 'with a direct Provider subclass' do
91
+ provider(:poise_test, auto: false) do
92
+ include described_class
93
+ end
94
+
95
+ it { is_expected.to be_nil }
96
+ end
97
+
98
+ context 'with an intermediary class' do
99
+ provider(:poise_parent, auto: false) do
100
+ def load_current_resource
101
+ 'helper'
102
+ end
103
+ end
104
+ provider(:poise_test, auto: false, parent: :poise_parent) do
105
+ include described_class
106
+ end
107
+
108
+ it { is_expected.to eq 'helper' }
109
+ end
110
+ end
111
+
112
+ describe 'Chef::DSL::Recipe include' do
113
+ resource(:poise_test)
114
+ provider(:poise_test) do
115
+ include described_class
116
+
117
+ def action_run
118
+ ruby_block 'test'
119
+ end
120
+ end
121
+ recipe do
122
+ poise_test 'test'
123
+ end
124
+
125
+ it { is_expected.to run_ruby_block('test') }
126
+ end
127
+ end # /describe Poise::Helpers::LWRPPolyfill::Provider
128
+ end
@@ -0,0 +1,87 @@
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
+
19
+ describe Poise::Helpers::NotifyingBlock do
20
+ before { step_into << 'ruby_block' }
21
+ resource(:poise_test, unwrap_notifying_block: false) do
22
+ def inner_action(val=nil)
23
+ set_or_return(:inner_action, val, {})
24
+ end
25
+ end
26
+ provider(:poise_test) do
27
+ include Poise::Helpers::LWRPPolyfill
28
+ include described_class
29
+
30
+ def action_run
31
+ notifying_block do
32
+ ruby_block 'inner' do
33
+ action new_resource.inner_action
34
+ block { }
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ context 'with updated inner resources' do
41
+ recipe do
42
+ poise_test 'test' do
43
+ inner_action :run
44
+ end
45
+ end
46
+
47
+ it 'marks the outer resource as updated' do
48
+ expect(subject.find_resource('poise_test', 'test').updated_by_last_action?).to be_truthy
49
+ end
50
+
51
+ it 'does not add the inner resource to the global collection' do
52
+ expect(subject.find_resource('ruby_block', 'inner ')).to be_nil
53
+ end
54
+ end # /context with updated inner resources
55
+
56
+ context 'without updated inner resources' do
57
+ recipe do
58
+ poise_test 'test' do
59
+ inner_action :nothing
60
+ end
61
+ end
62
+
63
+ it 'does not marks the outer resource as updated' do
64
+ expect(subject.find_resource('poise_test', 'test').updated_by_last_action?).to be_falsey
65
+ end
66
+ end # /context without updated inner resources
67
+
68
+ context 'with an exception raised inside the block' do
69
+ provider(:poise_test) do
70
+ include Poise::Helpers::LWRPPolyfill
71
+ include described_class
72
+
73
+ def action_run
74
+ notifying_block do
75
+ ruby_block 'inner' do
76
+ block { raise 'Boom!' }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ recipe do
82
+ poise_test 'test'
83
+ end
84
+
85
+ it { expect { subject }.to raise_error(RuntimeError) }
86
+ end # /context with an exception raised inside the block
87
+ end
@@ -0,0 +1,82 @@
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
+
19
+ describe Poise::Helpers::OptionCollector do
20
+ resource(:poise_test) do
21
+ include described_class
22
+ attribute(:options, option_collector: true)
23
+ end
24
+ provider(:poise_test)
25
+
26
+ context 'with a block' do
27
+ recipe do
28
+ poise_test 'test' do
29
+ options do
30
+ one '1'
31
+ two 2
32
+ end
33
+ end
34
+ end
35
+
36
+ it { is_expected.to run_poise_test('test').with(options: {'one' => '1', 'two' => 2}) }
37
+ end # /context with a block
38
+
39
+ context 'with a hash' do
40
+ recipe do
41
+ poise_test 'test' do
42
+ options one: '1', two: 2
43
+ end
44
+ end
45
+
46
+ it { is_expected.to run_poise_test('test').with(options: {'one' => '1', 'two' => 2}) }
47
+ end # /context with a hash
48
+
49
+ context 'with both a block and a hash' do
50
+ recipe do
51
+ poise_test 'test' do
52
+ options one: '1', two: 2 do
53
+ two 3
54
+ three 'three'
55
+ end
56
+ end
57
+ end
58
+
59
+ it { is_expected.to run_poise_test('test').with(options: {'one' => '1', 'two' => 3, 'three' => 'three'}) }
60
+ end # /context with both a block and a hash
61
+
62
+ context 'with a normal attribute too' do
63
+ resource(:poise_test) do
64
+ include Poise::Helpers::LWRPPolyfill
65
+ include described_class
66
+ attribute(:options, option_collector: true)
67
+ attribute(:value)
68
+ end
69
+ recipe do
70
+ poise_test 'test' do
71
+ options do
72
+ one '1'
73
+ end
74
+ value 2
75
+ end
76
+ end
77
+
78
+ it { is_expected.to run_poise_test('test').with(options: {'one' => '1'}, value: 2) }
79
+ end # /context with a normal attribute too
80
+
81
+ # TODO: Write tests for mixed symbol/string data
82
+ end
@@ -0,0 +1,39 @@
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
+
19
+ class ResourceNameHelper < Chef::Resource
20
+ include Poise::Helpers::ResourceName
21
+ provides(:provides_test)
22
+ end
23
+
24
+ describe Poise::Helpers::ResourceName do
25
+ context 'via class.name' do
26
+ resource(:poise_test, auto: false) do
27
+ include described_class
28
+ end
29
+ subject { resource(:poise_test).new(nil, nil).resource_name }
30
+
31
+ it { is_expected.to eq :poise_test }
32
+ end
33
+
34
+ context 'via provides' do
35
+ subject { ResourceNameHelper.new(nil, nil).resource_name }
36
+
37
+ it { is_expected.to eq :provides_test }
38
+ end
39
+ end
@@ -0,0 +1,94 @@
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
+
19
+ describe Poise::Helpers::SubcontextBlock do
20
+ resource(:poise_test)
21
+ recipe do
22
+ poise_test 'test'
23
+ end
24
+
25
+ # General sanity test
26
+ provider(:poise_test) do
27
+ include described_class
28
+ include Chef::DSL::Recipe
29
+
30
+ def action_run
31
+ top_level_collection = run_context.resource_collection
32
+ sub = subcontext_block do
33
+ expect(run_context.resource_collection).to_not be top_level_collection
34
+ expect(global_resource_collection).to be top_level_collection
35
+ expect(run_context.resource_collection.parent).to be top_level_collection
36
+
37
+ ruby_block 'inner'
38
+ end
39
+ expect(sub.resource_collection.find('ruby_block[inner]')).to be_truthy
40
+ end
41
+ end
42
+
43
+ it { is_expected.to_not run_ruby_block('inner') }
44
+
45
+ describe '#global_resource_collection' do
46
+ provider(:poise_test) do
47
+ include described_class
48
+ include Chef::DSL::Recipe
49
+
50
+ def action_run
51
+ top_level_collection = run_context.resource_collection
52
+ subcontext_block do
53
+ subcontext_block do
54
+ expect(global_resource_collection).to be top_level_collection
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ it { run_chef }
61
+ end # /describe #global_resource_collection
62
+
63
+ describe '#recursive_each' do
64
+ provider(:poise_test) do
65
+ include described_class
66
+ include Chef::DSL::Recipe
67
+
68
+ def action_run
69
+ ctx = subcontext_block do
70
+ ruby_block 'a'
71
+ ctx2 = subcontext_block do
72
+ ruby_block 'b'
73
+ ruby_block 'c'
74
+ end
75
+ expect(names(ctx2)).to eq %w{test a b c}
76
+ ruby_block 'd'
77
+ end
78
+ expect(names(ctx)).to eq %w{test a d}
79
+ end
80
+
81
+ private
82
+
83
+ def names(ctx)
84
+ [].tap do |names|
85
+ ctx.resource_collection.recursive_each do |r|
86
+ names << r.name
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ it { run_chef }
93
+ end # /describe #recursive_each
94
+ end