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,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