From 6d30a2e10924dba539916383d95dd99074e4bd28 Mon Sep 17 00:00:00 2001 From: sachin007jain Date: Sat, 30 Jul 2022 22:53:15 +0530 Subject: Signed-off-by: sachin007jain Refactor knife cookbook upload for non-CLI use --- knife/lib/chef/knife.rb | 2 ++ knife/lib/chef/knife/cookbook_upload.rb | 7 +++++++ knife/spec/unit/knife/cookbook_upload_spec.rb | 28 +++++++++++++++++++++++++++ lib/chef/exceptions.rb | 8 ++++++++ 4 files changed, 45 insertions(+) diff --git a/knife/lib/chef/knife.rb b/knife/lib/chef/knife.rb index e5f8c36e32..9443bf39ba 100644 --- a/knife/lib/chef/knife.rb +++ b/knife/lib/chef/knife.rb @@ -68,6 +68,7 @@ class Chef attr_accessor :name_args attr_accessor :ui + attr_accessor :calling_request # knife acl subcommands are grouped in this category using this constant to verify. OPSCODE_HOSTED_CHEF_ACCESS_CONTROL = %w{acl group user}.freeze @@ -311,6 +312,7 @@ class Chef command_name_words = self.class.snake_case_name.split("_") + @calling_request = "CLI" # Mixlib::CLI ignores the embedded name_args @name_args = parse_options(argv) @name_args.delete(command_name_words.join("-")) diff --git a/knife/lib/chef/knife/cookbook_upload.rb b/knife/lib/chef/knife/cookbook_upload.rb index 357019212f..5653745894 100644 --- a/knife/lib/chef/knife/cookbook_upload.rb +++ b/knife/lib/chef/knife/cookbook_upload.rb @@ -163,6 +163,13 @@ class Chef end end end + { "status" => 200, "message" => "Success" } if @calling_request != "CLI" + rescue Exception => e + if calling_request == "API" + raise Exceptions::UnprocessableEntityAPI, e + else + raise + end end def server_side_cookbooks diff --git a/knife/spec/unit/knife/cookbook_upload_spec.rb b/knife/spec/unit/knife/cookbook_upload_spec.rb index a61eee9249..bc4e853329 100644 --- a/knife/spec/unit/knife/cookbook_upload_spec.rb +++ b/knife/spec/unit/knife/cookbook_upload_spec.rb @@ -48,6 +48,7 @@ describe Chef::Knife::CookbookUpload do let(:output) { StringIO.new } let(:name_args) { ["test_cookbook"] } + let(:calling_request) { "API" } let(:knife) do k = Chef::Knife::CookbookUpload.new @@ -57,6 +58,15 @@ describe Chef::Knife::CookbookUpload do k end + let(:knife_api) do + k = Chef::Knife::CookbookUpload.new + k.name_args = name_args + k.calling_request = calling_request + allow(k.ui).to receive(:stdout).and_return(output) + allow(k.ui).to receive(:stderr).and_return(output) + k + end + before(:each) do allow(Chef::CookbookLoader).to receive(:new).and_return(cookbook_loader) allow(Chef::CookbookLoader).to receive(:copy_to_tmp_dir_from_array).and_yield(cookbook_loader) @@ -100,6 +110,11 @@ describe Chef::Knife::CookbookUpload do it "should upload the cookbook" do expect { knife.run }.to raise_error(Chef::Exceptions::MetadataNotFound) end + + it "should raise the API error while upload the cookbook" do + expect { knife_api.run }.to raise_error(Chef::Exceptions::UnprocessableEntityAPI, { message: "No metadata.rb or metadata.json found for cookbook test_cookbook1 in /tmp/blah", status: 422 }.to_json) + end + end describe "when name attribute in metadata not set" do @@ -115,6 +130,10 @@ describe Chef::Knife::CookbookUpload do it "should upload the cookbook" do expect { knife.run }.to raise_error(Chef::Exceptions::MetadataNotValid) end + + it "should raise the API error while upload the cookbook" do + expect { knife_api.run }.to raise_error(Chef::Exceptions::UnprocessableEntityAPI, { message: "Cookbook loaded at path [/tmp/blah] has invalid metadata: The `name' attribute is required in cookbook metadata", status: 422 }.to_json) + end end describe "when specifying a cookbook name" do @@ -123,11 +142,20 @@ describe Chef::Knife::CookbookUpload do knife.run end + it "should upload the cookbook via external call i.e API" do + expect(knife_api).to receive(:upload).once + knife_api.run + end + it "should report on success" do expect(knife).to receive(:upload).once expect(knife.ui).to receive(:info).with(/Uploaded 1 cookbook/) knife.run end + + it "should report on success via external call i.e API" do + expect(knife_api.run).to eq({ "status" => 200, "message" => "Success" }) + end end describe "when specifying the same cookbook name twice" do diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index c60b7fc888..d531e1bff1 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -103,6 +103,14 @@ class Chef # Cookbook loader used to raise an argument error when cookbook not found. # for back compat, need to raise an error that inherits from ArgumentError class CookbookNotFoundInRepo < ArgumentError; end + + class UnprocessableEntityAPI < StandardError + def initialize(msg, exception_type = "API exception") + @exception_type = exception_type + super( { message: msg, status: 422 }.to_json) + end + end + class CookbookMergingError < RuntimeError; end class RecipeNotFound < ArgumentError; end # AttributeNotFound really means the attribute file could not be found -- cgit v1.2.1