chef 12.4.0 → 12.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef/api_client.rb +31 -129
  3. data/lib/chef/api_client_v1.rb +325 -0
  4. data/lib/chef/chef_class.rb +15 -7
  5. data/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +2 -2
  6. data/lib/chef/dsl/resources.rb +6 -4
  7. data/lib/chef/exceptions.rb +2 -2
  8. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +2 -1
  9. data/lib/chef/knife/bootstrap/templates/chef-full.erb +4 -4
  10. data/lib/chef/knife/client_bulk_delete.rb +2 -2
  11. data/lib/chef/knife/client_create.rb +4 -4
  12. data/lib/chef/knife/client_delete.rb +3 -3
  13. data/lib/chef/knife/client_edit.rb +10 -2
  14. data/lib/chef/knife/client_list.rb +2 -2
  15. data/lib/chef/knife/client_reregister.rb +2 -2
  16. data/lib/chef/knife/client_show.rb +2 -2
  17. data/lib/chef/knife/osc_user_create.rb +3 -3
  18. data/lib/chef/knife/osc_user_delete.rb +2 -2
  19. data/lib/chef/knife/osc_user_edit.rb +3 -3
  20. data/lib/chef/knife/osc_user_list.rb +2 -2
  21. data/lib/chef/knife/osc_user_reregister.rb +2 -2
  22. data/lib/chef/knife/osc_user_show.rb +2 -2
  23. data/lib/chef/knife/user_create.rb +3 -3
  24. data/lib/chef/knife/user_delete.rb +4 -4
  25. data/lib/chef/knife/user_edit.rb +3 -3
  26. data/lib/chef/knife/user_list.rb +2 -2
  27. data/lib/chef/knife/user_reregister.rb +2 -2
  28. data/lib/chef/knife/user_show.rb +2 -2
  29. data/lib/chef/node_map.rb +14 -18
  30. data/lib/chef/platform/handler_map.rb +45 -0
  31. data/lib/chef/platform/priority_map.rb +19 -32
  32. data/lib/chef/platform/provider_handler_map.rb +29 -0
  33. data/lib/chef/platform/provider_mapping.rb +3 -2
  34. data/lib/chef/platform/resource_handler_map.rb +29 -0
  35. data/lib/chef/platform/resource_priority_map.rb +0 -6
  36. data/lib/chef/provider.rb +1 -1
  37. data/lib/chef/provider/dsc_resource.rb +2 -2
  38. data/lib/chef/provider/dsc_script.rb +1 -1
  39. data/lib/chef/provider/mount/aix.rb +1 -1
  40. data/lib/chef/provider/package.rb +0 -31
  41. data/lib/chef/provider/package/aix.rb +1 -0
  42. data/lib/chef/provider/package/apt.rb +1 -0
  43. data/lib/chef/provider/package/homebrew.rb +1 -0
  44. data/lib/chef/provider/package/ips.rb +1 -0
  45. data/lib/chef/provider/package/macports.rb +1 -0
  46. data/lib/chef/provider/package/openbsd.rb +1 -0
  47. data/lib/chef/provider/package/pacman.rb +1 -0
  48. data/lib/chef/provider/package/paludis.rb +1 -0
  49. data/lib/chef/provider/package/portage.rb +2 -0
  50. data/lib/chef/provider/package/smartos.rb +1 -0
  51. data/lib/chef/provider/package/solaris.rb +2 -0
  52. data/lib/chef/provider/package/yum.rb +1 -0
  53. data/lib/chef/provider/package/zypper.rb +1 -0
  54. data/lib/chef/provider/service.rb +4 -22
  55. data/lib/chef/provider/service/debian.rb +2 -0
  56. data/lib/chef/provider/service/insserv.rb +2 -0
  57. data/lib/chef/provider/service/invokercd.rb +2 -0
  58. data/lib/chef/provider/service/openbsd.rb +1 -1
  59. data/lib/chef/provider/service/redhat.rb +2 -0
  60. data/lib/chef/provider/service/upstart.rb +3 -0
  61. data/lib/chef/provider_resolver.rb +59 -53
  62. data/lib/chef/resource.rb +22 -73
  63. data/lib/chef/resource/dsc_script.rb +1 -1
  64. data/lib/chef/resource/ips_package.rb +1 -0
  65. data/lib/chef/resource/mount.rb +8 -0
  66. data/lib/chef/resource/openbsd_package.rb +0 -11
  67. data/lib/chef/resource/solaris_package.rb +1 -4
  68. data/lib/chef/resource_resolver.rb +54 -26
  69. data/lib/chef/run_list/versioned_recipe_list.rb +6 -5
  70. data/lib/chef/user.rb +52 -188
  71. data/lib/chef/user_v1.rb +335 -0
  72. data/lib/chef/version.rb +1 -1
  73. data/spec/data/trusted_certs/opscode.pem +53 -56
  74. data/spec/functional/provider/whyrun_safe_ruby_block_spec.rb +1 -1
  75. data/spec/functional/resource/package_spec.rb +0 -2
  76. data/spec/integration/recipes/recipe_dsl_spec.rb +661 -126
  77. data/spec/spec_helper.rb +19 -13
  78. data/spec/support/shared/unit/api_versioning.rb +2 -2
  79. data/spec/unit/api_client_spec.rb +22 -201
  80. data/spec/unit/api_client_v1_spec.rb +457 -0
  81. data/spec/unit/knife/client_bulk_delete_spec.rb +4 -4
  82. data/spec/unit/knife/client_create_spec.rb +1 -1
  83. data/spec/unit/knife/client_delete_spec.rb +3 -3
  84. data/spec/unit/knife/client_edit_spec.rb +14 -1
  85. data/spec/unit/knife/client_list_spec.rb +1 -1
  86. data/spec/unit/knife/client_reregister_spec.rb +2 -2
  87. data/spec/unit/knife/client_show_spec.rb +2 -2
  88. data/spec/unit/knife/osc_user_create_spec.rb +5 -5
  89. data/spec/unit/knife/osc_user_delete_spec.rb +1 -1
  90. data/spec/unit/knife/osc_user_edit_spec.rb +1 -1
  91. data/spec/unit/knife/osc_user_list_spec.rb +1 -1
  92. data/spec/unit/knife/osc_user_reregister_spec.rb +1 -1
  93. data/spec/unit/knife/osc_user_show_spec.rb +1 -1
  94. data/spec/unit/knife/user_create_spec.rb +1 -1
  95. data/spec/unit/knife/user_delete_spec.rb +2 -2
  96. data/spec/unit/knife/user_edit_spec.rb +2 -2
  97. data/spec/unit/knife/user_list_spec.rb +1 -1
  98. data/spec/unit/knife/user_reregister_spec.rb +1 -1
  99. data/spec/unit/knife/user_show_spec.rb +2 -2
  100. data/spec/unit/lwrp_spec.rb +146 -134
  101. data/spec/unit/node_map_spec.rb +12 -0
  102. data/spec/unit/platform_spec.rb +1 -1
  103. data/spec/unit/provider/deploy_spec.rb +1 -1
  104. data/spec/unit/provider/dsc_resource_spec.rb +3 -3
  105. data/spec/unit/provider/dsc_script_spec.rb +2 -2
  106. data/spec/unit/provider_resolver_spec.rb +170 -135
  107. data/spec/unit/recipe_spec.rb +3 -3
  108. data/spec/unit/resource/breakpoint_spec.rb +1 -1
  109. data/spec/unit/resource/cron_spec.rb +1 -1
  110. data/spec/unit/resource/directory_spec.rb +1 -1
  111. data/spec/unit/resource/dsc_resource_spec.rb +1 -1
  112. data/spec/unit/resource/dsc_script_spec.rb +2 -2
  113. data/spec/unit/resource/env_spec.rb +1 -1
  114. data/spec/unit/resource/erl_call_spec.rb +1 -1
  115. data/spec/unit/resource/file_spec.rb +1 -1
  116. data/spec/unit/resource/group_spec.rb +1 -1
  117. data/spec/unit/resource/link_spec.rb +1 -1
  118. data/spec/unit/resource/mdadm_spec.rb +1 -1
  119. data/spec/unit/resource/mount_spec.rb +1 -1
  120. data/spec/unit/resource/ohai_spec.rb +1 -1
  121. data/spec/unit/resource/registry_key_spec.rb +1 -1
  122. data/spec/unit/resource/route_spec.rb +1 -1
  123. data/spec/unit/resource/ruby_block_spec.rb +3 -3
  124. data/spec/unit/resource/user_spec.rb +1 -1
  125. data/spec/unit/resource/windows_service_spec.rb +1 -1
  126. data/spec/unit/resource_resolver_spec.rb +8 -4
  127. data/spec/unit/resource_spec.rb +89 -3
  128. data/spec/unit/run_list/versioned_recipe_list_spec.rb +115 -48
  129. data/spec/unit/user_spec.rb +97 -405
  130. data/spec/unit/user_v1_spec.rb +584 -0
  131. metadata +11 -6
  132. data/lib/chef/osc_user.rb +0 -194
  133. data/spec/unit/osc_user_spec.rb +0 -276
@@ -43,7 +43,7 @@ describe Chef::Resource::WhyrunSafeRubyBlock do
43
43
  end
44
44
 
45
45
  it "updates the evil laugh, even in why-run mode" do
46
- new_resource.run_action(new_resource.action)
46
+ Array(new_resource.action).each {|action| new_resource.run_action(action) }
47
47
  expect($evil_global_evil_laugh).to eq(:mwahahaha)
48
48
  expect(new_resource).to be_updated
49
49
  end
@@ -386,5 +386,3 @@ describe Chef::Resource::Package, metadata do
386
386
  end
387
387
 
388
388
  end
389
-
390
-
@@ -11,7 +11,7 @@ describe "Recipe DSL methods" do
11
11
  before(:all) { Namer.current_index = 1 }
12
12
  before { Namer.current_index += 1 }
13
13
 
14
- context "With resource 'base_thingy' declared as BaseThingy" do
14
+ context "with resource 'base_thingy' declared as BaseThingy" do
15
15
  before(:context) {
16
16
 
17
17
  class BaseThingy < Chef::Resource
@@ -19,6 +19,7 @@ describe "Recipe DSL methods" do
19
19
  default_action :create
20
20
 
21
21
  class<<self
22
+ attr_accessor :created_name
22
23
  attr_accessor :created_resource
23
24
  attr_accessor :created_provider
24
25
  end
@@ -30,6 +31,7 @@ describe "Recipe DSL methods" do
30
31
  def load_current_resource
31
32
  end
32
33
  def action_create
34
+ BaseThingy.created_name = new_resource.name
33
35
  BaseThingy.created_resource = new_resource.class
34
36
  BaseThingy.created_provider = self.class
35
37
  end
@@ -47,12 +49,38 @@ describe "Recipe DSL methods" do
47
49
  BaseThingy.created_provider = nil
48
50
  end
49
51
 
52
+ it "creates base_thingy when you call base_thingy in a recipe" do
53
+ recipe = converge {
54
+ base_thingy 'blah' do; end
55
+ }
56
+ expect(recipe.logged_warnings).to eq ''
57
+ expect(BaseThingy.created_name).to eq 'blah'
58
+ expect(BaseThingy.created_resource).to eq BaseThingy
59
+ end
60
+
61
+ it "errors out when you call base_thingy do ... end in a recipe" do
62
+ expect_converge {
63
+ base_thingy do; end
64
+ }.to raise_error(ArgumentError, 'You must supply a name when declaring a base_thingy resource')
65
+ end
66
+
67
+ it "emits a warning when you call base_thingy 'foo', 'bar' do ... end in a recipe" do
68
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
69
+ recipe = converge {
70
+ base_thingy 'foo', 'bar' do
71
+ end
72
+ }
73
+ expect(recipe.logged_warnings).to match(/Cannot create resource base_thingy with more than one argument. All arguments except the name \("foo"\) will be ignored. This will cause an error in Chef 13. Arguments: \["foo", "bar"\]/)
74
+ expect(BaseThingy.created_name).to eq 'foo'
75
+ expect(BaseThingy.created_resource).to eq BaseThingy
76
+ end
77
+
50
78
  context "Deprecated automatic resource DSL" do
51
79
  before do
52
80
  Chef::Config[:treat_deprecation_warnings_as_errors] = false
53
81
  end
54
82
 
55
- context "With a resource 'backcompat_thingy' declared in Chef::Resource and Chef::Provider" do
83
+ context "with a resource 'backcompat_thingy' declared in Chef::Resource and Chef::Provider" do
56
84
  before(:context) {
57
85
 
58
86
  class Chef::Resource::BackcompatThingy < Chef::Resource
@@ -97,7 +125,7 @@ describe "Recipe DSL methods" do
97
125
  end
98
126
  end
99
127
 
100
- context "With a resource named RecipeDSLSpecNamespace::Bar::BarThingy" do
128
+ context "with a resource named RecipeDSLSpecNamespace::Bar::BarThingy" do
101
129
  before(:context) {
102
130
 
103
131
  class RecipeDSLSpecNamespace::Bar::BarThingy < BaseThingy
@@ -112,7 +140,7 @@ describe "Recipe DSL methods" do
112
140
  end
113
141
  end
114
142
 
115
- context "With a resource named Chef::Resource::NoNameThingy with resource_name nil" do
143
+ context "with a resource named Chef::Resource::NoNameThingy with resource_name nil" do
116
144
  before(:context) {
117
145
 
118
146
  class Chef::Resource::NoNameThingy < BaseThingy
@@ -128,7 +156,7 @@ describe "Recipe DSL methods" do
128
156
  end
129
157
  end
130
158
 
131
- context "With a resource named AnotherNoNameThingy with resource_name :another_thingy_name" do
159
+ context "with a resource named AnotherNoNameThingy with resource_name :another_thingy_name" do
132
160
  before(:context) {
133
161
 
134
162
  class AnotherNoNameThingy < BaseThingy
@@ -152,7 +180,7 @@ describe "Recipe DSL methods" do
152
180
  end
153
181
  end
154
182
 
155
- context "With a resource named AnotherNoNameThingy2 with resource_name :another_thingy_name2; resource_name :another_thingy_name3" do
183
+ context "with a resource named AnotherNoNameThingy2 with resource_name :another_thingy_name2; resource_name :another_thingy_name3" do
156
184
  before(:context) {
157
185
 
158
186
  class AnotherNoNameThingy2 < BaseThingy
@@ -184,7 +212,7 @@ describe "Recipe DSL methods" do
184
212
  end
185
213
 
186
214
  context "provides overriding resource_name" do
187
- context "With a resource named AnotherNoNameThingy3 with provides :another_no_name_thingy3, os: 'blarghle'" do
215
+ context "with a resource named AnotherNoNameThingy3 with provides :another_no_name_thingy3, os: 'blarghle'" do
188
216
  before(:context) {
189
217
 
190
218
  class AnotherNoNameThingy3 < BaseThingy
@@ -213,7 +241,7 @@ describe "Recipe DSL methods" do
213
241
  end
214
242
  end
215
243
 
216
- context "With a resource named AnotherNoNameThingy4 with two provides" do
244
+ context "with a resource named AnotherNoNameThingy4 with two provides" do
217
245
  before(:context) {
218
246
 
219
247
  class AnotherNoNameThingy4 < BaseThingy
@@ -253,7 +281,7 @@ describe "Recipe DSL methods" do
253
281
  end
254
282
  end
255
283
 
256
- context "With a resource named AnotherNoNameThingy5, a different resource_name, and a provides with the original resource_name" do
284
+ context "with a resource named AnotherNoNameThingy5, a different resource_name, and a provides with the original resource_name" do
257
285
  before(:context) {
258
286
 
259
287
  class AnotherNoNameThingy5 < BaseThingy
@@ -290,7 +318,7 @@ describe "Recipe DSL methods" do
290
318
  end
291
319
  end
292
320
 
293
- context "With a resource named AnotherNoNameThingy6, a provides with the original resource name, and a different resource_name" do
321
+ context "with a resource named AnotherNoNameThingy6, a provides with the original resource name, and a different resource_name" do
294
322
  before(:context) {
295
323
 
296
324
  class AnotherNoNameThingy6 < BaseThingy
@@ -327,7 +355,7 @@ describe "Recipe DSL methods" do
327
355
  end
328
356
  end
329
357
 
330
- context "With a resource named AnotherNoNameThingy7, a new resource_name, and provides with that new resource name" do
358
+ context "with a resource named AnotherNoNameThingy7, a new resource_name, and provides with that new resource name" do
331
359
  before(:context) {
332
360
 
333
361
  class AnotherNoNameThingy7 < BaseThingy
@@ -365,7 +393,7 @@ describe "Recipe DSL methods" do
365
393
  end
366
394
 
367
395
  # opposite order from the previous test (provides, then resource_name)
368
- context "With a resource named AnotherNoNameThingy8, a provides with a new resource name, and resource_name with that new resource name" do
396
+ context "with a resource named AnotherNoNameThingy8, a provides with a new resource name, and resource_name with that new resource name" do
369
397
  before(:context) {
370
398
 
371
399
  class AnotherNoNameThingy8 < BaseThingy
@@ -401,119 +429,6 @@ describe "Recipe DSL methods" do
401
429
  }.to raise_error(NoMethodError)
402
430
  end
403
431
  end
404
-
405
- context "With a resource TwoClassesOneDsl" do
406
- let(:class_name) { "TwoClassesOneDsl#{Namer.current_index}" }
407
- let(:dsl_method) { :"two_classes_one_dsl#{Namer.current_index}" }
408
-
409
- before {
410
- eval <<-EOM, nil, __FILE__, __LINE__+1
411
- class #{class_name} < BaseThingy
412
- resource_name #{dsl_method.inspect}
413
- end
414
- EOM
415
- }
416
- context "and resource BlahModule::TwoClassesOneDsl" do
417
- before {
418
- eval <<-EOM, nil, __FILE__, __LINE__+1
419
- module BlahModule
420
- class #{class_name} < BaseThingy
421
- resource_name #{dsl_method.inspect}
422
- end
423
- end
424
- EOM
425
- }
426
- it "two_classes_one_dsl resolves to BlahModule::TwoClassesOneDsl (alphabetical)" do
427
- dsl_method = self.dsl_method
428
- recipe = converge {
429
- instance_eval("#{dsl_method} 'blah' do; end")
430
- }
431
- expect(recipe.logged_warnings).to eq ''
432
- expect(BaseThingy.created_resource).to eq eval("BlahModule::#{class_name}")
433
- end
434
- it "resource_matching_short_name returns BlahModule::TwoClassesOneDsl" do
435
- expect(Chef::Resource.resource_matching_short_name(dsl_method)).to eq eval("BlahModule::#{class_name}")
436
- end
437
- end
438
- context "and resource BlahModule::TwoClassesOneDsl with resource_name nil" do
439
- before {
440
- eval <<-EOM, nil, __FILE__, __LINE__+1
441
- module BlahModule
442
- class BlahModule::#{class_name} < BaseThingy
443
- resource_name nil
444
- end
445
- end
446
- EOM
447
- }
448
- it "two_classes_one_dsl resolves to ::TwoClassesOneDsl" do
449
- dsl_method = self.dsl_method
450
- recipe = converge {
451
- instance_eval("#{dsl_method} 'blah' do; end")
452
- }
453
- expect(recipe.logged_warnings).to eq ''
454
- expect(BaseThingy.created_resource).to eq eval("::#{class_name}")
455
- end
456
- it "resource_matching_short_name returns ::TwoClassesOneDsl" do
457
- expect(Chef::Resource.resource_matching_short_name(dsl_method)).to eq eval("::#{class_name}")
458
- end
459
- end
460
- context "and resource BlahModule::TwoClassesOneDsl with resource_name :argh" do
461
- before {
462
- eval <<-EOM, nil, __FILE__, __LINE__+1
463
- module BlahModule
464
- class BlahModule::#{class_name} < BaseThingy
465
- resource_name :argh
466
- end
467
- end
468
- EOM
469
- }
470
- it "two_classes_one_dsl resolves to ::TwoClassesOneDsl" do
471
- dsl_method = self.dsl_method
472
- recipe = converge {
473
- instance_eval("#{dsl_method} 'blah' do; end")
474
- }
475
- expect(recipe.logged_warnings).to eq ''
476
- expect(BaseThingy.created_resource).to eq eval("::#{class_name}")
477
- end
478
- it "resource_matching_short_name returns ::TwoClassesOneDsl" do
479
- expect(Chef::Resource.resource_matching_short_name(dsl_method)).to eq eval("::#{class_name}")
480
- end
481
- end
482
- context "and resource BlahModule::TwoClassesOneDsl with provides :two_classes_one_dsl, os: 'blarghle'" do
483
- before {
484
- eval <<-EOM, nil, __FILE__, __LINE__+1
485
- module BlahModule
486
- class BlahModule::#{class_name} < BaseThingy
487
- resource_name #{dsl_method.inspect}
488
- provides #{dsl_method.inspect}, os: 'blarghle'
489
- end
490
- end
491
- EOM
492
- }
493
-
494
- it "and os = blarghle, two_classes_one_dsl resolves to BlahModule::TwoClassesOneDsl" do
495
- dsl_method = self.dsl_method
496
- recipe = converge {
497
- # this is an ugly way to test, make Cheffish expose node attrs
498
- run_context.node.automatic[:os] = 'blarghle'
499
- instance_eval("#{dsl_method} 'blah' do; end")
500
- }
501
- expect(recipe.logged_warnings).to eq ''
502
- expect(BaseThingy.created_resource).to eq eval("BlahModule::#{class_name}")
503
- end
504
-
505
- it "and os = linux, two_classes_one_dsl resolves to ::TwoClassesOneDsl" do
506
- dsl_method = self.dsl_method
507
- recipe = converge {
508
- # this is an ugly way to test, make Cheffish expose node attrs
509
- run_context.node.automatic[:os] = 'linux'
510
- instance_eval("#{dsl_method} 'blah' do; end")
511
- }
512
- expect(recipe.logged_warnings).to eq ''
513
- expect(BaseThingy.created_resource).to eq eval("::#{class_name}")
514
- end
515
- end
516
- end
517
432
  end
518
433
  end
519
434
 
@@ -833,7 +748,7 @@ describe "Recipe DSL methods" do
833
748
  end
834
749
  end
835
750
 
836
- context "With platform-specific resources 'my_super_thingy_foo' and 'my_super_thingy_bar'" do
751
+ context "with platform-specific resources 'my_super_thingy_foo' and 'my_super_thingy_bar'" do
837
752
  before(:context) {
838
753
  class MySuperThingyFoo < BaseThingy
839
754
  resource_name :my_super_thingy_foo
@@ -924,6 +839,601 @@ describe "Recipe DSL methods" do
924
839
  end
925
840
  end
926
841
  end
842
+
843
+ context "with a resource named 'B' with resource name :two_classes_one_dsl" do
844
+ let(:two_classes_one_dsl) { :"two_classes_one_dsl#{Namer.current_index}" }
845
+ let(:resource_class) {
846
+ result = Class.new(BaseThingy) do
847
+ def self.name
848
+ "B"
849
+ end
850
+ def self.to_s; name; end
851
+ def self.inspect; name.inspect; end
852
+ end
853
+ result.resource_name two_classes_one_dsl
854
+ result
855
+ }
856
+ before { resource_class } # pull on it so it gets defined before the recipe runs
857
+
858
+ context "and another resource named 'A' with resource_name :two_classes_one_dsl" do
859
+ let(:resource_class_a) {
860
+ result = Class.new(BaseThingy) do
861
+ def self.name
862
+ "A"
863
+ end
864
+ def self.to_s; name; end
865
+ def self.inspect; name.inspect; end
866
+ end
867
+ result.resource_name two_classes_one_dsl
868
+ result
869
+ }
870
+ before { resource_class_a } # pull on it so it gets defined before the recipe runs
871
+
872
+ it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
873
+ two_classes_one_dsl = self.two_classes_one_dsl
874
+ recipe = converge {
875
+ instance_eval("#{two_classes_one_dsl} 'blah'")
876
+ }
877
+ expect(recipe.logged_warnings).to eq ''
878
+ expect(BaseThingy.created_resource).to eq resource_class_a
879
+ end
880
+
881
+ it "resource_matching_short_name returns B" do
882
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_a
883
+ end
884
+ end
885
+
886
+ context "and another resource named 'Z' with resource_name :two_classes_one_dsl" do
887
+ let(:resource_class_z) {
888
+ result = Class.new(BaseThingy) do
889
+ def self.name
890
+ "Z"
891
+ end
892
+ def self.to_s; name; end
893
+ def self.inspect; name.inspect; end
894
+ end
895
+ result.resource_name two_classes_one_dsl
896
+ result
897
+ }
898
+ before { resource_class_z } # pull on it so it gets defined before the recipe runs
899
+
900
+ it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
901
+ two_classes_one_dsl = self.two_classes_one_dsl
902
+ recipe = converge {
903
+ instance_eval("#{two_classes_one_dsl} 'blah'")
904
+ }
905
+ expect(recipe.logged_warnings).to eq ''
906
+ expect(BaseThingy.created_resource).to eq resource_class
907
+ end
908
+
909
+ it "resource_matching_short_name returns B" do
910
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
911
+ end
912
+
913
+ context "and a priority array [ Z, B ]" do
914
+ before do
915
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z, resource_class ])
916
+ end
917
+
918
+ it "two_classes_one_dsl resolves to Z (respects the priority array)" do
919
+ two_classes_one_dsl = self.two_classes_one_dsl
920
+ recipe = converge {
921
+ instance_eval("#{two_classes_one_dsl} 'blah'")
922
+ }
923
+ expect(recipe.logged_warnings).to eq ''
924
+ expect(BaseThingy.created_resource).to eq resource_class_z
925
+ end
926
+
927
+ it "resource_matching_short_name returns B" do
928
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
929
+ end
930
+
931
+ context "when Z provides(:two_classes_one_dsl) { false }" do
932
+ before do
933
+ resource_class_z.provides(two_classes_one_dsl) { false }
934
+ end
935
+
936
+ it "two_classes_one_dsl resolves to B (picks the next thing in the priority array)" do
937
+ two_classes_one_dsl = self.two_classes_one_dsl
938
+ recipe = converge {
939
+ instance_eval("#{two_classes_one_dsl} 'blah'")
940
+ }
941
+ expect(recipe.logged_warnings).to eq ''
942
+ expect(BaseThingy.created_resource).to eq resource_class
943
+ end
944
+
945
+ it "resource_matching_short_name returns B" do
946
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
947
+ end
948
+ end
949
+ end
950
+
951
+ context "and priority arrays [ B ] and [ Z ]" do
952
+ before do
953
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class ])
954
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z ])
955
+ end
956
+
957
+ it "two_classes_one_dsl resolves to Z (respects the most recent priority array)" do
958
+ two_classes_one_dsl = self.two_classes_one_dsl
959
+ recipe = converge {
960
+ instance_eval("#{two_classes_one_dsl} 'blah'")
961
+ }
962
+ expect(recipe.logged_warnings).to eq ''
963
+ expect(BaseThingy.created_resource).to eq resource_class_z
964
+ end
965
+
966
+ it "resource_matching_short_name returns B" do
967
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
968
+ end
969
+
970
+ context "when Z provides(:two_classes_one_dsl) { false }" do
971
+ before do
972
+ resource_class_z.provides(two_classes_one_dsl) { false }
973
+ end
974
+
975
+ it "two_classes_one_dsl resolves to B (picks the first match from the other priority array)" do
976
+ two_classes_one_dsl = self.two_classes_one_dsl
977
+ recipe = converge {
978
+ instance_eval("#{two_classes_one_dsl} 'blah'")
979
+ }
980
+ expect(recipe.logged_warnings).to eq ''
981
+ expect(BaseThingy.created_resource).to eq resource_class
982
+ end
983
+
984
+ it "resource_matching_short_name returns B" do
985
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
986
+ end
987
+ end
988
+ end
989
+
990
+ context "and a priority array [ Z ]" do
991
+ before do
992
+ Chef.set_resource_priority_array(two_classes_one_dsl, [ resource_class_z ])
993
+ end
994
+
995
+ context "when Z provides(:two_classes_one_dsl) { false }" do
996
+ before do
997
+ resource_class_z.provides(two_classes_one_dsl) { false }
998
+ end
999
+
1000
+ it "two_classes_one_dsl resolves to B (picks the first match outside the priority array)" do
1001
+ two_classes_one_dsl = self.two_classes_one_dsl
1002
+ recipe = converge {
1003
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1004
+ }
1005
+ expect(recipe.logged_warnings).to eq ''
1006
+ expect(BaseThingy.created_resource).to eq resource_class
1007
+ end
1008
+
1009
+ it "resource_matching_short_name returns B" do
1010
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
1011
+ end
1012
+ end
1013
+ end
1014
+
1015
+ end
1016
+
1017
+ context "and a provider named 'B' which provides :two_classes_one_dsl" do
1018
+ before do
1019
+ resource_class.send(:define_method, :provider) { nil }
1020
+ end
1021
+
1022
+ let(:provider_class) {
1023
+ result = Class.new(BaseThingy::Provider) do
1024
+ def self.name
1025
+ "B"
1026
+ end
1027
+ def self.to_s; name; end
1028
+ def self.inspect; name.inspect; end
1029
+ end
1030
+ result.provides two_classes_one_dsl
1031
+ result
1032
+ }
1033
+ before { provider_class } # pull on it so it gets defined before the recipe runs
1034
+
1035
+ context "and another provider named 'A'" do
1036
+ let(:provider_class_a) {
1037
+ result = Class.new(BaseThingy::Provider) do
1038
+ def self.name
1039
+ "A"
1040
+ end
1041
+ def self.to_s; name; end
1042
+ def self.inspect; name.inspect; end
1043
+ end
1044
+ result
1045
+ }
1046
+ context "which provides :two_classes_one_dsl" do
1047
+ before { provider_class_a.provides two_classes_one_dsl }
1048
+
1049
+ it "two_classes_one_dsl resolves to A (alphabetically earliest)" do
1050
+ two_classes_one_dsl = self.two_classes_one_dsl
1051
+ recipe = converge {
1052
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1053
+ }
1054
+ expect(recipe.logged_warnings).to eq ''
1055
+ expect(BaseThingy.created_provider).to eq provider_class_a
1056
+ end
1057
+ end
1058
+ context "which provides(:two_classes_one_dsl) { false }" do
1059
+ before { provider_class_a.provides(two_classes_one_dsl) { false } }
1060
+
1061
+ it "two_classes_one_dsl resolves to B (since A declined)" do
1062
+ two_classes_one_dsl = self.two_classes_one_dsl
1063
+ recipe = converge {
1064
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1065
+ }
1066
+ expect(recipe.logged_warnings).to eq ''
1067
+ expect(BaseThingy.created_provider).to eq provider_class
1068
+ end
1069
+ end
1070
+ end
1071
+
1072
+ context "and another provider named 'Z'" do
1073
+ let(:provider_class_z) {
1074
+ result = Class.new(BaseThingy::Provider) do
1075
+ def self.name
1076
+ "Z"
1077
+ end
1078
+ def self.to_s; name; end
1079
+ def self.inspect; name.inspect; end
1080
+ end
1081
+ result
1082
+ }
1083
+ before { provider_class_z } # pull on it so it gets defined before the recipe runs
1084
+
1085
+ context "which provides :two_classes_one_dsl" do
1086
+ before { provider_class_z.provides two_classes_one_dsl }
1087
+
1088
+ it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
1089
+ two_classes_one_dsl = self.two_classes_one_dsl
1090
+ recipe = converge {
1091
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1092
+ }
1093
+ expect(recipe.logged_warnings).to eq ''
1094
+ expect(BaseThingy.created_provider).to eq provider_class
1095
+ end
1096
+
1097
+ context "with a priority array [ Z, B ]" do
1098
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
1099
+
1100
+ it "two_classes_one_dsl resolves to Z (respects the priority map)" do
1101
+ two_classes_one_dsl = self.two_classes_one_dsl
1102
+ recipe = converge {
1103
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1104
+ }
1105
+ expect(recipe.logged_warnings).to eq ''
1106
+ expect(BaseThingy.created_provider).to eq provider_class_z
1107
+ end
1108
+ end
1109
+ end
1110
+
1111
+ context "which provides(:two_classes_one_dsl) { false }" do
1112
+ before { provider_class_z.provides(two_classes_one_dsl) { false } }
1113
+
1114
+ context "with a priority array [ Z, B ]" do
1115
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z, provider_class ] }
1116
+
1117
+ it "two_classes_one_dsl resolves to B (the next one in the priority map)" do
1118
+ two_classes_one_dsl = self.two_classes_one_dsl
1119
+ recipe = converge {
1120
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1121
+ }
1122
+ expect(recipe.logged_warnings).to eq ''
1123
+ expect(BaseThingy.created_provider).to eq provider_class
1124
+ end
1125
+ end
1126
+
1127
+ context "with priority arrays [ B ] and [ Z ]" do
1128
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class_z ] }
1129
+ before { Chef.set_provider_priority_array two_classes_one_dsl, [ provider_class ] }
1130
+
1131
+ it "two_classes_one_dsl resolves to B (the one in the next priority map)" do
1132
+ two_classes_one_dsl = self.two_classes_one_dsl
1133
+ recipe = converge {
1134
+ instance_eval("#{two_classes_one_dsl} 'blah'")
1135
+ }
1136
+ expect(recipe.logged_warnings).to eq ''
1137
+ expect(BaseThingy.created_provider).to eq provider_class
1138
+ end
1139
+ end
1140
+ end
1141
+ end
1142
+ end
1143
+
1144
+ context "and another resource Blarghle with provides :two_classes_one_dsl, os: 'blarghle'" do
1145
+ let(:resource_class_blarghle) {
1146
+ result = Class.new(BaseThingy) do
1147
+ def self.name
1148
+ "Blarghle"
1149
+ end
1150
+ def self.to_s; name; end
1151
+ def self.inspect; name.inspect; end
1152
+ end
1153
+ result.resource_name two_classes_one_dsl
1154
+ result.provides two_classes_one_dsl, os: 'blarghle'
1155
+ result
1156
+ }
1157
+ before { resource_class_blarghle } # pull on it so it gets defined before the recipe runs
1158
+
1159
+ it "on os = blarghle, two_classes_one_dsl resolves to Blarghle" do
1160
+ two_classes_one_dsl = self.two_classes_one_dsl
1161
+ recipe = converge {
1162
+ # this is an ugly way to test, make Cheffish expose node attrs
1163
+ run_context.node.automatic[:os] = 'blarghle'
1164
+ instance_eval("#{two_classes_one_dsl} 'blah' do; end")
1165
+ }
1166
+ expect(recipe.logged_warnings).to eq ''
1167
+ expect(BaseThingy.created_resource).to eq resource_class_blarghle
1168
+ end
1169
+
1170
+ it "on os = linux, two_classes_one_dsl resolves to B" do
1171
+ two_classes_one_dsl = self.two_classes_one_dsl
1172
+ recipe = converge {
1173
+ # this is an ugly way to test, make Cheffish expose node attrs
1174
+ run_context.node.automatic[:os] = 'linux'
1175
+ instance_eval("#{two_classes_one_dsl} 'blah' do; end")
1176
+ }
1177
+ expect(recipe.logged_warnings).to eq ''
1178
+ expect(BaseThingy.created_resource).to eq resource_class
1179
+ end
1180
+ end
1181
+ end
1182
+
1183
+ context "with a resource MyResource" do
1184
+ let(:resource_class) { Class.new(BaseThingy) do
1185
+ def self.called_provides
1186
+ @called_provides
1187
+ end
1188
+ def to_s
1189
+ "MyResource"
1190
+ end
1191
+ end }
1192
+ let(:my_resource) { :"my_resource#{Namer.current_index}" }
1193
+ let(:blarghle_blarghle_little_star) { :"blarghle_blarghle_little_star#{Namer.current_index}" }
1194
+
1195
+ context "with resource_name :my_resource" do
1196
+ before {
1197
+ resource_class.resource_name my_resource
1198
+ }
1199
+
1200
+ context "with provides? returning true to my_resource" do
1201
+ before {
1202
+ my_resource = self.my_resource
1203
+ resource_class.define_singleton_method(:provides?) do |node, resource_name|
1204
+ @called_provides = true
1205
+ resource_name == my_resource
1206
+ end
1207
+ }
1208
+
1209
+ it "my_resource returns the resource and calls provides?, but does not emit a warning" do
1210
+ dsl_name = self.my_resource
1211
+ recipe = converge {
1212
+ instance_eval("#{dsl_name} 'foo'")
1213
+ }
1214
+ expect(recipe.logged_warnings).to eq ''
1215
+ expect(BaseThingy.created_resource).to eq resource_class
1216
+ expect(resource_class.called_provides).to be_truthy
1217
+ end
1218
+ end
1219
+
1220
+ context "with provides? returning true to blarghle_blarghle_little_star and not resource_name" do
1221
+ before do
1222
+ blarghle_blarghle_little_star = self.blarghle_blarghle_little_star
1223
+ resource_class.define_singleton_method(:provides?) do |node, resource_name|
1224
+ @called_provides = true
1225
+ resource_name == blarghle_blarghle_little_star
1226
+ end
1227
+ end
1228
+
1229
+ it "my_resource does not return the resource" do
1230
+ dsl_name = self.my_resource
1231
+ expect_converge {
1232
+ instance_eval("#{dsl_name} 'foo'")
1233
+ }.to raise_error(Chef::Exceptions::NoSuchResourceType)
1234
+ expect(resource_class.called_provides).to be_truthy
1235
+ end
1236
+
1237
+ it "blarghle_blarghle_little_star 'foo' returns the resource and emits a warning" do
1238
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
1239
+ dsl_name = self.blarghle_blarghle_little_star
1240
+ recipe = converge {
1241
+ instance_eval("#{dsl_name} 'foo'")
1242
+ }
1243
+ expect(recipe.logged_warnings).to include "WARN: #{resource_class}.provides? returned true when asked if it provides DSL #{dsl_name}, but provides :#{dsl_name} was never called!"
1244
+ expect(BaseThingy.created_resource).to eq resource_class
1245
+ expect(resource_class.called_provides).to be_truthy
1246
+ end
1247
+ end
1248
+
1249
+ context "and a provider" do
1250
+ let(:provider_class) do
1251
+ Class.new(BaseThingy::Provider) do
1252
+ def self.name
1253
+ "MyProvider"
1254
+ end
1255
+ def self.to_s; name; end
1256
+ def self.inspect; name.inspect; end
1257
+ def self.called_provides
1258
+ @called_provides
1259
+ end
1260
+ end
1261
+ end
1262
+
1263
+ before do
1264
+ resource_class.send(:define_method, :provider) { nil }
1265
+ end
1266
+
1267
+ context "that provides :my_resource" do
1268
+ before do
1269
+ provider_class.provides my_resource
1270
+ end
1271
+
1272
+ context "with supports? returning true" do
1273
+ before do
1274
+ provider_class.define_singleton_method(:supports?) { |resource,action| true }
1275
+ end
1276
+
1277
+ it "my_resource runs the provider and does not emit a warning" do
1278
+ my_resource = self.my_resource
1279
+ recipe = converge {
1280
+ instance_eval("#{my_resource} 'foo'")
1281
+ }
1282
+ expect(recipe.logged_warnings).to eq ''
1283
+ expect(BaseThingy.created_provider).to eq provider_class
1284
+ end
1285
+
1286
+ context "and another provider supporting :my_resource with supports? false" do
1287
+ let(:provider_class2) do
1288
+ Class.new(BaseThingy::Provider) do
1289
+ def self.name
1290
+ "MyProvider2"
1291
+ end
1292
+ def self.to_s; name; end
1293
+ def self.inspect; name.inspect; end
1294
+ def self.called_provides
1295
+ @called_provides
1296
+ end
1297
+ provides my_resource
1298
+ def self.supports?(resource, action)
1299
+ false
1300
+ end
1301
+ end
1302
+ end
1303
+
1304
+ it "my_resource runs the first provider" do
1305
+ my_resource = self.my_resource
1306
+ recipe = converge {
1307
+ instance_eval("#{my_resource} 'foo'")
1308
+ }
1309
+ expect(recipe.logged_warnings).to eq ''
1310
+ expect(BaseThingy.created_provider).to eq provider_class
1311
+ end
1312
+ end
1313
+ end
1314
+
1315
+ context "with supports? returning false" do
1316
+ before do
1317
+ provider_class.define_singleton_method(:supports?) { |resource,action| false }
1318
+ end
1319
+
1320
+ # TODO no warning? ick
1321
+ it "my_resource runs the provider anyway" do
1322
+ my_resource = self.my_resource
1323
+ recipe = converge {
1324
+ instance_eval("#{my_resource} 'foo'")
1325
+ }
1326
+ expect(recipe.logged_warnings).to eq ''
1327
+ expect(BaseThingy.created_provider).to eq provider_class
1328
+ end
1329
+
1330
+ context "and another provider supporting :my_resource with supports? true" do
1331
+ let(:provider_class2) do
1332
+ my_resource = self.my_resource
1333
+ Class.new(BaseThingy::Provider) do
1334
+ def self.name
1335
+ "MyProvider2"
1336
+ end
1337
+ def self.to_s; name; end
1338
+ def self.inspect; name.inspect; end
1339
+ def self.called_provides
1340
+ @called_provides
1341
+ end
1342
+ provides my_resource
1343
+ def self.supports?(resource, action)
1344
+ true
1345
+ end
1346
+ end
1347
+ end
1348
+ before { provider_class2 } # make sure the provider class shows up
1349
+
1350
+ it "my_resource runs the other provider" do
1351
+ my_resource = self.my_resource
1352
+ recipe = converge {
1353
+ instance_eval("#{my_resource} 'foo'")
1354
+ }
1355
+ expect(recipe.logged_warnings).to eq ''
1356
+ expect(BaseThingy.created_provider).to eq provider_class2
1357
+ end
1358
+ end
1359
+ end
1360
+ end
1361
+
1362
+ context "with provides? returning true" do
1363
+ before {
1364
+ my_resource = self.my_resource
1365
+ provider_class.define_singleton_method(:provides?) do |node, resource|
1366
+ @called_provides = true
1367
+ resource.declared_type == my_resource
1368
+ end
1369
+ }
1370
+
1371
+ context "that provides :my_resource" do
1372
+ before {
1373
+ provider_class.provides my_resource
1374
+ }
1375
+
1376
+ it "my_resource calls the provider (and calls provides?), but does not emit a warning" do
1377
+ my_resource = self.my_resource
1378
+ recipe = converge {
1379
+ instance_eval("#{my_resource} 'foo'")
1380
+ }
1381
+ expect(recipe.logged_warnings).to eq ''
1382
+ expect(BaseThingy.created_provider).to eq provider_class
1383
+ expect(provider_class.called_provides).to be_truthy
1384
+ end
1385
+ end
1386
+
1387
+ context "that does not call provides :my_resource" do
1388
+ it "my_resource calls the provider (and calls provides?), and emits a warning" do
1389
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
1390
+ my_resource = self.my_resource
1391
+ recipe = converge {
1392
+ instance_eval("#{my_resource} 'foo'")
1393
+ }
1394
+ expect(recipe.logged_warnings).to include("WARN: #{provider_class}.provides? returned true when asked if it provides DSL #{my_resource}, but provides :#{my_resource} was never called!")
1395
+ expect(BaseThingy.created_provider).to eq provider_class
1396
+ expect(provider_class.called_provides).to be_truthy
1397
+ end
1398
+ end
1399
+ end
1400
+
1401
+ context "with provides? returning false to my_resource" do
1402
+ before {
1403
+ my_resource = self.my_resource
1404
+ provider_class.define_singleton_method(:provides?) do |node, resource|
1405
+ @called_provides = true
1406
+ false
1407
+ end
1408
+ }
1409
+
1410
+ context "that provides :my_resource" do
1411
+ before {
1412
+ provider_class.provides my_resource
1413
+ }
1414
+
1415
+ it "my_resource fails to find a provider (and calls provides)" do
1416
+ my_resource = self.my_resource
1417
+ expect_converge {
1418
+ instance_eval("#{my_resource} 'foo'")
1419
+ }.to raise_error(Chef::Exceptions::ProviderNotFound)
1420
+ expect(provider_class.called_provides).to be_truthy
1421
+ end
1422
+ end
1423
+
1424
+ context "that does not provide :my_resource" do
1425
+ it "my_resource fails to find a provider (and calls provides)" do
1426
+ my_resource = self.my_resource
1427
+ expect_converge {
1428
+ instance_eval("#{my_resource} 'foo'")
1429
+ }.to raise_error(Chef::Exceptions::ProviderNotFound)
1430
+ expect(provider_class.called_provides).to be_truthy
1431
+ end
1432
+ end
1433
+ end
1434
+ end
1435
+ end
1436
+ end
927
1437
  end
928
1438
 
929
1439
  before(:all) { Namer.current_index = 0 }
@@ -969,4 +1479,29 @@ describe "Recipe DSL methods" do
969
1479
  end
970
1480
  end
971
1481
  end
1482
+
1483
+ context "with a dynamically defined resource and regular provider" do
1484
+ before(:context) do
1485
+ Class.new(Chef::Resource) do
1486
+ resource_name :lw_resource_with_hw_provider_test_case
1487
+ default_action :create
1488
+ attr_accessor :created_provider
1489
+ end
1490
+ class Chef::Provider::LwResourceWithHwProviderTestCase < Chef::Provider
1491
+ def load_current_resource
1492
+ end
1493
+ def action_create
1494
+ new_resource.created_provider = self.class
1495
+ end
1496
+ end
1497
+ end
1498
+
1499
+ it "looks up the provider in Chef::Provider converting the resource name from snake case to camel case" do
1500
+ resource = nil
1501
+ recipe = converge {
1502
+ resource = lw_resource_with_hw_provider_test_case 'blah' do; end
1503
+ }
1504
+ expect(resource.created_provider).to eq(Chef::Provider::LwResourceWithHwProviderTestCase)
1505
+ end
1506
+ end
972
1507
  end