summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsachin007jain <sachin.jain@chef.io>2022-07-30 22:53:15 +0530
committersachin007jain <sachin.jain@chef.io>2022-08-01 21:54:41 +0530
commit6d30a2e10924dba539916383d95dd99074e4bd28 (patch)
treea7599cb5cd822ee198491eb6712e41d7d9fed922
parent4df5e4e43c773f9f3a7b69d4a5cd85af81448da9 (diff)
downloadchef-sanjain/INFWS-135-knife-API-support.tar.gz
Signed-off-by: sachin007jain <sachin.jain@chef.io>sanjain/INFWS-135-knife-API-support
Refactor knife cookbook upload for non-CLI use
-rw-r--r--knife/lib/chef/knife.rb2
-rw-r--r--knife/lib/chef/knife/cookbook_upload.rb7
-rw-r--r--knife/spec/unit/knife/cookbook_upload_spec.rb28
-rw-r--r--lib/chef/exceptions.rb8
4 files changed, 45 insertions, 0 deletions
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