chef 12.2.1 → 12.3.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef.rb +1 -0
  3. data/lib/chef/application/apply.rb +5 -0
  4. data/lib/chef/application/client.rb +10 -0
  5. data/lib/chef/application/knife.rb +5 -1
  6. data/lib/chef/application/solo.rb +5 -0
  7. data/lib/chef/chef_class.rb +130 -0
  8. data/lib/chef/client.rb +15 -7
  9. data/lib/chef/config.rb +13 -0
  10. data/lib/chef/event_loggers/windows_eventlog.rb +11 -5
  11. data/lib/chef/http.rb +13 -3
  12. data/lib/chef/http/basic_client.rb +21 -4
  13. data/lib/chef/http/socketless_chef_zero_client.rb +207 -0
  14. data/lib/chef/knife.rb +3 -0
  15. data/lib/chef/knife/bootstrap.rb +1 -1
  16. data/lib/chef/knife/core/status_presenter.rb +12 -11
  17. data/lib/chef/knife/ssh.rb +3 -1
  18. data/lib/chef/knife/status.rb +32 -7
  19. data/lib/chef/local_mode.rb +13 -3
  20. data/lib/chef/mixin/provides.rb +32 -0
  21. data/lib/chef/platform/provider_priority_map.rb +16 -7
  22. data/lib/chef/platform/resource_priority_map.rb +37 -0
  23. data/lib/chef/policy_builder/expand_node_object.rb +14 -0
  24. data/lib/chef/policy_builder/policyfile.rb +0 -1
  25. data/lib/chef/provider.rb +5 -20
  26. data/lib/chef/provider/package/rubygems.rb +4 -1
  27. data/lib/chef/provider/service/macosx.rb +66 -30
  28. data/lib/chef/provider_resolver.rb +10 -5
  29. data/lib/chef/resource.rb +5 -39
  30. data/lib/chef/resource/gem_package.rb +5 -0
  31. data/lib/chef/resource/link.rb +1 -1
  32. data/lib/chef/resource/macosx_service.rb +59 -0
  33. data/lib/chef/resource/remote_file.rb +0 -4
  34. data/lib/chef/resource_resolver.rb +101 -0
  35. data/lib/chef/rest.rb +4 -5
  36. data/lib/chef/search/query.rb +1 -1
  37. data/lib/chef/server_api.rb +1 -0
  38. data/lib/chef/version.rb +1 -1
  39. data/spec/data/lwrp/providers/buck_passer.rb +2 -1
  40. data/spec/data/lwrp/resources/bar.rb +1 -1
  41. data/spec/data/{big_json.json → nested.json} +2 -2
  42. data/spec/functional/event_loggers/windows_eventlog_spec.rb +14 -0
  43. data/spec/functional/resource/execute_spec.rb +1 -1
  44. data/spec/integration/client/client_spec.rb +12 -1
  45. data/spec/integration/client/ipv6_spec.rb +1 -1
  46. data/spec/integration/knife/common_options_spec.rb +3 -3
  47. data/spec/integration/recipes/lwrp_inline_resources_spec.rb +1 -1
  48. data/spec/integration/solo/solo_spec.rb +7 -5
  49. data/spec/unit/application/client_spec.rb +10 -0
  50. data/spec/unit/chef_class_spec.rb +91 -0
  51. data/spec/unit/client_spec.rb +13 -0
  52. data/spec/unit/http/basic_client_spec.rb +43 -6
  53. data/spec/unit/http/socketless_chef_zero_client_spec.rb +174 -0
  54. data/spec/unit/http_spec.rb +14 -0
  55. data/spec/unit/json_compat_spec.rb +7 -20
  56. data/spec/unit/knife/ssh_spec.rb +18 -0
  57. data/spec/unit/knife/status_spec.rb +69 -3
  58. data/spec/unit/knife_spec.rb +5 -0
  59. data/spec/unit/provider/package/rubygems_spec.rb +19 -0
  60. data/spec/unit/provider/service/macosx_spec.rb +230 -203
  61. data/spec/unit/provider_resolver_spec.rb +1 -0
  62. data/spec/unit/recipe_spec.rb +48 -0
  63. data/spec/unit/resource/link_spec.rb +15 -0
  64. data/spec/unit/resource_spec.rb +6 -6
  65. data/spec/unit/rest_spec.rb +9 -0
  66. data/spec/unit/search/query_spec.rb +24 -0
  67. data/spec/unit/shell_spec.rb +3 -1
  68. metadata +16 -9
  69. data/spec/data/big_json_plus_one.json +0 -2
@@ -76,7 +76,7 @@ END_CLIENT_RB
76
76
 
77
77
  let(:chef_dir) { File.join(File.dirname(__FILE__), "..", "..", "..", "bin") }
78
78
 
79
- let(:chef_client_cmd) { %Q[ruby '#{chef_dir}/chef-client' -c "#{path_to('config/client.rb')}" -lwarn] }
79
+ let(:chef_client_cmd) { %Q[ruby '#{chef_dir}/chef-client' --minimal-ohai -c "#{path_to('config/client.rb')}" -lwarn] }
80
80
 
81
81
  after do
82
82
  FileUtils.rm_rf(cache_path)
@@ -39,7 +39,7 @@ describe 'knife common options', :workstation do
39
39
 
40
40
  it 'knife raw /nodes/x should retrieve the node' do
41
41
  knife('raw /nodes/x').should_succeed( /"name": "x"/ )
42
- expect(Chef::Config.chef_server_url).to eq('http://localhost:9999')
42
+ expect(Chef::Config.chef_server_url).to eq('chefzero://localhost:9999')
43
43
  end
44
44
  end
45
45
 
@@ -101,7 +101,7 @@ EOM
101
101
 
102
102
  it 'knife raw -z --chef-zero-port=9999 /nodes/x retrieves the node' do
103
103
  knife('raw -z --chef-zero-port=9999 /nodes/x').should_succeed( /"name": "x"/ )
104
- expect(Chef::Config.chef_server_url).to eq('http://localhost:9999')
104
+ expect(Chef::Config.chef_server_url).to eq('chefzero://localhost:9999')
105
105
  end
106
106
 
107
107
  context 'when the default port (8889) is already bound' do
@@ -149,7 +149,7 @@ EOM
149
149
 
150
150
  it 'knife raw -z --chef-zero-port=9999 /nodes/x retrieves the node' do
151
151
  knife('raw -z --chef-zero-port=9999 /nodes/x').should_succeed( /"name": "x"/ )
152
- expect(Chef::Config.chef_server_url).to eq('http://localhost:9999')
152
+ expect(Chef::Config.chef_server_url).to eq('chefzero://localhost:9999')
153
153
  end
154
154
  end
155
155
  end
@@ -16,7 +16,7 @@ describe "LWRPs with inline resources" do
16
16
  # machine that has omnibus chef installed. In that case we need to ensure
17
17
  # we're running `chef-client` from the source tree and not the external one.
18
18
  # cf. CHEF-4914
19
- let(:chef_client) { "ruby '#{chef_dir}/chef-client'" }
19
+ let(:chef_client) { "ruby '#{chef_dir}/chef-client' --minimal-ohai" }
20
20
 
21
21
  when_the_repository "has a cookbook with a nested LWRP" do
22
22
  before do
@@ -15,6 +15,8 @@ describe "chef-solo" do
15
15
 
16
16
  let(:cookbook_ancient_100_metadata_rb) { cb_metadata("ancient", "1.0.0") }
17
17
 
18
+ let(:chef_solo) { "ruby bin/chef-solo --minimal-ohai" }
19
+
18
20
  when_the_repository "has a cookbook with a basic recipe" do
19
21
  before do
20
22
  file 'cookbooks/x/metadata.rb', cookbook_x_100_metadata_rb
@@ -26,7 +28,7 @@ describe "chef-solo" do
26
28
  cookbook_path "#{path_to('cookbooks')}"
27
29
  file_cache_path "#{path_to('config/cache')}"
28
30
  EOM
29
- result = shell_out("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
31
+ result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
30
32
  result.error!
31
33
  expect(result.stdout).to include("ITWORKS")
32
34
  end
@@ -41,7 +43,7 @@ EOM
41
43
  {"run_list":["x::default"]}
42
44
  E
43
45
 
44
- result = shell_out("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -j '#{path_to('config/node.json')}' -l debug", :cwd => chef_dir)
46
+ result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -j '#{path_to('config/node.json')}' -l debug", :cwd => chef_dir)
45
47
  result.error!
46
48
  expect(result.stdout).to include("ITWORKS")
47
49
  end
@@ -62,7 +64,7 @@ E
62
64
  cookbook_path "#{path_to('cookbooks')}"
63
65
  file_cache_path "#{path_to('config/cache')}"
64
66
  EOM
65
- result = shell_out("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
67
+ result = shell_out("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' -l debug", :cwd => chef_dir)
66
68
  expect(result.exitstatus).to eq(0) # For CHEF-5120 this becomes 1
67
69
  expect(result.stdout).to include("WARN: MissingCookbookDependency")
68
70
  end
@@ -95,14 +97,14 @@ EOM
95
97
  chef_dir = File.join(File.dirname(__FILE__), "..", "..", "..")
96
98
 
97
99
  # Instantiate the first chef-solo run
98
- s1 = Process.spawn("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \
100
+ s1 = Process.spawn("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \
99
101
  -l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir)
100
102
 
101
103
  # Give it some time to progress
102
104
  sleep 1
103
105
 
104
106
  # Instantiate the second chef-solo run
105
- s2 = Process.spawn("ruby bin/chef-solo -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \
107
+ s2 = Process.spawn("#{chef_solo} -c \"#{path_to('config/solo.rb')}\" -o 'x::default' \
106
108
  -l debug -L #{path_to('logs/runs.log')}", :chdir => chef_dir)
107
109
 
108
110
  Process.waitpid(s1)
@@ -131,6 +131,16 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
131
131
 
132
132
  end
133
133
 
134
+ describe "when --no-listen is set" do
135
+
136
+ it "configures listen = false" do
137
+ app.config[:listen] = false
138
+ app.reconfigure
139
+ expect(Chef::Config[:listen]).to eq(false)
140
+ end
141
+
142
+ end
143
+
134
144
  describe "when the json_attribs configuration option is specified" do
135
145
 
136
146
  let(:json_attribs) { {"a" => "b"} }
@@ -0,0 +1,91 @@
1
+ #
2
+ # Author:: Lamont Granquist (<lamont@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 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
+ describe "Chef class" do
22
+ let(:platform) { "debian" }
23
+
24
+ let(:node) do
25
+ node = Chef::Node.new
26
+ node.automatic['platform'] = platform
27
+ node
28
+ end
29
+
30
+ let(:run_context) do
31
+ Chef::RunContext.new(node, nil, nil)
32
+ end
33
+
34
+ let(:resource_priority_map) do
35
+ double("Chef::Platform::ResourcePriorityMap")
36
+ end
37
+
38
+ let(:provider_priority_map) do
39
+ double("Chef::Platform::ProviderPriorityMap")
40
+ end
41
+
42
+ before do
43
+ Chef.set_run_context(run_context)
44
+ Chef.set_node(node)
45
+ Chef.set_resource_priority_map(resource_priority_map)
46
+ Chef.set_provider_priority_map(provider_priority_map)
47
+ end
48
+
49
+ after do
50
+ Chef.reset!
51
+ end
52
+
53
+ context "priority maps" do
54
+ context "#get_provider_priority_array" do
55
+ it "should use the current node to get the right priority_map" do
56
+ expect(provider_priority_map).to receive(:get_priority_array).with(node, :http_request).and_return("stuff")
57
+ expect(Chef.get_provider_priority_array(:http_request)).to eql("stuff")
58
+ end
59
+ end
60
+ context "#get_resource_priority_array" do
61
+ it "should use the current node to get the right priority_map" do
62
+ expect(resource_priority_map).to receive(:get_priority_array).with(node, :http_request).and_return("stuff")
63
+ expect(Chef.get_resource_priority_array(:http_request)).to eql("stuff")
64
+ end
65
+ end
66
+ context "#set_provider_priority_array" do
67
+ it "should delegate to the provider_priority_map" do
68
+ expect(provider_priority_map).to receive(:set_priority_array).with(:http_request, ["a", "b"], platform: "debian").and_return("stuff")
69
+ expect(Chef.set_provider_priority_array(:http_request, ["a", "b"], platform: "debian")).to eql("stuff")
70
+ end
71
+ end
72
+ context "#set_priority_map_for_resource" do
73
+ it "should delegate to the resource_priority_map" do
74
+ expect(resource_priority_map).to receive(:set_priority_array).with(:http_request, ["a", "b"], platform: "debian").and_return("stuff")
75
+ expect(Chef.set_resource_priority_array(:http_request, ["a", "b"], platform: "debian")).to eql("stuff")
76
+ end
77
+ end
78
+ end
79
+
80
+ context "#run_context" do
81
+ it "should return the injected RunContext" do
82
+ expect(Chef.run_context).to eql(run_context)
83
+ end
84
+ end
85
+
86
+ context "#node" do
87
+ it "should return the injected Node" do
88
+ expect(Chef.node).to eql(node)
89
+ end
90
+ end
91
+ end
@@ -78,6 +78,19 @@ describe Chef::Client do
78
78
  allow(Ohai::System).to receive(:new).and_return(ohai_system)
79
79
  end
80
80
 
81
+ context "when minimal ohai is configured" do
82
+ before do
83
+ Chef::Config[:minimal_ohai] = true
84
+ end
85
+
86
+ it "runs ohai with only the minimum required plugins" do
87
+ expected_filter = %w[fqdn machinename hostname platform platform_version os os_version]
88
+ expect(ohai_system).to receive(:all_plugins).with(expected_filter)
89
+ client.run_ohai
90
+ end
91
+
92
+ end
93
+
81
94
  describe "authentication protocol selection" do
82
95
  after do
83
96
  Chef::Config[:authentication_protocol_version] = "1.0"
@@ -21,7 +21,7 @@ require 'chef/http/basic_client'
21
21
  describe "HTTP Connection" do
22
22
 
23
23
  let(:uri) { URI("https://example.com:4443") }
24
- subject { Chef::HTTP::BasicClient.new(uri) }
24
+ subject(:basic_client) { Chef::HTTP::BasicClient.new(uri) }
25
25
 
26
26
  describe ".new" do
27
27
  it "creates an instance" do
@@ -45,11 +45,6 @@ describe "HTTP Connection" do
45
45
  let(:proxy_port) { 8080 }
46
46
  let(:proxy) { "#{proxy_prefix}#{proxy_host}:#{proxy_port}" }
47
47
 
48
- before do
49
- Chef::Config["#{uri.scheme}_proxy"] = proxy
50
- Chef::Config[:no_proxy] = nil
51
- end
52
-
53
48
  it "should contain the host" do
54
49
  proxy_uri = subject.proxy_uri
55
50
  expect(proxy_uri.host).to eq(proxy_host)
@@ -63,14 +58,56 @@ describe "HTTP Connection" do
63
58
 
64
59
  context "when the config setting is normalized (does not contain the scheme)" do
65
60
  include_examples "a proxy uri" do
61
+
66
62
  let(:proxy_prefix) { "" }
63
+
64
+ before do
65
+ Chef::Config["#{uri.scheme}_proxy"] = proxy
66
+ Chef::Config[:no_proxy] = nil
67
+ end
68
+
67
69
  end
68
70
  end
69
71
 
70
72
  context "when the config setting is not normalized (contains the scheme)" do
71
73
  include_examples "a proxy uri" do
72
74
  let(:proxy_prefix) { "#{uri.scheme}://" }
75
+
76
+ before do
77
+ Chef::Config["#{uri.scheme}_proxy"] = proxy
78
+ Chef::Config[:no_proxy] = nil
79
+ end
80
+
81
+ end
82
+ end
83
+
84
+ context "when the proxy is set by the environment" do
85
+
86
+ include_examples "a proxy uri" do
87
+
88
+ let(:env) do
89
+ {
90
+ "https_proxy" => "https://proxy.mycorp.com:8080",
91
+ "https_proxy_user" => "jane_username",
92
+ "https_proxy_pass" => "opensesame"
93
+ }
94
+ end
95
+
96
+ let(:proxy_uri) { URI.parse(env["https_proxy"]) }
97
+
98
+ before do
99
+ allow(basic_client).to receive(:env).and_return(env)
100
+ end
101
+
102
+ it "sets the proxy user" do
103
+ expect(basic_client.http_proxy_user(proxy_uri)).to eq("jane_username")
104
+ end
105
+
106
+ it "sets the proxy pass" do
107
+ expect(basic_client.http_proxy_pass(proxy_uri)).to eq("opensesame")
108
+ end
73
109
  end
110
+
74
111
  end
75
112
  end
76
113
  end
@@ -0,0 +1,174 @@
1
+ #--
2
+ # Author:: Daniel DeLeo (<dan@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, 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 'chef/http/socketless_chef_zero_client'
20
+
21
+ describe Chef::HTTP::SocketlessChefZeroClient do
22
+
23
+ let(:relative_url) { "" }
24
+ let(:uri_str) { "chefzero://localhost:1/#{relative_url}" }
25
+ let(:uri) { URI(uri_str) }
26
+
27
+ subject(:zero_client) { Chef::HTTP::SocketlessChefZeroClient.new(uri) }
28
+
29
+ it "has a host" do
30
+ expect(zero_client.host).to eq("localhost")
31
+ end
32
+
33
+ it "has a port" do
34
+ expect(zero_client.port).to eq(1)
35
+ end
36
+
37
+ describe "converting requests to rack format" do
38
+
39
+ let(:expected_rack_req) do
40
+ {
41
+ "SCRIPT_NAME" => "",
42
+ "SERVER_NAME" => "localhost",
43
+ "REQUEST_METHOD" => method.to_s.upcase,
44
+ "PATH_INFO" => uri.path,
45
+ "QUERY_STRING" => uri.query,
46
+ "SERVER_PORT" => uri.port,
47
+ "HTTP_HOST" => "localhost:#{uri.port}",
48
+ "rack.url_scheme" => "chefzero",
49
+ }
50
+ end
51
+
52
+ context "when the request has no body" do
53
+
54
+ let(:method) { :GET }
55
+ let(:relative_url) { "clients" }
56
+ let(:headers) { { "Accept" => "application/json" } }
57
+ let(:body) { false }
58
+ let(:expected_body_str) { "" }
59
+
60
+ let(:rack_req) { zero_client.req_to_rack(method, uri, body, headers) }
61
+
62
+ it "creates a rack request env" do
63
+ # StringIO doesn't implement == in a way that we can compare, so we
64
+ # check rack.input individually and then iterate over everything else
65
+ expect(rack_req["rack.input"].string).to eq(expected_body_str)
66
+ expected_rack_req.each do |key, value|
67
+ expect(rack_req[key]).to eq(value)
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ context "when the request has a body" do
74
+
75
+ let(:method) { :PUT }
76
+ let(:relative_url) { "clients/foo" }
77
+ let(:headers) { { "Accept" => "application/json" } }
78
+ let(:body) { "bunch o' JSON" }
79
+ let(:expected_body_str) { "bunch o' JSON" }
80
+
81
+ let(:rack_req) { zero_client.req_to_rack(method, uri, body, headers) }
82
+
83
+ it "creates a rack request env" do
84
+ # StringIO doesn't implement == in a way that we can compare, so we
85
+ # check rack.input individually and then iterate over everything else
86
+ expect(rack_req["rack.input"].string).to eq(expected_body_str)
87
+ expected_rack_req.each do |key, value|
88
+ expect(rack_req[key]).to eq(value)
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ describe "converting responses to Net::HTTP objects" do
97
+
98
+ let(:net_http_response) { zero_client.to_net_http(code, headers, body) }
99
+
100
+ context "when the request was successful (2XX)" do
101
+
102
+ let(:code) { 200 }
103
+ let(:headers) { { "Content-Type" => "Application/JSON" } }
104
+ let(:body) { [ "bunch o' JSON" ] }
105
+
106
+ it "creates a Net::HTTP success response object" do
107
+ expect(net_http_response).to be_a_kind_of(Net::HTTPOK)
108
+ expect(net_http_response.read_body).to eq("bunch o' JSON")
109
+ expect(net_http_response["content-type"]).to eq("Application/JSON")
110
+ end
111
+
112
+ it "does not fail when calling read_body with a block" do
113
+ expect(net_http_response.read_body {|chunk| chunk }).to eq("bunch o' JSON")
114
+ end
115
+
116
+ end
117
+
118
+ context "when the requested object doesn't exist (404)" do
119
+
120
+ let(:code) { 404 }
121
+ let(:headers) { { "Content-Type" => "Application/JSON" } }
122
+ let(:body) { [ "nope" ] }
123
+
124
+ it "creates a Net::HTTPNotFound response object" do
125
+ expect(net_http_response).to be_a_kind_of(Net::HTTPNotFound)
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ describe "request-response round trip" do
132
+
133
+ let(:method) { :GET }
134
+ let(:relative_url) { "clients" }
135
+ let(:headers) { { "Accept" => "application/json" } }
136
+ let(:body) { false }
137
+
138
+ let(:expected_rack_req) do
139
+ {
140
+ "SCRIPT_NAME" => "",
141
+ "SERVER_NAME" => "localhost",
142
+ "REQUEST_METHOD" => method.to_s.upcase,
143
+ "PATH_INFO" => uri.path,
144
+ "QUERY_STRING" => uri.query,
145
+ "SERVER_PORT" => uri.port,
146
+ "HTTP_HOST" => "localhost:#{uri.port}",
147
+ "rack.url_scheme" => "chefzero",
148
+ "rack.input" => an_instance_of(StringIO),
149
+ }
150
+ end
151
+
152
+
153
+ let(:response_code) { 200 }
154
+ let(:response_headers) { { "Content-Type" => "Application/JSON" } }
155
+ let(:response_body) { [ "bunch o' JSON" ] }
156
+
157
+ let(:rack_response) { [ response_code, response_headers, response_body ] }
158
+
159
+ let(:response) { zero_client.request(method, uri, body, headers) }
160
+
161
+ before do
162
+ expect(ChefZero::SocketlessServerMap).to receive(:request).with(1, expected_rack_req).and_return(rack_response)
163
+ end
164
+
165
+ it "makes a rack request to Chef Zero and returns the response as a Net::HTTP object" do
166
+ _client, net_http_response = response
167
+ expect(net_http_response).to be_a_kind_of(Net::HTTPOK)
168
+ expect(net_http_response.code).to eq("200")
169
+ expect(net_http_response.body).to eq("bunch o' JSON")
170
+ end
171
+
172
+ end
173
+
174
+ end