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,339 @@
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::Subresources::Child do
20
+ resource(:poise_container) do
21
+ include Poise::Helpers::ResourceName
22
+ include Poise::Helpers::Subresources::Container
23
+ end
24
+ provider(:poise_container)
25
+ provider(:poise_test)
26
+
27
+ describe '#parent' do
28
+ let(:container) { chef_run.poise_container('test') }
29
+ resource(:poise_test) do
30
+ include described_class
31
+ parent_type :poise_container
32
+ end
33
+
34
+ context 'with a resource parent' do
35
+ recipe do
36
+ c = poise_container 'test'
37
+ poise_test 'test' do
38
+ parent c
39
+ end
40
+ end
41
+
42
+ it { is_expected.to run_poise_test('test').with(parent: container) }
43
+ end # /context with a resource parent
44
+
45
+ context 'with a string name parent' do
46
+ recipe do
47
+ poise_container 'test'
48
+ poise_test 'test' do
49
+ parent 'test'
50
+ end
51
+ end
52
+
53
+ it { is_expected.to run_poise_test('test').with(parent: container) }
54
+ end # /context with a string name parent
55
+
56
+ context 'with an explicit string parent' do
57
+ recipe do
58
+ poise_container 'test'
59
+ poise_test 'test' do
60
+ parent 'poise_container[test]'
61
+ end
62
+ end
63
+
64
+ it { is_expected.to run_poise_test('test').with(parent: container) }
65
+ end # /context with an explicit string parent
66
+
67
+ context 'with a hash parent' do
68
+ recipe do
69
+ poise_container 'test'
70
+ poise_test 'test' do
71
+ parent poise_container: 'test'
72
+ end
73
+ end
74
+
75
+ it { is_expected.to run_poise_test('test').with(parent: container) }
76
+ end # /context with a hash parent
77
+
78
+ context 'with a parent of the wrong type' do
79
+ recipe do
80
+ ruby_block 'test'
81
+ poise_test 'test' do
82
+ parent 'ruby_block[test]'
83
+ end
84
+ end
85
+
86
+ it { expect { subject }.to raise_error Poise::Error }
87
+ end # /context with a parent of the wrong type
88
+
89
+ context 'with a sibling parent' do
90
+ recipe do
91
+ poise_container 'test'
92
+ poise_test 'test'
93
+ end
94
+
95
+ it { is_expected.to run_poise_test('test').with(parent: container) }
96
+ end # /context with a sibling parent
97
+
98
+ context 'with no parent' do
99
+ recipe do
100
+ poise_test 'test'
101
+ end
102
+
103
+ it { expect { subject }.to raise_error Poise::Error }
104
+ end # /context with no parent
105
+
106
+ context 'with an optional parent' do
107
+ resource(:poise_test) do
108
+ include described_class
109
+ parent_type :poise_container
110
+ parent_optional true
111
+ end
112
+ recipe do
113
+ poise_test 'test'
114
+ end
115
+
116
+ it { is_expected.to run_poise_test('test').with(parent: nil) }
117
+ end # /context with an optional parent
118
+
119
+ context 'with a default parent in a nested scope' do
120
+ resource(:poise_wrapper, unwrap_notifying_block: false) do
121
+ include Poise::Helpers::ResourceName
122
+ include Poise::Helpers::Subresources::Container
123
+ end
124
+ provider(:poise_wrapper) do
125
+ include Poise::Helpers::LWRPPolyfill
126
+ include Poise::Helpers::NotifyingBlock
127
+ def action_run
128
+ notifying_block do
129
+ poise_container new_resource.name
130
+ end
131
+ end
132
+ end
133
+ recipe do
134
+ poise_wrapper 'wrapper' do
135
+ action :nothing
136
+ end.run_action(:run)
137
+ poise_test 'test'
138
+ end
139
+
140
+ it { is_expected.to run_poise_test('test').with(parent: be_truthy) }
141
+ it { expect(chef_run.poise_container('wrapper')).to be_nil }
142
+ end # /context with a default parent in a nested scope
143
+
144
+ context 'with no automatic parent' do
145
+ resource(:poise_test) do
146
+ include described_class
147
+ parent_type :poise_container
148
+ parent_auto false
149
+ end
150
+ recipe do
151
+ poise_container 'test'
152
+ poise_test 'test'
153
+ end
154
+
155
+ it { expect { run_chef }.to raise_error(Poise::Error) }
156
+ end # /context with no automatic parent
157
+
158
+ context 'with no automatic parent but optional' do
159
+ resource(:poise_test) do
160
+ include described_class
161
+ parent_type :poise_container
162
+ parent_optional true
163
+ parent_auto false
164
+ end
165
+ recipe do
166
+ poise_container 'test'
167
+ poise_test 'test'
168
+ end
169
+
170
+ it { is_expected.to run_poise_test('test').with(parent: be_nil) }
171
+ end # /context with no automatic parent but optional
172
+ end # /describe #parent
173
+
174
+ describe '.parent_type' do
175
+ subject { resource(:poise_test).parent_type }
176
+
177
+ context 'set directly' do
178
+ resource(:poise_test) do
179
+ include described_class
180
+ parent_type String
181
+ end
182
+
183
+ it { is_expected.to eq String }
184
+ end # /context set directly
185
+
186
+ context 'set on a parent class' do
187
+ resource(:poise_parent) do
188
+ include described_class
189
+ parent_type String
190
+ end
191
+ resource(:poise_test, parent: :poise_parent)
192
+
193
+ it { is_expected.to eq String }
194
+ end # /context set on a parent class
195
+
196
+ context 'not set' do
197
+ resource(:poise_test) do
198
+ include described_class
199
+ end
200
+
201
+ it { is_expected.to eq Chef::Resource }
202
+ end # /context not set
203
+
204
+ context 'set to a symbol' do
205
+ resource(:poise_test) do
206
+ include described_class
207
+ parent_type :something
208
+ end
209
+
210
+ it { is_expected.to eq :something }
211
+ end # /context set to a symbol
212
+
213
+ context 'set to an invalid value' do
214
+ resource(:poise_test) do
215
+ include described_class
216
+ end
217
+
218
+ it do
219
+ expect { resource(:poise_test).parent_type('invalid') }.to raise_error Poise::Error
220
+ end
221
+ end # /context set to an invalid value
222
+ end # /describe .parent_type
223
+
224
+ describe '.parent_optional' do
225
+ subject { resource(:poise_test).parent_optional }
226
+
227
+ context 'set directly' do
228
+ resource(:poise_test) do
229
+ include described_class
230
+ parent_optional true
231
+ end
232
+
233
+ it { is_expected.to eq true }
234
+ end # /context set directly
235
+
236
+ context 'set on a parent class' do
237
+ resource(:poise_parent) do
238
+ include described_class
239
+ parent_optional true
240
+ end
241
+ resource(:poise_test, parent: :poise_parent)
242
+
243
+ it { is_expected.to eq true }
244
+ end # /context set on a parent class
245
+
246
+ context 'not set' do
247
+ resource(:poise_test) do
248
+ include described_class
249
+ end
250
+
251
+ it { is_expected.to eq false }
252
+ end # /context not set
253
+ end # /describe .parent_optional
254
+
255
+ describe '.parent_auto' do
256
+ subject { resource(:poise_test).parent_auto }
257
+
258
+ context 'set directly' do
259
+ resource(:poise_test) do
260
+ include described_class
261
+ parent_auto true
262
+ end
263
+
264
+ it { is_expected.to eq true }
265
+ end # /context set directly
266
+
267
+ context 'set on a parent class' do
268
+ resource(:poise_parent) do
269
+ include described_class
270
+ parent_auto true
271
+ end
272
+ resource(:poise_test, parent: :poise_parent)
273
+
274
+ it { is_expected.to eq true }
275
+ end # /context set on a parent class
276
+
277
+ context 'not set' do
278
+ resource(:poise_test) do
279
+ include described_class
280
+ end
281
+
282
+ it { is_expected.to eq true }
283
+ end # /context not set
284
+ end
285
+
286
+ describe '.parent_attribute' do
287
+ resource(:poise_test) do
288
+ include described_class
289
+ parent_type :poise_container
290
+ parent_attribute :other, type: :poise_container
291
+ end
292
+ recipe do
293
+ poise_container 'one'
294
+ poise_container 'two'
295
+ poise_test 'test' do
296
+ parent_other 'one'
297
+ end
298
+ end
299
+
300
+ it do
301
+ is_expected.to run_poise_test('test').with(
302
+ parent: chef_run.poise_container('two'),
303
+ parent_other: chef_run.poise_container('one'),
304
+ )
305
+ end
306
+ end # /describe .parent_attribute
307
+
308
+ describe 'ParentRef' do
309
+ subject { chef_run.poise_test('two').to_text }
310
+
311
+ context 'with a parent' do
312
+ resource(:poise_test) do
313
+ include described_class
314
+ parent_type :poise_container
315
+ end
316
+ recipe(subject: false) do
317
+ poise_container 'one'
318
+ poise_test 'two'
319
+ end
320
+
321
+ it { is_expected.to include 'parent poise_container[one]' }
322
+ # Negative test for the Resource#to_text format.
323
+ it { is_expected.to_not include 'poise_container("one")' }
324
+ end # /context with a parent
325
+
326
+ context 'without a parent' do
327
+ resource(:poise_test) do
328
+ include described_class
329
+ parent_type :poise_container
330
+ parent_optional true
331
+ end
332
+ recipe(subject: false) do
333
+ poise_test 'two'
334
+ end
335
+
336
+ it { is_expected.to include 'parent nil' }
337
+ end # /context without a parent
338
+ end # /describe ParentRef
339
+ end
@@ -0,0 +1,175 @@
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::Subresources::Container do
20
+ let(:chefspec_options) { {log_level: :error} } # deprecation spam
21
+ provider(:poise_test)
22
+ resource(:inner)
23
+ provider(:inner)
24
+ # Make sure we run ruby_blocks because of the order fixed magic.
25
+ step_into(:ruby_block)
26
+
27
+ context 'with a single subresource' do
28
+ resource(:poise_test) do
29
+ include described_class
30
+ end
31
+ recipe do
32
+ poise_test 'container' do
33
+ inner 'inner'
34
+ end
35
+ end
36
+
37
+ it { is_expected.to run_poise_test('container') }
38
+ it { is_expected.to run_inner('container::inner').with(source_line: start_with("#{__FILE__}:33")) }
39
+ end # /context with a single subresource
40
+
41
+ context 'with a multiple subresources' do
42
+ resource(:poise_test) do
43
+ include described_class
44
+ end
45
+ recipe do
46
+ poise_test 'container' do
47
+ inner 'inner'
48
+ inner 'inner2'
49
+ inner 'inner3'
50
+ end
51
+ end
52
+
53
+ it { is_expected.to run_poise_test('container') }
54
+ it { is_expected.to run_inner('container::inner') }
55
+ it { is_expected.to run_inner('container::inner2') }
56
+ it { is_expected.to run_inner('container::inner3') }
57
+ end # /context with a multiple subresources
58
+
59
+ context 'with an explicit namespace' do
60
+ resource(:poise_test) do
61
+ include described_class
62
+ container_namespace('name')
63
+ end
64
+ recipe do
65
+ poise_test 'container' do
66
+ inner 'inner'
67
+ end
68
+ end
69
+
70
+ it { is_expected.to run_poise_test('container') }
71
+ it { is_expected.to run_inner('name::inner') }
72
+ end # /context with an explicit namespace
73
+
74
+ context 'with an explicit namespace and no inner name' do
75
+ resource(:poise_test) do
76
+ include described_class
77
+ container_namespace('name')
78
+ end
79
+ recipe do
80
+ poise_test 'container' do
81
+ inner ''
82
+ end
83
+ end
84
+
85
+ it { is_expected.to run_poise_test('container') }
86
+ it { is_expected.to run_inner('name') }
87
+ end # /context with an explicit namespace and no inner name
88
+
89
+ context 'with an explicit Proc namespace' do
90
+ resource(:poise_test) do
91
+ include described_class
92
+ container_namespace(Proc.new { name + '_name' })
93
+ end
94
+ recipe do
95
+ poise_test 'container' do
96
+ inner 'inner'
97
+ end
98
+ end
99
+
100
+ it { is_expected.to run_poise_test('container') }
101
+ it { is_expected.to run_inner('container_name::inner') }
102
+ end # /context with an explicit Proc namespace
103
+
104
+ context 'with a no namespace' do
105
+ resource(:poise_test) do
106
+ include described_class
107
+ container_namespace(false)
108
+ end
109
+ recipe do
110
+ poise_test 'container' do
111
+ inner 'inner'
112
+ end
113
+ end
114
+
115
+ it { is_expected.to run_poise_test('container') }
116
+ it { is_expected.to run_inner('inner') }
117
+ end # /context with a no namespace
118
+
119
+ context 'with a no namespace and no inner name' do
120
+ resource(:poise_test) do
121
+ include described_class
122
+ container_namespace(false)
123
+ end
124
+ recipe do
125
+ poise_test 'container' do
126
+ inner ''
127
+ end
128
+ end
129
+
130
+ it { is_expected.to run_poise_test('container') }
131
+ it { is_expected.to run_inner('container') }
132
+ end # /context with a no namespace and no inner name
133
+
134
+ describe 'resource order' do
135
+ resource(:poise_test) do
136
+ include described_class
137
+ end
138
+ provider(:poise_test) do
139
+ def action_run
140
+ expect(node.run_state['order']).to eq 0
141
+ node.run_state['order'] += 1
142
+ end
143
+ end
144
+ resource(:inner) do
145
+ def val(val=nil)
146
+ set_or_return(:val, val, {})
147
+ end
148
+ end
149
+ provider(:inner) do
150
+ def action_run
151
+ expect(node.run_state['order']).to eq new_resource.val
152
+ node.run_state['order'] += 1
153
+ end
154
+ end
155
+ recipe do
156
+ node.run_state['order'] = 0
157
+ poise_test 'container' do
158
+ inner 'one' do
159
+ val 1
160
+ end
161
+ inner 'two' do
162
+ val 2
163
+ end
164
+ end
165
+ end
166
+
167
+ it do
168
+ # The dreaded multi-assertion test. Really I just need to force it to run,
169
+ # these assertions are just additional sanity.
170
+ is_expected.to run_poise_test('container')
171
+ is_expected.to run_inner('container::one')
172
+ is_expected.to run_inner('container::two')
173
+ end
174
+ end # /describe resource order
175
+ end