cheffish 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +120 -120
  4. data/Rakefile +23 -23
  5. data/lib/chef/provider/chef_acl.rb +439 -439
  6. data/lib/chef/provider/chef_client.rb +53 -53
  7. data/lib/chef/provider/chef_container.rb +55 -55
  8. data/lib/chef/provider/chef_data_bag.rb +55 -55
  9. data/lib/chef/provider/chef_data_bag_item.rb +278 -278
  10. data/lib/chef/provider/chef_environment.rb +83 -83
  11. data/lib/chef/provider/chef_group.rb +83 -83
  12. data/lib/chef/provider/chef_mirror.rb +169 -169
  13. data/lib/chef/provider/chef_node.rb +87 -87
  14. data/lib/chef/provider/chef_organization.rb +155 -155
  15. data/lib/chef/provider/chef_resolved_cookbooks.rb +46 -46
  16. data/lib/chef/provider/chef_role.rb +84 -84
  17. data/lib/chef/provider/chef_user.rb +59 -59
  18. data/lib/chef/provider/private_key.rb +225 -225
  19. data/lib/chef/provider/public_key.rb +88 -88
  20. data/lib/chef/resource/chef_acl.rb +69 -69
  21. data/lib/chef/resource/chef_client.rb +48 -48
  22. data/lib/chef/resource/chef_container.rb +22 -22
  23. data/lib/chef/resource/chef_data_bag.rb +22 -22
  24. data/lib/chef/resource/chef_data_bag_item.rb +121 -121
  25. data/lib/chef/resource/chef_environment.rb +77 -77
  26. data/lib/chef/resource/chef_group.rb +53 -53
  27. data/lib/chef/resource/chef_mirror.rb +52 -52
  28. data/lib/chef/resource/chef_node.rb +22 -22
  29. data/lib/chef/resource/chef_organization.rb +69 -69
  30. data/lib/chef/resource/chef_resolved_cookbooks.rb +35 -35
  31. data/lib/chef/resource/chef_role.rb +110 -110
  32. data/lib/chef/resource/chef_user.rb +56 -56
  33. data/lib/chef/resource/private_key.rb +48 -48
  34. data/lib/chef/resource/public_key.rb +25 -25
  35. data/lib/cheffish.rb +235 -235
  36. data/lib/cheffish/actor_provider_base.rb +131 -131
  37. data/lib/cheffish/basic_chef_client.rb +184 -184
  38. data/lib/cheffish/chef_provider_base.rb +246 -246
  39. data/lib/cheffish/chef_run.rb +162 -162
  40. data/lib/cheffish/chef_run_data.rb +19 -19
  41. data/lib/cheffish/chef_run_listener.rb +30 -30
  42. data/lib/cheffish/key_formatter.rb +113 -113
  43. data/lib/cheffish/merged_config.rb +94 -94
  44. data/lib/cheffish/recipe_dsl.rb +157 -157
  45. data/lib/cheffish/rspec.rb +8 -8
  46. data/lib/cheffish/rspec/chef_run_support.rb +83 -83
  47. data/lib/cheffish/rspec/matchers.rb +4 -4
  48. data/lib/cheffish/rspec/matchers/be_idempotent.rb +16 -16
  49. data/lib/cheffish/rspec/matchers/emit_no_warnings_or_errors.rb +15 -15
  50. data/lib/cheffish/rspec/matchers/have_updated.rb +37 -37
  51. data/lib/cheffish/rspec/matchers/partially_match.rb +63 -63
  52. data/lib/cheffish/rspec/recipe_run_wrapper.rb +59 -59
  53. data/lib/cheffish/rspec/repository_support.rb +108 -108
  54. data/lib/cheffish/server_api.rb +52 -52
  55. data/lib/cheffish/version.rb +3 -3
  56. data/lib/cheffish/with_pattern.rb +21 -21
  57. data/spec/functional/fingerprint_spec.rb +64 -64
  58. data/spec/functional/merged_config_spec.rb +19 -19
  59. data/spec/functional/server_api_spec.rb +13 -13
  60. data/spec/integration/chef_acl_spec.rb +879 -879
  61. data/spec/integration/chef_client_spec.rb +105 -105
  62. data/spec/integration/chef_container_spec.rb +33 -33
  63. data/spec/integration/chef_group_spec.rb +309 -309
  64. data/spec/integration/chef_mirror_spec.rb +491 -491
  65. data/spec/integration/chef_node_spec.rb +786 -786
  66. data/spec/integration/chef_organization_spec.rb +226 -226
  67. data/spec/integration/chef_role_spec.rb +78 -78
  68. data/spec/integration/chef_user_spec.rb +85 -85
  69. data/spec/integration/private_key_spec.rb +399 -399
  70. data/spec/integration/recipe_dsl_spec.rb +28 -28
  71. data/spec/integration/rspec/converge_spec.rb +183 -183
  72. data/spec/support/key_support.rb +29 -29
  73. data/spec/support/spec_support.rb +15 -15
  74. data/spec/unit/get_private_key_spec.rb +131 -131
  75. data/spec/unit/recipe_run_wrapper_spec.rb +37 -37
  76. metadata +3 -4
@@ -1,786 +1,786 @@
1
- require 'support/spec_support'
2
- require 'cheffish/rspec/chef_run_support'
3
- require 'chef/resource/chef_node'
4
- require 'chef/provider/chef_node'
5
-
6
- describe Chef::Resource::ChefNode do
7
- extend Cheffish::RSpec::ChefRunSupport
8
-
9
- when_the_chef_12_server 'is in multi-org mode' do
10
- organization 'foo'
11
-
12
- before :each do
13
- Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
14
- end
15
-
16
- context 'and is empty' do
17
- context 'and we run a recipe that creates node "blah"' do
18
- it 'the node gets created' do
19
- expect_recipe {
20
- chef_node 'blah'
21
- }.to have_updated 'chef_node[blah]', :create
22
- expect(get('nodes/blah')['name']).to eq('blah')
23
- end
24
- end
25
-
26
- # TODO why-run mode
27
-
28
- context 'and another chef server is running on port 8899' do
29
- before :each do
30
- @server = ChefZero::Server.new(:port => 8899)
31
- @server.start_background
32
- end
33
-
34
- after :each do
35
- @server.stop
36
- end
37
-
38
- context 'and a recipe is run that creates node "blah" on the second chef server using with_chef_server' do
39
-
40
- it 'the node is created on the second chef server but not the first' do
41
- expect_recipe {
42
- with_chef_server 'http://127.0.0.1:8899'
43
- chef_node 'blah'
44
- }.to have_updated 'chef_node[blah]', :create
45
- expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
46
- expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
47
- end
48
- end
49
-
50
- context 'and a recipe is run that creates node "blah" on the second chef server using chef_server' do
51
-
52
- it 'the node is created on the second chef server but not the first' do
53
- expect_recipe {
54
- chef_node 'blah' do
55
- chef_server({ :chef_server_url => 'http://127.0.0.1:8899' })
56
- end
57
- }.to have_updated 'chef_node[blah]', :create
58
- expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
59
- expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
60
- end
61
- end
62
- end
63
- end
64
-
65
- context 'and has a node named "blah"' do
66
- node 'blah', {}
67
-
68
- it 'chef_node "blah" does not get created or updated' do
69
- expect_recipe {
70
- chef_node 'blah'
71
- }.not_to have_updated 'chef_node[blah]', :create
72
- end
73
- end
74
-
75
- context 'and has a node named "blah" with tags' do
76
- node 'blah', {
77
- 'normal' => { 'tags' => [ 'a', 'b' ] }
78
- }
79
-
80
- context 'with chef_node "blah" that sets attributes' do
81
- with_converge do
82
- chef_node 'blah' do
83
- attributes({})
84
- end
85
- end
86
-
87
- it 'the tags in attributes are used' do
88
- expect(get('nodes/blah')['normal']['tags']).to eq([ 'a', 'b' ])
89
- end
90
- end
91
-
92
- context 'with chef_node "blah" that sets attributes with tags in them' do
93
- with_converge do
94
- chef_node 'blah' do
95
- attributes 'tags' => [ 'c', 'd' ]
96
- end
97
- end
98
-
99
- it 'the tags in attributes are used' do
100
- expect(get('nodes/blah')['normal']['tags']).to eq([ 'c', 'd' ])
101
- end
102
- end
103
- end
104
-
105
- describe '#complete' do
106
- context 'when the Chef server has a node named "blah" with everything in it' do
107
- node 'blah', {
108
- 'chef_environment' => 'blah',
109
- 'run_list' => [ 'recipe[bjork]' ],
110
- 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
111
- 'default' => { 'foo2' => 'bar2' },
112
- 'automatic' => { 'foo3' => 'bar3' },
113
- 'override' => { 'foo4' => 'bar4' }
114
- }
115
-
116
- it 'chef_node with no attributes modifies nothing' do
117
- expect_recipe {
118
- chef_node 'blah'
119
- }.to be_up_to_date
120
- expect(get('nodes/blah')).to include(
121
- 'name' => 'blah',
122
- 'chef_environment' => 'blah',
123
- 'run_list' => [ 'recipe[bjork]' ],
124
- 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
125
- 'default' => { 'foo2' => 'bar2' },
126
- 'automatic' => { 'foo3' => 'bar3' },
127
- 'override' => { 'foo4' => 'bar4' }
128
- )
129
- end
130
-
131
- it 'chef_node with complete true removes everything except default, automatic and override' do
132
- expect_recipe {
133
- chef_node 'blah' do
134
- complete true
135
- end
136
- }.to be_updated
137
- expect(get('nodes/blah')).to include(
138
- 'name' => 'blah',
139
- 'chef_environment' => '_default',
140
- 'run_list' => [ ],
141
- 'normal' => { 'tags' => [ 'a', 'b' ] },
142
- 'default' => { 'foo2' => 'bar2' },
143
- 'automatic' => { 'foo3' => 'bar3' },
144
- 'override' => { 'foo4' => 'bar4' }
145
- )
146
- end
147
-
148
- it 'chef_node with complete true sets the given attributes' do
149
- expect_recipe {
150
- chef_node 'blah' do
151
- chef_environment 'x'
152
- run_list [ 'recipe[y]' ]
153
- attributes 'a' => 'b'
154
- tags 'c', 'd'
155
- complete true
156
- end
157
- }.to be_updated
158
- expect(get('nodes/blah')).to include(
159
- 'name' => 'blah',
160
- 'chef_environment' => 'x',
161
- 'run_list' => [ 'recipe[y]' ],
162
- 'normal' => { 'a' => 'b', 'tags' => [ 'c', 'd' ] },
163
- 'default' => { 'foo2' => 'bar2' },
164
- 'automatic' => { 'foo3' => 'bar3' },
165
- 'override' => { 'foo4' => 'bar4' }
166
- )
167
- end
168
-
169
- it 'chef_node with complete true and partial attributes sets the given attributes' do
170
- expect_recipe {
171
- chef_node 'blah' do
172
- chef_environment 'x'
173
- recipe 'y'
174
- attribute 'a', 'b'
175
- tags 'c', 'd'
176
- complete true
177
- end
178
- }.to be_updated
179
- expect(get('nodes/blah')).to include(
180
- 'name' => 'blah',
181
- 'chef_environment' => 'x',
182
- 'run_list' => [ 'recipe[y]' ],
183
- 'normal' => { 'a' => 'b', 'tags' => [ 'c', 'd' ] },
184
- 'default' => { 'foo2' => 'bar2' },
185
- 'automatic' => { 'foo3' => 'bar3' },
186
- 'override' => { 'foo4' => 'bar4' }
187
- )
188
- end
189
- end
190
- end
191
-
192
- describe '#attributes' do
193
- context 'with a node with normal attributes a => b and c => { d => e }' do
194
- node 'blah', {
195
- 'normal' => {
196
- 'a' => 'b',
197
- 'c' => { 'd' => 'e' },
198
- 'tags' => [ 'a', 'b' ]
199
- },
200
- 'automatic' => {
201
- 'x' => 'y'
202
- },
203
- 'chef_environment' => 'desert'
204
- }
205
-
206
- it 'chef_node with attributes {} removes all normal attributes but leaves tags, automatic and environment alone' do
207
- expect_recipe {
208
- chef_node 'blah' do
209
- attributes({})
210
- end
211
- }.to have_updated('chef_node[blah]', :create)
212
- expect(get('nodes/blah')).to include(
213
- 'normal' => { 'tags' => [ 'a', 'b' ] },
214
- 'automatic' => { 'x' => 'y' },
215
- 'chef_environment' => 'desert'
216
- )
217
- end
218
-
219
- it 'chef_node with attributes { c => d } replaces normal but not tags/automatic/environment' do
220
- expect_recipe {
221
- chef_node 'blah' do
222
- attributes 'c' => 'd'
223
- end
224
- }.to have_updated('chef_node[blah]', :create)
225
- expect(get('nodes/blah')).to include(
226
- 'normal' => { 'c' => 'd', 'tags' => [ 'a', 'b' ] },
227
- 'automatic' => { 'x' => 'y' },
228
- 'chef_environment' => 'desert'
229
- )
230
- end
231
-
232
- it 'chef_node with attributes { c => f => g, y => z } replaces normal but not tags/automatic/environment' do
233
- expect_recipe {
234
- chef_node 'blah' do
235
- attributes 'c' => { 'f' => 'g' }, 'y' => 'z'
236
- end
237
- }.to have_updated('chef_node[blah]', :create)
238
- expect(get('nodes/blah')).to include(
239
- 'normal' => { 'c' => { 'f' => 'g' }, 'y' => 'z', 'tags' => [ 'a', 'b' ] },
240
- 'automatic' => { 'x' => 'y' },
241
- 'chef_environment' => 'desert'
242
- )
243
- end
244
-
245
- it 'chef_node with attributes { tags => [ "x" ] } replaces normal and tags but not automatic/environment' do
246
- expect_recipe {
247
- chef_node 'blah' do
248
- attributes 'tags' => [ 'x' ]
249
- end
250
- }.to have_updated('chef_node[blah]', :create)
251
- expect(get('nodes/blah')).to include(
252
- 'normal' => { 'tags' => [ 'x' ] },
253
- 'automatic' => { 'x' => 'y' },
254
- 'chef_environment' => 'desert'
255
- )
256
- end
257
-
258
- it 'chef_node with tags "x" and attributes { "tags" => [ "y" ] } sets tags to "x"' do
259
- expect_recipe {
260
- chef_node 'blah' do
261
- tags 'x'
262
- attributes 'tags' => [ 'y' ]
263
- end
264
- }.to have_updated('chef_node[blah]', :create)
265
- expect(get('nodes/blah')).to include(
266
- 'normal' => {
267
- 'tags' => [ 'x' ]
268
- },
269
- 'automatic' => { 'x' => 'y' },
270
- 'chef_environment' => 'desert'
271
- )
272
- end
273
- end
274
- end
275
-
276
- describe '#attribute' do
277
- context 'with a node with normal attributes a => b and c => { d => e }' do
278
- node 'blah', {
279
- 'normal' => {
280
- 'a' => 'b',
281
- 'c' => { 'd' => 'e' },
282
- 'tags' => [ 'a', 'b' ]
283
- },
284
- 'automatic' => {
285
- 'x' => 'y'
286
- },
287
- 'chef_environment' => 'desert'
288
- }
289
-
290
- context 'basic scenarios' do
291
- it 'chef_node with no attributes, leaves it alone' do
292
- expect_recipe {
293
- chef_node 'blah'
294
- }.not_to have_updated('chef_node[blah]', :create)
295
- expect(get('nodes/blah')).to include(
296
- 'normal' => {
297
- 'a' => 'b',
298
- 'c' => { 'd' => 'e' },
299
- 'tags' => [ 'a', 'b' ]
300
- },
301
- 'automatic' => { 'x' => 'y' },
302
- 'chef_environment' => 'desert'
303
- )
304
- end
305
-
306
- it 'chef_node with attribute d, e adds the attribute' do
307
- expect_recipe {
308
- chef_node 'blah' do
309
- attribute 'd', 'e'
310
- end
311
- }.to have_updated('chef_node[blah]', :create)
312
- expect(get('nodes/blah')).to include(
313
- 'normal' => {
314
- 'a' => 'b',
315
- 'c' => { 'd' => 'e' },
316
- 'd' => 'e',
317
- 'tags' => [ 'a', 'b' ]
318
- },
319
- 'automatic' => { 'x' => 'y' },
320
- 'chef_environment' => 'desert'
321
- )
322
- end
323
-
324
- it 'chef_node with attribute tags, [ "x" ] replaces tags' do
325
- expect_recipe {
326
- chef_node 'blah' do
327
- attribute 'tags', [ 'x' ]
328
- end
329
- }.to have_updated('chef_node[blah]', :create)
330
- expect(get('nodes/blah')).to include(
331
- 'normal' => {
332
- 'a' => 'b',
333
- 'c' => { 'd' => 'e' },
334
- 'tags' => [ 'x' ]
335
- },
336
- 'automatic' => { 'x' => 'y' },
337
- 'chef_environment' => 'desert'
338
- )
339
- end
340
-
341
- it 'chef_node with attribute c, x replaces the attribute' do
342
- expect_recipe {
343
- chef_node 'blah' do
344
- attribute 'c', 'x'
345
- end
346
- }.to have_updated('chef_node[blah]', :create)
347
- expect(get('nodes/blah')).to include(
348
- 'normal' => {
349
- 'a' => 'b',
350
- 'c' => 'x',
351
- 'tags' => [ 'a', 'b' ]
352
- },
353
- 'automatic' => { 'x' => 'y' },
354
- 'chef_environment' => 'desert'
355
- )
356
- end
357
-
358
- it 'chef_node with attribute c, { d => x } replaces the attribute' do
359
- expect_recipe {
360
- chef_node 'blah' do
361
- attribute 'c', { 'd' => 'x' }
362
- end
363
- }.to have_updated('chef_node[blah]', :create)
364
- expect(get('nodes/blah')).to include(
365
- 'normal' => {
366
- 'a' => 'b',
367
- 'c' => { 'd' => 'x' },
368
- 'tags' => [ 'a', 'b' ]
369
- },
370
- 'automatic' => { 'x' => 'y' },
371
- 'chef_environment' => 'desert'
372
- )
373
- end
374
-
375
- it 'chef_node with attribute [ c, d ], x replaces the attribute' do
376
- expect_recipe {
377
- chef_node 'blah' do
378
- attribute [ 'c', 'd' ], 'x'
379
- end
380
- }.to have_updated('chef_node[blah]', :create)
381
- expect(get('nodes/blah')).to include(
382
- 'normal' => {
383
- 'a' => 'b',
384
- 'c' => { 'd' => 'x' },
385
- 'tags' => [ 'a', 'b' ]
386
- },
387
- 'automatic' => { 'x' => 'y' },
388
- 'chef_environment' => 'desert'
389
- )
390
- end
391
-
392
- it 'chef_node with attribute [ a, b ], x raises an error' do
393
- expect {
394
- converge {
395
- chef_node 'blah' do
396
- attribute [ 'a', 'b' ], 'x'
397
- end
398
- }
399
- }.to raise_error /Attempt to set \["a", "b"\] to x when \["a"\] is not a hash/
400
- end
401
-
402
- it 'chef_node with attribute [ a, b, c ], x raises an error' do
403
- expect {
404
- converge {
405
- chef_node 'blah' do
406
- attribute [ 'a', 'b', 'c' ], 'x'
407
- end
408
- }
409
- }.to raise_error /Attempt to set \["a", "b", "c"\] to x when \["a"\] is not a hash/
410
- end
411
-
412
- it 'chef_node with attribute [ x, y ], z adds a new attribute' do
413
- expect_recipe {
414
- chef_node 'blah' do
415
- attribute [ 'x', 'y' ], 'z'
416
- end
417
- }.to have_updated('chef_node[blah]', :create)
418
- expect(get('nodes/blah')).to include(
419
- 'normal' => {
420
- 'a' => 'b',
421
- 'c' => { 'd' => 'e' },
422
- 'x' => { 'y' => 'z' },
423
- 'tags' => [ 'a', 'b' ]
424
- },
425
- 'automatic' => { 'x' => 'y' },
426
- 'chef_environment' => 'desert'
427
- )
428
- end
429
-
430
- it 'chef_node with attribute [], {} clears all attributes' do
431
- expect_recipe {
432
- chef_node 'blah' do
433
- attribute([], {})
434
- end
435
- }.to have_updated('chef_node[blah]', :create)
436
- expect(get('nodes/blah')).to include(
437
- 'normal' => { },
438
- 'automatic' => { 'x' => 'y' },
439
- 'chef_environment' => 'desert'
440
- )
441
- end
442
- end
443
-
444
- context 'delete' do
445
- it 'chef_node with attribute a, :delete deletes the attribute' do
446
- expect_recipe {
447
- chef_node 'blah' do
448
- attribute 'a', :delete
449
- end
450
- }.to have_updated('chef_node[blah]', :create)
451
- expect(get('nodes/blah')).to include(
452
- 'normal' => {
453
- 'c' => { 'd' => 'e' },
454
- 'tags' => [ 'a', 'b' ]
455
- },
456
- 'automatic' => { 'x' => 'y' },
457
- 'chef_environment' => 'desert'
458
- )
459
- end
460
-
461
- it 'chef_node with attribute c, :delete deletes the attribute' do
462
- expect_recipe {
463
- chef_node 'blah' do
464
- attribute 'c', :delete
465
- end
466
- }.to have_updated('chef_node[blah]', :create)
467
- expect(get('nodes/blah')).to include(
468
- 'normal' => {
469
- 'a' => 'b',
470
- 'tags' => [ 'a', 'b' ]
471
- },
472
- 'automatic' => { 'x' => 'y' },
473
- 'chef_environment' => 'desert'
474
- )
475
- end
476
-
477
- it 'chef_node with attribute [ c, d ], :delete deletes the attribute' do
478
- expect_recipe {
479
- chef_node 'blah' do
480
- attribute [ 'c', 'd' ], :delete
481
- end
482
- }.to have_updated('chef_node[blah]', :create)
483
- expect(get('nodes/blah')).to include(
484
- 'normal' => {
485
- 'a' => 'b',
486
- 'c' => {},
487
- 'tags' => [ 'a', 'b' ]
488
- },
489
- 'automatic' => { 'x' => 'y' },
490
- 'chef_environment' => 'desert'
491
- )
492
- end
493
-
494
- it 'chef_node with attribute xyz, :delete does nothing' do
495
- expect_recipe {
496
- chef_node 'blah' do
497
- attribute 'xyz', :delete
498
- end
499
- }.not_to have_updated('chef_node[blah]', :create)
500
- expect(get('nodes/blah')).to include(
501
- 'normal' => {
502
- 'a' => 'b',
503
- 'c' => { 'd' => 'e' },
504
- 'tags' => [ 'a', 'b' ]
505
- },
506
- 'automatic' => { 'x' => 'y' },
507
- 'chef_environment' => 'desert'
508
- )
509
- end
510
-
511
- it 'chef_node with attribute [ c, x ], :delete does nothing' do
512
- expect_recipe {
513
- chef_node 'blah' do
514
- attribute [ 'c', 'x' ], :delete
515
- end
516
- }.not_to have_updated('chef_node[blah]', :create)
517
- expect(get('nodes/blah')).to include(
518
- 'normal' => {
519
- 'a' => 'b',
520
- 'c' => { 'd' => 'e' },
521
- 'tags' => [ 'a', 'b' ]
522
- },
523
- 'automatic' => { 'x' => 'y' },
524
- 'chef_environment' => 'desert'
525
- )
526
- end
527
- end
528
-
529
- context 'types' do
530
- it 'chef_node with attribute a, true sets a to true' do
531
- expect_recipe {
532
- chef_node 'blah' do
533
- attribute 'a', true
534
- end
535
- }.to be_updated
536
- expect(get('nodes/blah')).to include(
537
- 'normal' => {
538
- 'a' => true,
539
- 'c' => { 'd' => 'e' },
540
- 'tags' => [ 'a', 'b' ]
541
- },
542
- 'automatic' => { 'x' => 'y' },
543
- 'chef_environment' => 'desert'
544
- )
545
- end
546
-
547
- it 'chef_node with attribute a, 1 sets a to 1' do
548
- expect_recipe {
549
- chef_node 'blah' do
550
- attribute 'a', 1
551
- end
552
- }.to be_updated
553
- expect(get('nodes/blah')).to include(
554
- 'normal' => {
555
- 'a' => 1,
556
- 'c' => { 'd' => 'e' },
557
- 'tags' => [ 'a', 'b' ]
558
- },
559
- 'automatic' => { 'x' => 'y' },
560
- 'chef_environment' => 'desert'
561
- )
562
- end
563
-
564
- it 'chef_node with attribute a, "1" sets a to "1"' do
565
- expect_recipe {
566
- chef_node 'blah' do
567
- attribute 'a', "1"
568
- end
569
- }.to be_updated
570
- expect(get('nodes/blah')).to include(
571
- 'normal' => {
572
- 'a' => "1",
573
- 'c' => { 'd' => 'e' },
574
- 'tags' => [ 'a', 'b' ]
575
- },
576
- 'automatic' => { 'x' => 'y' },
577
- 'chef_environment' => 'desert'
578
- )
579
- end
580
-
581
- it 'chef_node with attribute a, "" sets a to ""' do
582
- expect_recipe {
583
- chef_node 'blah' do
584
- attribute 'a', ""
585
- end
586
- }.to be_updated
587
- expect(get('nodes/blah')).to include(
588
- 'normal' => {
589
- 'a' => "",
590
- 'c' => { 'd' => 'e' },
591
- 'tags' => [ 'a', 'b' ]
592
- },
593
- 'automatic' => { 'x' => 'y' },
594
- 'chef_environment' => 'desert'
595
- )
596
- end
597
-
598
- it 'chef_node with attribute a, nil sets a to nil' do
599
- expect_recipe {
600
- chef_node 'blah' do
601
- attribute 'a', nil
602
- end
603
- }.to be_updated
604
- expect(get('nodes/blah')).to include(
605
- 'normal' => {
606
- 'a' => nil,
607
- 'c' => { 'd' => 'e' },
608
- 'tags' => [ 'a', 'b' ]
609
- },
610
- 'automatic' => { 'x' => 'y' },
611
- 'chef_environment' => 'desert'
612
- )
613
- end
614
- end
615
-
616
- context 'multiple attribute definitions' do
617
- it 'chef_node with attribute a, x and c, y replaces both attributes' do
618
- expect_recipe {
619
- chef_node 'blah' do
620
- attribute 'a', 'x'
621
- attribute 'c', 'y'
622
- end
623
- }.to be_updated
624
- expect(get('nodes/blah')).to include(
625
- 'normal' => {
626
- 'a' => 'x',
627
- 'c' => 'y',
628
- 'tags' => [ 'a', 'b' ]
629
- },
630
- 'automatic' => { 'x' => 'y' },
631
- 'chef_environment' => 'desert'
632
- )
633
- end
634
-
635
- it 'chef_node with attribute m, x and n, y adds both attributes' do
636
- expect_recipe {
637
- chef_node 'blah' do
638
- attribute 'm', 'x'
639
- attribute 'n', 'y'
640
- end
641
- }.to be_updated
642
- expect(get('nodes/blah')).to include(
643
- 'normal' => {
644
- 'a' => 'b',
645
- 'c' => { 'd' => 'e' },
646
- 'm' => 'x',
647
- 'n' => 'y',
648
- 'tags' => [ 'a', 'b' ]
649
- },
650
- 'automatic' => { 'x' => 'y' },
651
- 'chef_environment' => 'desert'
652
- )
653
- end
654
-
655
- it 'chef_node with attribute [x, y], z and [x, yy], zz adds both attributes' do
656
- expect_recipe {
657
- chef_node 'blah' do
658
- attribute [ 'x', 'y' ], 'z'
659
- attribute [ 'x', 'yy' ], 'zz'
660
- end
661
- }.to be_updated
662
- expect(get('nodes/blah')).to include(
663
- 'normal' => {
664
- 'a' => 'b',
665
- 'c' => { 'd' => 'e' },
666
- 'x' => {
667
- 'y' => 'z',
668
- 'yy' => 'zz'
669
- },
670
- 'tags' => [ 'a', 'b' ]
671
- },
672
- 'automatic' => { 'x' => 'y' },
673
- 'chef_environment' => 'desert'
674
- )
675
- end
676
-
677
- describe 'precedence' do
678
- it 'chef_node with attribute a, 1 and a, 2 sets a to 2' do
679
- expect_recipe {
680
- chef_node 'blah' do
681
- attribute 'a', 1
682
- attribute 'a', 2
683
- end
684
- }.to be_updated
685
- expect(get('nodes/blah')).to include(
686
- 'normal' => {
687
- 'a' => 2,
688
- 'c' => { 'd' => 'e' },
689
- 'tags' => [ 'a', 'b' ]
690
- },
691
- 'automatic' => { 'x' => 'y' },
692
- 'chef_environment' => 'desert'
693
- )
694
- end
695
-
696
- it 'chef_node with attribute [ x, y ], 1 and [ x, y ], 2 sets [ x, y ], 2' do
697
- expect_recipe {
698
- chef_node 'blah' do
699
- attribute [ 'x', 'y' ], 1
700
- attribute [ 'x', 'y' ], 2
701
- end
702
- }.to be_updated
703
- expect(get('nodes/blah')).to include(
704
- 'normal' => {
705
- 'a' => 'b',
706
- 'c' => { 'd' => 'e' },
707
- 'x' => { 'y' => 2 },
708
- 'tags' => [ 'a', 'b' ]
709
- },
710
- 'automatic' => { 'x' => 'y' },
711
- 'chef_environment' => 'desert'
712
- )
713
- end
714
-
715
- it 'chef_node with attribute [ c, e ], { a => 1 }, [ c, e ], { b => 2 } sets b only' do
716
- expect_recipe {
717
- chef_node 'blah' do
718
- attribute [ 'c', 'e' ], { 'a' => 1 }
719
- attribute [ 'c', 'e' ], { 'b' => 2 }
720
- end
721
- }.to be_updated
722
- expect(get('nodes/blah')).to include(
723
- 'normal' => {
724
- 'a' => 'b',
725
- 'c' => { 'd' => 'e', 'e' => { 'b' => 2 } },
726
- 'tags' => [ 'a', 'b' ]
727
- },
728
- 'automatic' => { 'x' => 'y' },
729
- 'chef_environment' => 'desert'
730
- )
731
- end
732
-
733
- it 'chef_node with attribute [ c, e ], { a => 1 }, [ c, e, b ], 2 sets both' do
734
- expect_recipe {
735
- chef_node 'blah' do
736
- attribute [ 'c', 'e' ], { 'a' => 1 }
737
- attribute [ 'c', 'e', 'b' ], 2
738
- end
739
- }.to be_updated
740
- expect(get('nodes/blah')).to include(
741
- 'normal' => {
742
- 'a' => 'b',
743
- 'c' => { 'd' => 'e', 'e' => { 'a' => 1, 'b' => 2 } },
744
- 'tags' => [ 'a', 'b' ]
745
- },
746
- 'automatic' => { 'x' => 'y' },
747
- 'chef_environment' => 'desert'
748
- )
749
- end
750
-
751
- it 'chef_node with attribute [ c, e, b ], 2, [ c, e ], { a => 1 } sets a only' do
752
- expect_recipe {
753
- chef_node 'blah' do
754
- attribute [ 'c', 'e', 'b' ], 2
755
- attribute [ 'c', 'e' ], { 'a' => 1 }
756
- end
757
- }.to be_updated
758
- expect(get('nodes/blah')).to include(
759
- 'normal' => {
760
- 'a' => 'b',
761
- 'c' => { 'd' => 'e', 'e' => { 'a' => 1 } },
762
- 'tags' => [ 'a', 'b' ]
763
- },
764
- 'automatic' => { 'x' => 'y' },
765
- 'chef_environment' => 'desert'
766
- )
767
- end
768
- end
769
- end
770
- end
771
- end
772
- end
773
-
774
- when_the_chef_server 'is in OSC mode' do
775
- context 'and is empty' do
776
- context 'and we run a recipe that creates node "blah"' do
777
- it 'the node gets created' do
778
- expect_recipe {
779
- chef_node 'blah'
780
- }.to have_updated 'chef_node[blah]', :create
781
- expect(get('nodes/blah')['name']).to eq('blah')
782
- end
783
- end
784
- end
785
- end
786
- end
1
+ require 'support/spec_support'
2
+ require 'cheffish/rspec/chef_run_support'
3
+ require 'chef/resource/chef_node'
4
+ require 'chef/provider/chef_node'
5
+
6
+ describe Chef::Resource::ChefNode do
7
+ extend Cheffish::RSpec::ChefRunSupport
8
+
9
+ when_the_chef_12_server 'is in multi-org mode' do
10
+ organization 'foo'
11
+
12
+ before :each do
13
+ Chef::Config.chef_server_url = URI.join(Chef::Config.chef_server_url, '/organizations/foo').to_s
14
+ end
15
+
16
+ context 'and is empty' do
17
+ context 'and we run a recipe that creates node "blah"' do
18
+ it 'the node gets created' do
19
+ expect_recipe {
20
+ chef_node 'blah'
21
+ }.to have_updated 'chef_node[blah]', :create
22
+ expect(get('nodes/blah')['name']).to eq('blah')
23
+ end
24
+ end
25
+
26
+ # TODO why-run mode
27
+
28
+ context 'and another chef server is running on port 8899' do
29
+ before :each do
30
+ @server = ChefZero::Server.new(:port => 8899)
31
+ @server.start_background
32
+ end
33
+
34
+ after :each do
35
+ @server.stop
36
+ end
37
+
38
+ context 'and a recipe is run that creates node "blah" on the second chef server using with_chef_server' do
39
+
40
+ it 'the node is created on the second chef server but not the first' do
41
+ expect_recipe {
42
+ with_chef_server 'http://127.0.0.1:8899'
43
+ chef_node 'blah'
44
+ }.to have_updated 'chef_node[blah]', :create
45
+ expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
46
+ expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
47
+ end
48
+ end
49
+
50
+ context 'and a recipe is run that creates node "blah" on the second chef server using chef_server' do
51
+
52
+ it 'the node is created on the second chef server but not the first' do
53
+ expect_recipe {
54
+ chef_node 'blah' do
55
+ chef_server({ :chef_server_url => 'http://127.0.0.1:8899' })
56
+ end
57
+ }.to have_updated 'chef_node[blah]', :create
58
+ expect { get('nodes/blah') }.to raise_error(Net::HTTPServerException)
59
+ expect(get('http://127.0.0.1:8899/nodes/blah')['name']).to eq('blah')
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'and has a node named "blah"' do
66
+ node 'blah', {}
67
+
68
+ it 'chef_node "blah" does not get created or updated' do
69
+ expect_recipe {
70
+ chef_node 'blah'
71
+ }.not_to have_updated 'chef_node[blah]', :create
72
+ end
73
+ end
74
+
75
+ context 'and has a node named "blah" with tags' do
76
+ node 'blah', {
77
+ 'normal' => { 'tags' => [ 'a', 'b' ] }
78
+ }
79
+
80
+ context 'with chef_node "blah" that sets attributes' do
81
+ with_converge do
82
+ chef_node 'blah' do
83
+ attributes({})
84
+ end
85
+ end
86
+
87
+ it 'the tags in attributes are used' do
88
+ expect(get('nodes/blah')['normal']['tags']).to eq([ 'a', 'b' ])
89
+ end
90
+ end
91
+
92
+ context 'with chef_node "blah" that sets attributes with tags in them' do
93
+ with_converge do
94
+ chef_node 'blah' do
95
+ attributes 'tags' => [ 'c', 'd' ]
96
+ end
97
+ end
98
+
99
+ it 'the tags in attributes are used' do
100
+ expect(get('nodes/blah')['normal']['tags']).to eq([ 'c', 'd' ])
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '#complete' do
106
+ context 'when the Chef server has a node named "blah" with everything in it' do
107
+ node 'blah', {
108
+ 'chef_environment' => 'blah',
109
+ 'run_list' => [ 'recipe[bjork]' ],
110
+ 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
111
+ 'default' => { 'foo2' => 'bar2' },
112
+ 'automatic' => { 'foo3' => 'bar3' },
113
+ 'override' => { 'foo4' => 'bar4' }
114
+ }
115
+
116
+ it 'chef_node with no attributes modifies nothing' do
117
+ expect_recipe {
118
+ chef_node 'blah'
119
+ }.to be_up_to_date
120
+ expect(get('nodes/blah')).to include(
121
+ 'name' => 'blah',
122
+ 'chef_environment' => 'blah',
123
+ 'run_list' => [ 'recipe[bjork]' ],
124
+ 'normal' => { 'foo' => 'bar', 'tags' => [ 'a', 'b' ] },
125
+ 'default' => { 'foo2' => 'bar2' },
126
+ 'automatic' => { 'foo3' => 'bar3' },
127
+ 'override' => { 'foo4' => 'bar4' }
128
+ )
129
+ end
130
+
131
+ it 'chef_node with complete true removes everything except default, automatic and override' do
132
+ expect_recipe {
133
+ chef_node 'blah' do
134
+ complete true
135
+ end
136
+ }.to be_updated
137
+ expect(get('nodes/blah')).to include(
138
+ 'name' => 'blah',
139
+ 'chef_environment' => '_default',
140
+ 'run_list' => [ ],
141
+ 'normal' => { 'tags' => [ 'a', 'b' ] },
142
+ 'default' => { 'foo2' => 'bar2' },
143
+ 'automatic' => { 'foo3' => 'bar3' },
144
+ 'override' => { 'foo4' => 'bar4' }
145
+ )
146
+ end
147
+
148
+ it 'chef_node with complete true sets the given attributes' do
149
+ expect_recipe {
150
+ chef_node 'blah' do
151
+ chef_environment 'x'
152
+ run_list [ 'recipe[y]' ]
153
+ attributes 'a' => 'b'
154
+ tags 'c', 'd'
155
+ complete true
156
+ end
157
+ }.to be_updated
158
+ expect(get('nodes/blah')).to include(
159
+ 'name' => 'blah',
160
+ 'chef_environment' => 'x',
161
+ 'run_list' => [ 'recipe[y]' ],
162
+ 'normal' => { 'a' => 'b', 'tags' => [ 'c', 'd' ] },
163
+ 'default' => { 'foo2' => 'bar2' },
164
+ 'automatic' => { 'foo3' => 'bar3' },
165
+ 'override' => { 'foo4' => 'bar4' }
166
+ )
167
+ end
168
+
169
+ it 'chef_node with complete true and partial attributes sets the given attributes' do
170
+ expect_recipe {
171
+ chef_node 'blah' do
172
+ chef_environment 'x'
173
+ recipe 'y'
174
+ attribute 'a', 'b'
175
+ tags 'c', 'd'
176
+ complete true
177
+ end
178
+ }.to be_updated
179
+ expect(get('nodes/blah')).to include(
180
+ 'name' => 'blah',
181
+ 'chef_environment' => 'x',
182
+ 'run_list' => [ 'recipe[y]' ],
183
+ 'normal' => { 'a' => 'b', 'tags' => [ 'c', 'd' ] },
184
+ 'default' => { 'foo2' => 'bar2' },
185
+ 'automatic' => { 'foo3' => 'bar3' },
186
+ 'override' => { 'foo4' => 'bar4' }
187
+ )
188
+ end
189
+ end
190
+ end
191
+
192
+ describe '#attributes' do
193
+ context 'with a node with normal attributes a => b and c => { d => e }' do
194
+ node 'blah', {
195
+ 'normal' => {
196
+ 'a' => 'b',
197
+ 'c' => { 'd' => 'e' },
198
+ 'tags' => [ 'a', 'b' ]
199
+ },
200
+ 'automatic' => {
201
+ 'x' => 'y'
202
+ },
203
+ 'chef_environment' => 'desert'
204
+ }
205
+
206
+ it 'chef_node with attributes {} removes all normal attributes but leaves tags, automatic and environment alone' do
207
+ expect_recipe {
208
+ chef_node 'blah' do
209
+ attributes({})
210
+ end
211
+ }.to have_updated('chef_node[blah]', :create)
212
+ expect(get('nodes/blah')).to include(
213
+ 'normal' => { 'tags' => [ 'a', 'b' ] },
214
+ 'automatic' => { 'x' => 'y' },
215
+ 'chef_environment' => 'desert'
216
+ )
217
+ end
218
+
219
+ it 'chef_node with attributes { c => d } replaces normal but not tags/automatic/environment' do
220
+ expect_recipe {
221
+ chef_node 'blah' do
222
+ attributes 'c' => 'd'
223
+ end
224
+ }.to have_updated('chef_node[blah]', :create)
225
+ expect(get('nodes/blah')).to include(
226
+ 'normal' => { 'c' => 'd', 'tags' => [ 'a', 'b' ] },
227
+ 'automatic' => { 'x' => 'y' },
228
+ 'chef_environment' => 'desert'
229
+ )
230
+ end
231
+
232
+ it 'chef_node with attributes { c => f => g, y => z } replaces normal but not tags/automatic/environment' do
233
+ expect_recipe {
234
+ chef_node 'blah' do
235
+ attributes 'c' => { 'f' => 'g' }, 'y' => 'z'
236
+ end
237
+ }.to have_updated('chef_node[blah]', :create)
238
+ expect(get('nodes/blah')).to include(
239
+ 'normal' => { 'c' => { 'f' => 'g' }, 'y' => 'z', 'tags' => [ 'a', 'b' ] },
240
+ 'automatic' => { 'x' => 'y' },
241
+ 'chef_environment' => 'desert'
242
+ )
243
+ end
244
+
245
+ it 'chef_node with attributes { tags => [ "x" ] } replaces normal and tags but not automatic/environment' do
246
+ expect_recipe {
247
+ chef_node 'blah' do
248
+ attributes 'tags' => [ 'x' ]
249
+ end
250
+ }.to have_updated('chef_node[blah]', :create)
251
+ expect(get('nodes/blah')).to include(
252
+ 'normal' => { 'tags' => [ 'x' ] },
253
+ 'automatic' => { 'x' => 'y' },
254
+ 'chef_environment' => 'desert'
255
+ )
256
+ end
257
+
258
+ it 'chef_node with tags "x" and attributes { "tags" => [ "y" ] } sets tags to "x"' do
259
+ expect_recipe {
260
+ chef_node 'blah' do
261
+ tags 'x'
262
+ attributes 'tags' => [ 'y' ]
263
+ end
264
+ }.to have_updated('chef_node[blah]', :create)
265
+ expect(get('nodes/blah')).to include(
266
+ 'normal' => {
267
+ 'tags' => [ 'x' ]
268
+ },
269
+ 'automatic' => { 'x' => 'y' },
270
+ 'chef_environment' => 'desert'
271
+ )
272
+ end
273
+ end
274
+ end
275
+
276
+ describe '#attribute' do
277
+ context 'with a node with normal attributes a => b and c => { d => e }' do
278
+ node 'blah', {
279
+ 'normal' => {
280
+ 'a' => 'b',
281
+ 'c' => { 'd' => 'e' },
282
+ 'tags' => [ 'a', 'b' ]
283
+ },
284
+ 'automatic' => {
285
+ 'x' => 'y'
286
+ },
287
+ 'chef_environment' => 'desert'
288
+ }
289
+
290
+ context 'basic scenarios' do
291
+ it 'chef_node with no attributes, leaves it alone' do
292
+ expect_recipe {
293
+ chef_node 'blah'
294
+ }.not_to have_updated('chef_node[blah]', :create)
295
+ expect(get('nodes/blah')).to include(
296
+ 'normal' => {
297
+ 'a' => 'b',
298
+ 'c' => { 'd' => 'e' },
299
+ 'tags' => [ 'a', 'b' ]
300
+ },
301
+ 'automatic' => { 'x' => 'y' },
302
+ 'chef_environment' => 'desert'
303
+ )
304
+ end
305
+
306
+ it 'chef_node with attribute d, e adds the attribute' do
307
+ expect_recipe {
308
+ chef_node 'blah' do
309
+ attribute 'd', 'e'
310
+ end
311
+ }.to have_updated('chef_node[blah]', :create)
312
+ expect(get('nodes/blah')).to include(
313
+ 'normal' => {
314
+ 'a' => 'b',
315
+ 'c' => { 'd' => 'e' },
316
+ 'd' => 'e',
317
+ 'tags' => [ 'a', 'b' ]
318
+ },
319
+ 'automatic' => { 'x' => 'y' },
320
+ 'chef_environment' => 'desert'
321
+ )
322
+ end
323
+
324
+ it 'chef_node with attribute tags, [ "x" ] replaces tags' do
325
+ expect_recipe {
326
+ chef_node 'blah' do
327
+ attribute 'tags', [ 'x' ]
328
+ end
329
+ }.to have_updated('chef_node[blah]', :create)
330
+ expect(get('nodes/blah')).to include(
331
+ 'normal' => {
332
+ 'a' => 'b',
333
+ 'c' => { 'd' => 'e' },
334
+ 'tags' => [ 'x' ]
335
+ },
336
+ 'automatic' => { 'x' => 'y' },
337
+ 'chef_environment' => 'desert'
338
+ )
339
+ end
340
+
341
+ it 'chef_node with attribute c, x replaces the attribute' do
342
+ expect_recipe {
343
+ chef_node 'blah' do
344
+ attribute 'c', 'x'
345
+ end
346
+ }.to have_updated('chef_node[blah]', :create)
347
+ expect(get('nodes/blah')).to include(
348
+ 'normal' => {
349
+ 'a' => 'b',
350
+ 'c' => 'x',
351
+ 'tags' => [ 'a', 'b' ]
352
+ },
353
+ 'automatic' => { 'x' => 'y' },
354
+ 'chef_environment' => 'desert'
355
+ )
356
+ end
357
+
358
+ it 'chef_node with attribute c, { d => x } replaces the attribute' do
359
+ expect_recipe {
360
+ chef_node 'blah' do
361
+ attribute 'c', { 'd' => 'x' }
362
+ end
363
+ }.to have_updated('chef_node[blah]', :create)
364
+ expect(get('nodes/blah')).to include(
365
+ 'normal' => {
366
+ 'a' => 'b',
367
+ 'c' => { 'd' => 'x' },
368
+ 'tags' => [ 'a', 'b' ]
369
+ },
370
+ 'automatic' => { 'x' => 'y' },
371
+ 'chef_environment' => 'desert'
372
+ )
373
+ end
374
+
375
+ it 'chef_node with attribute [ c, d ], x replaces the attribute' do
376
+ expect_recipe {
377
+ chef_node 'blah' do
378
+ attribute [ 'c', 'd' ], 'x'
379
+ end
380
+ }.to have_updated('chef_node[blah]', :create)
381
+ expect(get('nodes/blah')).to include(
382
+ 'normal' => {
383
+ 'a' => 'b',
384
+ 'c' => { 'd' => 'x' },
385
+ 'tags' => [ 'a', 'b' ]
386
+ },
387
+ 'automatic' => { 'x' => 'y' },
388
+ 'chef_environment' => 'desert'
389
+ )
390
+ end
391
+
392
+ it 'chef_node with attribute [ a, b ], x raises an error' do
393
+ expect {
394
+ converge {
395
+ chef_node 'blah' do
396
+ attribute [ 'a', 'b' ], 'x'
397
+ end
398
+ }
399
+ }.to raise_error /Attempt to set \["a", "b"\] to x when \["a"\] is not a hash/
400
+ end
401
+
402
+ it 'chef_node with attribute [ a, b, c ], x raises an error' do
403
+ expect {
404
+ converge {
405
+ chef_node 'blah' do
406
+ attribute [ 'a', 'b', 'c' ], 'x'
407
+ end
408
+ }
409
+ }.to raise_error /Attempt to set \["a", "b", "c"\] to x when \["a"\] is not a hash/
410
+ end
411
+
412
+ it 'chef_node with attribute [ x, y ], z adds a new attribute' do
413
+ expect_recipe {
414
+ chef_node 'blah' do
415
+ attribute [ 'x', 'y' ], 'z'
416
+ end
417
+ }.to have_updated('chef_node[blah]', :create)
418
+ expect(get('nodes/blah')).to include(
419
+ 'normal' => {
420
+ 'a' => 'b',
421
+ 'c' => { 'd' => 'e' },
422
+ 'x' => { 'y' => 'z' },
423
+ 'tags' => [ 'a', 'b' ]
424
+ },
425
+ 'automatic' => { 'x' => 'y' },
426
+ 'chef_environment' => 'desert'
427
+ )
428
+ end
429
+
430
+ it 'chef_node with attribute [], {} clears all attributes' do
431
+ expect_recipe {
432
+ chef_node 'blah' do
433
+ attribute([], {})
434
+ end
435
+ }.to have_updated('chef_node[blah]', :create)
436
+ expect(get('nodes/blah')).to include(
437
+ 'normal' => { },
438
+ 'automatic' => { 'x' => 'y' },
439
+ 'chef_environment' => 'desert'
440
+ )
441
+ end
442
+ end
443
+
444
+ context 'delete' do
445
+ it 'chef_node with attribute a, :delete deletes the attribute' do
446
+ expect_recipe {
447
+ chef_node 'blah' do
448
+ attribute 'a', :delete
449
+ end
450
+ }.to have_updated('chef_node[blah]', :create)
451
+ expect(get('nodes/blah')).to include(
452
+ 'normal' => {
453
+ 'c' => { 'd' => 'e' },
454
+ 'tags' => [ 'a', 'b' ]
455
+ },
456
+ 'automatic' => { 'x' => 'y' },
457
+ 'chef_environment' => 'desert'
458
+ )
459
+ end
460
+
461
+ it 'chef_node with attribute c, :delete deletes the attribute' do
462
+ expect_recipe {
463
+ chef_node 'blah' do
464
+ attribute 'c', :delete
465
+ end
466
+ }.to have_updated('chef_node[blah]', :create)
467
+ expect(get('nodes/blah')).to include(
468
+ 'normal' => {
469
+ 'a' => 'b',
470
+ 'tags' => [ 'a', 'b' ]
471
+ },
472
+ 'automatic' => { 'x' => 'y' },
473
+ 'chef_environment' => 'desert'
474
+ )
475
+ end
476
+
477
+ it 'chef_node with attribute [ c, d ], :delete deletes the attribute' do
478
+ expect_recipe {
479
+ chef_node 'blah' do
480
+ attribute [ 'c', 'd' ], :delete
481
+ end
482
+ }.to have_updated('chef_node[blah]', :create)
483
+ expect(get('nodes/blah')).to include(
484
+ 'normal' => {
485
+ 'a' => 'b',
486
+ 'c' => {},
487
+ 'tags' => [ 'a', 'b' ]
488
+ },
489
+ 'automatic' => { 'x' => 'y' },
490
+ 'chef_environment' => 'desert'
491
+ )
492
+ end
493
+
494
+ it 'chef_node with attribute xyz, :delete does nothing' do
495
+ expect_recipe {
496
+ chef_node 'blah' do
497
+ attribute 'xyz', :delete
498
+ end
499
+ }.not_to have_updated('chef_node[blah]', :create)
500
+ expect(get('nodes/blah')).to include(
501
+ 'normal' => {
502
+ 'a' => 'b',
503
+ 'c' => { 'd' => 'e' },
504
+ 'tags' => [ 'a', 'b' ]
505
+ },
506
+ 'automatic' => { 'x' => 'y' },
507
+ 'chef_environment' => 'desert'
508
+ )
509
+ end
510
+
511
+ it 'chef_node with attribute [ c, x ], :delete does nothing' do
512
+ expect_recipe {
513
+ chef_node 'blah' do
514
+ attribute [ 'c', 'x' ], :delete
515
+ end
516
+ }.not_to have_updated('chef_node[blah]', :create)
517
+ expect(get('nodes/blah')).to include(
518
+ 'normal' => {
519
+ 'a' => 'b',
520
+ 'c' => { 'd' => 'e' },
521
+ 'tags' => [ 'a', 'b' ]
522
+ },
523
+ 'automatic' => { 'x' => 'y' },
524
+ 'chef_environment' => 'desert'
525
+ )
526
+ end
527
+ end
528
+
529
+ context 'types' do
530
+ it 'chef_node with attribute a, true sets a to true' do
531
+ expect_recipe {
532
+ chef_node 'blah' do
533
+ attribute 'a', true
534
+ end
535
+ }.to be_updated
536
+ expect(get('nodes/blah')).to include(
537
+ 'normal' => {
538
+ 'a' => true,
539
+ 'c' => { 'd' => 'e' },
540
+ 'tags' => [ 'a', 'b' ]
541
+ },
542
+ 'automatic' => { 'x' => 'y' },
543
+ 'chef_environment' => 'desert'
544
+ )
545
+ end
546
+
547
+ it 'chef_node with attribute a, 1 sets a to 1' do
548
+ expect_recipe {
549
+ chef_node 'blah' do
550
+ attribute 'a', 1
551
+ end
552
+ }.to be_updated
553
+ expect(get('nodes/blah')).to include(
554
+ 'normal' => {
555
+ 'a' => 1,
556
+ 'c' => { 'd' => 'e' },
557
+ 'tags' => [ 'a', 'b' ]
558
+ },
559
+ 'automatic' => { 'x' => 'y' },
560
+ 'chef_environment' => 'desert'
561
+ )
562
+ end
563
+
564
+ it 'chef_node with attribute a, "1" sets a to "1"' do
565
+ expect_recipe {
566
+ chef_node 'blah' do
567
+ attribute 'a', "1"
568
+ end
569
+ }.to be_updated
570
+ expect(get('nodes/blah')).to include(
571
+ 'normal' => {
572
+ 'a' => "1",
573
+ 'c' => { 'd' => 'e' },
574
+ 'tags' => [ 'a', 'b' ]
575
+ },
576
+ 'automatic' => { 'x' => 'y' },
577
+ 'chef_environment' => 'desert'
578
+ )
579
+ end
580
+
581
+ it 'chef_node with attribute a, "" sets a to ""' do
582
+ expect_recipe {
583
+ chef_node 'blah' do
584
+ attribute 'a', ""
585
+ end
586
+ }.to be_updated
587
+ expect(get('nodes/blah')).to include(
588
+ 'normal' => {
589
+ 'a' => "",
590
+ 'c' => { 'd' => 'e' },
591
+ 'tags' => [ 'a', 'b' ]
592
+ },
593
+ 'automatic' => { 'x' => 'y' },
594
+ 'chef_environment' => 'desert'
595
+ )
596
+ end
597
+
598
+ it 'chef_node with attribute a, nil sets a to nil' do
599
+ expect_recipe {
600
+ chef_node 'blah' do
601
+ attribute 'a', nil
602
+ end
603
+ }.to be_updated
604
+ expect(get('nodes/blah')).to include(
605
+ 'normal' => {
606
+ 'a' => nil,
607
+ 'c' => { 'd' => 'e' },
608
+ 'tags' => [ 'a', 'b' ]
609
+ },
610
+ 'automatic' => { 'x' => 'y' },
611
+ 'chef_environment' => 'desert'
612
+ )
613
+ end
614
+ end
615
+
616
+ context 'multiple attribute definitions' do
617
+ it 'chef_node with attribute a, x and c, y replaces both attributes' do
618
+ expect_recipe {
619
+ chef_node 'blah' do
620
+ attribute 'a', 'x'
621
+ attribute 'c', 'y'
622
+ end
623
+ }.to be_updated
624
+ expect(get('nodes/blah')).to include(
625
+ 'normal' => {
626
+ 'a' => 'x',
627
+ 'c' => 'y',
628
+ 'tags' => [ 'a', 'b' ]
629
+ },
630
+ 'automatic' => { 'x' => 'y' },
631
+ 'chef_environment' => 'desert'
632
+ )
633
+ end
634
+
635
+ it 'chef_node with attribute m, x and n, y adds both attributes' do
636
+ expect_recipe {
637
+ chef_node 'blah' do
638
+ attribute 'm', 'x'
639
+ attribute 'n', 'y'
640
+ end
641
+ }.to be_updated
642
+ expect(get('nodes/blah')).to include(
643
+ 'normal' => {
644
+ 'a' => 'b',
645
+ 'c' => { 'd' => 'e' },
646
+ 'm' => 'x',
647
+ 'n' => 'y',
648
+ 'tags' => [ 'a', 'b' ]
649
+ },
650
+ 'automatic' => { 'x' => 'y' },
651
+ 'chef_environment' => 'desert'
652
+ )
653
+ end
654
+
655
+ it 'chef_node with attribute [x, y], z and [x, yy], zz adds both attributes' do
656
+ expect_recipe {
657
+ chef_node 'blah' do
658
+ attribute [ 'x', 'y' ], 'z'
659
+ attribute [ 'x', 'yy' ], 'zz'
660
+ end
661
+ }.to be_updated
662
+ expect(get('nodes/blah')).to include(
663
+ 'normal' => {
664
+ 'a' => 'b',
665
+ 'c' => { 'd' => 'e' },
666
+ 'x' => {
667
+ 'y' => 'z',
668
+ 'yy' => 'zz'
669
+ },
670
+ 'tags' => [ 'a', 'b' ]
671
+ },
672
+ 'automatic' => { 'x' => 'y' },
673
+ 'chef_environment' => 'desert'
674
+ )
675
+ end
676
+
677
+ describe 'precedence' do
678
+ it 'chef_node with attribute a, 1 and a, 2 sets a to 2' do
679
+ expect_recipe {
680
+ chef_node 'blah' do
681
+ attribute 'a', 1
682
+ attribute 'a', 2
683
+ end
684
+ }.to be_updated
685
+ expect(get('nodes/blah')).to include(
686
+ 'normal' => {
687
+ 'a' => 2,
688
+ 'c' => { 'd' => 'e' },
689
+ 'tags' => [ 'a', 'b' ]
690
+ },
691
+ 'automatic' => { 'x' => 'y' },
692
+ 'chef_environment' => 'desert'
693
+ )
694
+ end
695
+
696
+ it 'chef_node with attribute [ x, y ], 1 and [ x, y ], 2 sets [ x, y ], 2' do
697
+ expect_recipe {
698
+ chef_node 'blah' do
699
+ attribute [ 'x', 'y' ], 1
700
+ attribute [ 'x', 'y' ], 2
701
+ end
702
+ }.to be_updated
703
+ expect(get('nodes/blah')).to include(
704
+ 'normal' => {
705
+ 'a' => 'b',
706
+ 'c' => { 'd' => 'e' },
707
+ 'x' => { 'y' => 2 },
708
+ 'tags' => [ 'a', 'b' ]
709
+ },
710
+ 'automatic' => { 'x' => 'y' },
711
+ 'chef_environment' => 'desert'
712
+ )
713
+ end
714
+
715
+ it 'chef_node with attribute [ c, e ], { a => 1 }, [ c, e ], { b => 2 } sets b only' do
716
+ expect_recipe {
717
+ chef_node 'blah' do
718
+ attribute [ 'c', 'e' ], { 'a' => 1 }
719
+ attribute [ 'c', 'e' ], { 'b' => 2 }
720
+ end
721
+ }.to be_updated
722
+ expect(get('nodes/blah')).to include(
723
+ 'normal' => {
724
+ 'a' => 'b',
725
+ 'c' => { 'd' => 'e', 'e' => { 'b' => 2 } },
726
+ 'tags' => [ 'a', 'b' ]
727
+ },
728
+ 'automatic' => { 'x' => 'y' },
729
+ 'chef_environment' => 'desert'
730
+ )
731
+ end
732
+
733
+ it 'chef_node with attribute [ c, e ], { a => 1 }, [ c, e, b ], 2 sets both' do
734
+ expect_recipe {
735
+ chef_node 'blah' do
736
+ attribute [ 'c', 'e' ], { 'a' => 1 }
737
+ attribute [ 'c', 'e', 'b' ], 2
738
+ end
739
+ }.to be_updated
740
+ expect(get('nodes/blah')).to include(
741
+ 'normal' => {
742
+ 'a' => 'b',
743
+ 'c' => { 'd' => 'e', 'e' => { 'a' => 1, 'b' => 2 } },
744
+ 'tags' => [ 'a', 'b' ]
745
+ },
746
+ 'automatic' => { 'x' => 'y' },
747
+ 'chef_environment' => 'desert'
748
+ )
749
+ end
750
+
751
+ it 'chef_node with attribute [ c, e, b ], 2, [ c, e ], { a => 1 } sets a only' do
752
+ expect_recipe {
753
+ chef_node 'blah' do
754
+ attribute [ 'c', 'e', 'b' ], 2
755
+ attribute [ 'c', 'e' ], { 'a' => 1 }
756
+ end
757
+ }.to be_updated
758
+ expect(get('nodes/blah')).to include(
759
+ 'normal' => {
760
+ 'a' => 'b',
761
+ 'c' => { 'd' => 'e', 'e' => { 'a' => 1 } },
762
+ 'tags' => [ 'a', 'b' ]
763
+ },
764
+ 'automatic' => { 'x' => 'y' },
765
+ 'chef_environment' => 'desert'
766
+ )
767
+ end
768
+ end
769
+ end
770
+ end
771
+ end
772
+ end
773
+
774
+ when_the_chef_server 'is in OSC mode' do
775
+ context 'and is empty' do
776
+ context 'and we run a recipe that creates node "blah"' do
777
+ it 'the node gets created' do
778
+ expect_recipe {
779
+ chef_node 'blah'
780
+ }.to have_updated 'chef_node[blah]', :create
781
+ expect(get('nodes/blah')['name']).to eq('blah')
782
+ end
783
+ end
784
+ end
785
+ end
786
+ end