diff options
-rw-r--r-- | lib/chef/api_client.rb | 39 | ||||
-rw-r--r-- | lib/chef/mixin/api_version_request_handling.rb | 9 | ||||
-rw-r--r-- | lib/chef/user.rb | 11 | ||||
-rw-r--r-- | spec/support/shared/unit/api_versioning.rb | 44 | ||||
-rw-r--r-- | spec/support/shared/unit/user_and_client_shared.rb | 3 | ||||
-rw-r--r-- | spec/unit/api_client_spec.rb | 19 | ||||
-rw-r--r-- | spec/unit/user_spec.rb | 29 |
7 files changed, 131 insertions, 23 deletions
diff --git a/lib/chef/api_client.rb b/lib/chef/api_client.rb index 9e964081ec..383095b273 100644 --- a/lib/chef/api_client.rb +++ b/lib/chef/api_client.rb @@ -55,6 +55,14 @@ class Chef @chef_rest_v1 ||= get_versioned_rest_object(Chef::Config[:chef_server_url], "1") end + def http_api + @http_api ||= Chef::REST.new(Chef::Config[:chef_server_url]) + end + + def self.http_api + Chef::REST.new(Chef::Config[:chef_server_url]) + end + # Gets or sets the client name. # # @params [Optional String] The name must be alpha-numeric plus - and _. @@ -173,10 +181,6 @@ class Chef from_hash(Chef::JSONCompat.parse(j)) end - def self.http_api - Chef::REST.new(Chef::Config[:chef_server_url]) - end - def self.reregister(name) api_client = load(name) api_client.reregister @@ -225,13 +229,27 @@ class Chef end def reregister - reregistered_self = http_api.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true }) + # Try API V0 and if it fails due to V0 not being supported, raise the proper error message. + # reregister only supported in API V0 or lesser. + reregistered_self = chef_rest_v0.put("clients/#{name}", { :name => name, :admin => admin, :validator => validator, :private_key => true }) if reregistered_self.respond_to?(:[]) private_key(reregistered_self["private_key"]) else private_key(reregistered_self.private_key) end self + rescue Net::HTTPServerException => e + # if there was a 406 related to versioning, give error explaining that + # only API version 0 is supported for reregister command + if e.response.code == "406" && e.response["x-ops-server-api-version"] + version_header = Chef::JSONCompat.from_json(e.response["x-ops-server-api-version"]) + min_version = version_header["min_version"] + max_version = version_header["max_version"] + error_msg = reregister_only_v0_supported_error_msg(max_version, min_version) + raise Chef::Exceptions::OnlyApiVersion0SupportedForAction.new(error_msg) + else + raise e + end end # Updates the client via the REST API @@ -243,8 +261,10 @@ class Chef # Delete this comment after V0 support is dropped. payload = { :name => name } payload[:validator] = validator unless validator.nil? - # this field is ignored in API V1, but left for backwards-compat, - # can remove after OSC 11 support is finished? + + # DEPRECATION + # This field is ignored in API V1, but left for backwards-compat, + # can remove after API V0 is no longer supported. payload[:admin] = admin unless admin.nil? begin @@ -308,10 +328,5 @@ class Chef # "public_key:'#{public_key}' private_key:'#{private_key}'" # end - # TODO delete? - def http_api - @http_api ||= Chef::REST.new(Chef::Config[:chef_server_url]) - end - end end diff --git a/lib/chef/mixin/api_version_request_handling.rb b/lib/chef/mixin/api_version_request_handling.rb index a818ba2a14..851bcb4968 100644 --- a/lib/chef/mixin/api_version_request_handling.rb +++ b/lib/chef/mixin/api_version_request_handling.rb @@ -46,5 +46,14 @@ class Chef true end + def reregister_only_v0_supported_error_msg(max_version, min_version) +<<-EOH +The reregister command only supports server API version 0. +The server that received the request supports a min version of #{min_version} and a max version of #{max_version}. +User keys are now managed via the key rotation commmands. +Please refer to the documentation on how to manage your keys via the key rotation commands. +EOH + end + end end diff --git a/lib/chef/user.rb b/lib/chef/user.rb index 6758ed671d..0ec7e87ed3 100644 --- a/lib/chef/user.rb +++ b/lib/chef/user.rb @@ -225,19 +225,10 @@ class Chef end end - def reregister_only_v0_supported_error_msg(max_version, min_version) -<<-EOH -The reregister command only supports server API version 0. -The server that received the request supports a min version of #{min_version} and a max version of #{max_version}. -User keys are now managed via the key rotation commmands. -Please refer to the documentation on how to manage your keys via the key rotation commands. -EOH - end - # Note: remove after API v0 no longer supported by client (and knife command). def reregister begin - payload = self.to_hash.merge({:private_key => true}) + payload = self.to_hash.merge({"private_key" => true}) reregistered_self = chef_root_rest_v0.put("users/#{username}", payload) private_key(reregistered_self["private_key"]) # only V0 supported for reregister diff --git a/spec/support/shared/unit/api_versioning.rb b/spec/support/shared/unit/api_versioning.rb index ffa424a78d..61fdfe7faf 100644 --- a/spec/support/shared/unit/api_versioning.rb +++ b/spec/support/shared/unit/api_versioning.rb @@ -16,7 +16,12 @@ # limitations under the License. # +require "chef/exceptions" + shared_examples_for "version handling" do + let(:response_406) { OpenStruct.new(:code => '406') } + let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) } + before do allow(rest_v1).to receive(http_verb).and_raise(exception_406) end @@ -31,3 +36,42 @@ shared_examples_for "version handling" do end end # when the server does not support the min or max server API version that Chef::User supports end # version handling + +shared_examples_for "user and client reregister" do + let(:response_406) { OpenStruct.new(:code => '406') } + let(:exception_406) { Net::HTTPServerException.new("406 Not Acceptable", response_406) } + let(:generic_exception) { Exception.new } + let(:min_version) { "2" } + let(:max_version) { "5" } + let(:return_hash_406) { + { + "min_version" => min_version, + "max_version" => max_version, + "request_version" => "30" + } + } + + context "when V0 is not supported by the server" do + context "when the exception is 406 and returns x-ops-server-api-version header" do + before do + allow(rest_v0).to receive(:put).and_raise(exception_406) + allow(response_406).to receive(:[]).with('x-ops-server-api-version').and_return(Chef::JSONCompat.to_json(return_hash_406)) + end + + it "raises an error about only V0 being supported" do + expect(object).to receive(:reregister_only_v0_supported_error_msg).with(max_version, min_version) + expect{ object.reregister }.to raise_error(Chef::Exceptions::OnlyApiVersion0SupportedForAction) + end + + end + context "when the exception is not versioning related" do + before do + allow(rest_v0).to receive(:put).and_raise(generic_exception) + end + + it "raises the original error" do + expect{ object.reregister }.to raise_error(generic_exception) + end + end + end +end diff --git a/spec/support/shared/unit/user_and_client_shared.rb b/spec/support/shared/unit/user_and_client_shared.rb index 36a7a7aeff..b0f3902922 100644 --- a/spec/support/shared/unit/user_and_client_shared.rb +++ b/spec/support/shared/unit/user_and_client_shared.rb @@ -111,4 +111,5 @@ shared_examples_for "user or client create" do end # when the server supports API V0 end # when server API V1 is not valid on the Chef Server receiving the request -end +end # user or client create + diff --git a/spec/unit/api_client_spec.rb b/spec/unit/api_client_spec.rb index b903c0e3c7..e1ffa9252a 100644 --- a/spec/unit/api_client_spec.rb +++ b/spec/unit/api_client_spec.rb @@ -490,5 +490,24 @@ describe Chef::ApiClient do end # when a valid client is defined end # update + # DEPRECATION + # This can be removed after API V0 support is gone + describe "reregister" do + context "when server API V0 is valid on the Chef Server receiving the request" do + it "creates a new object via the API" do + expect(@client.chef_rest_v0).to receive(:put).with("clients/#{@client.name}", payload.merge({:private_key => true})).and_return({}) + @client.reregister + end + end # when server API V0 is valid on the Chef Server receiving the request + + context "when server API V0 is not supported by the Chef Server" do + # from spec/support/shared/unit/api_versioning.rb + it_should_behave_like "user and client reregister" do + let(:object) { @client } + let(:rest_v0) { @client.chef_rest_v0 } + end + end # when server API V0 is not supported by the Chef Server + end # reregister + end end diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb index d9872ef5a8..15d9591712 100644 --- a/spec/unit/user_spec.rb +++ b/spec/unit/user_spec.rb @@ -504,6 +504,35 @@ describe Chef::User do end # create + # DEPRECATION + # This can be removed after API V0 support is gone + describe "reregister" do + let(:payload) { + { + "username" => "some_username", + } + } + + before do + @user.username "some_username" + end + + context "when server API V0 is valid on the Chef Server receiving the request" do + it "creates a new object via the API" do + expect(@user.chef_root_rest_v0).to receive(:put).with("users/#{@user.username}", payload.merge({"private_key" => true})).and_return({}) + @user.reregister + end + end # when server API V0 is valid on the Chef Server receiving the request + + context "when server API V0 is not supported by the Chef Server" do + # from spec/support/shared/unit/api_versioning.rb + it_should_behave_like "user and client reregister" do + let(:object) { @user } + let(:rest_v0) { @user.chef_root_rest_v0 } + end + end # when server API V0 is not supported by the Chef Server + end # reregister + end # Versioned API Interactions describe "API Interactions" do |