From 519f4fdac2d70c730ab1447f6174d33d8eeea3f1 Mon Sep 17 00:00:00 2001 From: Vasu1105 Date: Thu, 18 Jun 2020 00:08:51 +0530 Subject: Fix for #9686: knife config use profile doesn't validate that the profile exist Signed-off-by: Vasu1105 --- lib/chef/knife/config_use_profile.rb | 20 ++++++-- spec/integration/knife/config_use_profile_spec.rb | 57 ++++++++++++++++++++++- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/lib/chef/knife/config_use_profile.rb b/lib/chef/knife/config_use_profile.rb index 134ae5e8b6..745a250523 100644 --- a/lib/chef/knife/config_use_profile.rb +++ b/lib/chef/knife/config_use_profile.rb @@ -33,17 +33,27 @@ class Chef end def run + credentials_data = self.class.config_loader.parse_credentials_file context_file = ChefConfig::PathHelper.home(".chef", "context").freeze profile = @name_args[0]&.strip - if profile && !profile.empty? + if profile.nil? || profile.empty? + show_usage + ui.fatal("You must specify a profile") + exit 1 + end + + if credentials_data.nil? || credentials_data.empty? + ui.fatal("No profiles found, #{self.class.config_loader.credentials_file_path} does not exist or is empty") + exit 1 + end + + if credentials_data[profile].nil? + raise ChefConfig::ConfigurationError, "Profile #{profile} doesn't exist. Please add it to #{self.class.config_loader.credentials_file_path} and if it is profile with DNS name check that you are not missing single quotes around it as per docs https://docs.chef.io/workstation/knife_setup/#knife-profiles." + else # Ensure the .chef/ folder exists. FileUtils.mkdir_p(File.dirname(context_file)) IO.write(context_file, "#{profile}\n") ui.msg("Set default profile to #{profile}") - else - show_usage - ui.fatal("You must specify a profile") - exit 1 end end diff --git a/spec/integration/knife/config_use_profile_spec.rb b/spec/integration/knife/config_use_profile_spec.rb index 213fe19f88..9451e74325 100644 --- a/spec/integration/knife/config_use_profile_spec.rb +++ b/spec/integration/knife/config_use_profile_spec.rb @@ -30,6 +30,7 @@ describe "knife config use-profile", :workstation do knife("config", "use-profile", *cmd_args, instance_filter: lambda { |instance| # Fake the failsafe check because this command doesn't actually process knife.rb. $__KNIFE_INTEGRATION_FAILSAFE_CHECK << " ole" + allow(File).to receive(:file?).and_call_original }) end @@ -73,15 +74,56 @@ describe "knife config use-profile", :workstation do context "with an argument" do let(:cmd_args) { %w{production} } + before { file(".chef/credentials", <<~EOH) } + [production] + client_name = "testuser" + client_key = "testkey.pem" + chef_server_url = "https://example.com/organizations/testorg" + EOH it do is_expected.to eq "Set default profile to production\n" expect(File.read(path_to(".chef/context"))).to eq "production\n" end end + context "with no credentials file" do + let(:cmd_args) { %w{production} } + subject { knife_use_profile.stderr } + it { is_expected.to eq "FATAL: No profiles found, #{path_to(".chef/credentials")} does not exist or is empty\n" } + end + + context "with an empty credentials file" do + let(:cmd_args) { %w{production} } + before { file(".chef/credentials", "") } + subject { knife_use_profile.stderr } + it { is_expected.to eq "FATAL: No profiles found, #{path_to(".chef/credentials")} does not exist or is empty\n" } + end + + context "with an wrong argument" do + let(:cmd_args) { %w{staging} } + before { file(".chef/credentials", <<~EOH) } + [production] + client_name = "testuser" + client_key = "testkey.pem" + chef_server_url = "https://example.com/organizations/testorg" + EOH + subject { knife_use_profile } + it { expect { subject }.to raise_error ChefConfig::ConfigurationError, "Profile staging doesn't exist. Please add it to #{path_to(".chef/credentials")} and if it is profile with DNS name check that you are not missing single quotes around it as per docs https://docs.chef.io/workstation/knife_setup/#knife-profiles." } + end + context "with $CHEF_HOME" do let(:cmd_args) { %w{staging} } - before { ENV["CHEF_HOME"] = path_to("chefhome"); file("chefhome/tmp", "") } + before do + ENV["CHEF_HOME"] = path_to("chefhome"); file("chefhome/tmp", "") + file("chefhome/.chef/credentials", <<~EOH + [staging] + client_name = "testuser" + client_key = "testkey.pem" + chef_server_url = "https://example.com/organizations/testorg" + EOH + ) + end + it do is_expected.to eq "Set default profile to staging\n" expect(File.read(path_to("chefhome/.chef/context"))).to eq "staging\n" @@ -91,7 +133,18 @@ describe "knife config use-profile", :workstation do context "with $KNIFE_HOME" do let(:cmd_args) { %w{development} } - before { ENV["KNIFE_HOME"] = path_to("knifehome"); file("knifehome/tmp", "") } + + before do + ENV["KNIFE_HOME"] = path_to("knifehome"); file("knifehome/tmp", "") + file("knifehome/.chef/credentials", <<~EOH + [development] + client_name = "testuser" + client_key = "testkey.pem" + chef_server_url = "https://example.com/organizations/testorg" + EOH + ) + end + it do is_expected.to eq "Set default profile to development\n" expect(File.read(path_to("knifehome/.chef/context"))).to eq "development\n" -- cgit v1.2.1