poise 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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