chef 12.4.0-universal-mingw32 → 12.4.1-universal-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
data/spec/spec_helper.rb CHANGED
@@ -87,12 +87,14 @@ Dir["spec/support/**/*.rb"].
87
87
  OHAI_SYSTEM = Ohai::System.new
88
88
  OHAI_SYSTEM.all_plugins("platform")
89
89
 
90
- TEST_PLATFORM =
91
- (OHAI_SYSTEM['platform'] ||
92
- 'unknown_test_platform').dup.freeze
93
- TEST_PLATFORM_VERSION =
94
- (OHAI_SYSTEM['platform_version'] ||
95
- 'unknown_platform_version').dup.freeze
90
+ test_node = Chef::Node.new
91
+ test_node.automatic['os'] = (OHAI_SYSTEM['os'] || 'unknown_os').dup.freeze
92
+ test_node.automatic['platform_family'] = (OHAI_SYSTEM['platform_family'] || 'unknown_platform_family').dup.freeze
93
+ test_node.automatic['platform'] = (OHAI_SYSTEM['platform'] || 'unknown_platform').dup.freeze
94
+ test_node.automatic['platform_version'] = (OHAI_SYSTEM['platform_version'] || 'unknown_platform_version').dup.freeze
95
+ TEST_NODE = test_node.freeze
96
+ TEST_PLATFORM = TEST_NODE['platform']
97
+ TEST_PLATFORM_VERSION = TEST_NODE['platform_version']
96
98
 
97
99
  RSpec.configure do |config|
98
100
  config.include(Matchers)
@@ -162,13 +164,17 @@ RSpec.configure do |config|
162
164
  config.filter_run_excluding :provider => lambda {|criteria|
163
165
  type, target_provider = criteria.first
164
166
 
165
- platform = TEST_PLATFORM.dup
166
- platform_version = TEST_PLATFORM_VERSION.dup
167
-
168
- begin
169
- provider_for_running_platform = Chef::Platform.find_provider(platform, platform_version, type)
170
- provider_for_running_platform != target_provider
171
- rescue ArgumentError # no provider for platform
167
+ node = TEST_NODE.dup
168
+ resource_class = Chef::ResourceResolver.resolve(type, node: node)
169
+ if resource_class
170
+ resource = resource_class.new('test', Chef::RunContext.new(node, nil, nil))
171
+ begin
172
+ provider = resource.provider_for_action(Array(resource_class.default_action).first)
173
+ provider.class != target_provider
174
+ rescue Chef::Exceptions::ProviderNotFound # no provider for platform
175
+ true
176
+ end
177
+ else
172
178
  true
173
179
  end
174
180
  }
@@ -26,7 +26,7 @@ shared_examples_for "version handling" do
26
26
  allow(rest_v1).to receive(http_verb).and_raise(exception_406)
27
27
  end
28
28
 
29
- context "when the server does not support the min or max server API version that Chef::User supports" do
29
+ context "when the server does not support the min or max server API version that Chef::UserV1 supports" do
30
30
  before do
31
31
  allow(object).to receive(:server_client_api_version_intersection).and_return([])
32
32
  end
@@ -34,7 +34,7 @@ shared_examples_for "version handling" do
34
34
  it "raises the original exception" do
35
35
  expect{ object.send(method) }.to raise_error(exception_406)
36
36
  end
37
- end # when the server does not support the min or max server API version that Chef::User supports
37
+ end # when the server does not support the min or max server API version that Chef::UserV1 supports
38
38
  end # version handling
39
39
 
40
40
  shared_examples_for "user and client reregister" do
@@ -21,6 +21,11 @@ require 'spec_helper'
21
21
  require 'chef/api_client'
22
22
  require 'tempfile'
23
23
 
24
+ # DEPRECATION NOTE
25
+ #
26
+ # This code will be removed in Chef 13 in favor of the code in Chef::ApiClientV1,
27
+ # which will be moved to this namespace. New development should occur in
28
+ # Chef::ApiClientV1 until the time before Chef 13.
24
29
  describe Chef::ApiClient do
25
30
  before(:each) do
26
31
  @client = Chef::ApiClient.new
@@ -53,20 +58,6 @@ describe Chef::ApiClient do
53
58
  expect { @client.admin(Hash.new) }.to raise_error(ArgumentError)
54
59
  end
55
60
 
56
- it "has an create_key flag attribute" do
57
- @client.create_key(true)
58
- expect(@client.create_key).to be_truthy
59
- end
60
-
61
- it "create_key defaults to false" do
62
- expect(@client.create_key).to be_falsey
63
- end
64
-
65
- it "allows only boolean values for the create_key flag" do
66
- expect { @client.create_key(false) }.not_to raise_error
67
- expect { @client.create_key(Hash.new) }.to raise_error(ArgumentError)
68
- end
69
-
70
61
  it "has a 'validator' flag attribute" do
71
62
  @client.validator(true)
72
63
  expect(@client.validator).to be_truthy
@@ -129,12 +120,6 @@ describe Chef::ApiClient do
129
120
  expect(@json).to include(%q{"validator":false})
130
121
  end
131
122
 
132
- it "includes the 'create_key' flag when present" do
133
- @client.create_key(true)
134
- @json = @client.to_json
135
- expect(@json).to include(%q{"create_key":true})
136
- end
137
-
138
123
  it "includes the private key when present" do
139
124
  @client.private_key("monkeypants")
140
125
  expect(@client.to_json).to include(%q{"private_key":"monkeypants"})
@@ -143,15 +128,11 @@ describe Chef::ApiClient do
143
128
  it "does not include the private key if not present" do
144
129
  expect(@json).not_to include("private_key")
145
130
  end
146
-
147
- include_examples "to_json equivalent to Chef::JSONCompat.to_json" do
148
- let(:jsonable) { @client }
149
- end
150
131
  end
151
132
 
152
133
  describe "when deserializing from JSON (string) using ApiClient#from_json" do
153
134
  let(:client_string) do
154
- "{\"name\":\"black\",\"public_key\":\"crowes\",\"private_key\":\"monkeypants\",\"admin\":true,\"validator\":true,\"create_key\":true}"
135
+ "{\"name\":\"black\",\"public_key\":\"crowes\",\"private_key\":\"monkeypants\",\"admin\":true,\"validator\":true}"
155
136
  end
156
137
 
157
138
  let(:client) do
@@ -178,10 +159,6 @@ describe Chef::ApiClient do
178
159
  expect(client.admin).to be_truthy
179
160
  end
180
161
 
181
- it "preserves the create_key status" do
182
- expect(client.create_key).to be_truthy
183
- end
184
-
185
162
  it "preserves the 'validator' status" do
186
163
  expect(client.validator).to be_truthy
187
164
  end
@@ -199,7 +176,6 @@ describe Chef::ApiClient do
199
176
  "private_key" => "monkeypants",
200
177
  "admin" => true,
201
178
  "validator" => true,
202
- "create_key" => true,
203
179
  "json_class" => "Chef::ApiClient"
204
180
  }
205
181
  end
@@ -224,10 +200,6 @@ describe Chef::ApiClient do
224
200
  expect(client.admin).to be_truthy
225
201
  end
226
202
 
227
- it "preserves the create_key status" do
228
- expect(client.create_key).to be_truthy
229
- end
230
-
231
203
  it "preserves the 'validator' status" do
232
204
  expect(client.validator).to be_truthy
233
205
  end
@@ -243,18 +215,16 @@ describe Chef::ApiClient do
243
215
 
244
216
  before(:each) do
245
217
  client = {
246
- "name" => "black",
247
- "clientname" => "black",
248
- "public_key" => "crowes",
249
- "private_key" => "monkeypants",
250
- "admin" => true,
251
- "create_key" => true,
252
- "validator" => true,
253
- "json_class" => "Chef::ApiClient"
218
+ "name" => "black",
219
+ "clientname" => "black",
220
+ "public_key" => "crowes",
221
+ "private_key" => "monkeypants",
222
+ "admin" => true,
223
+ "validator" => true,
224
+ "json_class" => "Chef::ApiClient"
254
225
  }
255
-
256
- @http_client = double("Chef::REST mock")
257
- allow(Chef::REST).to receive(:new).and_return(@http_client)
226
+ @http_client = double("Chef::ServerAPI mock")
227
+ allow(Chef::ServerAPI).to receive(:new).and_return(@http_client)
258
228
  expect(@http_client).to receive(:get).with("clients/black").and_return(client)
259
229
  @client = Chef::ApiClient.load(client['name'])
260
230
  end
@@ -275,10 +245,6 @@ describe Chef::ApiClient do
275
245
  expect(@client.admin).to be_a_kind_of(TrueClass)
276
246
  end
277
247
 
278
- it "preserves the create_key status" do
279
- expect(@client.create_key).to be_a_kind_of(TrueClass)
280
- end
281
-
282
248
  it "preserves the 'validator' status" do
283
249
  expect(@client.validator).to be_a_kind_of(TrueClass)
284
250
  end
@@ -304,18 +270,13 @@ describe Chef::ApiClient do
304
270
  File.open(Chef::Config[:client_key], "r") {|f| f.read.chomp }
305
271
  end
306
272
 
307
- it "has an HTTP client configured with default credentials" do
308
- expect(@client.http_api).to be_a_kind_of(Chef::REST)
309
- expect(@client.http_api.client_name).to eq("silent-bob")
310
- expect(@client.http_api.signing_key.to_s).to eq(private_key_data)
311
- end
312
273
  end
313
274
 
314
275
 
315
276
  describe "when requesting a new key" do
316
277
  before do
317
278
  @http_client = double("Chef::REST mock")
318
- allow(Chef::REST).to receive(:new).and_return(@http_client)
279
+ allow(Chef::ServerAPI).to receive(:new).and_return(@http_client)
319
280
  end
320
281
 
321
282
  context "and the client does not exist on the server" do
@@ -332,34 +293,24 @@ describe Chef::ApiClient do
332
293
  end
333
294
 
334
295
  context "and the client exists" do
335
- let(:chef_rest_v0_mock) { double('chef rest root v0 object') }
336
- let(:payload) {
337
- {:name => "lost-my-key", :admin => false, :validator => false, :private_key => true}
338
- }
339
-
340
296
  before do
341
297
  @api_client_without_key = Chef::ApiClient.new
342
298
  @api_client_without_key.name("lost-my-key")
343
- allow(@api_client_without_key).to receive(:chef_rest_v0).and_return(chef_rest_v0_mock)
344
- #allow(@api_client_with_key).to receive(:http_api).and_return(_api_mock)
345
-
346
- allow(chef_rest_v0_mock).to receive(:put).with("clients/lost-my-key", payload).and_return(@api_client_with_key)
347
- allow(chef_rest_v0_mock).to receive(:get).with("clients/lost-my-key").and_return(@api_client_without_key)
348
- allow(@http_client).to receive(:get).with("clients/lost-my-key").and_return(@api_client_without_key)
299
+ expect(@http_client).to receive(:get).with("clients/lost-my-key").and_return(@api_client_without_key)
349
300
  end
350
301
 
302
+
351
303
  context "and the client exists on a Chef 11-like server" do
352
304
  before do
353
305
  @api_client_with_key = Chef::ApiClient.new
354
306
  @api_client_with_key.name("lost-my-key")
355
307
  @api_client_with_key.private_key("the new private key")
356
- allow(@api_client_with_key).to receive(:chef_rest_v0).and_return(chef_rest_v0_mock)
308
+ expect(@http_client).to receive(:put).
309
+ with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :validator => false, :private_key => true).
310
+ and_return(@api_client_with_key)
357
311
  end
358
312
 
359
313
  it "returns an ApiClient with a private key" do
360
- expect(chef_rest_v0_mock).to receive(:put).with("clients/lost-my-key", payload).
361
- and_return(@api_client_with_key)
362
-
363
314
  response = Chef::ApiClient.reregister("lost-my-key")
364
315
  # no sane == method for ApiClient :'(
365
316
  expect(response).to eq(@api_client_without_key)
@@ -372,7 +323,7 @@ describe Chef::ApiClient do
372
323
  context "and the client exists on a Chef 10-like server" do
373
324
  before do
374
325
  @api_client_with_key = {"name" => "lost-my-key", "private_key" => "the new private key"}
375
- expect(chef_rest_v0_mock).to receive(:put).
326
+ expect(@http_client).to receive(:put).
376
327
  with("clients/lost-my-key", :name => "lost-my-key", :admin => false, :validator => false, :private_key => true).
377
328
  and_return(@api_client_with_key)
378
329
  end
@@ -390,134 +341,4 @@ describe Chef::ApiClient do
390
341
 
391
342
  end
392
343
  end
393
-
394
- describe "Versioned API Interactions" do
395
- let(:response_406) { OpenStruct.new(:code => '406') }
396
- let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) }
397
- let(:payload) {
398
- {
399
- :name => "some_name",
400
- :validator => true,
401
- :admin => true
402
- }
403
- }
404
-
405
- before do
406
- @client = Chef::ApiClient.new
407
- allow(@client).to receive(:chef_rest_v0).and_return(double('chef rest root v0 object'))
408
- allow(@client).to receive(:chef_rest_v1).and_return(double('chef rest root v1 object'))
409
- @client.name "some_name"
410
- @client.validator true
411
- @client.admin true
412
- end
413
-
414
- describe "create" do
415
-
416
- # from spec/support/shared/unit/user_and_client_shared.rb
417
- it_should_behave_like "user or client create" do
418
- let(:object) { @client }
419
- let(:error) { Chef::Exceptions::InvalidClientAttribute }
420
- let(:rest_v0) { @client.chef_rest_v0 }
421
- let(:rest_v1) { @client.chef_rest_v1 }
422
- let(:url) { "clients" }
423
- end
424
-
425
- context "when API V1 is not supported by the server" do
426
- # from spec/support/shared/unit/api_versioning.rb
427
- it_should_behave_like "version handling" do
428
- let(:object) { @client }
429
- let(:method) { :create }
430
- let(:http_verb) { :post }
431
- let(:rest_v1) { @client.chef_rest_v1 }
432
- end
433
- end
434
-
435
- end # create
436
-
437
- describe "update" do
438
- context "when a valid client is defined" do
439
-
440
- shared_examples_for "client updating" do
441
- it "updates the client" do
442
- expect(rest). to receive(:put).with("clients/some_name", payload)
443
- @client.update
444
- end
445
-
446
- context "when only the name field exists" do
447
-
448
- before do
449
- # needed since there is no way to set to nil via code
450
- @client.instance_variable_set(:@validator, nil)
451
- @client.instance_variable_set(:@admin, nil)
452
- end
453
-
454
- after do
455
- @client.validator true
456
- @client.admin true
457
- end
458
-
459
- it "updates the client with only the name" do
460
- expect(rest). to receive(:put).with("clients/some_name", {:name => "some_name"})
461
- @client.update
462
- end
463
- end
464
-
465
- end
466
-
467
- context "when API V1 is supported by the server" do
468
-
469
- it_should_behave_like "client updating" do
470
- let(:rest) { @client.chef_rest_v1 }
471
- end
472
-
473
- end # when API V1 is supported by the server
474
-
475
- context "when API V1 is not supported by the server" do
476
- context "when no version is supported" do
477
- # from spec/support/shared/unit/api_versioning.rb
478
- it_should_behave_like "version handling" do
479
- let(:object) { @client }
480
- let(:method) { :create }
481
- let(:http_verb) { :post }
482
- let(:rest_v1) { @client.chef_rest_v1 }
483
- end
484
- end # when no version is supported
485
-
486
- context "when API V0 is supported" do
487
-
488
- before do
489
- allow(@client.chef_rest_v1).to receive(:put).and_raise(exception_406)
490
- allow(@client).to receive(:server_client_api_version_intersection).and_return([0])
491
- end
492
-
493
- it_should_behave_like "client updating" do
494
- let(:rest) { @client.chef_rest_v0 }
495
- end
496
-
497
- end
498
-
499
- end # when API V1 is not supported by the server
500
- end # when a valid client is defined
501
- end # update
502
-
503
- # DEPRECATION
504
- # This can be removed after API V0 support is gone
505
- describe "reregister" do
506
- context "when server API V0 is valid on the Chef Server receiving the request" do
507
- it "creates a new object via the API" do
508
- expect(@client.chef_rest_v0).to receive(:put).with("clients/#{@client.name}", payload.merge({:private_key => true})).and_return({})
509
- @client.reregister
510
- end
511
- end # when server API V0 is valid on the Chef Server receiving the request
512
-
513
- context "when server API V0 is not supported by the Chef Server" do
514
- # from spec/support/shared/unit/api_versioning.rb
515
- it_should_behave_like "user and client reregister" do
516
- let(:object) { @client }
517
- let(:rest_v0) { @client.chef_rest_v0 }
518
- end
519
- end # when server API V0 is not supported by the Chef Server
520
- end # reregister
521
-
522
- end
523
344
  end
@@ -0,0 +1,457 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'spec_helper'
20
+
21
+ require 'chef/api_client_v1'
22
+ require 'tempfile'
23
+
24
+ describe Chef::ApiClientV1 do
25
+ before(:each) do
26
+ @client = Chef::ApiClientV1.new
27
+ end
28
+
29
+ it "has a name attribute" do
30
+ @client.name("ops_master")
31
+ expect(@client.name).to eq("ops_master")
32
+ end
33
+
34
+ it "does not allow spaces in the name" do
35
+ expect { @client.name "ops master" }.to raise_error(ArgumentError)
36
+ end
37
+
38
+ it "only allows string values for the name" do
39
+ expect { @client.name Hash.new }.to raise_error(ArgumentError)
40
+ end
41
+
42
+ it "has an admin flag attribute" do
43
+ @client.admin(true)
44
+ expect(@client.admin).to be_truthy
45
+ end
46
+
47
+ it "defaults to non-admin" do
48
+ expect(@client.admin).to be_falsey
49
+ end
50
+
51
+ it "allows only boolean values for the admin flag" do
52
+ expect { @client.admin(false) }.not_to raise_error
53
+ expect { @client.admin(Hash.new) }.to raise_error(ArgumentError)
54
+ end
55
+
56
+ it "has an create_key flag attribute" do
57
+ @client.create_key(true)
58
+ expect(@client.create_key).to be_truthy
59
+ end
60
+
61
+ it "create_key defaults to false" do
62
+ expect(@client.create_key).to be_falsey
63
+ end
64
+
65
+ it "allows only boolean values for the create_key flag" do
66
+ expect { @client.create_key(false) }.not_to raise_error
67
+ expect { @client.create_key(Hash.new) }.to raise_error(ArgumentError)
68
+ end
69
+
70
+ it "has a 'validator' flag attribute" do
71
+ @client.validator(true)
72
+ expect(@client.validator).to be_truthy
73
+ end
74
+
75
+ it "defaults to non-validator" do
76
+ expect(@client.validator).to be_falsey
77
+ end
78
+
79
+ it "allows only boolean values for the 'validator' flag" do
80
+ expect { @client.validator(false) }.not_to raise_error
81
+ expect { @client.validator(Hash.new) }.to raise_error(ArgumentError)
82
+ end
83
+
84
+ it "has a public key attribute" do
85
+ @client.public_key("super public")
86
+ expect(@client.public_key).to eq("super public")
87
+ end
88
+
89
+ it "accepts only String values for the public key" do
90
+ expect { @client.public_key "" }.not_to raise_error
91
+ expect { @client.public_key Hash.new }.to raise_error(ArgumentError)
92
+ end
93
+
94
+
95
+ it "has a private key attribute" do
96
+ @client.private_key("super private")
97
+ expect(@client.private_key).to eq("super private")
98
+ end
99
+
100
+ it "accepts only String values for the private key" do
101
+ expect { @client.private_key "" }.not_to raise_error
102
+ expect { @client.private_key Hash.new }.to raise_error(ArgumentError)
103
+ end
104
+
105
+ describe "when serializing to JSON" do
106
+ before(:each) do
107
+ @client.name("black")
108
+ @client.public_key("crowes")
109
+ @json = @client.to_json
110
+ end
111
+
112
+ it "serializes as a JSON object" do
113
+ expect(@json).to match(/^\{.+\}$/)
114
+ end
115
+
116
+ it "includes the name value" do
117
+ expect(@json).to include(%q{"name":"black"})
118
+ end
119
+
120
+ it "includes the public key value" do
121
+ expect(@json).to include(%{"public_key":"crowes"})
122
+ end
123
+
124
+ it "includes the 'admin' flag" do
125
+ expect(@json).to include(%q{"admin":false})
126
+ end
127
+
128
+ it "includes the 'validator' flag" do
129
+ expect(@json).to include(%q{"validator":false})
130
+ end
131
+
132
+ it "includes the 'create_key' flag when present" do
133
+ @client.create_key(true)
134
+ @json = @client.to_json
135
+ expect(@json).to include(%q{"create_key":true})
136
+ end
137
+
138
+ it "includes the private key when present" do
139
+ @client.private_key("monkeypants")
140
+ expect(@client.to_json).to include(%q{"private_key":"monkeypants"})
141
+ end
142
+
143
+ it "does not include the private key if not present" do
144
+ expect(@json).not_to include("private_key")
145
+ end
146
+
147
+ include_examples "to_json equivalent to Chef::JSONCompat.to_json" do
148
+ let(:jsonable) { @client }
149
+ end
150
+ end
151
+
152
+ describe "when deserializing from JSON (string) using ApiClient#from_json" do
153
+ let(:client_string) do
154
+ "{\"name\":\"black\",\"public_key\":\"crowes\",\"private_key\":\"monkeypants\",\"admin\":true,\"validator\":true,\"create_key\":true}"
155
+ end
156
+
157
+ let(:client) do
158
+ Chef::ApiClientV1.from_json(client_string)
159
+ end
160
+
161
+ it "does not require a 'json_class' string" do
162
+ expect(Chef::JSONCompat.parse(client_string)["json_class"]).to eq(nil)
163
+ end
164
+
165
+ it "should deserialize to a Chef::ApiClientV1 object" do
166
+ expect(client).to be_a_kind_of(Chef::ApiClientV1)
167
+ end
168
+
169
+ it "preserves the name" do
170
+ expect(client.name).to eq("black")
171
+ end
172
+
173
+ it "preserves the public key" do
174
+ expect(client.public_key).to eq("crowes")
175
+ end
176
+
177
+ it "preserves the admin status" do
178
+ expect(client.admin).to be_truthy
179
+ end
180
+
181
+ it "preserves the create_key status" do
182
+ expect(client.create_key).to be_truthy
183
+ end
184
+
185
+ it "preserves the 'validator' status" do
186
+ expect(client.validator).to be_truthy
187
+ end
188
+
189
+ it "includes the private key if present" do
190
+ expect(client.private_key).to eq("monkeypants")
191
+ end
192
+ end
193
+
194
+ describe "when deserializing from JSON (hash) using ApiClientV1#from_json" do
195
+ let(:client_hash) do
196
+ {
197
+ "name" => "black",
198
+ "public_key" => "crowes",
199
+ "private_key" => "monkeypants",
200
+ "admin" => true,
201
+ "validator" => true,
202
+ "create_key" => true
203
+ }
204
+ end
205
+
206
+ let(:client) do
207
+ Chef::ApiClientV1.from_json(Chef::JSONCompat.to_json(client_hash))
208
+ end
209
+
210
+ it "should deserialize to a Chef::ApiClientV1 object" do
211
+ expect(client).to be_a_kind_of(Chef::ApiClientV1)
212
+ end
213
+
214
+ it "preserves the name" do
215
+ expect(client.name).to eq("black")
216
+ end
217
+
218
+ it "preserves the public key" do
219
+ expect(client.public_key).to eq("crowes")
220
+ end
221
+
222
+ it "preserves the admin status" do
223
+ expect(client.admin).to be_truthy
224
+ end
225
+
226
+ it "preserves the create_key status" do
227
+ expect(client.create_key).to be_truthy
228
+ end
229
+
230
+ it "preserves the 'validator' status" do
231
+ expect(client.validator).to be_truthy
232
+ end
233
+
234
+ it "includes the private key if present" do
235
+ expect(client.private_key).to eq("monkeypants")
236
+ end
237
+ end
238
+
239
+ describe "when loading from JSON" do
240
+ before do
241
+ end
242
+
243
+ before(:each) do
244
+ client = {
245
+ "name" => "black",
246
+ "clientname" => "black",
247
+ "public_key" => "crowes",
248
+ "private_key" => "monkeypants",
249
+ "admin" => true,
250
+ "create_key" => true,
251
+ "validator" => true
252
+ }
253
+
254
+ @http_client = double("Chef::ServerAPI mock")
255
+ allow(Chef::ServerAPI).to receive(:new).and_return(@http_client)
256
+ expect(@http_client).to receive(:get).with("clients/black").and_return(client)
257
+ @client = Chef::ApiClientV1.load(client['name'])
258
+ end
259
+
260
+ it "should deserialize to a Chef::ApiClientV1 object" do
261
+ expect(@client).to be_a_kind_of(Chef::ApiClientV1)
262
+ end
263
+
264
+ it "preserves the name" do
265
+ expect(@client.name).to eq("black")
266
+ end
267
+
268
+ it "preserves the public key" do
269
+ expect(@client.public_key).to eq("crowes")
270
+ end
271
+
272
+ it "preserves the admin status" do
273
+ expect(@client.admin).to be_a_kind_of(TrueClass)
274
+ end
275
+
276
+ it "preserves the create_key status" do
277
+ expect(@client.create_key).to be_a_kind_of(TrueClass)
278
+ end
279
+
280
+ it "preserves the 'validator' status" do
281
+ expect(@client.validator).to be_a_kind_of(TrueClass)
282
+ end
283
+
284
+ it "includes the private key if present" do
285
+ expect(@client.private_key).to eq("monkeypants")
286
+ end
287
+
288
+ end
289
+
290
+ describe "with correctly configured API credentials" do
291
+ before do
292
+ Chef::Config[:node_name] = "silent-bob"
293
+ Chef::Config[:client_key] = File.expand_path('ssl/private_key.pem', CHEF_SPEC_DATA)
294
+ end
295
+
296
+ after do
297
+ Chef::Config[:node_name] = nil
298
+ Chef::Config[:client_key] = nil
299
+ end
300
+
301
+ let :private_key_data do
302
+ File.open(Chef::Config[:client_key], "r") {|f| f.read.chomp }
303
+ end
304
+
305
+ end
306
+
307
+
308
+ describe "when requesting a new key" do
309
+ before do
310
+ @http_client = double("Chef::ServerAPI mock")
311
+ allow(Chef::ServerAPI).to receive(:new).and_return(@http_client)
312
+ end
313
+
314
+ context "and the client does not exist on the server" do
315
+ before do
316
+ @a_404_response = Net::HTTPNotFound.new("404 not found and such", nil, nil)
317
+ @a_404_exception = Net::HTTPServerException.new("404 not found exception", @a_404_response)
318
+
319
+ expect(@http_client).to receive(:get).with("clients/lost-my-key").and_raise(@a_404_exception)
320
+ end
321
+
322
+ it "raises a 404 error" do
323
+ expect { Chef::ApiClientV1.reregister("lost-my-key") }.to raise_error(Net::HTTPServerException)
324
+ end
325
+ end
326
+ end
327
+
328
+ describe "Versioned API Interactions" do
329
+ let(:response_406) { OpenStruct.new(:code => '406') }
330
+ let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) }
331
+ let(:payload) {
332
+ {
333
+ :name => "some_name",
334
+ :validator => true,
335
+ :admin => true
336
+ }
337
+ }
338
+
339
+ before do
340
+ @client = Chef::ApiClientV1.new
341
+ allow(@client).to receive(:chef_rest_v0).and_return(double('chef rest root v0 object'))
342
+ allow(@client).to receive(:chef_rest_v1).and_return(double('chef rest root v1 object'))
343
+ @client.name "some_name"
344
+ @client.validator true
345
+ @client.admin true
346
+ end
347
+
348
+ describe "create" do
349
+
350
+ # from spec/support/shared/unit/user_and_client_shared.rb
351
+ it_should_behave_like "user or client create" do
352
+ let(:object) { @client }
353
+ let(:error) { Chef::Exceptions::InvalidClientAttribute }
354
+ let(:rest_v0) { @client.chef_rest_v0 }
355
+ let(:rest_v1) { @client.chef_rest_v1 }
356
+ let(:url) { "clients" }
357
+ end
358
+
359
+ context "when API V1 is not supported by the server" do
360
+ # from spec/support/shared/unit/api_versioning.rb
361
+ it_should_behave_like "version handling" do
362
+ let(:object) { @client }
363
+ let(:method) { :create }
364
+ let(:http_verb) { :post }
365
+ let(:rest_v1) { @client.chef_rest_v1 }
366
+ end
367
+ end
368
+
369
+ end # create
370
+
371
+ describe "update" do
372
+ context "when a valid client is defined" do
373
+
374
+ shared_examples_for "client updating" do
375
+ it "updates the client" do
376
+ expect(rest). to receive(:put).with("clients/some_name", payload).and_return(payload)
377
+ @client.update
378
+ end
379
+
380
+ context "when only the name field exists" do
381
+
382
+ before do
383
+ # needed since there is no way to set to nil via code
384
+ @client.instance_variable_set(:@validator, nil)
385
+ @client.instance_variable_set(:@admin, nil)
386
+ end
387
+
388
+ after do
389
+ @client.validator true
390
+ @client.admin true
391
+ end
392
+
393
+ it "updates the client with only the name" do
394
+ expect(rest). to receive(:put).with("clients/some_name", {:name => "some_name"}).and_return({:name => "some_name"})
395
+ @client.update
396
+ end
397
+ end
398
+
399
+ end
400
+
401
+ context "when API V1 is supported by the server" do
402
+
403
+ it_should_behave_like "client updating" do
404
+ let(:rest) { @client.chef_rest_v1 }
405
+ end
406
+
407
+ end # when API V1 is supported by the server
408
+
409
+ context "when API V1 is not supported by the server" do
410
+ context "when no version is supported" do
411
+ # from spec/support/shared/unit/api_versioning.rb
412
+ it_should_behave_like "version handling" do
413
+ let(:object) { @client }
414
+ let(:method) { :create }
415
+ let(:http_verb) { :post }
416
+ let(:rest_v1) { @client.chef_rest_v1 }
417
+ end
418
+ end # when no version is supported
419
+
420
+ context "when API V0 is supported" do
421
+
422
+ before do
423
+ allow(@client.chef_rest_v1).to receive(:put).and_raise(exception_406)
424
+ allow(@client).to receive(:server_client_api_version_intersection).and_return([0])
425
+ end
426
+
427
+ it_should_behave_like "client updating" do
428
+ let(:rest) { @client.chef_rest_v0 }
429
+ end
430
+
431
+ end
432
+
433
+ end # when API V1 is not supported by the server
434
+ end # when a valid client is defined
435
+ end # update
436
+
437
+ # DEPRECATION
438
+ # This can be removed after API V0 support is gone
439
+ describe "reregister" do
440
+ context "when server API V0 is valid on the Chef Server receiving the request" do
441
+ it "creates a new object via the API" do
442
+ expect(@client.chef_rest_v0).to receive(:put).with("clients/#{@client.name}", payload.merge({:private_key => true})).and_return({})
443
+ @client.reregister
444
+ end
445
+ end # when server API V0 is valid on the Chef Server receiving the request
446
+
447
+ context "when server API V0 is not supported by the Chef Server" do
448
+ # from spec/support/shared/unit/api_versioning.rb
449
+ it_should_behave_like "user and client reregister" do
450
+ let(:object) { @client }
451
+ let(:rest_v0) { @client.chef_rest_v0 }
452
+ end
453
+ end # when server API V0 is not supported by the Chef Server
454
+ end # reregister
455
+
456
+ end
457
+ end